Vanessa 2025-02-18 21:45:53 +08:00
parent 22a6c34d94
commit fd42a78e25
2 changed files with 227 additions and 223 deletions

View File

@ -409,11 +409,11 @@
}
}
table[contenteditable="false"] + .protyle-action__table {
table[contenteditable="false"] + .protyle-action__table > .table__resize {
display: none;
}
table[contenteditable="true"] + .protyle-action__table {
table + .protyle-action__table {
position: absolute;
top: 4px;
height: 0;

View File

@ -811,7 +811,7 @@ export class WYSIWYG {
documentSelf.onmousemove = (moveEvent: MouseEvent) => {
let moveTarget: boolean | HTMLElement = moveEvent.target as HTMLElement;
// table cell select
if (!protyle.disabled && tableBlockElement && tableBlockElement.contains(moveTarget) &&
if (tableBlockElement && tableBlockElement.contains(moveTarget) &&
!hasClosestByClassName(tableBlockElement, "protyle-wysiwyg__embed")) {
if (moveTarget.classList.contains("table__select")) {
moveTarget.classList.add("fn__none");
@ -1084,7 +1084,7 @@ export class WYSIWYG {
});
protyle.selectElement.classList.add("fn__none");
protyle.selectElement.removeAttribute("style");
if (!protyle.disabled && tableBlockElement) {
if (tableBlockElement) {
// @ts-ignore
tableBlockElement.firstElementChild.style.webkitUserModify = "";
const tableSelectElement = tableBlockElement.querySelector(".table__select") as HTMLElement;
@ -1093,207 +1093,209 @@ export class WYSIWYG {
getSelection().getRangeAt(0).collapse(false);
}
window.siyuan.menus.menu.remove();
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.mergeCell,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const colIndexList: number[] = [];
const colCount = tableBlockElement.querySelectorAll("th").length;
let fnNoneMax = 0;
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
let isTHead = false;
let isTBody = false;
tableBlockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement, index: number) => {
if (item.classList.contains("fn__none")) {
// 合并的元素中间有 fn__none 的元素
if (item.previousElementSibling && item.previousElementSibling.isSameNode(selectCellElements[selectCellElements.length - 1])) {
selectCellElements.push(item);
if (!isTHead && item.parentElement.parentElement.tagName === "THEAD") {
isTHead = true;
} else if (!isTBody && item.parentElement.parentElement.tagName === "TBODY") {
isTBody = true;
}
} else {
if (index < fnNoneMax && colIndexList.includes((index + 1) % colCount)) {
if (!protyle.disabled) {
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.mergeCell,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const colIndexList: number[] = [];
const colCount = tableBlockElement.querySelectorAll("th").length;
let fnNoneMax = 0;
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
let isTHead = false;
let isTBody = false;
tableBlockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement, index: number) => {
if (item.classList.contains("fn__none")) {
// 合并的元素中间有 fn__none 的元素
if (item.previousElementSibling && item.previousElementSibling.isSameNode(selectCellElements[selectCellElements.length - 1])) {
selectCellElements.push(item);
if (!isTHead && item.parentElement.parentElement.tagName === "THEAD") {
isTHead = true;
} else if (!isTBody && item.parentElement.parentElement.tagName === "TBODY") {
isTBody = true;
}
} else {
if (index < fnNoneMax && colIndexList.includes((index + 1) % colCount)) {
selectCellElements.push(item);
if (!isTHead && item.parentElement.parentElement.tagName === "THEAD") {
isTHead = true;
} else if (!isTBody && item.parentElement.parentElement.tagName === "TBODY") {
isTBody = true;
}
}
}
}
} else {
if (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);
if (!isTHead && item.parentElement.parentElement.tagName === "THEAD") {
isTHead = true;
} else if (!isTBody && item.parentElement.parentElement.tagName === "TBODY") {
isTBody = true;
}
colIndexList.push((index + 1) % colCount);
// https://github.com/siyuan-note/insider/issues/1014
fnNoneMax = Math.max((item.rowSpan - 1) * colCount + index + 1, fnNoneMax);
}
}
});
tableSelectElement.removeAttribute("style");
const oldHTML = tableBlockElement.outerHTML;
let cellElement = selectCellElements[0];
let colSpan = cellElement.colSpan;
let index = 1;
while (cellElement.nextElementSibling && cellElement.nextElementSibling.isSameNode(selectCellElements[index])) {
cellElement = cellElement.nextElementSibling as HTMLTableCellElement;
if (!cellElement.classList.contains("fn__none")) { // https://github.com/siyuan-note/insider/issues/1007#issuecomment-1046195608
colSpan += cellElement.colSpan;
}
index++;
}
let html = "";
let rowElement: Element = selectCellElements[0].parentElement;
let rowSpan = selectCellElements[0].rowSpan;
selectCellElements.forEach((item, index) => {
let cellHTML = item.innerHTML.trim();
if (cellHTML.endsWith("<br>")) {
cellHTML = cellHTML.substr(0, cellHTML.length - 4);
}
html += cellHTML + ((!cellHTML || index === selectCellElements.length - 1) ? "" : "<br>");
if (index !== 0) {
if (!rowElement.isSameNode(item.parentElement)) {
if (!item.classList.contains("fn__none")) { // https://github.com/siyuan-note/insider/issues/1011
rowSpan += item.rowSpan;
}
rowElement = item.parentElement;
if (selectCellElements[0].parentElement.parentElement.tagName === "THEAD" && item.parentElement.parentElement.tagName !== "THEAD") {
selectCellElements[0].parentElement.parentElement.insertAdjacentElement("beforeend", item.parentElement);
}
}
item.classList.add("fn__none");
item.innerHTML = "";
}
});
// https://github.com/siyuan-note/insider/issues/1017
if (isTHead && isTBody) {
rowElement = rowElement.parentElement.nextElementSibling.firstElementChild;
while (rowElement && rowElement.parentElement.tagName !== "THEAD") {
let colSpanCount = 0;
let noneCount = 0;
Array.from(rowElement.children).forEach((item: HTMLTableCellElement) => {
colSpanCount += item.colSpan - 1;
if (item.classList.contains("fn__none")) {
noneCount++;
}
});
if (colSpanCount !== noneCount) {
selectCellElements[0].parentElement.parentElement.insertAdjacentElement("beforeend", rowElement);
rowElement = rowElement.parentElement.nextElementSibling.firstElementChild;
} else {
break;
if (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);
if (!isTHead && item.parentElement.parentElement.tagName === "THEAD") {
isTHead = true;
} else if (!isTBody && item.parentElement.parentElement.tagName === "TBODY") {
isTBody = true;
}
colIndexList.push((index + 1) % colCount);
// https://github.com/siyuan-note/insider/issues/1014
fnNoneMax = Math.max((item.rowSpan - 1) * colCount + index + 1, fnNoneMax);
}
}
});
tableSelectElement.removeAttribute("style");
const oldHTML = tableBlockElement.outerHTML;
let cellElement = selectCellElements[0];
let colSpan = cellElement.colSpan;
let index = 1;
while (cellElement.nextElementSibling && cellElement.nextElementSibling.isSameNode(selectCellElements[index])) {
cellElement = cellElement.nextElementSibling as HTMLTableCellElement;
if (!cellElement.classList.contains("fn__none")) { // https://github.com/siyuan-note/insider/issues/1007#issuecomment-1046195608
colSpan += cellElement.colSpan;
}
index++;
}
let html = "";
let rowElement: Element = selectCellElements[0].parentElement;
let rowSpan = selectCellElements[0].rowSpan;
selectCellElements.forEach((item, index) => {
let cellHTML = item.innerHTML.trim();
if (cellHTML.endsWith("<br>")) {
cellHTML = cellHTML.substr(0, cellHTML.length - 4);
}
html += cellHTML + ((!cellHTML || index === selectCellElements.length - 1) ? "" : "<br>");
if (index !== 0) {
if (!rowElement.isSameNode(item.parentElement)) {
if (!item.classList.contains("fn__none")) { // https://github.com/siyuan-note/insider/issues/1011
rowSpan += item.rowSpan;
}
rowElement = item.parentElement;
if (selectCellElements[0].parentElement.parentElement.tagName === "THEAD" && item.parentElement.parentElement.tagName !== "THEAD") {
selectCellElements[0].parentElement.parentElement.insertAdjacentElement("beforeend", item.parentElement);
}
}
item.classList.add("fn__none");
item.innerHTML = "";
}
});
// https://github.com/siyuan-note/insider/issues/1017
if (isTHead && isTBody) {
rowElement = rowElement.parentElement.nextElementSibling.firstElementChild;
while (rowElement && rowElement.parentElement.tagName !== "THEAD") {
let colSpanCount = 0;
let noneCount = 0;
Array.from(rowElement.children).forEach((item: HTMLTableCellElement) => {
colSpanCount += item.colSpan - 1;
if (item.classList.contains("fn__none")) {
noneCount++;
}
});
if (colSpanCount !== noneCount) {
selectCellElements[0].parentElement.parentElement.insertAdjacentElement("beforeend", rowElement);
rowElement = rowElement.parentElement.nextElementSibling.firstElementChild;
} else {
break;
}
}
}
}
// 合并背景色不会修改,需要等计算完毕
setTimeout(() => {
if (tableBlockElement) {
selectCellElements[0].innerHTML = html + "<wbr>";
selectCellElements[0].colSpan = colSpan;
selectCellElements[0].rowSpan = rowSpan;
focusByWbr(selectCellElements[0], document.createRange());
updateTransaction(protyle, tableBlockElement.getAttribute("data-node-id"), tableBlockElement.outerHTML, oldHTML);
}
});
// 合并背景色不会修改,需要等计算完毕
setTimeout(() => {
if (tableBlockElement) {
selectCellElements[0].innerHTML = html + "<wbr>";
selectCellElements[0].colSpan = colSpan;
selectCellElements[0].rowSpan = rowSpan;
focusByWbr(selectCellElements[0], document.createRange());
updateTransaction(protyle, tableBlockElement.getAttribute("data-node-id"), tableBlockElement.outerHTML, oldHTML);
}
});
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignLeft",
accelerator: window.siyuan.config.keymap.editor.general.alignLeft.custom,
label: window.siyuan.languages.alignLeft,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "left", getEditorRange(tableBlockElement));
}).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignLeft",
accelerator: window.siyuan.config.keymap.editor.general.alignLeft.custom,
label: window.siyuan.languages.alignLeft,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "left", getEditorRange(tableBlockElement));
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignCenter",
accelerator: window.siyuan.config.keymap.editor.general.alignCenter.custom,
label: window.siyuan.languages.alignCenter,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "center", getEditorRange(tableBlockElement));
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignCenter",
accelerator: window.siyuan.config.keymap.editor.general.alignCenter.custom,
label: window.siyuan.languages.alignCenter,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "center", getEditorRange(tableBlockElement));
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignRight",
accelerator: window.siyuan.config.keymap.editor.general.alignRight.custom,
label: window.siyuan.languages.alignRight,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "right", getEditorRange(tableBlockElement));
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconAlignRight",
accelerator: window.siyuan.config.keymap.editor.general.alignRight.custom,
label: window.siyuan.languages.alignRight,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "right", getEditorRange(tableBlockElement));
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "",
label: window.siyuan.languages.useDefaultAlign,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "", getEditorRange(tableBlockElement));
}).element);
window.siyuan.menus.menu.append(new MenuItem({
icon: "",
label: window.siyuan.languages.useDefaultAlign,
click: () => {
if (tableBlockElement) {
const selectCellElements: HTMLTableCellElement[] = [];
const scrollLeft = tableBlockElement.firstElementChild.scrollLeft;
tableBlockElement.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.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) {
selectCellElements.push(item);
}
});
tableSelectElement.removeAttribute("style");
setTableAlign(protyle, selectCellElements, tableBlockElement, "", getEditorRange(tableBlockElement));
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
}).element);
window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element);
}
window.siyuan.menus.menu.append(new MenuItem({
icon: "iconCopy",
accelerator: "⌘C",
@ -1305,42 +1307,44 @@ export class WYSIWYG {
}
}
}).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",
accelerator: "⌦",
click() {
clearTableCell(protyle, tableBlockElement as HTMLElement);
}
}).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 text = await readClipboard();
paste(protyle, Object.assign(text, {target: tableBlockElement as HTMLElement}));
} catch (e) {
console.log(e);
if (!protyle.disabled) {
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);
}).element);
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.clear,
icon: "iconTrashcan",
accelerator: "⌦",
click() {
clearTableCell(protyle, tableBlockElement as HTMLElement);
}
}).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 text = await readClipboard();
paste(protyle, Object.assign(text, {target: tableBlockElement as HTMLElement}));
} catch (e) {
console.log(e);
}
}
}
}).element);
}
window.siyuan.menus.menu.popup({x: mouseUpEvent.clientX - 8, y: mouseUpEvent.clientY - 16});
}
}