This commit is contained in:
parent
505cf51efe
commit
6fe03226c5
3 changed files with 143 additions and 12 deletions
|
@ -7,7 +7,7 @@ import {
|
|||
focusBlock,
|
||||
focusByWbr,
|
||||
getEditorRange,
|
||||
getSelectionOffset,
|
||||
getSelectionOffset, setLastNodeRange,
|
||||
} from "./selection";
|
||||
import {Constants} from "../../constants";
|
||||
import {highlightRender} from "../render/highlightRender";
|
||||
|
@ -199,6 +199,33 @@ const processAV = (range: Range, html: string, protyle: IProtyle, blockElement:
|
|||
});
|
||||
};
|
||||
|
||||
const processTable = (range: Range, html: string, protyle: IProtyle, blockElement: HTMLElement) => {
|
||||
const tempElement = document.createElement("template");
|
||||
tempElement.innerHTML = html;
|
||||
const cellElements = tempElement.content.querySelectorAll("th, td");
|
||||
if (cellElements.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const scrollLeft = blockElement.firstElementChild.scrollLeft;
|
||||
const tableSelectElement = blockElement.querySelector(".table__select") as HTMLElement;
|
||||
let index = 0;
|
||||
const oldHTML = blockElement.outerHTML;
|
||||
blockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
blockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => {
|
||||
if (!item.classList.contains("fn__none") &&
|
||||
item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth &&
|
||||
item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight &&
|
||||
cellElements.length > index) {
|
||||
item.innerHTML = cellElements[index].innerHTML;
|
||||
index++;
|
||||
setLastNodeRange(item, range, false);
|
||||
}
|
||||
});
|
||||
range.collapse(false);
|
||||
updateTransaction(protyle, blockElement.getAttribute("data-node-id"), blockElement.outerHTML, oldHTML);
|
||||
return true;
|
||||
}
|
||||
|
||||
export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
|
||||
// 移动端插入嵌入块时,获取到的 range 为旧值
|
||||
useProtyleRange = false,
|
||||
|
@ -217,13 +244,13 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
|
|||
isBlock = true;
|
||||
}
|
||||
}
|
||||
let blockElement = hasClosestBlock(range.startContainer) as Element;
|
||||
let blockElement = hasClosestBlock(range.startContainer) as HTMLElement;
|
||||
if (!blockElement) {
|
||||
// 使用鼠标点击选则模版提示列表后 range 丢失
|
||||
if (protyle.toolbar.range) {
|
||||
blockElement = hasClosestBlock(protyle.toolbar.range.startContainer) as Element;
|
||||
blockElement = hasClosestBlock(protyle.toolbar.range.startContainer) as HTMLElement;
|
||||
} else {
|
||||
blockElement = protyle.wysiwyg.element.firstElementChild as Element;
|
||||
blockElement = protyle.wysiwyg.element.firstElementChild as HTMLElement;
|
||||
}
|
||||
}
|
||||
if (!blockElement) {
|
||||
|
@ -234,6 +261,10 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
|
|||
processAV(range, html, protyle, blockElement as HTMLElement);
|
||||
return;
|
||||
}
|
||||
if (blockElement.classList.contains("table") && blockElement.querySelector(".table__select").clientWidth > 0 &&
|
||||
processTable(range, html, protyle, blockElement)) {
|
||||
return;
|
||||
}
|
||||
let id = blockElement.getAttribute("data-node-id");
|
||||
range.insertNode(document.createElement("wbr"));
|
||||
let oldHTML = blockElement.outerHTML;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {getTextStar, paste} from "../util/paste";
|
||||
import {getTextStar, paste, pasteText} from "../util/paste";
|
||||
import {
|
||||
hasClosestBlock,
|
||||
hasClosestByAttribute,
|
||||
|
@ -62,7 +62,7 @@ import {openGlobalSearch} from "../../search/util";
|
|||
import {popSearch} from "../../mobile/menu/search";
|
||||
/// #endif
|
||||
import {BlockPanel} from "../../block/Panel";
|
||||
import {isInIOS, isOnlyMeta} from "../util/compatibility";
|
||||
import {isInIOS, isOnlyMeta, readText} from "../util/compatibility";
|
||||
import {MenuItem} from "../../menus/Menu";
|
||||
import {fetchPost} from "../../util/fetch";
|
||||
import {onGet} from "../util/onGet";
|
||||
|
@ -274,9 +274,10 @@ export class WYSIWYG {
|
|||
}
|
||||
const selectImgElement = nodeElement.querySelector(".img--select");
|
||||
const selectAVElement = nodeElement.querySelector(".av__row--select, .av__cell--select");
|
||||
const selectTableElement = nodeElement.querySelector(".table__select")?.clientWidth > 0;
|
||||
let selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
|
||||
if (selectElements.length === 0 && range.toString() === "" && !range.cloneContents().querySelector("img") &&
|
||||
!selectImgElement && !selectAVElement) {
|
||||
!selectImgElement && !selectAVElement && !selectTableElement) {
|
||||
nodeElement.classList.add("protyle-wysiwyg--select");
|
||||
countBlockWord([nodeElement.getAttribute("data-node-id")]);
|
||||
selectElements = [nodeElement];
|
||||
|
@ -331,6 +332,31 @@ export class WYSIWYG {
|
|||
textPlain = textPlain.substring(0, textPlain.length - 2);
|
||||
html = html.substring(0, html.length - 1) + "]";
|
||||
}
|
||||
} else if (selectTableElement) {
|
||||
const selectCellElements: HTMLTableCellElement[] = [];
|
||||
const scrollLeft = nodeElement.firstElementChild.scrollLeft;
|
||||
const tableSelectElement = nodeElement.querySelector(".table__select") as HTMLElement;
|
||||
html = '<table>'
|
||||
nodeElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => {
|
||||
if (!item.classList.contains("fn__none") &&
|
||||
item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth &&
|
||||
item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight) {
|
||||
selectCellElements.push(item);
|
||||
}
|
||||
});
|
||||
selectCellElements.forEach((item, index) => {
|
||||
if (index === 0 || !item.previousElementSibling ||
|
||||
!item.previousElementSibling.isSameNode(selectCellElements[index - 1])) {
|
||||
html += "<tr>"
|
||||
}
|
||||
html += item.outerHTML;
|
||||
if (!item.nextElementSibling || !selectCellElements[index + 1] ||
|
||||
!item.nextElementSibling.isSameNode(selectCellElements[index + 1])) {
|
||||
html += "</tr>";
|
||||
}
|
||||
})
|
||||
html += '</table>'
|
||||
textPlain = protyle.lute.HTML2Md(html);
|
||||
} else {
|
||||
const tempElement = document.createElement("div");
|
||||
// https://github.com/siyuan-note/siyuan/issues/5540
|
||||
|
@ -394,8 +420,8 @@ export class WYSIWYG {
|
|||
textPlain = textPlain || protyle.lute.BlockDOM2StdMd(html).trimEnd();
|
||||
textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
|
||||
event.clipboardData.setData("text/plain", textPlain);
|
||||
event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
|
||||
event.clipboardData.setData("text/siyuan", html);
|
||||
event.clipboardData.setData("text/html", selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
|
||||
event.clipboardData.setData("text/siyuan", selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html);
|
||||
});
|
||||
|
||||
this.element.addEventListener("mousedown", (event: MouseEvent) => {
|
||||
|
@ -1222,6 +1248,28 @@ export class WYSIWYG {
|
|||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
icon: "iconCopy",
|
||||
accelerator: "⌘C",
|
||||
label: window.siyuan.languages.copy,
|
||||
click() {
|
||||
if (tableBlockElement) {
|
||||
focusByRange(getEditorRange(tableBlockElement));
|
||||
document.execCommand("copy");
|
||||
}
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
icon: "iconCut",
|
||||
accelerator: "⌘X",
|
||||
label: window.siyuan.languages.cut,
|
||||
click() {
|
||||
if (tableBlockElement) {
|
||||
focusByRange(getEditorRange(tableBlockElement));
|
||||
document.execCommand("cut");
|
||||
}
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
label: window.siyuan.languages.clear,
|
||||
icon: "iconTrashcan",
|
||||
|
@ -1238,6 +1286,7 @@ export class WYSIWYG {
|
|||
});
|
||||
tableSelectElement.removeAttribute("style");
|
||||
const oldHTML = tableBlockElement.outerHTML;
|
||||
tableBlockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
selectCellElements.forEach(item => {
|
||||
item.innerHTML = "";
|
||||
});
|
||||
|
@ -1245,6 +1294,23 @@ export class WYSIWYG {
|
|||
}
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
label: window.siyuan.languages.paste,
|
||||
icon: "iconPaste",
|
||||
accelerator: "⌘V",
|
||||
async click() {
|
||||
if (document.queryCommandSupported("paste")) {
|
||||
document.execCommand("paste");
|
||||
} else if (tableBlockElement) {
|
||||
try {
|
||||
const clipText = await readText();
|
||||
pasteText(protyle, clipText, tableBlockElement);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).element);
|
||||
window.siyuan.menus.menu.popup({x: mouseUpEvent.clientX - 8, y: mouseUpEvent.clientY - 16});
|
||||
}
|
||||
}
|
||||
|
@ -1359,9 +1425,10 @@ export class WYSIWYG {
|
|||
event.preventDefault();
|
||||
const selectImgElement = nodeElement.querySelector(".img--select");
|
||||
const selectAVElement = nodeElement.querySelector(".av__row--select, .av__cell--select");
|
||||
const selectTableElement = nodeElement.querySelector(".table__select")?.clientWidth > 0;
|
||||
let selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
|
||||
if (selectElements.length === 0 && range.toString() === "" && !range.cloneContents().querySelector("img") &&
|
||||
!selectImgElement && !selectAVElement) {
|
||||
!selectImgElement && !selectAVElement && !selectTableElement) {
|
||||
nodeElement.classList.add("protyle-wysiwyg--select");
|
||||
selectElements = [nodeElement];
|
||||
}
|
||||
|
@ -1395,6 +1462,35 @@ export class WYSIWYG {
|
|||
const cellsValue = updateCellsValue(protyle, nodeElement);
|
||||
html = JSON.stringify(cellsValue.json);
|
||||
textPlain = cellsValue.text;
|
||||
} else if (selectTableElement) {
|
||||
const selectCellElements: HTMLTableCellElement[] = [];
|
||||
const scrollLeft = nodeElement.firstElementChild.scrollLeft;
|
||||
const tableSelectElement = nodeElement.querySelector(".table__select") as HTMLElement;
|
||||
html = '<table>'
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
nodeElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => {
|
||||
if (!item.classList.contains("fn__none") &&
|
||||
item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth &&
|
||||
item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight) {
|
||||
selectCellElements.push(item);
|
||||
}
|
||||
});
|
||||
selectCellElements.forEach((item, index) => {
|
||||
if (index === 0 || !item.previousElementSibling ||
|
||||
!item.previousElementSibling.isSameNode(selectCellElements[index - 1])) {
|
||||
html += "<tr>"
|
||||
}
|
||||
html += item.outerHTML;
|
||||
if (!item.nextElementSibling || !selectCellElements[index + 1] ||
|
||||
!item.nextElementSibling.isSameNode(selectCellElements[index + 1])) {
|
||||
html += "</tr>";
|
||||
}
|
||||
item.innerHTML = "";
|
||||
})
|
||||
html += '</table>'
|
||||
textPlain = protyle.lute.HTML2Md(html);
|
||||
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
||||
} else {
|
||||
const id = nodeElement.getAttribute("data-node-id");
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
|
@ -1550,8 +1646,8 @@ export class WYSIWYG {
|
|||
}
|
||||
textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
|
||||
event.clipboardData.setData("text/plain", textPlain);
|
||||
event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
|
||||
event.clipboardData.setData("text/siyuan", html);
|
||||
event.clipboardData.setData("text/html", selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
|
||||
event.clipboardData.setData("text/siyuan", selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html);
|
||||
});
|
||||
|
||||
let beforeContextmenuRange: Range;
|
||||
|
|
4
app/src/types/protyle.d.ts
vendored
4
app/src/types/protyle.d.ts
vendored
|
@ -276,6 +276,10 @@ declare class Lute {
|
|||
public BlockDOM2InlineBlockDOM(html: string): string;
|
||||
|
||||
public BlockDOM2HTML(html: string): string;
|
||||
|
||||
public HTML2Md(html: string): string;
|
||||
|
||||
public HTML2BlockDOM(html: string): string;
|
||||
}
|
||||
|
||||
declare const webkitAudioContext: {
|
||||
|
|
Loading…
Add table
Reference in a new issue