UNPKG

@cairn214/fluent-editor

Version:

A rich text editor based on Quill 2.0, which extends rich modules and formats on the basis of Quill. It's powerful and out-of-the-box.

1,040 lines (1,039 loc) 37.7 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const Quill = require("quill"); const editor_utils = require("../../config/editor.utils.cjs.js"); const method = require("../../utils/method.cjs.js"); const tableConfig = require("../table-config.cjs.js"); const index = require("../utils/index.cjs.js"); const header = require("./header.cjs.js"); const list = require("./list.cjs.js"); const Break = Quill.imports["blots/break"]; const Block = Quill.imports["blots/block"]; const Container = Quill.imports["blots/container"]; class TableCellLine extends Block { static create(value) { const node = super.create(value); if (value.tdBgColor) { node.setAttribute(`data-parent-bg`, value.tdBgColor); delete value.tdBgColor; } tableConfig.CELL_IDENTITY_KEYS.forEach((key) => { const identityMaker = key === "row" ? rowId : cellId; node.setAttribute(`data-${key}`, value[key] || identityMaker()); }); tableConfig.CELL_ATTRIBUTES.forEach((attrName) => { const keyValue = value[attrName] || tableConfig.CELL_DEFAULT[attrName]; keyValue && node.setAttribute(`data-${attrName}`, keyValue); }); if (value.height) { node.setAttribute("height", value.height); } return node; } static formats(domNode) { const formats = {}; if (formats.list) { formats.list = domNode.classList.item(0); } return reduceFormats(domNode, formats); } toggleAttribute(name, value) { if (value) { this.domNode.setAttribute(name, value); } else { this.domNode.removeAttribute(name); } } formatChildren(name, value) { this.children.forEach((child) => { child.format && child.format(name, value); if (!child.domNode.style) { return; } switch (name) { case "cell-bg": if (child.domNode.tagName === "SPAN" && value) { child.domNode.style.backgroundColor = value; } else { child.domNode.style.backgroundColor = "initial"; } break; case "cell-border-color": if (child.domNode.tagName === "SPAN" && value) { child.domNode.style.border = value; } else { child.domNode.style.border = "initial"; } break; default: break; } }); } format(name, value) { if ([...tableConfig.CELL_ATTRIBUTES, ...tableConfig.CELL_IDENTITY_KEYS, "parent-bg"].includes(name)) { if (value) { this.domNode.setAttribute(`data-${name}`, value); } else { this.domNode.removeAttribute(`data-${name}`); } } else if (name === "header") { if (!value) { return; } const { row, cell, rowspan, colspan } = TableCellLine.formats(this.domNode); super.format(name, { value, row, cell, rowspan, colspan }); } else { super.format(name, value); } switch (true) { case name === "cell-bg": { this.toggleAttribute("data-cell-bg", value); if (value) { this.domNode.style.backgroundColor = value; } else { this.domNode.style.backgroundColor = "initial"; } } break; case name === "cell-border-color": { this.toggleAttribute("data-cell-border-color", value); if (value) { this.domNode.style.border = value; } else { this.domNode.style.border = "initial"; } } break; } } optimize(context) { super.optimize(context); const { row, cell, rowspan, colspan, cellBg } = this.domNode.dataset; const formats = TableCellLine.formats(this.domNode); const parentFormats = this.parent.formats(); if (this.statics.requiredContainer && !(this.parent instanceof this.statics.requiredContainer)) { this.wrap(this.statics.requiredContainer.blotName, { row, cell, rowspan, colspan, cellBg }); } else if (!method.compare(formats, parentFormats)) { this.parent.format("row", formats.row); this.parent.format("cell", formats.cell); this.parent.format("rowspan", formats.rowspan); this.parent.format("colspan", formats.colspan); formats["cell-bg"] && this.parent.setCellBg(formats["cell-bg"]); formats["cell-border-color"] && this.parent.setCellBorderColor(formats["cell-border-color"]); } const parentHeight = this.domNode.getAttribute("height"); if (parentHeight) { this.parent.domNode.style.height = parentHeight; } } tableCell() { return this.parent; } } TableCellLine.blotName = "table-cell-line"; TableCellLine.className = "qlbt-cell-line"; TableCellLine.tagName = "DIV"; class TableCell extends Container { static create(value = { row: rowId() }) { const node = super.create(value); tableConfig.CELL_IDENTITY_KEYS.forEach((key) => { node.setAttribute(`data-${key}`, value[key]); }); tableConfig.CELL_ATTRIBUTES.forEach((attrName) => { if (value[attrName]) { node.setAttribute(attrName, value[attrName]); } }); return node; } static formats(domNode) { const formats = { height: void 0, row: void 0 }; formats.height = domNode.getAttribute("height") || void 0; if (domNode.hasAttribute("data-row")) { formats.row = domNode.getAttribute("data-row"); } if (domNode.hasAttribute("data-cell-bg")) { formats["cell-bg"] = domNode.getAttribute("data-cell-bg") || void 0; } if (domNode.hasAttribute("data-cell-border-color")) { formats["cell-border-color"] = domNode.getAttribute("data-cell-border-color") || void 0; } return tableConfig.CELL_ATTRIBUTES.reduce((formats2, attribute) => { if (domNode.hasAttribute(attribute)) { formats2[attribute] = domNode.getAttribute(attribute); } return formats2; }, formats); } checkMerge() { if (super.checkMerge() && !editor_utils.isNullOrUndefined(this.next.children.head)) { const getCellId = (node) => { return node.formats && node.formats()[node.statics.blotName] || { cell: node.domNode.getAttribute("data-cell") }; }; const thisHead = getCellId(this.children.head); const thisTail = getCellId(this.children.tail); const nextHead = getCellId(this.next.children.head); const nextTail = getCellId(this.next.children.tail); return thisHead.cell === thisTail.cell && thisHead.cell === nextHead.cell && thisHead.cell === nextTail.cell; } return false; } cellOffset() { if (this.parent) { return this.parent.children.indexOf(this); } return -1; } formats() { const formats = {}; if (this.domNode.hasAttribute("data-row")) { formats.row = this.domNode.getAttribute("data-row"); } if (this.domNode.hasAttribute("data-cell")) { formats.cell = this.domNode.getAttribute("data-cell"); } return tableConfig.CELL_ATTRIBUTES.reduce((tableFormats, attribute) => { if (this.domNode.hasAttribute(attribute)) { tableFormats[attribute] = this.domNode.getAttribute(attribute); } return tableFormats; }, formats); } toggleAttribute(name, value) { if (value) { this.domNode.setAttribute(name, value); } else { this.domNode.removeAttribute(name); } } formatChildren(name, value) { this.children.forEach((child) => { child.format(name, value); }); } /** * this method is for TableCellLine to change cell background color * if use `format('cell-bg', value)` will loop trigger * TableCellLine.optimize -> TableCell.format -> TableCellLine.optimize ... */ setCellBg(value) { if (value) { this.domNode.style.backgroundColor = value; } else { this.domNode.style.backgroundColor = "initial"; } } setCellBorderColor(value) { if (value) { this.domNode.style.border = value; const table = this.domNode.closest("table"); const rows = Array.from(table.querySelectorAll("tr")); const rowIndex = rows.findIndex((row) => row.contains(this.domNode)); const cellIndex = Array.from(rows[rowIndex].children).indexOf(this.domNode); if (rowIndex > 0) { const upperCell = rows[rowIndex - 1].children[cellIndex]; if (upperCell) { upperCell.style.borderBottom = value; } } if (rowIndex < rows.length - 1) { const lowerCell = rows[rowIndex + 1].children[cellIndex]; if (lowerCell) { lowerCell.style.borderTop = value; } } if (cellIndex > 0) { const leftCell = rows[rowIndex].children[cellIndex - 1]; leftCell.style.borderRight = value; } if (cellIndex < rows[rowIndex].children.length - 1) { const rightCell = rows[rowIndex].children[cellIndex + 1]; rightCell.style.borderLeft = value; } } else { this.domNode.style.border = "initial"; } } format(name, value) { const quill = Quill.find(this.scroll.domNode.parentNode); switch (true) { case name === "cell-bg": { this.toggleAttribute("data-cell-bg", value); this.toggleAttribute("data-parent-bg", value); this.formatChildren(name, value); this.setCellBg(value); break; } case name === "cell-border-color": { this.toggleAttribute("data-cell-border-color", value); this.setCellBorderColor(value); break; } case tableConfig.CELL_ATTRIBUTES.includes(name): this.toggleAttribute(name, value); break; case ["row", "cell"].includes(name): this.toggleAttribute(`data-${name}`, value); break; case name === "background": { const hasBgColor = this.domNode.querySelectorAll("div.qlbt-cell-line[data-parent-bg]"); hasBgColor.forEach((child) => child.removeAttribute("data-parent-bg")); this.domNode.style.background = ""; this.domNode.style.backgroundColor = value; this.children.head.format("parent-bg", value); break; } case name === "size": { const start = quill.getIndex(this.children.head); const total = quill.getIndex(this.children.tail) + this.children.tail.length(); const length = total - start > 0 ? total - start : 0; quill.setSelection(start, length, Quill.sources.USER); quill.format(name, value, Quill.sources.USER); quill.setSelection(start); break; } } } optimize(context) { const hasBg = Array.from(this.domNode.childNodes).find((item) => item.getAttribute("data-parent-bg")); const bgColor = hasBg && hasBg.getAttribute("data-parent-bg"); if (bgColor && bgColor !== this.domNode.style.backgroundColor) { this.domNode.style.backgroundColor = bgColor; } const rId = this.domNode.getAttribute("data-row"); if (this.statics.requiredContainer && !(this.parent instanceof this.statics.requiredContainer)) { this.wrap(this.statics.requiredContainer.blotName, { row: rId }); } else if (rId !== this.parent.formats().row) { this.parent.format("row", rId); } this.children.forEach((child) => { if (editor_utils.isNullOrUndefined(child.next)) { return; } const childFormats = this.getFormat(child.domNode); const nextFormats = this.getFormat(child.next.domNode); if (childFormats.cell !== nextFormats.cell) { const next = this.splitAfter(child); if (next) { next.optimize(); } if (this.prev) { this.prev.optimize(); } } }); super.optimize(context); } // 兼容读取TableCell中的子blot,包括table-cell-line、line、head getFormat(domNode) { const formats = {}; const firstChild = domNode.childNodes[0]; if (firstChild && domNode.tagName === "OL") { formats.list = firstChild.classList.item(0); } return reduceFormats(domNode, formats); } row() { return this.parent; } rowOffset() { if (this.row()) { return -1; } return this.row().rowOffset(); } table() { return this.row() && this.row().table(); } } TableCell.blotName = "table"; TableCell.tagName = "TD"; class TableRow extends Container { static create(value) { const node = super.create(value); if (value.row) { node.setAttribute("data-row", value.row); } return node; } checkMerge() { if (super.checkMerge() && !editor_utils.isNullOrUndefined(this.next.children.head)) { const thisHead = this.children.head.formats(); const thisTail = this.children.tail.formats(); const nextHead = this.next.children.head.formats(); const nextTail = this.next.children.tail.formats(); return thisHead.row === thisTail.row && thisHead.row === nextHead.row && thisHead.row === nextTail.row; } return false; } formats() { return ["row"].reduce((formats, attrName) => { if (this.domNode.hasAttribute(`data-${attrName}`)) { formats[attrName] = this.domNode.getAttribute(`data-${attrName}`); } return formats; }, {}); } format(key, value) { this.domNode.setAttribute(`data-${key}`, value); } optimize(context) { if (this.statics.requiredContainer && !(this.parent instanceof this.statics.requiredContainer)) { this.wrap(this.statics.requiredContainer.blotName); } this.children.forEach((child) => { if (editor_utils.isNullOrUndefined(child.next)) { return; } const childFormats = child.formats(); const nextFormats = child.next.formats(); if (childFormats.row !== nextFormats.row) { const next = this.splitAfter(child); if (next) { next.optimize(); } if (this.prev) { this.prev.optimize(); } } }); super.optimize(context); } rowOffset() { if (!this.parent) { return -1; } return this.parent.children.indexOf(this); } table() { return this.parent && this.parent.parent; } } TableRow.blotName = "table-row"; TableRow.tagName = "TR"; class TableBody extends Container { } TableBody.blotName = "table-body"; TableBody.tagName = "TBODY"; class TableCol extends Block { static create(value) { const node = super.create(value); tableConfig.COL_ATTRIBUTES.forEach((attrName) => { node.setAttribute(`${attrName}`, value[attrName] || tableConfig.COL_DEFAULT[attrName]); }); return node; } static formats(domNode) { return tableConfig.COL_ATTRIBUTES.reduce((formats, attribute) => { if (domNode.hasAttribute(`${attribute}`)) { formats[attribute] = domNode.getAttribute(`${attribute}`) || void 0; } return formats; }, {}); } format(name, value) { if (tableConfig.COL_ATTRIBUTES.includes(name)) { this.domNode.setAttribute(`${name}`, value || tableConfig.COL_DEFAULT[name]); } else { super.format(name, value); } } html() { return this.domNode.outerHTML; } } TableCol.blotName = "table-col"; TableCol.tagName = "col"; class TableColGroup extends Container { optimize(context) { super.optimize(context); if (this.parent && this.statics.requiredContainer && this.parent instanceof this.statics.requiredContainer) { this.parent.updateTableWidth(); } if (this.parent.parent.domNode.className === "quill-better-table-wrapper" && this.parent.parent.domNode.tagName === "DIV" && this.parent.domNode.children.length >= 2 && this.parent.domNode.children[0].tagName === "COLGROUP" && this.parent.domNode.children[1].tagName === "TBODY") { let trId = ""; let colSpan = 0; let colgroupNumber = 0; for (let i = 0; i < this.parent.domNode.children.length; i++) { if (this.parent.domNode.children[i].tagName === "TBODY") { if (trId === "") { trId = this.parent.domNode.children[i].children[0].getAttribute("data-row"); } colSpan = this.findTdColspanInTbody(this.parent.domNode.children[i], trId); } else if (this.parent.domNode.children[i].tagName === "COLGROUP") { colgroupNumber = this.parent.domNode.children[i].children.length; } } let elementSibling = this.parent.domNode.nextElementSibling; while (elementSibling && elementSibling.tagName === "TABLE") { for (let i = 0; i < elementSibling.children.length; i++) { if (elementSibling.children[i].tagName === "TBODY") { colSpan += this.findTdColspanInTbody(elementSibling.children[i], trId); } } elementSibling = elementSibling.nextElementSibling; } if (colgroupNumber < colSpan) { const length = colSpan - colgroupNumber; for (let i = 0; i < length; i++) { const newCol = document.createElement("col"); newCol.width = this.parent.domNode.children[0].children[this.parent.domNode.children[0].children.length - 1].width; const newBr = document.createElement("br"); newCol.appendChild(newBr); this.parent.domNode.children[0].appendChild(newCol); this.parent.domNode.style.width += newCol.width; } } } } // this.parent.domNode.children[1].children[0].children[0].colSpan findTdColspanInTbody(tbody, trId) { let colSpan = 0; for (let i = 0; i < tbody.children.length; i++) { if (tbody.children[i].getAttribute("data-row") !== trId) { return colSpan; } for (let j = 0; j < tbody.children[i].children.length; j++) { if (tbody.children[i].children[j].colSpan) { colSpan += tbody.children[i].children[j].colSpan; } } } return colSpan; } } TableColGroup.blotName = "table-col-group"; TableColGroup.tagName = "colgroup"; class TableContainer extends Container { static create() { const node = super.create(); return node; } constructor(scroll, domNode) { super(scroll, domNode); domNode.setAttribute("contenteditable", false); this.updateTableWidth(); } updateTableWidth() { let colGroup = this.colGroup(); if (!colGroup) { if (this.parent && this.parent.children.head && this.domNode.hasAttribute("style")) { colGroup = this.parent.children.head.children.head; this.domNode = this.parent.children.head.domNode; } else if (this.domNode.tagName === "TABLE") { return; } else { return; } } const tableWidth = colGroup.children.reduce((sumWidth, col) => { const tableCol = col.formats()[TableCol.blotName]; let tableColWidth = tableConfig.COL_DEFAULT.width; if (tableCol && tableCol.width) { tableColWidth = Number.parseInt(tableCol.width, 10); } sumWidth = sumWidth + tableColWidth; return sumWidth; }, 0); this.domNode.removeAttribute("style"); this.domNode.style.width = `${tableWidth}px`; if (colGroup.next) { setTimeout(() => { let tdIndex = 0; let maxTds; const colNum = colGroup.children.length; const tableRows = this.descendants(TableRow); for (let i = 0; i < tableRows.length; i++) { const tds = tableRows[i].domNode.querySelectorAll("td"); if (tds.length === colNum) { maxTds = tds; break; } } colGroup.children.forEach((col) => { if (maxTds && col.domNode.width === "auto") { const width = getComputedStyle(maxTds[tdIndex]).width; const num = Number.parseInt(width, 10); col.domNode.width = num < tableConfig.COL_DEFAULT.width && tableConfig.COL_DEFAULT.width || num; } tdIndex++; }); }); } } cells(column) { return this.rows().map((row) => row.children.at(column)); } colGroup() { return this.children.head; } deleteColumns(compareRect, delIndexes = [], editorWrapper) { const [body] = this.descendants(TableBody); if (editor_utils.isNullOrUndefined(body) || editor_utils.isNullOrUndefined(body.children.head)) { return; } const tableCells = this.descendants(TableCell); const removedCells = []; const modifiedCells = []; tableCells.forEach((cell) => { const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); if (cellRect.x + tableConfig.ERROR_LIMIT > compareRect.x && cellRect.x1 - tableConfig.ERROR_LIMIT < compareRect.x1) { removedCells.push(cell); } else if (cellRect.x < compareRect.x + tableConfig.ERROR_LIMIT && cellRect.x1 > compareRect.x1 - tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); } }); if (removedCells.length === tableCells.length) { this.tableDestroy(); return true; } delIndexes.forEach(() => { const col = this.colGroup().children.at(delIndexes[0]); if (!col || this.colGroup().children.at(delIndexes[0]).domNode !== this.colGroup().domNode.children[delIndexes[0]]) { this.colGroup().domNode.removeChild(this.colGroup().domNode.children[delIndexes[0]]); } else { col.remove(); } }); removedCells.forEach((cell) => { cell.remove(); }); modifiedCells.forEach((cell) => { const cellColspan = Number.parseInt(cell.formats().colspan, 10); cell.format("colspan", cellColspan - delIndexes.length); }); this.updateTableWidth(); } deleteRow(compareRect, editorWrapper) { const [body] = this.descendants(TableBody); if (editor_utils.isNullOrUndefined(body) || editor_utils.isNullOrUndefined(body.children.head)) { return; } const tableCells = this.descendants(TableCell); const tableRows = this.descendants(TableRow); const removedCells = []; const modifiedCells = []; const fallCells = []; tableCells.forEach((cell) => { const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); if (cellRect.y > compareRect.y - tableConfig.ERROR_LIMIT && cellRect.y1 < compareRect.y1 + tableConfig.ERROR_LIMIT) { removedCells.push(cell); } else if (cellRect.y < compareRect.y + tableConfig.ERROR_LIMIT && cellRect.y1 > compareRect.y1 - tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); if (Math.abs(cellRect.y - compareRect.y) < tableConfig.ERROR_LIMIT) { fallCells.push(cell); } } }); if (removedCells.length === tableCells.length) { this.tableDestroy(); return; } const removedRowsLength = this.rows().reduce((sum, row) => { const rowRect = index.getRelativeRect(row.domNode.getBoundingClientRect(), editorWrapper); if (rowRect.y > compareRect.y - tableConfig.ERROR_LIMIT && rowRect.y1 < compareRect.y1 + tableConfig.ERROR_LIMIT) { sum += 1; } return sum; }, 0); fallCells.forEach((cell) => { const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); const nextRow = cell.parent.next; const cellsInNextRow = nextRow.children; const refCell = cellsInNextRow.reduce((ref, compareCell) => { const compareCellRect = index.getRelativeRect(compareCell.domNode.getBoundingClientRect(), editorWrapper); if (cellRect.x1 - compareCellRect.x < tableConfig.ERROR_LIMIT) { ref = compareCell; } return ref; }, null); nextRow.insertBefore(cell, refCell); const curRowId = nextRow.formats().row; cell.format("row", curRowId); cell.children.forEach((cellLine) => { cellLine.format("row", curRowId); }); }); modifiedCells.forEach((cell) => { const cellRowspan = Number.parseInt(cell.formats().rowspan, 10); const curRowspan = cellRowspan - removedRowsLength; cell.domNode.removeAttribute("style"); cell.format("rowspan", curRowspan); cell.children.forEach((cellLine) => { cellLine.format("rowspan", curRowspan); }); }); removedCells.forEach((cell) => { cell.remove(); }); tableRows.forEach((row) => { if (row.children.length === 0) { row.remove(); } }); } tableDestroy() { const quill = Quill.find(this.scroll.domNode.parentNode); const tableModule = quill.getModule("better-table"); this.remove(); tableModule.hideTableTools(); quill.update(Quill.sources.USER); } insertCell(tableRow, ref, bg = "") { const id = cellId(); const rId = tableRow.formats().row; const tableCell = this.scroll.create( TableCell.blotName, { ...tableConfig.CELL_DEFAULT, row: rId } ); tableCell.domNode.style.backgroundColor = bg; const cellLine = this.scroll.create(TableCellLine.blotName, { row: rId, cell: id }); tableCell.appendChild(cellLine); if (ref) { tableRow.insertBefore(tableCell, ref); } else { tableRow.appendChild(tableCell); } } insertColumn(compareRect, colIndex, isRight = true, editorWrapper) { const [body] = this.descendants(TableBody); const [tableColGroup] = this.descendants(TableColGroup); const tableCols = this.descendants(TableCol); const addAsideCells = []; const modifiedCells = []; const affectedCells = []; if (editor_utils.isNullOrUndefined(body) || editor_utils.isNullOrUndefined(body.children.head)) { return; } const tableCells = this.descendants(TableCell); tableCells.forEach((cell) => { const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); if (isRight) { if (Math.abs(cellRect.x1 - compareRect.x1) < tableConfig.ERROR_LIMIT) { addAsideCells.push(cell); } else if (compareRect.x1 - cellRect.x > tableConfig.ERROR_LIMIT && compareRect.x1 - cellRect.x1 < -tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); } } else { if (Math.abs(cellRect.x - compareRect.x) < tableConfig.ERROR_LIMIT) { addAsideCells.push(cell); } else if (compareRect.x - cellRect.x > tableConfig.ERROR_LIMIT && compareRect.x - cellRect.x1 < -tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); } } }); addAsideCells.forEach((cell) => { const ref = isRight ? cell.next : cell; const id = cellId(); const tableRow = cell.parent; const rId = tableRow.formats().row; const cellFormats = cell.formats(); const tableCell = this.scroll.create( TableCell.blotName, { ...tableConfig.CELL_DEFAULT, row: rId, rowspan: cellFormats.rowspan } ); const cellLine = this.scroll.create(TableCellLine.blotName, { row: rId, cell: id, rowspan: cellFormats.rowspan }); tableCell.appendChild(cellLine); if (ref) { tableRow.insertBefore(tableCell, ref); } else { tableRow.appendChild(tableCell); } affectedCells.push(tableCell); }); const tableCol = this.scroll.create(TableCol.blotName, true); let colRef; if (isRight) { colRef = tableCols[colIndex] && tableCols[colIndex].next; } else { colRef = tableCols[colIndex]; } if (colRef) { tableColGroup.insertBefore(tableCol, colRef); } else { tableColGroup.appendChild(tableCol); } modifiedCells.forEach((cell) => { const cellColspan = cell.formats().colspan; cell.format("colspan", Number.parseInt(cellColspan, 10) + 1); affectedCells.push(cell); }); affectedCells.sort((cellA, cellB) => { const y1 = cellA.domNode.getBoundingClientRect().y; const y2 = cellB.domNode.getBoundingClientRect().y; return y1 - y2; }); this.updateTableWidth(); return affectedCells; } insertRow(compareRect, isDown, editorWrapper) { const [body] = this.descendants(TableBody); if (editor_utils.isNullOrUndefined(body) || editor_utils.isNullOrUndefined(body.children.head)) { return; } const tableCells = this.descendants(TableCell); const rId = rowId(); const newRow = this.scroll.create(TableRow.blotName, { row: rId }); const addBelowCells = []; const modifiedCells = []; const affectedCells = []; tableCells.forEach((cell) => { const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); if (isDown) { if (Math.abs(cellRect.y1 - compareRect.y1) < tableConfig.ERROR_LIMIT) { addBelowCells.push(cell); } else if (compareRect.y1 - cellRect.y > tableConfig.ERROR_LIMIT && compareRect.y1 - cellRect.y1 < -tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); } } else { if (Math.abs(cellRect.y - compareRect.y) < tableConfig.ERROR_LIMIT) { addBelowCells.push(cell); } else if (compareRect.y - cellRect.y > tableConfig.ERROR_LIMIT && compareRect.y - cellRect.y1 < -tableConfig.ERROR_LIMIT) { modifiedCells.push(cell); } } }); const sortFunc = (cellA, cellB) => { const x1 = cellA.domNode.getBoundingClientRect().x; const x2 = cellB.domNode.getBoundingClientRect().x; return x1 - x2; }; addBelowCells.sort(sortFunc); addBelowCells.forEach((cell) => { const cId = cellId(); const cellFormats = cell.formats(); const tableCell = this.scroll.create( TableCell.blotName, { ...tableConfig.CELL_DEFAULT, row: rId, cell: cId, colspan: cellFormats.colspan } ); const cellLine = this.scroll.create(TableCellLine.blotName, { row: rId, cell: cId, colspan: cellFormats.colspan }); const empty = this.scroll.create(Break.blotName); cellLine.appendChild(empty); tableCell.appendChild(cellLine); newRow.appendChild(tableCell); affectedCells.push(tableCell); }); modifiedCells.forEach((cell) => { const cellRowspan = Number.parseInt(cell.formats().rowspan, 10); cell.format("rowspan", cellRowspan + 1); affectedCells.push(cell); }); const refRow = this.rows().find((row) => { const rowRect = index.getRelativeRect(row.domNode.getBoundingClientRect(), editorWrapper); if (isDown) { return Math.abs(rowRect.y - compareRect.y - compareRect.height) < tableConfig.ERROR_LIMIT; } else { return Math.abs(rowRect.y - compareRect.y) < tableConfig.ERROR_LIMIT; } }); body.insertBefore(newRow, refRow); affectedCells.sort(sortFunc); return affectedCells; } mergeCells(_compareRect, mergingCells, rowspan, colspan, _editorWrapper) { const mergedCell = mergingCells.reduce((result, tableCell, index2) => { if (index2 !== 0) { if (result) { tableCell.moveChildren(result); } tableCell.remove(); } else { tableCell.format("colspan", colspan); tableCell.format("rowspan", rowspan); result = tableCell; if (rowspan > 1) { const minHeight = tableConfig.CELL_MIN_HEIGHT * rowspan + rowspan - 1; const cellHeight = Number.parseInt(tableCell.domNode.style.height, 10) || 0; if (cellHeight < minHeight) { tableCell.domNode.style.height = `${minHeight}px`; } } } return result; }, null); const rId = mergedCell.domNode.getAttribute("data-row"); const cId = mergedCell.children.head.domNode.getAttribute("data-cell"); mergedCell.children.forEach((cellLine) => { cellLine.domNode.setAttribute("data-parent-bg", mergedCell.domNode.style.backgroundColor); if (cellLine.children.head.domNode.style) { cellLine.children.head.domNode.style.backgroundColor = mergedCell.domNode.style.backgroundColor; } if (!cellLine.prev || cellLine.domNode.textContent.trim()) { cellLine.format("cell", cId); cellLine.format("row", rId); cellLine.format("colspan", colspan); cellLine.format("rowspan", rowspan); } else { cellLine.remove(); } }); return mergedCell; } unmergeCells(unmergingCells, editorWrapper) { let cellFormats = {}; let cellRowspan = 1; let cellColspan = 1; unmergingCells.forEach((tableCell) => { const tableCellBgColor = tableCell.domNode.style.backgroundColor; cellFormats = tableCell.formats(); cellRowspan = cellFormats.rowspan; cellColspan = cellFormats.colspan; if (cellColspan > 1) { const ref = tableCell.next; const row = tableCell.row(); tableCell.format("colspan", 1); if (tableCell.domNode.children && tableCell.domNode.children[0].tagName === "DIV" && tableCell.domNode.children[0].getAttribute("data-colspan")) { tableCell.domNode.children[0].setAttribute("data-colspan", 1); } for (let colspanIndex = cellColspan; colspanIndex > 1; colspanIndex--) { this.insertCell(row, ref, tableCellBgColor); } } if (cellRowspan > 1) { let rowspanIndex = cellRowspan; let nextRow = tableCell.row().next; while (rowspanIndex > 1) { const refInNextRow = nextRow.children.reduce((result, cell) => { const compareRect = index.getRelativeRect(tableCell.domNode.getBoundingClientRect(), editorWrapper); const cellRect = index.getRelativeRect(cell.domNode.getBoundingClientRect(), editorWrapper); if (Math.abs(compareRect.x1 - cellRect.x) < tableConfig.ERROR_LIMIT) { result = cell; } return result; }, null); for (let colspanIndex = cellColspan; colspanIndex > 0; colspanIndex--) { this.insertCell(nextRow, refInNextRow, tableCellBgColor); } rowspanIndex -= 1; nextRow = nextRow.next; } tableCell.domNode.removeAttribute("style"); if (tableCell.domNode.children && tableCell.domNode.children[0].tagName === "DIV" && tableCell.domNode.children[0].getAttribute("data-rowspan")) { tableCell.domNode.children[0].setAttribute("data-rowspan", 1); } tableCell.format("rowspan", 1); } }); } emptyCells(selectedTds) { selectedTds.forEach((selectedTd) => { const cellFormats = selectedTd.formats(); const cellLine = this.scroll.create(TableCellLine.blotName, { row: cellFormats.row || rowId(), cell: cellFormats.cell || cellId(), rowspan: cellFormats.rowspan, colspan: cellFormats.colspan }); const empty = this.scroll.create(Break.blotName); cellLine.appendChild(empty); selectedTd.domNode.innerHTML = ""; selectedTd.appendChild(cellLine); }); } rows() { const body = this.children.tail; if (editor_utils.isNullOrUndefined(body)) { return []; } return body.children.map((row) => row); } } TableContainer.blotName = "ql-table-container"; TableContainer.className = "quill-better-table"; TableContainer.tagName = "TABLE"; class TableViewWrapper extends Container { constructor(scroll, domNode) { super(scroll, domNode); const quill = Quill.find(scroll.domNode.parentNode); if (quill.options.readOnly) { domNode.style.overflow = "auto"; } domNode.addEventListener( "scroll", (e) => { const tableModule = quill.getModule("better-table"); if (tableModule.columnTool) { tableModule.columnTool.domNode.scrollLeft = e.target.scrollLeft; } if (tableModule.tableSelection && tableModule.tableSelection.selectedTds.length > 0) { tableModule.tableSelection.repositionHelpLines(); } }, false ); } } TableViewWrapper.blotName = "table-view"; TableViewWrapper.className = "quill-better-table-wrapper"; TableViewWrapper.tagName = "DIV"; TableViewWrapper.allowedChildren = [TableContainer]; TableContainer.requiredContainer = TableViewWrapper; TableContainer.allowedChildren = [TableBody, TableColGroup]; TableBody.requiredContainer = TableContainer; TableBody.allowedChildren = [TableRow]; TableRow.requiredContainer = TableBody; TableRow.allowedChildren = [TableCell]; TableCell.requiredContainer = TableRow; TableCell.allowedChildren = [TableCellLine, header.default, list.default, list.ListContainer]; TableCellLine.requiredContainer = TableCell; TableColGroup.allowedChildren = [TableCol]; TableColGroup.requiredContainer = TableContainer; TableCol.requiredContainer = TableColGroup; function rowId() { const id = Math.random().toString(36).slice(2, 6); return `row-${id}`; } function cellId() { const id = Math.random().toString(36).slice(2, 6); return `cell-${id}`; } function reduceFormats(domNode, formats) { return [...tableConfig.CELL_ATTRIBUTES, ...tableConfig.CELL_IDENTITY_KEYS].reduce((tableFormats, attribute) => { if (domNode.hasAttribute(`data-${attribute}`)) { tableFormats[attribute] = domNode.getAttribute(`data-${attribute}`) || void 0; } return tableFormats; }, formats); } exports.CELL_ATTRIBUTES = tableConfig.CELL_ATTRIBUTES; exports.CELL_IDENTITY_KEYS = tableConfig.CELL_IDENTITY_KEYS; exports.TableBody = TableBody; exports.TableCell = TableCell; exports.TableCellLine = TableCellLine; exports.TableCol = TableCol; exports.TableColGroup = TableColGroup; exports.TableContainer = TableContainer; exports.TableRow = TableRow; exports.TableViewWrapper = TableViewWrapper; exports.cellId = cellId; exports.rowId = rowId; //# sourceMappingURL=table.cjs.js.map