Skip to content

Commit

Permalink
🎨 #10488
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 committed Oct 29, 2024
1 parent 505cf51 commit 6fe0322
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 12 deletions.
39 changes: 35 additions & 4 deletions app/src/protyle/util/insertHTML.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
focusBlock,
focusByWbr,
getEditorRange,
getSelectionOffset,
getSelectionOffset, setLastNodeRange,
} from "./selection";
import {Constants} from "../../constants";
import {highlightRender} from "../render/highlightRender";
Expand Down Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
112 changes: 104 additions & 8 deletions app/src/protyle/wysiwyg/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getTextStar, paste} from "../util/paste";
import {getTextStar, paste, pasteText} from "../util/paste";
import {
hasClosestBlock,
hasClosestByAttribute,
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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",
Expand All @@ -1238,13 +1286,31 @@ export class WYSIWYG {
});
tableSelectElement.removeAttribute("style");
const oldHTML = tableBlockElement.outerHTML;
tableBlockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
selectCellElements.forEach(item => {
item.innerHTML = "";
});
updateTransaction(protyle, tableBlockElement.getAttribute("data-node-id"), tableBlockElement.outerHTML, oldHTML);
}
}
}).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});
}
}
Expand Down Expand Up @@ -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];
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions app/src/types/protyle.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down

0 comments on commit 6fe0322

Please sign in to comment.