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.
		
		
		
		
		
			
		
			
				
					
					
						
							2329 lines
						
					
					
						
							77 KiB
						
					
					
				
			
		
		
	
	
							2329 lines
						
					
					
						
							77 KiB
						
					
					
				| var __defProp = Object.defineProperty;
 | |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
 | |
| var __getOwnPropNames = Object.getOwnPropertyNames;
 | |
| var __hasOwnProp = Object.prototype.hasOwnProperty;
 | |
| var __export = (target, all) => {
 | |
|   for (var name in all)
 | |
|     __defProp(target, name, { get: all[name], enumerable: true });
 | |
| };
 | |
| var __copyProps = (to, from, except, desc) => {
 | |
|   if (from && typeof from === "object" || typeof from === "function") {
 | |
|     for (let key of __getOwnPropNames(from))
 | |
|       if (!__hasOwnProp.call(to, key) && key !== except)
 | |
|         __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
 | |
|   }
 | |
|   return to;
 | |
| };
 | |
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
 | |
| 
 | |
| // src/index.ts
 | |
| var src_exports = {};
 | |
| __export(src_exports, {
 | |
|   CellBookmark: () => CellBookmark,
 | |
|   CellSelection: () => CellSelection,
 | |
|   ResizeState: () => ResizeState,
 | |
|   TableMap: () => TableMap,
 | |
|   TableView: () => TableView,
 | |
|   __clipCells: () => clipCells,
 | |
|   __insertCells: () => insertCells,
 | |
|   __pastedCells: () => pastedCells,
 | |
|   addColSpan: () => addColSpan,
 | |
|   addColumn: () => addColumn,
 | |
|   addColumnAfter: () => addColumnAfter,
 | |
|   addColumnBefore: () => addColumnBefore,
 | |
|   addRow: () => addRow,
 | |
|   addRowAfter: () => addRowAfter,
 | |
|   addRowBefore: () => addRowBefore,
 | |
|   cellAround: () => cellAround,
 | |
|   colCount: () => colCount,
 | |
|   columnIsHeader: () => columnIsHeader,
 | |
|   columnResizing: () => columnResizing,
 | |
|   columnResizingPluginKey: () => columnResizingPluginKey,
 | |
|   deleteColumn: () => deleteColumn,
 | |
|   deleteRow: () => deleteRow,
 | |
|   deleteTable: () => deleteTable,
 | |
|   findCell: () => findCell,
 | |
|   fixTables: () => fixTables,
 | |
|   fixTablesKey: () => fixTablesKey,
 | |
|   goToNextCell: () => goToNextCell,
 | |
|   handlePaste: () => handlePaste,
 | |
|   inSameTable: () => inSameTable,
 | |
|   isInTable: () => isInTable,
 | |
|   mergeCells: () => mergeCells,
 | |
|   moveCellForward: () => moveCellForward,
 | |
|   nextCell: () => nextCell,
 | |
|   pointsAtCell: () => pointsAtCell,
 | |
|   removeColSpan: () => removeColSpan,
 | |
|   removeColumn: () => removeColumn,
 | |
|   removeRow: () => removeRow,
 | |
|   rowIsHeader: () => rowIsHeader,
 | |
|   selectedRect: () => selectedRect,
 | |
|   selectionCell: () => selectionCell,
 | |
|   setCellAttr: () => setCellAttr,
 | |
|   splitCell: () => splitCell,
 | |
|   splitCellWithType: () => splitCellWithType,
 | |
|   tableEditing: () => tableEditing,
 | |
|   tableEditingKey: () => tableEditingKey,
 | |
|   tableNodeTypes: () => tableNodeTypes,
 | |
|   tableNodes: () => tableNodes,
 | |
|   toggleHeader: () => toggleHeader,
 | |
|   toggleHeaderCell: () => toggleHeaderCell,
 | |
|   toggleHeaderColumn: () => toggleHeaderColumn,
 | |
|   toggleHeaderRow: () => toggleHeaderRow,
 | |
|   updateColumnsOnResize: () => updateColumnsOnResize
 | |
| });
 | |
| module.exports = __toCommonJS(src_exports);
 | |
| var import_prosemirror_state7 = require("prosemirror-state");
 | |
| 
 | |
| // src/cellselection.ts
 | |
| var import_prosemirror_state2 = require("prosemirror-state");
 | |
| var import_prosemirror_view = require("prosemirror-view");
 | |
| var import_prosemirror_model = require("prosemirror-model");
 | |
| 
 | |
| // src/util.ts
 | |
| var import_prosemirror_state = require("prosemirror-state");
 | |
| 
 | |
| // src/tablemap.ts
 | |
| var readFromCache;
 | |
| var addToCache;
 | |
| if (typeof WeakMap != "undefined") {
 | |
|   let cache = /* @__PURE__ */ new WeakMap();
 | |
|   readFromCache = (key) => cache.get(key);
 | |
|   addToCache = (key, value) => {
 | |
|     cache.set(key, value);
 | |
|     return value;
 | |
|   };
 | |
| } else {
 | |
|   const cache = [];
 | |
|   const cacheSize = 10;
 | |
|   let cachePos = 0;
 | |
|   readFromCache = (key) => {
 | |
|     for (let i = 0; i < cache.length; i += 2)
 | |
|       if (cache[i] == key)
 | |
|         return cache[i + 1];
 | |
|   };
 | |
|   addToCache = (key, value) => {
 | |
|     if (cachePos == cacheSize)
 | |
|       cachePos = 0;
 | |
|     cache[cachePos++] = key;
 | |
|     return cache[cachePos++] = value;
 | |
|   };
 | |
| }
 | |
| var TableMap = class {
 | |
|   constructor(width, height, map, problems) {
 | |
|     this.width = width;
 | |
|     this.height = height;
 | |
|     this.map = map;
 | |
|     this.problems = problems;
 | |
|   }
 | |
|   findCell(pos) {
 | |
|     for (let i = 0; i < this.map.length; i++) {
 | |
|       const curPos = this.map[i];
 | |
|       if (curPos != pos)
 | |
|         continue;
 | |
|       const left = i % this.width, top = i / this.width | 0;
 | |
|       let right = left + 1, bottom = top + 1;
 | |
|       for (let j = 1; right < this.width && this.map[i + j] == curPos; j++)
 | |
|         right++;
 | |
|       for (let j = 1; bottom < this.height && this.map[i + this.width * j] == curPos; j++)
 | |
|         bottom++;
 | |
|       return { left, top, right, bottom };
 | |
|     }
 | |
|     throw new RangeError("No cell with offset " + pos + " found");
 | |
|   }
 | |
|   colCount(pos) {
 | |
|     for (let i = 0; i < this.map.length; i++)
 | |
|       if (this.map[i] == pos)
 | |
|         return i % this.width;
 | |
|     throw new RangeError("No cell with offset " + pos + " found");
 | |
|   }
 | |
|   nextCell(pos, axis, dir) {
 | |
|     const { left, right, top, bottom } = this.findCell(pos);
 | |
|     if (axis == "horiz") {
 | |
|       if (dir < 0 ? left == 0 : right == this.width)
 | |
|         return null;
 | |
|       return this.map[top * this.width + (dir < 0 ? left - 1 : right)];
 | |
|     } else {
 | |
|       if (dir < 0 ? top == 0 : bottom == this.height)
 | |
|         return null;
 | |
|       return this.map[left + this.width * (dir < 0 ? top - 1 : bottom)];
 | |
|     }
 | |
|   }
 | |
|   rectBetween(a, b) {
 | |
|     const {
 | |
|       left: leftA,
 | |
|       right: rightA,
 | |
|       top: topA,
 | |
|       bottom: bottomA
 | |
|     } = this.findCell(a);
 | |
|     const {
 | |
|       left: leftB,
 | |
|       right: rightB,
 | |
|       top: topB,
 | |
|       bottom: bottomB
 | |
|     } = this.findCell(b);
 | |
|     return {
 | |
|       left: Math.min(leftA, leftB),
 | |
|       top: Math.min(topA, topB),
 | |
|       right: Math.max(rightA, rightB),
 | |
|       bottom: Math.max(bottomA, bottomB)
 | |
|     };
 | |
|   }
 | |
|   cellsInRect(rect) {
 | |
|     const result = [], seen = {};
 | |
|     for (let row = rect.top; row < rect.bottom; row++) {
 | |
|       for (let col = rect.left; col < rect.right; col++) {
 | |
|         const index = row * this.width + col, pos = this.map[index];
 | |
|         if (seen[pos])
 | |
|           continue;
 | |
|         seen[pos] = true;
 | |
|         if ((col != rect.left || !col || this.map[index - 1] != pos) && (row != rect.top || !row || this.map[index - this.width] != pos))
 | |
|           result.push(pos);
 | |
|       }
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   positionAt(row, col, table) {
 | |
|     for (let i = 0, rowStart = 0; ; i++) {
 | |
|       const rowEnd = rowStart + table.child(i).nodeSize;
 | |
|       if (i == row) {
 | |
|         let index = col + row * this.width;
 | |
|         const rowEndIndex = (row + 1) * this.width;
 | |
|         while (index < rowEndIndex && this.map[index] < rowStart)
 | |
|           index++;
 | |
|         return index == rowEndIndex ? rowEnd - 1 : this.map[index];
 | |
|       }
 | |
|       rowStart = rowEnd;
 | |
|     }
 | |
|   }
 | |
|   static get(table) {
 | |
|     return readFromCache(table) || addToCache(table, computeMap(table));
 | |
|   }
 | |
| };
 | |
| function computeMap(table) {
 | |
|   if (table.type.spec.tableRole != "table")
 | |
|     throw new RangeError("Not a table node: " + table.type.name);
 | |
|   const width = findWidth(table), height = table.childCount;
 | |
|   const map = [];
 | |
|   let mapPos = 0;
 | |
|   let problems = null;
 | |
|   const colWidths = [];
 | |
|   for (let i = 0, e = width * height; i < e; i++)
 | |
|     map[i] = 0;
 | |
|   for (let row = 0, pos = 0; row < height; row++) {
 | |
|     const rowNode = table.child(row);
 | |
|     pos++;
 | |
|     for (let i = 0; ; i++) {
 | |
|       while (mapPos < map.length && map[mapPos] != 0)
 | |
|         mapPos++;
 | |
|       if (i == rowNode.childCount)
 | |
|         break;
 | |
|       const cellNode = rowNode.child(i);
 | |
|       const { colspan, rowspan, colwidth } = cellNode.attrs;
 | |
|       for (let h = 0; h < rowspan; h++) {
 | |
|         if (h + row >= height) {
 | |
|           (problems || (problems = [])).push({
 | |
|             type: "overlong_rowspan",
 | |
|             pos,
 | |
|             n: rowspan - h
 | |
|           });
 | |
|           break;
 | |
|         }
 | |
|         const start = mapPos + h * width;
 | |
|         for (let w = 0; w < colspan; w++) {
 | |
|           if (map[start + w] == 0)
 | |
|             map[start + w] = pos;
 | |
|           else
 | |
|             (problems || (problems = [])).push({
 | |
|               type: "collision",
 | |
|               row,
 | |
|               pos,
 | |
|               n: colspan - w
 | |
|             });
 | |
|           const colW = colwidth && colwidth[w];
 | |
|           if (colW) {
 | |
|             const widthIndex = (start + w) % width * 2, prev = colWidths[widthIndex];
 | |
|             if (prev == null || prev != colW && colWidths[widthIndex + 1] == 1) {
 | |
|               colWidths[widthIndex] = colW;
 | |
|               colWidths[widthIndex + 1] = 1;
 | |
|             } else if (prev == colW) {
 | |
|               colWidths[widthIndex + 1]++;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       mapPos += colspan;
 | |
|       pos += cellNode.nodeSize;
 | |
|     }
 | |
|     const expectedPos = (row + 1) * width;
 | |
|     let missing = 0;
 | |
|     while (mapPos < expectedPos)
 | |
|       if (map[mapPos++] == 0)
 | |
|         missing++;
 | |
|     if (missing)
 | |
|       (problems || (problems = [])).push({ type: "missing", row, n: missing });
 | |
|     pos++;
 | |
|   }
 | |
|   const tableMap = new TableMap(width, height, map, problems);
 | |
|   let badWidths = false;
 | |
|   for (let i = 0; !badWidths && i < colWidths.length; i += 2)
 | |
|     if (colWidths[i] != null && colWidths[i + 1] < height)
 | |
|       badWidths = true;
 | |
|   if (badWidths)
 | |
|     findBadColWidths(tableMap, colWidths, table);
 | |
|   return tableMap;
 | |
| }
 | |
| function findWidth(table) {
 | |
|   let width = -1, hasRowSpan = false;
 | |
|   for (let row = 0; row < table.childCount; row++) {
 | |
|     const rowNode = table.child(row);
 | |
|     let rowWidth = 0;
 | |
|     if (hasRowSpan)
 | |
|       for (let j = 0; j < row; j++) {
 | |
|         const prevRow = table.child(j);
 | |
|         for (let i = 0; i < prevRow.childCount; i++) {
 | |
|           const cell = prevRow.child(i);
 | |
|           if (j + cell.attrs.rowspan > row)
 | |
|             rowWidth += cell.attrs.colspan;
 | |
|         }
 | |
|       }
 | |
|     for (let i = 0; i < rowNode.childCount; i++) {
 | |
|       const cell = rowNode.child(i);
 | |
|       rowWidth += cell.attrs.colspan;
 | |
|       if (cell.attrs.rowspan > 1)
 | |
|         hasRowSpan = true;
 | |
|     }
 | |
|     if (width == -1)
 | |
|       width = rowWidth;
 | |
|     else if (width != rowWidth)
 | |
|       width = Math.max(width, rowWidth);
 | |
|   }
 | |
|   return width;
 | |
| }
 | |
| function findBadColWidths(map, colWidths, table) {
 | |
|   if (!map.problems)
 | |
|     map.problems = [];
 | |
|   for (let i = 0, seen = {}; i < map.map.length; i++) {
 | |
|     const pos = map.map[i];
 | |
|     if (seen[pos])
 | |
|       continue;
 | |
|     seen[pos] = true;
 | |
|     const node = table.nodeAt(pos);
 | |
|     let updated = null;
 | |
|     for (let j = 0; j < node.attrs.colspan; j++) {
 | |
|       const col = (i + j) % map.width, colWidth = colWidths[col * 2];
 | |
|       if (colWidth != null && (!node.attrs.colwidth || node.attrs.colwidth[j] != colWidth))
 | |
|         (updated || (updated = freshColWidth(node.attrs)))[j] = colWidth;
 | |
|     }
 | |
|     if (updated)
 | |
|       map.problems.unshift({
 | |
|         type: "colwidth mismatch",
 | |
|         pos,
 | |
|         colwidth: updated
 | |
|       });
 | |
|   }
 | |
| }
 | |
| function freshColWidth(attrs) {
 | |
|   if (attrs.colwidth)
 | |
|     return attrs.colwidth.slice();
 | |
|   const result = [];
 | |
|   for (let i = 0; i < attrs.colspan; i++)
 | |
|     result.push(0);
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| // src/schema.ts
 | |
| function getCellAttrs(dom, extraAttrs) {
 | |
|   if (typeof dom === "string") {
 | |
|     return {};
 | |
|   }
 | |
|   const widthAttr = dom.getAttribute("data-colwidth");
 | |
|   const widths = widthAttr && /^\d+(,\d+)*$/.test(widthAttr) ? widthAttr.split(",").map((s) => Number(s)) : null;
 | |
|   const colspan = Number(dom.getAttribute("colspan") || 1);
 | |
|   const result = {
 | |
|     colspan,
 | |
|     rowspan: Number(dom.getAttribute("rowspan") || 1),
 | |
|     colwidth: widths && widths.length == colspan ? widths : null
 | |
|   };
 | |
|   for (const prop in extraAttrs) {
 | |
|     const getter = extraAttrs[prop].getFromDOM;
 | |
|     const value = getter && getter(dom);
 | |
|     if (value != null)
 | |
|       result[prop] = value;
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function setCellAttrs(node, extraAttrs) {
 | |
|   const attrs = {};
 | |
|   if (node.attrs.colspan != 1)
 | |
|     attrs.colspan = node.attrs.colspan;
 | |
|   if (node.attrs.rowspan != 1)
 | |
|     attrs.rowspan = node.attrs.rowspan;
 | |
|   if (node.attrs.colwidth)
 | |
|     attrs["data-colwidth"] = node.attrs.colwidth.join(",");
 | |
|   for (const prop in extraAttrs) {
 | |
|     const setter = extraAttrs[prop].setDOMAttr;
 | |
|     if (setter)
 | |
|       setter(node.attrs[prop], attrs);
 | |
|   }
 | |
|   return attrs;
 | |
| }
 | |
| function tableNodes(options) {
 | |
|   const extraAttrs = options.cellAttributes || {};
 | |
|   const cellAttrs = {
 | |
|     colspan: { default: 1 },
 | |
|     rowspan: { default: 1 },
 | |
|     colwidth: { default: null }
 | |
|   };
 | |
|   for (const prop in extraAttrs)
 | |
|     cellAttrs[prop] = { default: extraAttrs[prop].default };
 | |
|   return {
 | |
|     table: {
 | |
|       content: "table_row+",
 | |
|       tableRole: "table",
 | |
|       isolating: true,
 | |
|       group: options.tableGroup,
 | |
|       parseDOM: [{ tag: "table" }],
 | |
|       toDOM() {
 | |
|         return ["table", ["tbody", 0]];
 | |
|       }
 | |
|     },
 | |
|     table_row: {
 | |
|       content: "(table_cell | table_header)*",
 | |
|       tableRole: "row",
 | |
|       parseDOM: [{ tag: "tr" }],
 | |
|       toDOM() {
 | |
|         return ["tr", 0];
 | |
|       }
 | |
|     },
 | |
|     table_cell: {
 | |
|       content: options.cellContent,
 | |
|       attrs: cellAttrs,
 | |
|       tableRole: "cell",
 | |
|       isolating: true,
 | |
|       parseDOM: [
 | |
|         { tag: "td", getAttrs: (dom) => getCellAttrs(dom, extraAttrs) }
 | |
|       ],
 | |
|       toDOM(node) {
 | |
|         return ["td", setCellAttrs(node, extraAttrs), 0];
 | |
|       }
 | |
|     },
 | |
|     table_header: {
 | |
|       content: options.cellContent,
 | |
|       attrs: cellAttrs,
 | |
|       tableRole: "header_cell",
 | |
|       isolating: true,
 | |
|       parseDOM: [
 | |
|         { tag: "th", getAttrs: (dom) => getCellAttrs(dom, extraAttrs) }
 | |
|       ],
 | |
|       toDOM(node) {
 | |
|         return ["th", setCellAttrs(node, extraAttrs), 0];
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function tableNodeTypes(schema) {
 | |
|   let result = schema.cached.tableNodeTypes;
 | |
|   if (!result) {
 | |
|     result = schema.cached.tableNodeTypes = {};
 | |
|     for (const name in schema.nodes) {
 | |
|       const type = schema.nodes[name], role = type.spec.tableRole;
 | |
|       if (role)
 | |
|         result[role] = type;
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| // src/util.ts
 | |
| var tableEditingKey = new import_prosemirror_state.PluginKey("selectingCells");
 | |
| function cellAround($pos) {
 | |
|   for (let d = $pos.depth - 1; d > 0; d--)
 | |
|     if ($pos.node(d).type.spec.tableRole == "row")
 | |
|       return $pos.node(0).resolve($pos.before(d + 1));
 | |
|   return null;
 | |
| }
 | |
| function cellWrapping($pos) {
 | |
|   for (let d = $pos.depth; d > 0; d--) {
 | |
|     const role = $pos.node(d).type.spec.tableRole;
 | |
|     if (role === "cell" || role === "header_cell")
 | |
|       return $pos.node(d);
 | |
|   }
 | |
|   return null;
 | |
| }
 | |
| function isInTable(state) {
 | |
|   const $head = state.selection.$head;
 | |
|   for (let d = $head.depth; d > 0; d--)
 | |
|     if ($head.node(d).type.spec.tableRole == "row")
 | |
|       return true;
 | |
|   return false;
 | |
| }
 | |
| function selectionCell(state) {
 | |
|   const sel = state.selection;
 | |
|   if ("$anchorCell" in sel && sel.$anchorCell) {
 | |
|     return sel.$anchorCell.pos > sel.$headCell.pos ? sel.$anchorCell : sel.$headCell;
 | |
|   } else if ("node" in sel && sel.node && sel.node.type.spec.tableRole == "cell") {
 | |
|     return sel.$anchor;
 | |
|   }
 | |
|   return cellAround(sel.$head) || cellNear(sel.$head);
 | |
| }
 | |
| function cellNear($pos) {
 | |
|   for (let after = $pos.nodeAfter, pos = $pos.pos; after; after = after.firstChild, pos++) {
 | |
|     const role = after.type.spec.tableRole;
 | |
|     if (role == "cell" || role == "header_cell")
 | |
|       return $pos.doc.resolve(pos);
 | |
|   }
 | |
|   for (let before = $pos.nodeBefore, pos = $pos.pos; before; before = before.lastChild, pos--) {
 | |
|     const role = before.type.spec.tableRole;
 | |
|     if (role == "cell" || role == "header_cell")
 | |
|       return $pos.doc.resolve(pos - before.nodeSize);
 | |
|   }
 | |
| }
 | |
| function pointsAtCell($pos) {
 | |
|   return $pos.parent.type.spec.tableRole == "row" && !!$pos.nodeAfter;
 | |
| }
 | |
| function moveCellForward($pos) {
 | |
|   return $pos.node(0).resolve($pos.pos + $pos.nodeAfter.nodeSize);
 | |
| }
 | |
| function inSameTable($a, $b) {
 | |
|   return $a.depth == $b.depth && $a.pos >= $b.start(-1) && $a.pos <= $b.end(-1);
 | |
| }
 | |
| function findCell($pos) {
 | |
|   return TableMap.get($pos.node(-1)).findCell($pos.pos - $pos.start(-1));
 | |
| }
 | |
| function colCount($pos) {
 | |
|   return TableMap.get($pos.node(-1)).colCount($pos.pos - $pos.start(-1));
 | |
| }
 | |
| function nextCell($pos, axis, dir) {
 | |
|   const start = $pos.start(-1), map = TableMap.get($pos.node(-1));
 | |
|   const moved = map.nextCell($pos.pos - start, axis, dir);
 | |
|   return moved == null ? null : $pos.node(0).resolve(start + moved);
 | |
| }
 | |
| function _setAttr(attrs, name, value) {
 | |
|   const result = {};
 | |
|   for (const prop in attrs)
 | |
|     result[prop] = attrs[prop];
 | |
|   result[name] = value;
 | |
|   return result;
 | |
| }
 | |
| function removeColSpan(attrs, pos, n = 1) {
 | |
|   const result = _setAttr(attrs, "colspan", attrs.colspan - n);
 | |
|   if (result.colwidth) {
 | |
|     result.colwidth = result.colwidth.slice();
 | |
|     result.colwidth.splice(pos, n);
 | |
|     if (!result.colwidth.some((w) => w > 0))
 | |
|       result.colwidth = null;
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function addColSpan(attrs, pos, n = 1) {
 | |
|   const result = _setAttr(attrs, "colspan", attrs.colspan + n);
 | |
|   if (result.colwidth) {
 | |
|     result.colwidth = result.colwidth.slice();
 | |
|     for (let i = 0; i < n; i++)
 | |
|       result.colwidth.splice(pos, 0, 0);
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| function columnIsHeader(map, table, col) {
 | |
|   const headerCell = tableNodeTypes(table.type.schema).header_cell;
 | |
|   for (let row = 0; row < map.height; row++)
 | |
|     if (table.nodeAt(map.map[col + row * map.width]).type != headerCell)
 | |
|       return false;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| // src/cellselection.ts
 | |
| var CellSelection = class extends import_prosemirror_state2.Selection {
 | |
|   constructor($anchorCell, $headCell = $anchorCell) {
 | |
|     const table = $anchorCell.node(-1), map = TableMap.get(table), start = $anchorCell.start(-1);
 | |
|     const rect = map.rectBetween(
 | |
|       $anchorCell.pos - start,
 | |
|       $headCell.pos - start
 | |
|     );
 | |
|     const doc = $anchorCell.node(0);
 | |
|     const cells = map.cellsInRect(rect).filter((p) => p != $headCell.pos - start);
 | |
|     cells.unshift($headCell.pos - start);
 | |
|     const ranges = cells.map((pos) => {
 | |
|       const cell = table.nodeAt(pos), from = pos + start + 1;
 | |
|       return new import_prosemirror_state2.SelectionRange(
 | |
|         doc.resolve(from),
 | |
|         doc.resolve(from + cell.content.size)
 | |
|       );
 | |
|     });
 | |
|     super(ranges[0].$from, ranges[0].$to, ranges);
 | |
|     this.$anchorCell = $anchorCell;
 | |
|     this.$headCell = $headCell;
 | |
|   }
 | |
|   map(doc, mapping) {
 | |
|     const $anchorCell = doc.resolve(mapping.map(this.$anchorCell.pos));
 | |
|     const $headCell = doc.resolve(mapping.map(this.$headCell.pos));
 | |
|     if (pointsAtCell($anchorCell) && pointsAtCell($headCell) && inSameTable($anchorCell, $headCell)) {
 | |
|       const tableChanged = this.$anchorCell.node(-1) != $anchorCell.node(-1);
 | |
|       if (tableChanged && this.isRowSelection())
 | |
|         return CellSelection.rowSelection($anchorCell, $headCell);
 | |
|       else if (tableChanged && this.isColSelection())
 | |
|         return CellSelection.colSelection($anchorCell, $headCell);
 | |
|       else
 | |
|         return new CellSelection($anchorCell, $headCell);
 | |
|     }
 | |
|     return import_prosemirror_state2.TextSelection.between($anchorCell, $headCell);
 | |
|   }
 | |
|   content() {
 | |
|     const table = this.$anchorCell.node(-1), map = TableMap.get(table), start = this.$anchorCell.start(-1);
 | |
|     const rect = map.rectBetween(
 | |
|       this.$anchorCell.pos - start,
 | |
|       this.$headCell.pos - start
 | |
|     );
 | |
|     const seen = {}, rows = [];
 | |
|     for (let row = rect.top; row < rect.bottom; row++) {
 | |
|       const rowContent = [];
 | |
|       for (let index = row * map.width + rect.left, col = rect.left; col < rect.right; col++, index++) {
 | |
|         const pos = map.map[index];
 | |
|         if (!seen[pos]) {
 | |
|           seen[pos] = true;
 | |
|           const cellRect = map.findCell(pos);
 | |
|           let cell = table.nodeAt(pos);
 | |
|           const extraLeft = rect.left - cellRect.left, extraRight = cellRect.right - rect.right;
 | |
|           if (extraLeft > 0 || extraRight > 0) {
 | |
|             let attrs = cell.attrs;
 | |
|             if (extraLeft > 0)
 | |
|               attrs = removeColSpan(attrs, 0, extraLeft);
 | |
|             if (extraRight > 0)
 | |
|               attrs = removeColSpan(
 | |
|                 attrs,
 | |
|                 attrs.colspan - extraRight,
 | |
|                 extraRight
 | |
|               );
 | |
|             if (cellRect.left < rect.left)
 | |
|               cell = cell.type.createAndFill(attrs);
 | |
|             else
 | |
|               cell = cell.type.create(attrs, cell.content);
 | |
|           }
 | |
|           if (cellRect.top < rect.top || cellRect.bottom > rect.bottom) {
 | |
|             const attrs = _setAttr(
 | |
|               cell.attrs,
 | |
|               "rowspan",
 | |
|               Math.min(cellRect.bottom, rect.bottom) - Math.max(cellRect.top, rect.top)
 | |
|             );
 | |
|             if (cellRect.top < rect.top)
 | |
|               cell = cell.type.createAndFill(attrs);
 | |
|             else
 | |
|               cell = cell.type.create(attrs, cell.content);
 | |
|           }
 | |
|           rowContent.push(cell);
 | |
|         }
 | |
|       }
 | |
|       rows.push(table.child(row).copy(import_prosemirror_model.Fragment.from(rowContent)));
 | |
|     }
 | |
|     const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
 | |
|     return new import_prosemirror_model.Slice(import_prosemirror_model.Fragment.from(fragment), 1, 1);
 | |
|   }
 | |
|   replace(tr, content = import_prosemirror_model.Slice.empty) {
 | |
|     const mapFrom = tr.steps.length, ranges = this.ranges;
 | |
|     for (let i = 0; i < ranges.length; i++) {
 | |
|       const { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom);
 | |
|       tr.replace(
 | |
|         mapping.map($from.pos),
 | |
|         mapping.map($to.pos),
 | |
|         i ? import_prosemirror_model.Slice.empty : content
 | |
|       );
 | |
|     }
 | |
|     const sel = import_prosemirror_state2.Selection.findFrom(
 | |
|       tr.doc.resolve(tr.mapping.slice(mapFrom).map(this.to)),
 | |
|       -1
 | |
|     );
 | |
|     if (sel)
 | |
|       tr.setSelection(sel);
 | |
|   }
 | |
|   replaceWith(tr, node) {
 | |
|     this.replace(tr, new import_prosemirror_model.Slice(import_prosemirror_model.Fragment.from(node), 0, 0));
 | |
|   }
 | |
|   forEachCell(f) {
 | |
|     const table = this.$anchorCell.node(-1), map = TableMap.get(table), start = this.$anchorCell.start(-1);
 | |
|     const cells = map.cellsInRect(
 | |
|       map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start)
 | |
|     );
 | |
|     for (let i = 0; i < cells.length; i++)
 | |
|       f(table.nodeAt(cells[i]), start + cells[i]);
 | |
|   }
 | |
|   isColSelection() {
 | |
|     const anchorTop = this.$anchorCell.index(-1), headTop = this.$headCell.index(-1);
 | |
|     if (Math.min(anchorTop, headTop) > 0)
 | |
|       return false;
 | |
|     const anchorBot = anchorTop + this.$anchorCell.nodeAfter.attrs.rowspan, headBot = headTop + this.$headCell.nodeAfter.attrs.rowspan;
 | |
|     return Math.max(anchorBot, headBot) == this.$headCell.node(-1).childCount;
 | |
|   }
 | |
|   static colSelection($anchorCell, $headCell = $anchorCell) {
 | |
|     const map = TableMap.get($anchorCell.node(-1)), start = $anchorCell.start(-1);
 | |
|     const anchorRect = map.findCell($anchorCell.pos - start), headRect = map.findCell($headCell.pos - start);
 | |
|     const doc = $anchorCell.node(0);
 | |
|     if (anchorRect.top <= headRect.top) {
 | |
|       if (anchorRect.top > 0)
 | |
|         $anchorCell = doc.resolve(start + map.map[anchorRect.left]);
 | |
|       if (headRect.bottom < map.height)
 | |
|         $headCell = doc.resolve(
 | |
|           start + map.map[map.width * (map.height - 1) + headRect.right - 1]
 | |
|         );
 | |
|     } else {
 | |
|       if (headRect.top > 0)
 | |
|         $headCell = doc.resolve(start + map.map[headRect.left]);
 | |
|       if (anchorRect.bottom < map.height)
 | |
|         $anchorCell = doc.resolve(
 | |
|           start + map.map[map.width * (map.height - 1) + anchorRect.right - 1]
 | |
|         );
 | |
|     }
 | |
|     return new CellSelection($anchorCell, $headCell);
 | |
|   }
 | |
|   isRowSelection() {
 | |
|     const map = TableMap.get(this.$anchorCell.node(-1)), start = this.$anchorCell.start(-1);
 | |
|     const anchorLeft = map.colCount(this.$anchorCell.pos - start), headLeft = map.colCount(this.$headCell.pos - start);
 | |
|     if (Math.min(anchorLeft, headLeft) > 0)
 | |
|       return false;
 | |
|     const anchorRight = anchorLeft + this.$anchorCell.nodeAfter.attrs.colspan, headRight = headLeft + this.$headCell.nodeAfter.attrs.colspan;
 | |
|     return Math.max(anchorRight, headRight) == map.width;
 | |
|   }
 | |
|   eq(other) {
 | |
|     return other instanceof CellSelection && other.$anchorCell.pos == this.$anchorCell.pos && other.$headCell.pos == this.$headCell.pos;
 | |
|   }
 | |
|   static rowSelection($anchorCell, $headCell = $anchorCell) {
 | |
|     const map = TableMap.get($anchorCell.node(-1)), start = $anchorCell.start(-1);
 | |
|     const anchorRect = map.findCell($anchorCell.pos - start), headRect = map.findCell($headCell.pos - start);
 | |
|     const doc = $anchorCell.node(0);
 | |
|     if (anchorRect.left <= headRect.left) {
 | |
|       if (anchorRect.left > 0)
 | |
|         $anchorCell = doc.resolve(start + map.map[anchorRect.top * map.width]);
 | |
|       if (headRect.right < map.width)
 | |
|         $headCell = doc.resolve(
 | |
|           start + map.map[map.width * (headRect.top + 1) - 1]
 | |
|         );
 | |
|     } else {
 | |
|       if (headRect.left > 0)
 | |
|         $headCell = doc.resolve(start + map.map[headRect.top * map.width]);
 | |
|       if (anchorRect.right < map.width)
 | |
|         $anchorCell = doc.resolve(
 | |
|           start + map.map[map.width * (anchorRect.top + 1) - 1]
 | |
|         );
 | |
|     }
 | |
|     return new CellSelection($anchorCell, $headCell);
 | |
|   }
 | |
|   toJSON() {
 | |
|     return {
 | |
|       type: "cell",
 | |
|       anchor: this.$anchorCell.pos,
 | |
|       head: this.$headCell.pos
 | |
|     };
 | |
|   }
 | |
|   static fromJSON(doc, json) {
 | |
|     return new CellSelection(doc.resolve(json.anchor), doc.resolve(json.head));
 | |
|   }
 | |
|   static create(doc, anchorCell, headCell = anchorCell) {
 | |
|     return new CellSelection(doc.resolve(anchorCell), doc.resolve(headCell));
 | |
|   }
 | |
|   getBookmark() {
 | |
|     return new CellBookmark(this.$anchorCell.pos, this.$headCell.pos);
 | |
|   }
 | |
| };
 | |
| CellSelection.prototype.visible = false;
 | |
| import_prosemirror_state2.Selection.jsonID("cell", CellSelection);
 | |
| var CellBookmark = class {
 | |
|   constructor(anchor, head) {
 | |
|     this.anchor = anchor;
 | |
|     this.head = head;
 | |
|   }
 | |
|   map(mapping) {
 | |
|     return new CellBookmark(mapping.map(this.anchor), mapping.map(this.head));
 | |
|   }
 | |
|   resolve(doc) {
 | |
|     const $anchorCell = doc.resolve(this.anchor), $headCell = doc.resolve(this.head);
 | |
|     if ($anchorCell.parent.type.spec.tableRole == "row" && $headCell.parent.type.spec.tableRole == "row" && $anchorCell.index() < $anchorCell.parent.childCount && $headCell.index() < $headCell.parent.childCount && inSameTable($anchorCell, $headCell))
 | |
|       return new CellSelection($anchorCell, $headCell);
 | |
|     else
 | |
|       return import_prosemirror_state2.Selection.near($headCell, 1);
 | |
|   }
 | |
| };
 | |
| function drawCellSelection(state) {
 | |
|   if (!(state.selection instanceof CellSelection))
 | |
|     return null;
 | |
|   const cells = [];
 | |
|   state.selection.forEachCell((node, pos) => {
 | |
|     cells.push(
 | |
|       import_prosemirror_view.Decoration.node(pos, pos + node.nodeSize, { class: "selectedCell" })
 | |
|     );
 | |
|   });
 | |
|   return import_prosemirror_view.DecorationSet.create(state.doc, cells);
 | |
| }
 | |
| function isCellBoundarySelection({ $from, $to }) {
 | |
|   if ($from.pos == $to.pos || $from.pos < $from.pos - 6)
 | |
|     return false;
 | |
|   let afterFrom = $from.pos, beforeTo = $to.pos, depth = $from.depth;
 | |
|   for (; depth >= 0; depth--, afterFrom++)
 | |
|     if ($from.after(depth + 1) < $from.end(depth))
 | |
|       break;
 | |
|   for (let d = $to.depth; d >= 0; d--, beforeTo--)
 | |
|     if ($to.before(d + 1) > $to.start(d))
 | |
|       break;
 | |
|   return afterFrom == beforeTo && /row|table/.test($from.node(depth).type.spec.tableRole);
 | |
| }
 | |
| function isTextSelectionAcrossCells({ $from, $to }) {
 | |
|   let fromCellBoundaryNode;
 | |
|   let toCellBoundaryNode;
 | |
|   for (let i = $from.depth; i > 0; i--) {
 | |
|     const node = $from.node(i);
 | |
|     if (node.type.spec.tableRole === "cell" || node.type.spec.tableRole === "header_cell") {
 | |
|       fromCellBoundaryNode = node;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   for (let i = $to.depth; i > 0; i--) {
 | |
|     const node = $to.node(i);
 | |
|     if (node.type.spec.tableRole === "cell" || node.type.spec.tableRole === "header_cell") {
 | |
|       toCellBoundaryNode = node;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   return fromCellBoundaryNode !== toCellBoundaryNode && $to.parentOffset === 0;
 | |
| }
 | |
| function normalizeSelection(state, tr, allowTableNodeSelection) {
 | |
|   const sel = (tr || state).selection;
 | |
|   const doc = (tr || state).doc;
 | |
|   let normalize;
 | |
|   let role;
 | |
|   if (sel instanceof import_prosemirror_state2.NodeSelection && (role = sel.node.type.spec.tableRole)) {
 | |
|     if (role == "cell" || role == "header_cell") {
 | |
|       normalize = CellSelection.create(doc, sel.from);
 | |
|     } else if (role == "row") {
 | |
|       const $cell = doc.resolve(sel.from + 1);
 | |
|       normalize = CellSelection.rowSelection($cell, $cell);
 | |
|     } else if (!allowTableNodeSelection) {
 | |
|       const map = TableMap.get(sel.node), start = sel.from + 1;
 | |
|       const lastCell = start + map.map[map.width * map.height - 1];
 | |
|       normalize = CellSelection.create(doc, start + 1, lastCell);
 | |
|     }
 | |
|   } else if (sel instanceof import_prosemirror_state2.TextSelection && isCellBoundarySelection(sel)) {
 | |
|     normalize = import_prosemirror_state2.TextSelection.create(doc, sel.from);
 | |
|   } else if (sel instanceof import_prosemirror_state2.TextSelection && isTextSelectionAcrossCells(sel)) {
 | |
|     normalize = import_prosemirror_state2.TextSelection.create(doc, sel.$from.start(), sel.$from.end());
 | |
|   }
 | |
|   if (normalize)
 | |
|     (tr || (tr = state.tr)).setSelection(normalize);
 | |
|   return tr;
 | |
| }
 | |
| 
 | |
| // src/fixtables.ts
 | |
| var import_prosemirror_state3 = require("prosemirror-state");
 | |
| var fixTablesKey = new import_prosemirror_state3.PluginKey("fix-tables");
 | |
| function changedDescendants(old, cur, offset, f) {
 | |
|   const oldSize = old.childCount, curSize = cur.childCount;
 | |
|   outer:
 | |
|     for (let i = 0, j = 0; i < curSize; i++) {
 | |
|       const child = cur.child(i);
 | |
|       for (let scan = j, e = Math.min(oldSize, i + 3); scan < e; scan++) {
 | |
|         if (old.child(scan) == child) {
 | |
|           j = scan + 1;
 | |
|           offset += child.nodeSize;
 | |
|           continue outer;
 | |
|         }
 | |
|       }
 | |
|       f(child, offset);
 | |
|       if (j < oldSize && old.child(j).sameMarkup(child))
 | |
|         changedDescendants(old.child(j), child, offset + 1, f);
 | |
|       else
 | |
|         child.nodesBetween(0, child.content.size, f, offset + 1);
 | |
|       offset += child.nodeSize;
 | |
|     }
 | |
| }
 | |
| function fixTables(state, oldState) {
 | |
|   let tr;
 | |
|   const check = (node, pos) => {
 | |
|     if (node.type.spec.tableRole == "table")
 | |
|       tr = fixTable(state, node, pos, tr);
 | |
|   };
 | |
|   if (!oldState)
 | |
|     state.doc.descendants(check);
 | |
|   else if (oldState.doc != state.doc)
 | |
|     changedDescendants(oldState.doc, state.doc, 0, check);
 | |
|   return tr;
 | |
| }
 | |
| function fixTable(state, table, tablePos, tr) {
 | |
|   const map = TableMap.get(table);
 | |
|   if (!map.problems)
 | |
|     return tr;
 | |
|   if (!tr)
 | |
|     tr = state.tr;
 | |
|   const mustAdd = [];
 | |
|   for (let i = 0; i < map.height; i++)
 | |
|     mustAdd.push(0);
 | |
|   for (let i = 0; i < map.problems.length; i++) {
 | |
|     const prob = map.problems[i];
 | |
|     if (prob.type == "collision") {
 | |
|       const cell = table.nodeAt(prob.pos);
 | |
|       for (let j = 0; j < cell.attrs.rowspan; j++)
 | |
|         mustAdd[prob.row + j] += prob.n;
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.map(tablePos + 1 + prob.pos),
 | |
|         null,
 | |
|         removeColSpan(cell.attrs, cell.attrs.colspan - prob.n, prob.n)
 | |
|       );
 | |
|     } else if (prob.type == "missing") {
 | |
|       mustAdd[prob.row] += prob.n;
 | |
|     } else if (prob.type == "overlong_rowspan") {
 | |
|       const cell = table.nodeAt(prob.pos);
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.map(tablePos + 1 + prob.pos),
 | |
|         null,
 | |
|         _setAttr(cell.attrs, "rowspan", cell.attrs.rowspan - prob.n)
 | |
|       );
 | |
|     } else if (prob.type == "colwidth mismatch") {
 | |
|       const cell = table.nodeAt(prob.pos);
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.map(tablePos + 1 + prob.pos),
 | |
|         null,
 | |
|         _setAttr(cell.attrs, "colwidth", prob.colwidth)
 | |
|       );
 | |
|     }
 | |
|   }
 | |
|   let first, last;
 | |
|   for (let i = 0; i < mustAdd.length; i++)
 | |
|     if (mustAdd[i]) {
 | |
|       if (first == null)
 | |
|         first = i;
 | |
|       last = i;
 | |
|     }
 | |
|   for (let i = 0, pos = tablePos + 1; i < map.height; i++) {
 | |
|     const row = table.child(i);
 | |
|     const end = pos + row.nodeSize;
 | |
|     const add = mustAdd[i];
 | |
|     if (add > 0) {
 | |
|       let tableNodeType = "cell";
 | |
|       if (row.firstChild) {
 | |
|         tableNodeType = row.firstChild.type.spec.tableRole;
 | |
|       }
 | |
|       const nodes = [];
 | |
|       for (let j = 0; j < add; j++)
 | |
|         nodes.push(tableNodeTypes(state.schema)[tableNodeType].createAndFill());
 | |
|       const side = (i == 0 || first == i - 1) && last == i ? pos + 1 : end - 1;
 | |
|       tr.insert(tr.mapping.map(side), nodes);
 | |
|     }
 | |
|     pos = end;
 | |
|   }
 | |
|   return tr.setMeta(fixTablesKey, { fixTables: true });
 | |
| }
 | |
| 
 | |
| // src/input.ts
 | |
| var import_prosemirror_model3 = require("prosemirror-model");
 | |
| var import_prosemirror_state4 = require("prosemirror-state");
 | |
| var import_prosemirror_keymap = require("prosemirror-keymap");
 | |
| 
 | |
| // src/copypaste.ts
 | |
| var import_prosemirror_model2 = require("prosemirror-model");
 | |
| var import_prosemirror_transform = require("prosemirror-transform");
 | |
| function pastedCells(slice) {
 | |
|   if (!slice.size)
 | |
|     return null;
 | |
|   let { content, openStart, openEnd } = slice;
 | |
|   while (content.childCount == 1 && (openStart > 0 && openEnd > 0 || content.firstChild.type.spec.tableRole == "table")) {
 | |
|     openStart--;
 | |
|     openEnd--;
 | |
|     content = content.firstChild.content;
 | |
|   }
 | |
|   const first = content.firstChild, role = first.type.spec.tableRole;
 | |
|   const schema = first.type.schema, rows = [];
 | |
|   if (role == "row") {
 | |
|     for (let i = 0; i < content.childCount; i++) {
 | |
|       let cells = content.child(i).content;
 | |
|       const left = i ? 0 : Math.max(0, openStart - 1);
 | |
|       const right = i < content.childCount - 1 ? 0 : Math.max(0, openEnd - 1);
 | |
|       if (left || right)
 | |
|         cells = fitSlice(
 | |
|           tableNodeTypes(schema).row,
 | |
|           new import_prosemirror_model2.Slice(cells, left, right)
 | |
|         ).content;
 | |
|       rows.push(cells);
 | |
|     }
 | |
|   } else if (role == "cell" || role == "header_cell") {
 | |
|     rows.push(
 | |
|       openStart || openEnd ? fitSlice(
 | |
|         tableNodeTypes(schema).row,
 | |
|         new import_prosemirror_model2.Slice(content, openStart, openEnd)
 | |
|       ).content : content
 | |
|     );
 | |
|   } else {
 | |
|     return null;
 | |
|   }
 | |
|   return ensureRectangular(schema, rows);
 | |
| }
 | |
| function ensureRectangular(schema, rows) {
 | |
|   const widths = [];
 | |
|   for (let i = 0; i < rows.length; i++) {
 | |
|     const row = rows[i];
 | |
|     for (let j = row.childCount - 1; j >= 0; j--) {
 | |
|       const { rowspan, colspan } = row.child(j).attrs;
 | |
|       for (let r = i; r < i + rowspan; r++)
 | |
|         widths[r] = (widths[r] || 0) + colspan;
 | |
|     }
 | |
|   }
 | |
|   let width = 0;
 | |
|   for (let r = 0; r < widths.length; r++)
 | |
|     width = Math.max(width, widths[r]);
 | |
|   for (let r = 0; r < widths.length; r++) {
 | |
|     if (r >= rows.length)
 | |
|       rows.push(import_prosemirror_model2.Fragment.empty);
 | |
|     if (widths[r] < width) {
 | |
|       const empty = tableNodeTypes(schema).cell.createAndFill(), cells = [];
 | |
|       for (let i = widths[r]; i < width; i++)
 | |
|         cells.push(empty);
 | |
|       rows[r] = rows[r].append(import_prosemirror_model2.Fragment.from(cells));
 | |
|     }
 | |
|   }
 | |
|   return { height: rows.length, width, rows };
 | |
| }
 | |
| function fitSlice(nodeType, slice) {
 | |
|   const node = nodeType.createAndFill();
 | |
|   const tr = new import_prosemirror_transform.Transform(node).replace(0, node.content.size, slice);
 | |
|   return tr.doc;
 | |
| }
 | |
| function clipCells({ width, height, rows }, newWidth, newHeight) {
 | |
|   if (width != newWidth) {
 | |
|     const added = [], newRows = [];
 | |
|     for (let row = 0; row < rows.length; row++) {
 | |
|       const frag = rows[row], cells = [];
 | |
|       for (let col = added[row] || 0, i = 0; col < newWidth; i++) {
 | |
|         let cell = frag.child(i % frag.childCount);
 | |
|         if (col + cell.attrs.colspan > newWidth)
 | |
|           cell = cell.type.create(
 | |
|             removeColSpan(
 | |
|               cell.attrs,
 | |
|               cell.attrs.colspan,
 | |
|               col + cell.attrs.colspan - newWidth
 | |
|             ),
 | |
|             cell.content
 | |
|           );
 | |
|         cells.push(cell);
 | |
|         col += cell.attrs.colspan;
 | |
|         for (let j = 1; j < cell.attrs.rowspan; j++)
 | |
|           added[row + j] = (added[row + j] || 0) + cell.attrs.colspan;
 | |
|       }
 | |
|       newRows.push(import_prosemirror_model2.Fragment.from(cells));
 | |
|     }
 | |
|     rows = newRows;
 | |
|     width = newWidth;
 | |
|   }
 | |
|   if (height != newHeight) {
 | |
|     const newRows = [];
 | |
|     for (let row = 0, i = 0; row < newHeight; row++, i++) {
 | |
|       const cells = [], source = rows[i % height];
 | |
|       for (let j = 0; j < source.childCount; j++) {
 | |
|         let cell = source.child(j);
 | |
|         if (row + cell.attrs.rowspan > newHeight)
 | |
|           cell = cell.type.create(
 | |
|             _setAttr(
 | |
|               cell.attrs,
 | |
|               "rowspan",
 | |
|               Math.max(1, newHeight - cell.attrs.rowspan)
 | |
|             ),
 | |
|             cell.content
 | |
|           );
 | |
|         cells.push(cell);
 | |
|       }
 | |
|       newRows.push(import_prosemirror_model2.Fragment.from(cells));
 | |
|     }
 | |
|     rows = newRows;
 | |
|     height = newHeight;
 | |
|   }
 | |
|   return { width, height, rows };
 | |
| }
 | |
| function growTable(tr, map, table, start, width, height, mapFrom) {
 | |
|   const schema = tr.doc.type.schema;
 | |
|   const types = tableNodeTypes(schema);
 | |
|   let empty;
 | |
|   let emptyHead;
 | |
|   if (width > map.width) {
 | |
|     for (let row = 0, rowEnd = 0; row < map.height; row++) {
 | |
|       const rowNode = table.child(row);
 | |
|       rowEnd += rowNode.nodeSize;
 | |
|       const cells = [];
 | |
|       let add;
 | |
|       if (rowNode.lastChild == null || rowNode.lastChild.type == types.cell)
 | |
|         add = empty || (empty = types.cell.createAndFill());
 | |
|       else
 | |
|         add = emptyHead || (emptyHead = types.header_cell.createAndFill());
 | |
|       for (let i = map.width; i < width; i++)
 | |
|         cells.push(add);
 | |
|       tr.insert(tr.mapping.slice(mapFrom).map(rowEnd - 1 + start), cells);
 | |
|     }
 | |
|   }
 | |
|   if (height > map.height) {
 | |
|     const cells = [];
 | |
|     for (let i = 0, start2 = (map.height - 1) * map.width; i < Math.max(map.width, width); i++) {
 | |
|       const header = i >= map.width ? false : table.nodeAt(map.map[start2 + i]).type == types.header_cell;
 | |
|       cells.push(
 | |
|         header ? emptyHead || (emptyHead = types.header_cell.createAndFill()) : empty || (empty = types.cell.createAndFill())
 | |
|       );
 | |
|     }
 | |
|     const emptyRow = types.row.create(null, import_prosemirror_model2.Fragment.from(cells)), rows = [];
 | |
|     for (let i = map.height; i < height; i++)
 | |
|       rows.push(emptyRow);
 | |
|     tr.insert(tr.mapping.slice(mapFrom).map(start + table.nodeSize - 2), rows);
 | |
|   }
 | |
|   return !!(empty || emptyHead);
 | |
| }
 | |
| function isolateHorizontal(tr, map, table, start, left, right, top, mapFrom) {
 | |
|   if (top == 0 || top == map.height)
 | |
|     return false;
 | |
|   let found = false;
 | |
|   for (let col = left; col < right; col++) {
 | |
|     const index = top * map.width + col, pos = map.map[index];
 | |
|     if (map.map[index - map.width] == pos) {
 | |
|       found = true;
 | |
|       const cell = table.nodeAt(pos);
 | |
|       const { top: cellTop, left: cellLeft } = map.findCell(pos);
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.slice(mapFrom).map(pos + start),
 | |
|         null,
 | |
|         _setAttr(cell.attrs, "rowspan", top - cellTop)
 | |
|       );
 | |
|       tr.insert(
 | |
|         tr.mapping.slice(mapFrom).map(map.positionAt(top, cellLeft, table)),
 | |
|         cell.type.createAndFill(
 | |
|           _setAttr(cell.attrs, "rowspan", cellTop + cell.attrs.rowspan - top)
 | |
|         )
 | |
|       );
 | |
|       col += cell.attrs.colspan - 1;
 | |
|     }
 | |
|   }
 | |
|   return found;
 | |
| }
 | |
| function isolateVertical(tr, map, table, start, top, bottom, left, mapFrom) {
 | |
|   if (left == 0 || left == map.width)
 | |
|     return false;
 | |
|   let found = false;
 | |
|   for (let row = top; row < bottom; row++) {
 | |
|     const index = row * map.width + left, pos = map.map[index];
 | |
|     if (map.map[index - 1] == pos) {
 | |
|       found = true;
 | |
|       const cell = table.nodeAt(pos), cellLeft = map.colCount(pos);
 | |
|       const updatePos = tr.mapping.slice(mapFrom).map(pos + start);
 | |
|       tr.setNodeMarkup(
 | |
|         updatePos,
 | |
|         null,
 | |
|         removeColSpan(
 | |
|           cell.attrs,
 | |
|           left - cellLeft,
 | |
|           cell.attrs.colspan - (left - cellLeft)
 | |
|         )
 | |
|       );
 | |
|       tr.insert(
 | |
|         updatePos + cell.nodeSize,
 | |
|         cell.type.createAndFill(removeColSpan(cell.attrs, 0, left - cellLeft))
 | |
|       );
 | |
|       row += cell.attrs.rowspan - 1;
 | |
|     }
 | |
|   }
 | |
|   return found;
 | |
| }
 | |
| function insertCells(state, dispatch, tableStart, rect, cells) {
 | |
|   let table = tableStart ? state.doc.nodeAt(tableStart - 1) : state.doc, map = TableMap.get(table);
 | |
|   const { top, left } = rect;
 | |
|   const right = left + cells.width, bottom = top + cells.height;
 | |
|   const tr = state.tr;
 | |
|   let mapFrom = 0;
 | |
|   function recomp() {
 | |
|     table = tableStart ? tr.doc.nodeAt(tableStart - 1) : tr.doc;
 | |
|     map = TableMap.get(table);
 | |
|     mapFrom = tr.mapping.maps.length;
 | |
|   }
 | |
|   if (growTable(tr, map, table, tableStart, right, bottom, mapFrom))
 | |
|     recomp();
 | |
|   if (isolateHorizontal(tr, map, table, tableStart, left, right, top, mapFrom))
 | |
|     recomp();
 | |
|   if (isolateHorizontal(tr, map, table, tableStart, left, right, bottom, mapFrom))
 | |
|     recomp();
 | |
|   if (isolateVertical(tr, map, table, tableStart, top, bottom, left, mapFrom))
 | |
|     recomp();
 | |
|   if (isolateVertical(tr, map, table, tableStart, top, bottom, right, mapFrom))
 | |
|     recomp();
 | |
|   for (let row = top; row < bottom; row++) {
 | |
|     const from = map.positionAt(row, left, table), to = map.positionAt(row, right, table);
 | |
|     tr.replace(
 | |
|       tr.mapping.slice(mapFrom).map(from + tableStart),
 | |
|       tr.mapping.slice(mapFrom).map(to + tableStart),
 | |
|       new import_prosemirror_model2.Slice(cells.rows[row - top], 0, 0)
 | |
|     );
 | |
|   }
 | |
|   recomp();
 | |
|   tr.setSelection(
 | |
|     new CellSelection(
 | |
|       tr.doc.resolve(tableStart + map.positionAt(top, left, table)),
 | |
|       tr.doc.resolve(tableStart + map.positionAt(bottom - 1, right - 1, table))
 | |
|     )
 | |
|   );
 | |
|   dispatch(tr);
 | |
| }
 | |
| 
 | |
| // src/input.ts
 | |
| var handleKeyDown = (0, import_prosemirror_keymap.keydownHandler)({
 | |
|   ArrowLeft: arrow("horiz", -1),
 | |
|   ArrowRight: arrow("horiz", 1),
 | |
|   ArrowUp: arrow("vert", -1),
 | |
|   ArrowDown: arrow("vert", 1),
 | |
|   "Shift-ArrowLeft": shiftArrow("horiz", -1),
 | |
|   "Shift-ArrowRight": shiftArrow("horiz", 1),
 | |
|   "Shift-ArrowUp": shiftArrow("vert", -1),
 | |
|   "Shift-ArrowDown": shiftArrow("vert", 1),
 | |
|   Backspace: deleteCellSelection,
 | |
|   "Mod-Backspace": deleteCellSelection,
 | |
|   Delete: deleteCellSelection,
 | |
|   "Mod-Delete": deleteCellSelection
 | |
| });
 | |
| function maybeSetSelection(state, dispatch, selection) {
 | |
|   if (selection.eq(state.selection))
 | |
|     return false;
 | |
|   if (dispatch)
 | |
|     dispatch(state.tr.setSelection(selection).scrollIntoView());
 | |
|   return true;
 | |
| }
 | |
| function arrow(axis, dir) {
 | |
|   return (state, dispatch, view) => {
 | |
|     const sel = state.selection;
 | |
|     if (sel instanceof CellSelection) {
 | |
|       return maybeSetSelection(
 | |
|         state,
 | |
|         dispatch,
 | |
|         import_prosemirror_state4.Selection.near(sel.$headCell, dir)
 | |
|       );
 | |
|     }
 | |
|     if (axis != "horiz" && !sel.empty)
 | |
|       return false;
 | |
|     const end = atEndOfCell(view, axis, dir);
 | |
|     if (end == null)
 | |
|       return false;
 | |
|     if (axis == "horiz") {
 | |
|       return maybeSetSelection(
 | |
|         state,
 | |
|         dispatch,
 | |
|         import_prosemirror_state4.Selection.near(state.doc.resolve(sel.head + dir), dir)
 | |
|       );
 | |
|     } else {
 | |
|       const $cell = state.doc.resolve(end);
 | |
|       const $next = nextCell($cell, axis, dir);
 | |
|       let newSel;
 | |
|       if ($next)
 | |
|         newSel = import_prosemirror_state4.Selection.near($next, 1);
 | |
|       else if (dir < 0)
 | |
|         newSel = import_prosemirror_state4.Selection.near(state.doc.resolve($cell.before(-1)), -1);
 | |
|       else
 | |
|         newSel = import_prosemirror_state4.Selection.near(state.doc.resolve($cell.after(-1)), 1);
 | |
|       return maybeSetSelection(state, dispatch, newSel);
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function shiftArrow(axis, dir) {
 | |
|   return (state, dispatch, view) => {
 | |
|     const sel = state.selection;
 | |
|     let cellSel;
 | |
|     if (sel instanceof CellSelection) {
 | |
|       cellSel = sel;
 | |
|     } else {
 | |
|       const end = atEndOfCell(view, axis, dir);
 | |
|       if (end == null)
 | |
|         return false;
 | |
|       cellSel = new CellSelection(state.doc.resolve(end));
 | |
|     }
 | |
|     const $head = nextCell(cellSel.$headCell, axis, dir);
 | |
|     if (!$head)
 | |
|       return false;
 | |
|     return maybeSetSelection(
 | |
|       state,
 | |
|       dispatch,
 | |
|       new CellSelection(cellSel.$anchorCell, $head)
 | |
|     );
 | |
|   };
 | |
| }
 | |
| function deleteCellSelection(state, dispatch) {
 | |
|   const sel = state.selection;
 | |
|   if (!(sel instanceof CellSelection))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const tr = state.tr, baseContent = tableNodeTypes(state.schema).cell.createAndFill().content;
 | |
|     sel.forEachCell((cell, pos) => {
 | |
|       if (!cell.content.eq(baseContent))
 | |
|         tr.replace(
 | |
|           tr.mapping.map(pos + 1),
 | |
|           tr.mapping.map(pos + cell.nodeSize - 1),
 | |
|           new import_prosemirror_model3.Slice(baseContent, 0, 0)
 | |
|         );
 | |
|     });
 | |
|     if (tr.docChanged)
 | |
|       dispatch(tr);
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function handleTripleClick(view, pos) {
 | |
|   const doc = view.state.doc, $cell = cellAround(doc.resolve(pos));
 | |
|   if (!$cell)
 | |
|     return false;
 | |
|   view.dispatch(view.state.tr.setSelection(new CellSelection($cell)));
 | |
|   return true;
 | |
| }
 | |
| function handlePaste(view, _, slice) {
 | |
|   if (!isInTable(view.state))
 | |
|     return false;
 | |
|   let cells = pastedCells(slice);
 | |
|   const sel = view.state.selection;
 | |
|   if (sel instanceof CellSelection) {
 | |
|     if (!cells)
 | |
|       cells = {
 | |
|         width: 1,
 | |
|         height: 1,
 | |
|         rows: [
 | |
|           import_prosemirror_model3.Fragment.from(
 | |
|             fitSlice(tableNodeTypes(view.state.schema).cell, slice)
 | |
|           )
 | |
|         ]
 | |
|       };
 | |
|     const table = sel.$anchorCell.node(-1), start = sel.$anchorCell.start(-1);
 | |
|     const rect = TableMap.get(table).rectBetween(
 | |
|       sel.$anchorCell.pos - start,
 | |
|       sel.$headCell.pos - start
 | |
|     );
 | |
|     cells = clipCells(cells, rect.right - rect.left, rect.bottom - rect.top);
 | |
|     insertCells(view.state, view.dispatch, start, rect, cells);
 | |
|     return true;
 | |
|   } else if (cells) {
 | |
|     const $cell = selectionCell(view.state), start = $cell.start(-1);
 | |
|     insertCells(
 | |
|       view.state,
 | |
|       view.dispatch,
 | |
|       start,
 | |
|       TableMap.get($cell.node(-1)).findCell($cell.pos - start),
 | |
|       cells
 | |
|     );
 | |
|     return true;
 | |
|   } else {
 | |
|     return false;
 | |
|   }
 | |
| }
 | |
| function handleMouseDown(view, startEvent) {
 | |
|   if (startEvent.ctrlKey || startEvent.metaKey)
 | |
|     return;
 | |
|   const startDOMCell = domInCell(view, startEvent.target);
 | |
|   let $anchor;
 | |
|   if (startEvent.shiftKey && view.state.selection instanceof CellSelection) {
 | |
|     setCellSelection(view.state.selection.$anchorCell, startEvent);
 | |
|     startEvent.preventDefault();
 | |
|   } else if (startEvent.shiftKey && startDOMCell && ($anchor = cellAround(view.state.selection.$anchor)) != null && cellUnderMouse(view, startEvent).pos != $anchor.pos) {
 | |
|     setCellSelection($anchor, startEvent);
 | |
|     startEvent.preventDefault();
 | |
|   } else if (!startDOMCell) {
 | |
|     return;
 | |
|   }
 | |
|   function setCellSelection($anchor2, event) {
 | |
|     let $head = cellUnderMouse(view, event);
 | |
|     const starting = tableEditingKey.getState(view.state) == null;
 | |
|     if (!$head || !inSameTable($anchor2, $head)) {
 | |
|       if (starting)
 | |
|         $head = $anchor2;
 | |
|       else
 | |
|         return;
 | |
|     }
 | |
|     const selection = new CellSelection($anchor2, $head);
 | |
|     if (starting || !view.state.selection.eq(selection)) {
 | |
|       const tr = view.state.tr.setSelection(selection);
 | |
|       if (starting)
 | |
|         tr.setMeta(tableEditingKey, $anchor2.pos);
 | |
|       view.dispatch(tr);
 | |
|     }
 | |
|   }
 | |
|   function stop() {
 | |
|     view.root.removeEventListener("mouseup", stop);
 | |
|     view.root.removeEventListener("dragstart", stop);
 | |
|     view.root.removeEventListener("mousemove", move);
 | |
|     if (tableEditingKey.getState(view.state) != null)
 | |
|       view.dispatch(view.state.tr.setMeta(tableEditingKey, -1));
 | |
|   }
 | |
|   function move(event) {
 | |
|     const anchor = tableEditingKey.getState(view.state);
 | |
|     let $anchor2;
 | |
|     if (anchor != null) {
 | |
|       $anchor2 = view.state.doc.resolve(anchor);
 | |
|     } else if (domInCell(view, event.target) != startDOMCell) {
 | |
|       $anchor2 = cellUnderMouse(view, startEvent);
 | |
|       if (!$anchor2)
 | |
|         return stop();
 | |
|     }
 | |
|     if ($anchor2)
 | |
|       setCellSelection($anchor2, event);
 | |
|   }
 | |
|   view.root.addEventListener("mouseup", stop);
 | |
|   view.root.addEventListener("dragstart", stop);
 | |
|   view.root.addEventListener("mousemove", move);
 | |
| }
 | |
| function atEndOfCell(view, axis, dir) {
 | |
|   if (!(view.state.selection instanceof import_prosemirror_state4.TextSelection))
 | |
|     return null;
 | |
|   const { $head } = view.state.selection;
 | |
|   for (let d = $head.depth - 1; d >= 0; d--) {
 | |
|     const parent = $head.node(d), index = dir < 0 ? $head.index(d) : $head.indexAfter(d);
 | |
|     if (index != (dir < 0 ? 0 : parent.childCount))
 | |
|       return null;
 | |
|     if (parent.type.spec.tableRole == "cell" || parent.type.spec.tableRole == "header_cell") {
 | |
|       const cellPos = $head.before(d);
 | |
|       const dirStr = axis == "vert" ? dir > 0 ? "down" : "up" : dir > 0 ? "right" : "left";
 | |
|       return view.endOfTextblock(dirStr) ? cellPos : null;
 | |
|     }
 | |
|   }
 | |
|   return null;
 | |
| }
 | |
| function domInCell(view, dom) {
 | |
|   for (; dom && dom != view.dom; dom = dom.parentNode)
 | |
|     if (dom.nodeName == "TD" || dom.nodeName == "TH")
 | |
|       return dom;
 | |
| }
 | |
| function cellUnderMouse(view, event) {
 | |
|   const mousePos = view.posAtCoords({
 | |
|     left: event.clientX,
 | |
|     top: event.clientY
 | |
|   });
 | |
|   if (!mousePos)
 | |
|     return null;
 | |
|   return mousePos ? cellAround(view.state.doc.resolve(mousePos.pos)) : null;
 | |
| }
 | |
| 
 | |
| // src/columnresizing.ts
 | |
| var import_prosemirror_state5 = require("prosemirror-state");
 | |
| var import_prosemirror_view2 = require("prosemirror-view");
 | |
| 
 | |
| // src/tableview.ts
 | |
| var TableView = class {
 | |
|   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"));
 | |
|     updateColumnsOnResize(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;
 | |
|     updateColumnsOnResize(node, this.colgroup, this.table, this.cellMinWidth);
 | |
|     return true;
 | |
|   }
 | |
|   ignoreMutation(record) {
 | |
|     return record.type == "attributes" && (record.target == this.table || this.colgroup.contains(record.target));
 | |
|   }
 | |
| };
 | |
| function updateColumnsOnResize(node, colgroup, table, cellMinWidth, overrideCol, overrideValue) {
 | |
|   let totalWidth = 0, fixedWidth = true;
 | |
|   let nextDOM = colgroup.firstChild;
 | |
|   const row = node.firstChild;
 | |
|   for (let i = 0, col = 0; i < row.childCount; i++) {
 | |
|     const { colspan, colwidth } = row.child(i).attrs;
 | |
|     for (let j = 0; j < colspan; j++, col++) {
 | |
|       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";
 | |
|   }
 | |
| }
 | |
| 
 | |
| // src/columnresizing.ts
 | |
| var columnResizingPluginKey = new import_prosemirror_state5.PluginKey(
 | |
|   "tableColumnResizing"
 | |
| );
 | |
| function columnResizing({
 | |
|   handleWidth = 5,
 | |
|   cellMinWidth = 25,
 | |
|   View = TableView,
 | |
|   lastColumnResizable = true
 | |
| } = {}) {
 | |
|   const plugin = new import_prosemirror_state5.Plugin({
 | |
|     key: columnResizingPluginKey,
 | |
|     state: {
 | |
|       init(_, state) {
 | |
|         this.spec.props.nodeViews[tableNodeTypes(state.schema).table.name] = (node, view) => new View(node, cellMinWidth, view);
 | |
|         return new ResizeState(-1, false);
 | |
|       },
 | |
|       apply(tr, prev) {
 | |
|         return prev.apply(tr);
 | |
|       }
 | |
|     },
 | |
|     props: {
 | |
|       attributes(state) {
 | |
|         const pluginState = columnResizingPluginKey.getState(state);
 | |
|         return pluginState.activeHandle > -1 ? { class: "resize-cursor" } : null;
 | |
|       },
 | |
|       handleDOMEvents: {
 | |
|         mousemove(view, event) {
 | |
|           handleMouseMove(
 | |
|             view,
 | |
|             event,
 | |
|             handleWidth,
 | |
|             cellMinWidth,
 | |
|             lastColumnResizable
 | |
|           );
 | |
|         },
 | |
|         mouseleave(view) {
 | |
|           handleMouseLeave(view);
 | |
|         },
 | |
|         mousedown(view, event) {
 | |
|           handleMouseDown2(view, event, cellMinWidth);
 | |
|         }
 | |
|       },
 | |
|       decorations(state) {
 | |
|         const pluginState = columnResizingPluginKey.getState(state);
 | |
|         if (pluginState.activeHandle > -1)
 | |
|           return handleDecorations(state, pluginState.activeHandle);
 | |
|       },
 | |
|       nodeViews: {}
 | |
|     }
 | |
|   });
 | |
|   return plugin;
 | |
| }
 | |
| var ResizeState = class {
 | |
|   constructor(activeHandle, dragging) {
 | |
|     this.activeHandle = activeHandle;
 | |
|     this.dragging = dragging;
 | |
|   }
 | |
|   apply(tr) {
 | |
|     let state = this;
 | |
|     const action = tr.getMeta(columnResizingPluginKey);
 | |
|     if (action && action.setHandle != null)
 | |
|       return new ResizeState(action.setHandle, null);
 | |
|     if (action && action.setDragging !== void 0)
 | |
|       return new ResizeState(state.activeHandle, action.setDragging);
 | |
|     if (state.activeHandle > -1 && tr.docChanged) {
 | |
|       let handle = tr.mapping.map(state.activeHandle, -1);
 | |
|       if (!pointsAtCell(tr.doc.resolve(handle)))
 | |
|         handle = null;
 | |
|       state = new ResizeState(handle, state.dragging);
 | |
|     }
 | |
|     return state;
 | |
|   }
 | |
| };
 | |
| function handleMouseMove(view, event, handleWidth, cellMinWidth, lastColumnResizable) {
 | |
|   const pluginState = columnResizingPluginKey.getState(view.state);
 | |
|   if (!pluginState.dragging) {
 | |
|     const target = domCellAround(event.target);
 | |
|     let cell = -1;
 | |
|     if (target) {
 | |
|       const { left, right } = target.getBoundingClientRect();
 | |
|       if (event.clientX - left <= handleWidth)
 | |
|         cell = edgeCell(view, event, "left");
 | |
|       else if (right - event.clientX <= handleWidth)
 | |
|         cell = edgeCell(view, event, "right");
 | |
|     }
 | |
|     if (cell != pluginState.activeHandle) {
 | |
|       if (!lastColumnResizable && cell !== -1) {
 | |
|         const $cell = view.state.doc.resolve(cell);
 | |
|         const table = $cell.node(-1), map = TableMap.get(table), start = $cell.start(-1);
 | |
|         const col = map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan - 1;
 | |
|         if (col == map.width - 1) {
 | |
|           return;
 | |
|         }
 | |
|       }
 | |
|       updateHandle(view, cell);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function handleMouseLeave(view) {
 | |
|   const pluginState = columnResizingPluginKey.getState(view.state);
 | |
|   if (pluginState.activeHandle > -1 && !pluginState.dragging)
 | |
|     updateHandle(view, -1);
 | |
| }
 | |
| function handleMouseDown2(view, event, cellMinWidth) {
 | |
|   const pluginState = columnResizingPluginKey.getState(view.state);
 | |
|   if (pluginState.activeHandle == -1 || pluginState.dragging)
 | |
|     return false;
 | |
|   const cell = view.state.doc.nodeAt(pluginState.activeHandle);
 | |
|   const width = currentColWidth(view, pluginState.activeHandle, cell.attrs);
 | |
|   view.dispatch(
 | |
|     view.state.tr.setMeta(columnResizingPluginKey, {
 | |
|       setDragging: { startX: event.clientX, startWidth: width }
 | |
|     })
 | |
|   );
 | |
|   function finish(event2) {
 | |
|     window.removeEventListener("mouseup", finish);
 | |
|     window.removeEventListener("mousemove", move);
 | |
|     const pluginState2 = columnResizingPluginKey.getState(view.state);
 | |
|     if (pluginState2.dragging) {
 | |
|       updateColumnWidth(
 | |
|         view,
 | |
|         pluginState2.activeHandle,
 | |
|         draggedWidth(pluginState2.dragging, event2, cellMinWidth)
 | |
|       );
 | |
|       view.dispatch(
 | |
|         view.state.tr.setMeta(columnResizingPluginKey, { setDragging: null })
 | |
|       );
 | |
|     }
 | |
|   }
 | |
|   function move(event2) {
 | |
|     if (!event2.which)
 | |
|       return finish(event2);
 | |
|     const pluginState2 = columnResizingPluginKey.getState(view.state);
 | |
|     if (pluginState2.dragging) {
 | |
|       const dragged = draggedWidth(pluginState2.dragging, event2, cellMinWidth);
 | |
|       displayColumnWidth(view, pluginState2.activeHandle, dragged, cellMinWidth);
 | |
|     }
 | |
|   }
 | |
|   window.addEventListener("mouseup", finish);
 | |
|   window.addEventListener("mousemove", move);
 | |
|   event.preventDefault();
 | |
|   return true;
 | |
| }
 | |
| function currentColWidth(view, cellPos, { colspan, colwidth }) {
 | |
|   const width = colwidth && colwidth[colwidth.length - 1];
 | |
|   if (width)
 | |
|     return width;
 | |
|   const dom = view.domAtPos(cellPos);
 | |
|   const node = dom.node.childNodes[dom.offset];
 | |
|   let domWidth = node.offsetWidth, parts = colspan;
 | |
|   if (colwidth) {
 | |
|     for (let i = 0; i < colspan; i++)
 | |
|       if (colwidth[i]) {
 | |
|         domWidth -= colwidth[i];
 | |
|         parts--;
 | |
|       }
 | |
|   }
 | |
|   return domWidth / parts;
 | |
| }
 | |
| function domCellAround(target) {
 | |
|   while (target && target.nodeName != "TD" && target.nodeName != "TH")
 | |
|     target = target.classList && target.classList.contains("ProseMirror") ? null : target.parentNode;
 | |
|   return target;
 | |
| }
 | |
| function edgeCell(view, event, side) {
 | |
|   const found = view.posAtCoords({ left: event.clientX, top: event.clientY });
 | |
|   if (!found)
 | |
|     return -1;
 | |
|   const { pos } = found;
 | |
|   const $cell = cellAround(view.state.doc.resolve(pos));
 | |
|   if (!$cell)
 | |
|     return -1;
 | |
|   if (side == "right")
 | |
|     return $cell.pos;
 | |
|   const map = TableMap.get($cell.node(-1)), start = $cell.start(-1);
 | |
|   const index = map.map.indexOf($cell.pos - start);
 | |
|   return index % map.width == 0 ? -1 : start + map.map[index - 1];
 | |
| }
 | |
| function draggedWidth(dragging, event, cellMinWidth) {
 | |
|   const offset = event.clientX - dragging.startX;
 | |
|   return Math.max(cellMinWidth, dragging.startWidth + offset);
 | |
| }
 | |
| function updateHandle(view, value) {
 | |
|   view.dispatch(
 | |
|     view.state.tr.setMeta(columnResizingPluginKey, { setHandle: value })
 | |
|   );
 | |
| }
 | |
| function updateColumnWidth(view, cell, width) {
 | |
|   const $cell = view.state.doc.resolve(cell);
 | |
|   const table = $cell.node(-1), map = TableMap.get(table), start = $cell.start(-1);
 | |
|   const col = map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan - 1;
 | |
|   const tr = view.state.tr;
 | |
|   for (let row = 0; row < map.height; row++) {
 | |
|     const mapIndex = row * map.width + col;
 | |
|     if (row && map.map[mapIndex] == map.map[mapIndex - map.width])
 | |
|       continue;
 | |
|     const pos = map.map[mapIndex], { attrs } = table.nodeAt(pos);
 | |
|     const index = attrs.colspan == 1 ? 0 : col - map.colCount(pos);
 | |
|     if (attrs.colwidth && attrs.colwidth[index] == width)
 | |
|       continue;
 | |
|     const colwidth = attrs.colwidth ? attrs.colwidth.slice() : zeroes(attrs.colspan);
 | |
|     colwidth[index] = width;
 | |
|     tr.setNodeMarkup(start + pos, null, _setAttr(attrs, "colwidth", colwidth));
 | |
|   }
 | |
|   if (tr.docChanged)
 | |
|     view.dispatch(tr);
 | |
| }
 | |
| function displayColumnWidth(view, cell, width, cellMinWidth) {
 | |
|   const $cell = view.state.doc.resolve(cell);
 | |
|   const table = $cell.node(-1), start = $cell.start(-1);
 | |
|   const col = TableMap.get(table).colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan - 1;
 | |
|   let dom = view.domAtPos($cell.start(-1)).node;
 | |
|   while (dom.nodeName != "TABLE")
 | |
|     dom = dom.parentNode;
 | |
|   updateColumnsOnResize(
 | |
|     table,
 | |
|     dom.firstChild,
 | |
|     dom,
 | |
|     cellMinWidth,
 | |
|     col,
 | |
|     width
 | |
|   );
 | |
| }
 | |
| function zeroes(n) {
 | |
|   const result = [];
 | |
|   for (let i = 0; i < n; i++)
 | |
|     result.push(0);
 | |
|   return result;
 | |
| }
 | |
| function handleDecorations(state, cell) {
 | |
|   const decorations = [];
 | |
|   const $cell = state.doc.resolve(cell);
 | |
|   const table = $cell.node(-1);
 | |
|   if (!table) {
 | |
|     return import_prosemirror_view2.DecorationSet.empty;
 | |
|   }
 | |
|   const map = TableMap.get(table);
 | |
|   const start = $cell.start(-1);
 | |
|   const col = map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan;
 | |
|   for (let row = 0; row < map.height; row++) {
 | |
|     const index = col + row * map.width - 1;
 | |
|     if ((col == map.width || map.map[index] != map.map[index + 1]) && (row == 0 || map.map[index - 1] != map.map[index - 1 - map.width])) {
 | |
|       const cellPos = map.map[index];
 | |
|       const pos = start + cellPos + table.nodeAt(cellPos).nodeSize - 1;
 | |
|       const dom = document.createElement("div");
 | |
|       dom.className = "column-resize-handle";
 | |
|       decorations.push(import_prosemirror_view2.Decoration.widget(pos, dom));
 | |
|     }
 | |
|   }
 | |
|   return import_prosemirror_view2.DecorationSet.create(state.doc, decorations);
 | |
| }
 | |
| 
 | |
| // src/commands.ts
 | |
| var import_prosemirror_state6 = require("prosemirror-state");
 | |
| var import_prosemirror_model4 = require("prosemirror-model");
 | |
| function selectedRect(state) {
 | |
|   const sel = state.selection, $pos = selectionCell(state);
 | |
|   const table = $pos.node(-1), tableStart = $pos.start(-1), map = TableMap.get(table);
 | |
|   let rect;
 | |
|   if (sel instanceof CellSelection)
 | |
|     rect = map.rectBetween(
 | |
|       sel.$anchorCell.pos - tableStart,
 | |
|       sel.$headCell.pos - tableStart
 | |
|     );
 | |
|   else
 | |
|     rect = map.findCell($pos.pos - tableStart);
 | |
|   rect.tableStart = tableStart;
 | |
|   rect.map = map;
 | |
|   rect.table = table;
 | |
|   return rect;
 | |
| }
 | |
| function addColumn(tr, { map, tableStart, table }, col) {
 | |
|   let refColumn = col > 0 ? -1 : 0;
 | |
|   if (columnIsHeader(map, table, col + refColumn))
 | |
|     refColumn = col == 0 || col == map.width ? null : 0;
 | |
|   for (let row = 0; row < map.height; row++) {
 | |
|     const index = row * map.width + col;
 | |
|     if (col > 0 && col < map.width && map.map[index - 1] == map.map[index]) {
 | |
|       const pos = map.map[index], cell = table.nodeAt(pos);
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.map(tableStart + pos),
 | |
|         null,
 | |
|         addColSpan(cell.attrs, col - map.colCount(pos))
 | |
|       );
 | |
|       row += cell.attrs.rowspan - 1;
 | |
|     } else {
 | |
|       const type = refColumn == null ? tableNodeTypes(table.type.schema).cell : table.nodeAt(map.map[index + refColumn]).type;
 | |
|       const pos = map.positionAt(row, col, table);
 | |
|       tr.insert(tr.mapping.map(tableStart + pos), type.createAndFill());
 | |
|     }
 | |
|   }
 | |
|   return tr;
 | |
| }
 | |
| function addColumnBefore(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state);
 | |
|     dispatch(addColumn(state.tr, rect, rect.left));
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function addColumnAfter(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state);
 | |
|     dispatch(addColumn(state.tr, rect, rect.right));
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function removeColumn(tr, { map, table, tableStart }, col) {
 | |
|   const mapStart = tr.mapping.maps.length;
 | |
|   for (let row = 0; row < map.height; ) {
 | |
|     const index = row * map.width + col, pos = map.map[index], cell = table.nodeAt(pos);
 | |
|     if (col > 0 && map.map[index - 1] == pos || col < map.width - 1 && map.map[index + 1] == pos) {
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.slice(mapStart).map(tableStart + pos),
 | |
|         null,
 | |
|         removeColSpan(cell.attrs, col - map.colCount(pos))
 | |
|       );
 | |
|     } else {
 | |
|       const start = tr.mapping.slice(mapStart).map(tableStart + pos);
 | |
|       tr.delete(start, start + cell.nodeSize);
 | |
|     }
 | |
|     row += cell.attrs.rowspan;
 | |
|   }
 | |
| }
 | |
| function deleteColumn(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state), tr = state.tr;
 | |
|     if (rect.left == 0 && rect.right == rect.map.width)
 | |
|       return false;
 | |
|     for (let i = rect.right - 1; ; i--) {
 | |
|       removeColumn(tr, rect, i);
 | |
|       if (i == rect.left)
 | |
|         break;
 | |
|       rect.table = rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc;
 | |
|       rect.map = TableMap.get(rect.table);
 | |
|     }
 | |
|     dispatch(tr);
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function rowIsHeader(map, table, row) {
 | |
|   const headerCell = tableNodeTypes(table.type.schema).header_cell;
 | |
|   for (let col = 0; col < map.width; col++)
 | |
|     if (table.nodeAt(map.map[col + row * map.width]).type != headerCell)
 | |
|       return false;
 | |
|   return true;
 | |
| }
 | |
| function addRow(tr, { map, tableStart, table }, row) {
 | |
|   let rowPos = tableStart;
 | |
|   for (let i = 0; i < row; i++)
 | |
|     rowPos += table.child(i).nodeSize;
 | |
|   const cells = [];
 | |
|   let refRow = row > 0 ? -1 : 0;
 | |
|   if (rowIsHeader(map, table, row + refRow))
 | |
|     refRow = row == 0 || row == map.height ? null : 0;
 | |
|   for (let col = 0, index = map.width * row; col < map.width; col++, index++) {
 | |
|     if (row > 0 && row < map.height && map.map[index] == map.map[index - map.width]) {
 | |
|       const pos = map.map[index], attrs = table.nodeAt(pos).attrs;
 | |
|       tr.setNodeMarkup(
 | |
|         tableStart + pos,
 | |
|         null,
 | |
|         _setAttr(attrs, "rowspan", attrs.rowspan + 1)
 | |
|       );
 | |
|       col += attrs.colspan - 1;
 | |
|     } else {
 | |
|       const type = refRow == null ? tableNodeTypes(table.type.schema).cell : table.nodeAt(map.map[index + refRow * map.width]).type;
 | |
|       cells.push(type.createAndFill());
 | |
|     }
 | |
|   }
 | |
|   tr.insert(rowPos, tableNodeTypes(table.type.schema).row.create(null, cells));
 | |
|   return tr;
 | |
| }
 | |
| function addRowBefore(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state);
 | |
|     dispatch(addRow(state.tr, rect, rect.top));
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function addRowAfter(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state);
 | |
|     dispatch(addRow(state.tr, rect, rect.bottom));
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function removeRow(tr, { map, table, tableStart }, row) {
 | |
|   let rowPos = 0;
 | |
|   for (let i = 0; i < row; i++)
 | |
|     rowPos += table.child(i).nodeSize;
 | |
|   const nextRow = rowPos + table.child(row).nodeSize;
 | |
|   const mapFrom = tr.mapping.maps.length;
 | |
|   tr.delete(rowPos + tableStart, nextRow + tableStart);
 | |
|   for (let col = 0, index = row * map.width; col < map.width; col++, index++) {
 | |
|     const pos = map.map[index];
 | |
|     if (row > 0 && pos == map.map[index - map.width]) {
 | |
|       const attrs = table.nodeAt(pos).attrs;
 | |
|       tr.setNodeMarkup(
 | |
|         tr.mapping.slice(mapFrom).map(pos + tableStart),
 | |
|         null,
 | |
|         _setAttr(attrs, "rowspan", attrs.rowspan - 1)
 | |
|       );
 | |
|       col += attrs.colspan - 1;
 | |
|     } else if (row < map.width && pos == map.map[index + map.width]) {
 | |
|       const cell = table.nodeAt(pos);
 | |
|       const copy = cell.type.create(
 | |
|         _setAttr(cell.attrs, "rowspan", cell.attrs.rowspan - 1),
 | |
|         cell.content
 | |
|       );
 | |
|       const newPos = map.positionAt(row + 1, col, table);
 | |
|       tr.insert(tr.mapping.slice(mapFrom).map(tableStart + newPos), copy);
 | |
|       col += cell.attrs.colspan - 1;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function deleteRow(state, dispatch) {
 | |
|   if (!isInTable(state))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const rect = selectedRect(state), tr = state.tr;
 | |
|     if (rect.top == 0 && rect.bottom == rect.map.height)
 | |
|       return false;
 | |
|     for (let i = rect.bottom - 1; ; i--) {
 | |
|       removeRow(tr, rect, i);
 | |
|       if (i == rect.top)
 | |
|         break;
 | |
|       rect.table = rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc;
 | |
|       rect.map = TableMap.get(rect.table);
 | |
|     }
 | |
|     dispatch(tr);
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function isEmpty(cell) {
 | |
|   const c = cell.content;
 | |
|   return c.childCount == 1 && c.firstChild.isTextblock && c.firstChild.childCount == 0;
 | |
| }
 | |
| function cellsOverlapRectangle({ width, height, map }, rect) {
 | |
|   let indexTop = rect.top * width + rect.left, indexLeft = indexTop;
 | |
|   let indexBottom = (rect.bottom - 1) * width + rect.left, indexRight = indexTop + (rect.right - rect.left - 1);
 | |
|   for (let i = rect.top; i < rect.bottom; i++) {
 | |
|     if (rect.left > 0 && map[indexLeft] == map[indexLeft - 1] || rect.right < width && map[indexRight] == map[indexRight + 1])
 | |
|       return true;
 | |
|     indexLeft += width;
 | |
|     indexRight += width;
 | |
|   }
 | |
|   for (let i = rect.left; i < rect.right; i++) {
 | |
|     if (rect.top > 0 && map[indexTop] == map[indexTop - width] || rect.bottom < height && map[indexBottom] == map[indexBottom + width])
 | |
|       return true;
 | |
|     indexTop++;
 | |
|     indexBottom++;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| function mergeCells(state, dispatch) {
 | |
|   const sel = state.selection;
 | |
|   if (!(sel instanceof CellSelection) || sel.$anchorCell.pos == sel.$headCell.pos)
 | |
|     return false;
 | |
|   const rect = selectedRect(state), { map } = rect;
 | |
|   if (cellsOverlapRectangle(map, rect))
 | |
|     return false;
 | |
|   if (dispatch) {
 | |
|     const tr = state.tr;
 | |
|     const seen = {};
 | |
|     let content = import_prosemirror_model4.Fragment.empty;
 | |
|     let mergedPos;
 | |
|     let mergedCell;
 | |
|     for (let row = rect.top; row < rect.bottom; row++) {
 | |
|       for (let col = rect.left; col < rect.right; col++) {
 | |
|         const cellPos = map.map[row * map.width + col], cell = rect.table.nodeAt(cellPos);
 | |
|         if (seen[cellPos])
 | |
|           continue;
 | |
|         seen[cellPos] = true;
 | |
|         if (mergedPos == null) {
 | |
|           mergedPos = cellPos;
 | |
|           mergedCell = cell;
 | |
|         } else {
 | |
|           if (!isEmpty(cell))
 | |
|             content = content.append(cell.content);
 | |
|           const mapped = tr.mapping.map(cellPos + rect.tableStart);
 | |
|           tr.delete(mapped, mapped + cell.nodeSize);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     tr.setNodeMarkup(
 | |
|       mergedPos + rect.tableStart,
 | |
|       null,
 | |
|       _setAttr(
 | |
|         addColSpan(
 | |
|           mergedCell.attrs,
 | |
|           mergedCell.attrs.colspan,
 | |
|           rect.right - rect.left - mergedCell.attrs.colspan
 | |
|         ),
 | |
|         "rowspan",
 | |
|         rect.bottom - rect.top
 | |
|       )
 | |
|     );
 | |
|     if (content.size) {
 | |
|       const end = mergedPos + 1 + mergedCell.content.size;
 | |
|       const start = isEmpty(mergedCell) ? mergedPos + 1 : end;
 | |
|       tr.replaceWith(start + rect.tableStart, end + rect.tableStart, content);
 | |
|     }
 | |
|     tr.setSelection(
 | |
|       new CellSelection(tr.doc.resolve(mergedPos + rect.tableStart))
 | |
|     );
 | |
|     dispatch(tr);
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function splitCell(state, dispatch) {
 | |
|   const nodeTypes = tableNodeTypes(state.schema);
 | |
|   return splitCellWithType(({ node }) => {
 | |
|     return nodeTypes[node.type.spec.tableRole];
 | |
|   })(state, dispatch);
 | |
| }
 | |
| function splitCellWithType(getCellType) {
 | |
|   return (state, dispatch) => {
 | |
|     const sel = state.selection;
 | |
|     let cellNode, cellPos;
 | |
|     if (!(sel instanceof CellSelection)) {
 | |
|       cellNode = cellWrapping(sel.$from);
 | |
|       if (!cellNode)
 | |
|         return false;
 | |
|       cellPos = cellAround(sel.$from).pos;
 | |
|     } else {
 | |
|       if (sel.$anchorCell.pos != sel.$headCell.pos)
 | |
|         return false;
 | |
|       cellNode = sel.$anchorCell.nodeAfter;
 | |
|       cellPos = sel.$anchorCell.pos;
 | |
|     }
 | |
|     if (cellNode.attrs.colspan == 1 && cellNode.attrs.rowspan == 1) {
 | |
|       return false;
 | |
|     }
 | |
|     if (dispatch) {
 | |
|       let baseAttrs = cellNode.attrs;
 | |
|       const attrs = [];
 | |
|       const colwidth = baseAttrs.colwidth;
 | |
|       if (baseAttrs.rowspan > 1)
 | |
|         baseAttrs = _setAttr(baseAttrs, "rowspan", 1);
 | |
|       if (baseAttrs.colspan > 1)
 | |
|         baseAttrs = _setAttr(baseAttrs, "colspan", 1);
 | |
|       const rect = selectedRect(state), tr = state.tr;
 | |
|       for (let i = 0; i < rect.right - rect.left; i++)
 | |
|         attrs.push(
 | |
|           colwidth ? _setAttr(
 | |
|             baseAttrs,
 | |
|             "colwidth",
 | |
|             colwidth && colwidth[i] ? [colwidth[i]] : null
 | |
|           ) : baseAttrs
 | |
|         );
 | |
|       let lastCell;
 | |
|       for (let row = rect.top; row < rect.bottom; row++) {
 | |
|         let pos = rect.map.positionAt(row, rect.left, rect.table);
 | |
|         if (row == rect.top)
 | |
|           pos += cellNode.nodeSize;
 | |
|         for (let col = rect.left, i = 0; col < rect.right; col++, i++) {
 | |
|           if (col == rect.left && row == rect.top)
 | |
|             continue;
 | |
|           tr.insert(
 | |
|             lastCell = tr.mapping.map(pos + rect.tableStart, 1),
 | |
|             getCellType({ node: cellNode, row, col }).createAndFill(attrs[i])
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|       tr.setNodeMarkup(
 | |
|         cellPos,
 | |
|         getCellType({ node: cellNode, row: rect.top, col: rect.left }),
 | |
|         attrs[0]
 | |
|       );
 | |
|       if (sel instanceof CellSelection)
 | |
|         tr.setSelection(
 | |
|           new CellSelection(
 | |
|             tr.doc.resolve(sel.$anchorCell.pos),
 | |
|             lastCell && tr.doc.resolve(lastCell)
 | |
|           )
 | |
|         );
 | |
|       dispatch(tr);
 | |
|     }
 | |
|     return true;
 | |
|   };
 | |
| }
 | |
| function setCellAttr(name, value) {
 | |
|   return function(state, dispatch) {
 | |
|     if (!isInTable(state))
 | |
|       return false;
 | |
|     const $cell = selectionCell(state);
 | |
|     if ($cell.nodeAfter.attrs[name] === value)
 | |
|       return false;
 | |
|     if (dispatch) {
 | |
|       const tr = state.tr;
 | |
|       if (state.selection instanceof CellSelection)
 | |
|         state.selection.forEachCell((node, pos) => {
 | |
|           if (node.attrs[name] !== value)
 | |
|             tr.setNodeMarkup(pos, null, _setAttr(node.attrs, name, value));
 | |
|         });
 | |
|       else
 | |
|         tr.setNodeMarkup(
 | |
|           $cell.pos,
 | |
|           null,
 | |
|           _setAttr($cell.nodeAfter.attrs, name, value)
 | |
|         );
 | |
|       dispatch(tr);
 | |
|     }
 | |
|     return true;
 | |
|   };
 | |
| }
 | |
| function deprecated_toggleHeader(type) {
 | |
|   return function(state, dispatch) {
 | |
|     if (!isInTable(state))
 | |
|       return false;
 | |
|     if (dispatch) {
 | |
|       const types = tableNodeTypes(state.schema);
 | |
|       const rect = selectedRect(state), tr = state.tr;
 | |
|       const cells = rect.map.cellsInRect(
 | |
|         type == "column" ? {
 | |
|           left: rect.left,
 | |
|           top: 0,
 | |
|           right: rect.right,
 | |
|           bottom: rect.map.height
 | |
|         } : type == "row" ? {
 | |
|           left: 0,
 | |
|           top: rect.top,
 | |
|           right: rect.map.width,
 | |
|           bottom: rect.bottom
 | |
|         } : rect
 | |
|       );
 | |
|       const nodes = cells.map((pos) => rect.table.nodeAt(pos));
 | |
|       for (let i = 0; i < cells.length; i++)
 | |
|         if (nodes[i].type == types.header_cell)
 | |
|           tr.setNodeMarkup(
 | |
|             rect.tableStart + cells[i],
 | |
|             types.cell,
 | |
|             nodes[i].attrs
 | |
|           );
 | |
|       if (tr.steps.length == 0)
 | |
|         for (let i = 0; i < cells.length; i++)
 | |
|           tr.setNodeMarkup(
 | |
|             rect.tableStart + cells[i],
 | |
|             types.header_cell,
 | |
|             nodes[i].attrs
 | |
|           );
 | |
|       dispatch(tr);
 | |
|     }
 | |
|     return true;
 | |
|   };
 | |
| }
 | |
| function isHeaderEnabledByType(type, rect, types) {
 | |
|   const cellPositions = rect.map.cellsInRect({
 | |
|     left: 0,
 | |
|     top: 0,
 | |
|     right: type == "row" ? rect.map.width : 1,
 | |
|     bottom: type == "column" ? rect.map.height : 1
 | |
|   });
 | |
|   for (let i = 0; i < cellPositions.length; i++) {
 | |
|     const cell = rect.table.nodeAt(cellPositions[i]);
 | |
|     if (cell && cell.type !== types.header_cell) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| function toggleHeader(type, options) {
 | |
|   options = options || { useDeprecatedLogic: false };
 | |
|   if (options.useDeprecatedLogic)
 | |
|     return deprecated_toggleHeader(type);
 | |
|   return function(state, dispatch) {
 | |
|     if (!isInTable(state))
 | |
|       return false;
 | |
|     if (dispatch) {
 | |
|       const types = tableNodeTypes(state.schema);
 | |
|       const rect = selectedRect(state), tr = state.tr;
 | |
|       const isHeaderRowEnabled = isHeaderEnabledByType("row", rect, types);
 | |
|       const isHeaderColumnEnabled = isHeaderEnabledByType(
 | |
|         "column",
 | |
|         rect,
 | |
|         types
 | |
|       );
 | |
|       const isHeaderEnabled = type === "column" ? isHeaderRowEnabled : type === "row" ? isHeaderColumnEnabled : false;
 | |
|       const selectionStartsAt = isHeaderEnabled ? 1 : 0;
 | |
|       const cellsRect = type == "column" ? {
 | |
|         left: 0,
 | |
|         top: selectionStartsAt,
 | |
|         right: 1,
 | |
|         bottom: rect.map.height
 | |
|       } : type == "row" ? {
 | |
|         left: selectionStartsAt,
 | |
|         top: 0,
 | |
|         right: rect.map.width,
 | |
|         bottom: 1
 | |
|       } : rect;
 | |
|       const newType = type == "column" ? isHeaderColumnEnabled ? types.cell : types.header_cell : type == "row" ? isHeaderRowEnabled ? types.cell : types.header_cell : types.cell;
 | |
|       rect.map.cellsInRect(cellsRect).forEach((relativeCellPos) => {
 | |
|         const cellPos = relativeCellPos + rect.tableStart;
 | |
|         const cell = tr.doc.nodeAt(cellPos);
 | |
|         if (cell) {
 | |
|           tr.setNodeMarkup(cellPos, newType, cell.attrs);
 | |
|         }
 | |
|       });
 | |
|       dispatch(tr);
 | |
|     }
 | |
|     return true;
 | |
|   };
 | |
| }
 | |
| var toggleHeaderRow = toggleHeader("row", {
 | |
|   useDeprecatedLogic: true
 | |
| });
 | |
| var toggleHeaderColumn = toggleHeader("column", {
 | |
|   useDeprecatedLogic: true
 | |
| });
 | |
| var toggleHeaderCell = toggleHeader("cell", {
 | |
|   useDeprecatedLogic: true
 | |
| });
 | |
| function findNextCell($cell, dir) {
 | |
|   if (dir < 0) {
 | |
|     const before = $cell.nodeBefore;
 | |
|     if (before)
 | |
|       return $cell.pos - before.nodeSize;
 | |
|     for (let row = $cell.index(-1) - 1, rowEnd = $cell.before(); row >= 0; row--) {
 | |
|       const rowNode = $cell.node(-1).child(row);
 | |
|       if (rowNode.childCount)
 | |
|         return rowEnd - 1 - rowNode.lastChild.nodeSize;
 | |
|       rowEnd -= rowNode.nodeSize;
 | |
|     }
 | |
|   } else {
 | |
|     if ($cell.index() < $cell.parent.childCount - 1)
 | |
|       return $cell.pos + $cell.nodeAfter.nodeSize;
 | |
|     const table = $cell.node(-1);
 | |
|     for (let row = $cell.indexAfter(-1), rowStart = $cell.after(); row < table.childCount; row++) {
 | |
|       const rowNode = table.child(row);
 | |
|       if (rowNode.childCount)
 | |
|         return rowStart + 1;
 | |
|       rowStart += rowNode.nodeSize;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| function goToNextCell(direction) {
 | |
|   return function(state, dispatch) {
 | |
|     if (!isInTable(state))
 | |
|       return false;
 | |
|     const cell = findNextCell(selectionCell(state), direction);
 | |
|     if (cell == null)
 | |
|       return false;
 | |
|     if (dispatch) {
 | |
|       const $cell = state.doc.resolve(cell);
 | |
|       dispatch(
 | |
|         state.tr.setSelection(import_prosemirror_state6.TextSelection.between($cell, moveCellForward($cell))).scrollIntoView()
 | |
|       );
 | |
|     }
 | |
|     return true;
 | |
|   };
 | |
| }
 | |
| function deleteTable(state, dispatch) {
 | |
|   const $pos = state.selection.$anchor;
 | |
|   for (let d = $pos.depth; d > 0; d--) {
 | |
|     const node = $pos.node(d);
 | |
|     if (node.type.spec.tableRole == "table") {
 | |
|       if (dispatch)
 | |
|         dispatch(
 | |
|           state.tr.delete($pos.before(d), $pos.after(d)).scrollIntoView()
 | |
|         );
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // src/index.ts
 | |
| function tableEditing({
 | |
|   allowTableNodeSelection = false
 | |
| } = {}) {
 | |
|   return new import_prosemirror_state7.Plugin({
 | |
|     key: tableEditingKey,
 | |
|     state: {
 | |
|       init() {
 | |
|         return null;
 | |
|       },
 | |
|       apply(tr, cur) {
 | |
|         const set = tr.getMeta(tableEditingKey);
 | |
|         if (set != null)
 | |
|           return set == -1 ? null : set;
 | |
|         if (cur == null || !tr.docChanged)
 | |
|           return cur;
 | |
|         const { deleted, pos } = tr.mapping.mapResult(cur);
 | |
|         return deleted ? null : pos;
 | |
|       }
 | |
|     },
 | |
|     props: {
 | |
|       decorations: drawCellSelection,
 | |
|       handleDOMEvents: {
 | |
|         mousedown: handleMouseDown
 | |
|       },
 | |
|       createSelectionBetween(view) {
 | |
|         if (tableEditingKey.getState(view.state) != null)
 | |
|           return view.state.selection;
 | |
|       },
 | |
|       handleTripleClick,
 | |
|       handleKeyDown,
 | |
|       handlePaste
 | |
|     },
 | |
|     appendTransaction(_, oldState, state) {
 | |
|       return normalizeSelection(
 | |
|         state,
 | |
|         fixTables(state, oldState),
 | |
|         allowTableNodeSelection
 | |
|       );
 | |
|     }
 | |
|   });
 | |
| }
 | |
| // Annotate the CommonJS export names for ESM import in node:
 | |
| 0 && (module.exports = {
 | |
|   CellBookmark,
 | |
|   CellSelection,
 | |
|   ResizeState,
 | |
|   TableMap,
 | |
|   TableView,
 | |
|   __clipCells,
 | |
|   __insertCells,
 | |
|   __pastedCells,
 | |
|   addColSpan,
 | |
|   addColumn,
 | |
|   addColumnAfter,
 | |
|   addColumnBefore,
 | |
|   addRow,
 | |
|   addRowAfter,
 | |
|   addRowBefore,
 | |
|   cellAround,
 | |
|   colCount,
 | |
|   columnIsHeader,
 | |
|   columnResizing,
 | |
|   columnResizingPluginKey,
 | |
|   deleteColumn,
 | |
|   deleteRow,
 | |
|   deleteTable,
 | |
|   findCell,
 | |
|   fixTables,
 | |
|   fixTablesKey,
 | |
|   goToNextCell,
 | |
|   handlePaste,
 | |
|   inSameTable,
 | |
|   isInTable,
 | |
|   mergeCells,
 | |
|   moveCellForward,
 | |
|   nextCell,
 | |
|   pointsAtCell,
 | |
|   removeColSpan,
 | |
|   removeColumn,
 | |
|   removeRow,
 | |
|   rowIsHeader,
 | |
|   selectedRect,
 | |
|   selectionCell,
 | |
|   setCellAttr,
 | |
|   splitCell,
 | |
|   splitCellWithType,
 | |
|   tableEditing,
 | |
|   tableEditingKey,
 | |
|   tableNodeTypes,
 | |
|   tableNodes,
 | |
|   toggleHeader,
 | |
|   toggleHeaderCell,
 | |
|   toggleHeaderColumn,
 | |
|   toggleHeaderRow,
 | |
|   updateColumnsOnResize
 | |
| });
 |