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.
		
		
		
		
		
			
		
			
				
					
					
						
							306 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							306 lines
						
					
					
						
							11 KiB
						
					
					
				| 'use strict';
 | |
| 
 | |
| Object.defineProperty(exports, '__esModule', { value: true });
 | |
| 
 | |
| var core = require('@tiptap/core');
 | |
| var prosemirrorTables = require('@tiptap/prosemirror-tables');
 | |
| var prosemirrorState = require('prosemirror-state');
 | |
| 
 | |
| 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;
 | |
| //# sourceMappingURL=tiptap-extension-table.cjs.map
 |