diff --git a/app/src/assets/scss/protyle/_protyle.scss b/app/src/assets/scss/protyle/_protyle.scss index f034b3fcb..58d0d6c43 100644 --- a/app/src/assets/scss/protyle/_protyle.scss +++ b/app/src/assets/scss/protyle/_protyle.scss @@ -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; diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 701b7bedd..b014553e6 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -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("
")) { - cellHTML = cellHTML.substr(0, cellHTML.length - 4); - } - html += cellHTML + ((!cellHTML || index === selectCellElements.length - 1) ? "" : "
"); - 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("
")) { + cellHTML = cellHTML.substr(0, cellHTML.length - 4); + } + html += cellHTML + ((!cellHTML || index === selectCellElements.length - 1) ? "" : "
"); + 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 + ""; - 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 + ""; + 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}); } }