You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					308 lines
				
				12 KiB
			
		
		
			
		
	
	
					308 lines
				
				12 KiB
			| 
											3 years ago
										 | (function (global, factory) { | ||
|  |   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/core'), require('@tiptap/prosemirror-tables'), require('prosemirror-state')) : | ||
|  |   typeof define === 'function' && define.amd ? define(['exports', '@tiptap/core', '@tiptap/prosemirror-tables', 'prosemirror-state'], factory) : | ||
|  |   (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/extension-table"] = {}, global.core, global.prosemirrorTables, global.prosemirrorState)); | ||
|  | })(this, (function (exports, core, prosemirrorTables, prosemirrorState) { 'use strict'; | ||
|  | 
 | ||
|  |   function updateColumns(node, colgroup, table, cellMinWidth, overrideCol, overrideValue) { | ||
|  |       let totalWidth = 0; | ||
|  |       let fixedWidth = true; | ||
|  |       let nextDOM = colgroup.firstChild; | ||
|  |       const row = node.firstChild; | ||
|  |       for (let i = 0, col = 0; i < row.childCount; i += 1) { | ||
|  |           const { colspan, colwidth } = row.child(i).attrs; | ||
|  |           for (let j = 0; j < colspan; j += 1, col += 1) { | ||
|  |               const hasWidth = overrideCol === col ? overrideValue : colwidth && colwidth[j]; | ||
|  |               const cssWidth = hasWidth ? `${hasWidth}px` : ''; | ||
|  |               totalWidth += hasWidth || cellMinWidth; | ||
|  |               if (!hasWidth) { | ||
|  |                   fixedWidth = false; | ||
|  |               } | ||
|  |               if (!nextDOM) { | ||
|  |                   colgroup.appendChild(document.createElement('col')).style.width = cssWidth; | ||
|  |               } | ||
|  |               else { | ||
|  |                   if (nextDOM.style.width !== cssWidth) { | ||
|  |                       nextDOM.style.width = cssWidth; | ||
|  |                   } | ||
|  |                   nextDOM = nextDOM.nextSibling; | ||
|  |               } | ||
|  |           } | ||
|  |       } | ||
|  |       while (nextDOM) { | ||
|  |           const after = nextDOM.nextSibling; | ||
|  |           nextDOM.parentNode.removeChild(nextDOM); | ||
|  |           nextDOM = after; | ||
|  |       } | ||
|  |       if (fixedWidth) { | ||
|  |           table.style.width = `${totalWidth}px`; | ||
|  |           table.style.minWidth = ''; | ||
|  |       } | ||
|  |       else { | ||
|  |           table.style.width = ''; | ||
|  |           table.style.minWidth = `${totalWidth}px`; | ||
|  |       } | ||
|  |   } | ||
|  |   class TableView { | ||
|  |       constructor(node, cellMinWidth) { | ||
|  |           this.node = node; | ||
|  |           this.cellMinWidth = cellMinWidth; | ||
|  |           this.dom = document.createElement('div'); | ||
|  |           this.dom.className = 'tableWrapper'; | ||
|  |           this.table = this.dom.appendChild(document.createElement('table')); | ||
|  |           this.colgroup = this.table.appendChild(document.createElement('colgroup')); | ||
|  |           updateColumns(node, this.colgroup, this.table, cellMinWidth); | ||
|  |           this.contentDOM = this.table.appendChild(document.createElement('tbody')); | ||
|  |       } | ||
|  |       update(node) { | ||
|  |           if (node.type !== this.node.type) { | ||
|  |               return false; | ||
|  |           } | ||
|  |           this.node = node; | ||
|  |           updateColumns(node, this.colgroup, this.table, this.cellMinWidth); | ||
|  |           return true; | ||
|  |       } | ||
|  |       ignoreMutation(mutation) { | ||
|  |           return mutation.type === 'attributes' && (mutation.target === this.table || this.colgroup.contains(mutation.target)); | ||
|  |       } | ||
|  |   } | ||
|  | 
 | ||
|  |   function createCell(cellType, cellContent) { | ||
|  |       if (cellContent) { | ||
|  |           return cellType.createChecked(null, cellContent); | ||
|  |       } | ||
|  |       return cellType.createAndFill(); | ||
|  |   } | ||
|  | 
 | ||
|  |   function getTableNodeTypes(schema) { | ||
|  |       if (schema.cached.tableNodeTypes) { | ||
|  |           return schema.cached.tableNodeTypes; | ||
|  |       } | ||
|  |       const roles = {}; | ||
|  |       Object.keys(schema.nodes).forEach(type => { | ||
|  |           const nodeType = schema.nodes[type]; | ||
|  |           if (nodeType.spec.tableRole) { | ||
|  |               roles[nodeType.spec.tableRole] = nodeType; | ||
|  |           } | ||
|  |       }); | ||
|  |       schema.cached.tableNodeTypes = roles; | ||
|  |       return roles; | ||
|  |   } | ||
|  | 
 | ||
|  |   function createTable(schema, rowsCount, colsCount, withHeaderRow, cellContent) { | ||
|  |       const types = getTableNodeTypes(schema); | ||
|  |       const headerCells = []; | ||
|  |       const cells = []; | ||
|  |       for (let index = 0; index < colsCount; index += 1) { | ||
|  |           const cell = createCell(types.cell, cellContent); | ||
|  |           if (cell) { | ||
|  |               cells.push(cell); | ||
|  |           } | ||
|  |           if (withHeaderRow) { | ||
|  |               const headerCell = createCell(types.header_cell, cellContent); | ||
|  |               if (headerCell) { | ||
|  |                   headerCells.push(headerCell); | ||
|  |               } | ||
|  |           } | ||
|  |       } | ||
|  |       const rows = []; | ||
|  |       for (let index = 0; index < rowsCount; index += 1) { | ||
|  |           rows.push(types.row.createChecked(null, withHeaderRow && index === 0 ? headerCells : cells)); | ||
|  |       } | ||
|  |       return types.table.createChecked(null, rows); | ||
|  |   } | ||
|  | 
 | ||
|  |   function isCellSelection(value) { | ||
|  |       return value instanceof prosemirrorTables.CellSelection; | ||
|  |   } | ||
|  | 
 | ||
|  |   const deleteTableWhenAllCellsSelected = ({ editor }) => { | ||
|  |       const { selection } = editor.state; | ||
|  |       if (!isCellSelection(selection)) { | ||
|  |           return false; | ||
|  |       } | ||
|  |       let cellCount = 0; | ||
|  |       const table = core.findParentNodeClosestToPos(selection.ranges[0].$from, node => { | ||
|  |           return node.type.name === 'table'; | ||
|  |       }); | ||
|  |       table === null || table === void 0 ? void 0 : table.node.descendants(node => { | ||
|  |           if (node.type.name === 'table') { | ||
|  |               return false; | ||
|  |           } | ||
|  |           if (['tableCell', 'tableHeader'].includes(node.type.name)) { | ||
|  |               cellCount += 1; | ||
|  |           } | ||
|  |       }); | ||
|  |       const allCellsSelected = cellCount === selection.ranges.length; | ||
|  |       if (!allCellsSelected) { | ||
|  |           return false; | ||
|  |       } | ||
|  |       editor.commands.deleteTable(); | ||
|  |       return true; | ||
|  |   }; | ||
|  | 
 | ||
|  |   const Table = core.Node.create({ | ||
|  |       name: 'table', | ||
|  |       // @ts-ignore
 | ||
|  |       addOptions() { | ||
|  |           return { | ||
|  |               HTMLAttributes: {}, | ||
|  |               resizable: false, | ||
|  |               handleWidth: 5, | ||
|  |               cellMinWidth: 25, | ||
|  |               // TODO: fix
 | ||
|  |               View: TableView, | ||
|  |               lastColumnResizable: true, | ||
|  |               allowTableNodeSelection: false, | ||
|  |           }; | ||
|  |       }, | ||
|  |       content: 'tableRow+', | ||
|  |       tableRole: 'table', | ||
|  |       isolating: true, | ||
|  |       group: 'block', | ||
|  |       parseHTML() { | ||
|  |           return [ | ||
|  |               { tag: 'table' }, | ||
|  |           ]; | ||
|  |       }, | ||
|  |       renderHTML({ HTMLAttributes }) { | ||
|  |           return ['table', core.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), ['tbody', 0]]; | ||
|  |       }, | ||
|  |       addCommands() { | ||
|  |           return { | ||
|  |               insertTable: ({ rows = 3, cols = 3, withHeaderRow = true } = {}) => ({ tr, dispatch, editor }) => { | ||
|  |                   const node = createTable(editor.schema, rows, cols, withHeaderRow); | ||
|  |                   if (dispatch) { | ||
|  |                       const offset = tr.selection.anchor + 1; | ||
|  |                       tr.replaceSelectionWith(node) | ||
|  |                           .scrollIntoView() | ||
|  |                           .setSelection(prosemirrorState.TextSelection.near(tr.doc.resolve(offset))); | ||
|  |                   } | ||
|  |                   return true; | ||
|  |               }, | ||
|  |               addColumnBefore: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.addColumnBefore(state, dispatch); | ||
|  |               }, | ||
|  |               addColumnAfter: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.addColumnAfter(state, dispatch); | ||
|  |               }, | ||
|  |               deleteColumn: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.deleteColumn(state, dispatch); | ||
|  |               }, | ||
|  |               addRowBefore: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.addRowBefore(state, dispatch); | ||
|  |               }, | ||
|  |               addRowAfter: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.addRowAfter(state, dispatch); | ||
|  |               }, | ||
|  |               deleteRow: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.deleteRow(state, dispatch); | ||
|  |               }, | ||
|  |               deleteTable: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.deleteTable(state, dispatch); | ||
|  |               }, | ||
|  |               mergeCells: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.mergeCells(state, dispatch); | ||
|  |               }, | ||
|  |               splitCell: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.splitCell(state, dispatch); | ||
|  |               }, | ||
|  |               toggleHeaderColumn: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.toggleHeader('column')(state, dispatch); | ||
|  |               }, | ||
|  |               toggleHeaderRow: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.toggleHeader('row')(state, dispatch); | ||
|  |               }, | ||
|  |               toggleHeaderCell: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.toggleHeaderCell(state, dispatch); | ||
|  |               }, | ||
|  |               mergeOrSplit: () => ({ state, dispatch }) => { | ||
|  |                   if (prosemirrorTables.mergeCells(state, dispatch)) { | ||
|  |                       return true; | ||
|  |                   } | ||
|  |                   return prosemirrorTables.splitCell(state, dispatch); | ||
|  |               }, | ||
|  |               setCellAttribute: (name, value) => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.setCellAttr(name, value)(state, dispatch); | ||
|  |               }, | ||
|  |               goToNextCell: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.goToNextCell(1)(state, dispatch); | ||
|  |               }, | ||
|  |               goToPreviousCell: () => ({ state, dispatch }) => { | ||
|  |                   return prosemirrorTables.goToNextCell(-1)(state, dispatch); | ||
|  |               }, | ||
|  |               fixTables: () => ({ state, dispatch }) => { | ||
|  |                   if (dispatch) { | ||
|  |                       prosemirrorTables.fixTables(state); | ||
|  |                   } | ||
|  |                   return true; | ||
|  |               }, | ||
|  |               setCellSelection: position => ({ tr, dispatch }) => { | ||
|  |                   if (dispatch) { | ||
|  |                       const selection = prosemirrorTables.CellSelection.create(tr.doc, position.anchorCell, position.headCell); | ||
|  |                       // @ts-ignore
 | ||
|  |                       tr.setSelection(selection); | ||
|  |                   } | ||
|  |                   return true; | ||
|  |               }, | ||
|  |           }; | ||
|  |       }, | ||
|  |       addKeyboardShortcuts() { | ||
|  |           return { | ||
|  |               Tab: () => { | ||
|  |                   if (this.editor.commands.goToNextCell()) { | ||
|  |                       return true; | ||
|  |                   } | ||
|  |                   if (!this.editor.can().addRowAfter()) { | ||
|  |                       return false; | ||
|  |                   } | ||
|  |                   return this.editor | ||
|  |                       .chain() | ||
|  |                       .addRowAfter() | ||
|  |                       .goToNextCell() | ||
|  |                       .run(); | ||
|  |               }, | ||
|  |               'Shift-Tab': () => this.editor.commands.goToPreviousCell(), | ||
|  |               Backspace: deleteTableWhenAllCellsSelected, | ||
|  |               'Mod-Backspace': deleteTableWhenAllCellsSelected, | ||
|  |               Delete: deleteTableWhenAllCellsSelected, | ||
|  |               'Mod-Delete': deleteTableWhenAllCellsSelected, | ||
|  |           }; | ||
|  |       }, | ||
|  |       addProseMirrorPlugins() { | ||
|  |           const isResizable = this.options.resizable && this.editor.isEditable; | ||
|  |           return [ | ||
|  |               ...(isResizable ? [prosemirrorTables.columnResizing({ | ||
|  |                       handleWidth: this.options.handleWidth, | ||
|  |                       cellMinWidth: this.options.cellMinWidth, | ||
|  |                       View: this.options.View, | ||
|  |                       // TODO: PR for @types/prosemirror-tables
 | ||
|  |                       // @ts-ignore (incorrect type)
 | ||
|  |                       lastColumnResizable: this.options.lastColumnResizable, | ||
|  |                   })] : []), | ||
|  |               prosemirrorTables.tableEditing({ | ||
|  |                   allowTableNodeSelection: this.options.allowTableNodeSelection, | ||
|  |               }), | ||
|  |           ]; | ||
|  |       }, | ||
|  |       extendNodeSchema(extension) { | ||
|  |           const context = { | ||
|  |               name: extension.name, | ||
|  |               options: extension.options, | ||
|  |               storage: extension.storage, | ||
|  |           }; | ||
|  |           return { | ||
|  |               tableRole: core.callOrReturn(core.getExtensionField(extension, 'tableRole', context)), | ||
|  |           }; | ||
|  |       }, | ||
|  |   }); | ||
|  | 
 | ||
|  |   exports.Table = Table; | ||
|  |   exports.createTable = createTable; | ||
|  |   exports["default"] = Table; | ||
|  | 
 | ||
|  |   Object.defineProperty(exports, '__esModule', { value: true }); | ||
|  | 
 | ||
|  | })); | ||
|  | //# sourceMappingURL=tiptap-extension-table.umd.js.map
 |