UNPKG

quill

Version:

Your powerful, rich text editor

192 lines (168 loc) 4.85 kB
import Block from '../blots/block'; import Container from '../blots/container'; class TableCell extends Block { static create(value) { const node = super.create(); if (value) { node.setAttribute('data-row', value); } else { node.setAttribute('data-row', tableId()); } return node; } static formats(domNode) { if (domNode.hasAttribute('data-row')) { return domNode.getAttribute('data-row'); } return undefined; } cellOffset() { if (this.parent) { return this.parent.children.indexOf(this); } return -1; } format(name, value) { if (name === TableCell.blotName && value) { this.domNode.setAttribute('data-row', value); } else { super.format(name, value); } } row() { return this.parent; } rowOffset() { if (this.row()) { return this.row().rowOffset(); } return -1; } table() { return this.row() && this.row().table(); } } TableCell.blotName = 'table'; TableCell.tagName = 'TD'; class TableRow extends Container { checkMerge() { if (super.checkMerge() && this.next.children.head != null) { 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.table === thisTail.table && thisHead.table === nextHead.table && thisHead.table === nextTail.table ); } return false; } optimize(...args) { super.optimize(...args); this.children.forEach(child => { if (child.next == null) return; const childFormats = child.formats(); const nextFormats = child.next.formats(); if (childFormats.table !== nextFormats.table) { const next = this.splitAfter(child); if (next) { next.optimize(); } // We might be able to merge with prev now if (this.prev) { this.prev.optimize(); } } }); } rowOffset() { if (this.parent) { return this.parent.children.indexOf(this); } return -1; } 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 TableContainer extends Container { balanceCells() { const rows = this.descendants(TableRow); const maxColumns = rows.reduce((max, row) => { return Math.max(row.children.length, max); }, 0); rows.forEach(row => { new Array(maxColumns - row.children.length).fill(0).forEach(() => { let value; if (row.children.head != null) { value = TableCell.formats(row.children.head.domNode); } const blot = this.scroll.create(TableCell.blotName, value); row.appendChild(blot); blot.optimize(); // Add break blot }); }); } cells(column) { return this.rows().map(row => row.children.at(column)); } deleteColumn(index) { const [body] = this.descendant(TableBody); if (body == null || body.children.head == null) return; body.children.forEach(row => { const cell = row.children.at(index); if (cell != null) { cell.remove(); } }); } insertColumn(index) { const [body] = this.descendant(TableBody); if (body == null || body.children.head == null) return; body.children.forEach(row => { const ref = row.children.at(index); const value = TableCell.formats(row.children.head.domNode); const cell = this.scroll.create(TableCell.blotName, value); row.insertBefore(cell, ref); }); } insertRow(index) { const [body] = this.descendant(TableBody); if (body == null || body.children.head == null) return; const id = tableId(); const row = this.scroll.create(TableRow.blotName); body.children.head.children.forEach(() => { const cell = this.scroll.create(TableCell.blotName, id); row.appendChild(cell); }); const ref = body.children.at(index); body.insertBefore(row, ref); } rows() { const body = this.children.head; if (body == null) return []; return body.children.map(row => row); } } TableContainer.blotName = 'table-container'; TableContainer.tagName = 'TABLE'; TableContainer.allowedChildren = [TableBody]; TableBody.requiredContainer = TableContainer; TableBody.allowedChildren = [TableRow]; TableRow.requiredContainer = TableBody; TableRow.allowedChildren = [TableCell]; TableCell.requiredContainer = TableRow; function tableId() { const id = Math.random() .toString(36) .slice(2, 6); return `row-${id}`; } export { TableCell, TableRow, TableBody, TableContainer, tableId };