123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493 |
- "use strict";
- 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_model = require("prosemirror-model");
- var import_prosemirror_state2 = require("prosemirror-state");
- var import_prosemirror_view = require("prosemirror-view");
- // 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;
- }
- // Find the dimensions of the cell at the given position.
- 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;
- const top = i / this.width | 0;
- let right = left + 1;
- let 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`);
- }
- // Find the left side of the cell at the given position.
- 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`);
- }
- // Find the next cell in the given direction, starting from the cell
- // at `pos`, if any.
- 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)];
- }
- }
- // Get the rectangle spanning the two given cells.
- 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)
- };
- }
- // Return the position of all cells that have the top left corner in
- // the given rectangle.
- cellsInRect(rect) {
- const result = [];
- const 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;
- const 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) {
- continue;
- }
- result.push(pos);
- }
- }
- return result;
- }
- // Return the position at which the cell at the given row and column
- // starts, or would start, if a cell started there.
- 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;
- }
- }
- // Find the table map for the given table node.
- 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;
- let 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 = [];
- const seen = {};
- for (let i = 0; i < map.map.length; i++) {
- const pos = map.map[i];
- if (seen[pos])
- continue;
- seen[pos] = true;
- const node = table.nodeAt(pos);
- if (!node) {
- throw new RangeError(`No cell with offset ${pos} found`);
- }
- let updated = null;
- const attrs = node.attrs;
- for (let j = 0; j < attrs.colspan; j++) {
- const col = (i + j) % map.width;
- const colWidth = colWidths[col * 2];
- if (colWidth != null && (!attrs.colwidth || attrs.colwidth[j] != colWidth))
- (updated || (updated = freshColWidth(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/util.ts
- var import_prosemirror_state = require("prosemirror-state");
- // 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;
- }
- const $cell = cellAround(sel.$head) || cellNear(sel.$head);
- if ($cell) {
- return $cell;
- }
- throw new RangeError(`No cell found around position ${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($cellA, $cellB) {
- return $cellA.depth == $cellB.depth && $cellA.pos >= $cellB.start(-1) && $cellA.pos <= $cellB.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 table = $pos.node(-1);
- const map = TableMap.get(table);
- const tableStart = $pos.start(-1);
- const moved = map.nextCell($pos.pos - tableStart, axis, dir);
- return moved == null ? null : $pos.node(0).resolve(tableStart + moved);
- }
- function removeColSpan(attrs, pos, n = 1) {
- const result = { ...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 = { ...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 _CellSelection extends import_prosemirror_state2.Selection {
- // A table selection is identified by its anchor and head cells. The
- // positions given to this constructor should point _before_ two
- // cells in the same table. They may be the same, to select a single
- // cell.
- constructor($anchorCell, $headCell = $anchorCell) {
- const table = $anchorCell.node(-1);
- const map = TableMap.get(table);
- const tableStart = $anchorCell.start(-1);
- const rect = map.rectBetween(
- $anchorCell.pos - tableStart,
- $headCell.pos - tableStart
- );
- const doc = $anchorCell.node(0);
- const cells = map.cellsInRect(rect).filter((p) => p != $headCell.pos - tableStart);
- cells.unshift($headCell.pos - tableStart);
- const ranges = cells.map((pos) => {
- const cell = table.nodeAt(pos);
- if (!cell) {
- throw RangeError(`No cell with offset ${pos} found`);
- }
- const from = tableStart + pos + 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);
- }
- // Returns a rectangular slice of table rows containing the selected
- // cells.
- content() {
- const table = this.$anchorCell.node(-1);
- const map = TableMap.get(table);
- const tableStart = this.$anchorCell.start(-1);
- const rect = map.rectBetween(
- this.$anchorCell.pos - tableStart,
- this.$headCell.pos - tableStart
- );
- const seen = {};
- const 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])
- continue;
- seen[pos] = true;
- const cellRect = map.findCell(pos);
- let cell = table.nodeAt(pos);
- if (!cell) {
- throw RangeError(`No cell with offset ${pos} found`);
- }
- const extraLeft = rect.left - cellRect.left;
- const 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);
- if (!cell) {
- throw RangeError(
- `Could not create cell with attrs ${JSON.stringify(attrs)}`
- );
- }
- } else {
- cell = cell.type.create(attrs, cell.content);
- }
- }
- if (cellRect.top < rect.top || cellRect.bottom > rect.bottom) {
- const attrs = {
- ...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);
- const map = TableMap.get(table);
- const tableStart = this.$anchorCell.start(-1);
- const cells = map.cellsInRect(
- map.rectBetween(
- this.$anchorCell.pos - tableStart,
- this.$headCell.pos - tableStart
- )
- );
- for (let i = 0; i < cells.length; i++) {
- f(table.nodeAt(cells[i]), tableStart + cells[i]);
- }
- }
- // True if this selection goes all the way from the top to the
- // bottom of the table.
- isColSelection() {
- const anchorTop = this.$anchorCell.index(-1);
- const headTop = this.$headCell.index(-1);
- if (Math.min(anchorTop, headTop) > 0)
- return false;
- const anchorBottom = anchorTop + this.$anchorCell.nodeAfter.attrs.rowspan;
- const headBottom = headTop + this.$headCell.nodeAfter.attrs.rowspan;
- return Math.max(anchorBottom, headBottom) == this.$headCell.node(-1).childCount;
- }
- // Returns the smallest column selection that covers the given anchor
- // and head cell.
- static colSelection($anchorCell, $headCell = $anchorCell) {
- const table = $anchorCell.node(-1);
- const map = TableMap.get(table);
- const tableStart = $anchorCell.start(-1);
- const anchorRect = map.findCell($anchorCell.pos - tableStart);
- const headRect = map.findCell($headCell.pos - tableStart);
- const doc = $anchorCell.node(0);
- if (anchorRect.top <= headRect.top) {
- if (anchorRect.top > 0)
- $anchorCell = doc.resolve(tableStart + map.map[anchorRect.left]);
- if (headRect.bottom < map.height)
- $headCell = doc.resolve(
- tableStart + map.map[map.width * (map.height - 1) + headRect.right - 1]
- );
- } else {
- if (headRect.top > 0)
- $headCell = doc.resolve(tableStart + map.map[headRect.left]);
- if (anchorRect.bottom < map.height)
- $anchorCell = doc.resolve(
- tableStart + map.map[map.width * (map.height - 1) + anchorRect.right - 1]
- );
- }
- return new _CellSelection($anchorCell, $headCell);
- }
- // True if this selection goes all the way from the left to the
- // right of the table.
- isRowSelection() {
- const table = this.$anchorCell.node(-1);
- const map = TableMap.get(table);
- const tableStart = this.$anchorCell.start(-1);
- const anchorLeft = map.colCount(this.$anchorCell.pos - tableStart);
- const headLeft = map.colCount(this.$headCell.pos - tableStart);
- if (Math.min(anchorLeft, headLeft) > 0)
- return false;
- const anchorRight = anchorLeft + this.$anchorCell.nodeAfter.attrs.colspan;
- const 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;
- }
- // Returns the smallest row selection that covers the given anchor
- // and head cell.
- static rowSelection($anchorCell, $headCell = $anchorCell) {
- const table = $anchorCell.node(-1);
- const map = TableMap.get(table);
- const tableStart = $anchorCell.start(-1);
- const anchorRect = map.findCell($anchorCell.pos - tableStart);
- const headRect = map.findCell($headCell.pos - tableStart);
- const doc = $anchorCell.node(0);
- if (anchorRect.left <= headRect.left) {
- if (anchorRect.left > 0)
- $anchorCell = doc.resolve(
- tableStart + map.map[anchorRect.top * map.width]
- );
- if (headRect.right < map.width)
- $headCell = doc.resolve(
- tableStart + map.map[map.width * (headRect.top + 1) - 1]
- );
- } else {
- if (headRect.left > 0)
- $headCell = doc.resolve(tableStart + map.map[headRect.top * map.width]);
- if (anchorRect.right < map.width)
- $anchorCell = doc.resolve(
- tableStart + 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 _CellBookmark {
- 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;
- let beforeTo = $to.pos;
- let 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);
- const 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);
- if (!cell)
- continue;
- const attrs = cell.attrs;
- for (let j = 0; j < attrs.rowspan; j++)
- mustAdd[prob.row + j] += prob.n;
- tr.setNodeMarkup(
- tr.mapping.map(tablePos + 1 + prob.pos),
- null,
- removeColSpan(attrs, 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);
- if (!cell)
- continue;
- tr.setNodeMarkup(tr.mapping.map(tablePos + 1 + prob.pos), null, {
- ...cell.attrs,
- rowspan: cell.attrs.rowspan - prob.n
- });
- } else if (prob.type == "colwidth mismatch") {
- const cell = table.nodeAt(prob.pos);
- if (!cell)
- continue;
- tr.setNodeMarkup(tr.mapping.map(tablePos + 1 + prob.pos), null, {
- ...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 role = "cell";
- if (row.firstChild) {
- role = row.firstChild.type.spec.tableRole;
- }
- const nodes = [];
- for (let j = 0; j < add; j++) {
- const node = tableNodeTypes(state.schema)[role].createAndFill();
- if (node)
- nodes.push(node);
- }
- 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.child(0).type.spec.tableRole == "table")) {
- openStart--;
- openEnd--;
- content = content.child(0).content;
- }
- const first = content.child(0);
- const 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();
- const 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 = [];
- const 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.createChecked(
- 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(
- {
- ...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, {
- ...cell.attrs,
- rowspan: top - cellTop
- });
- tr.insert(
- tr.mapping.slice(mapFrom).map(map.positionAt(top, cellLeft, table)),
- cell.type.createAndFill({
- ...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);
- const 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;
- if (!table) {
- throw new Error("No table found");
- }
- let 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;
- if (!table) {
- throw new Error("No table found");
- }
- 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) => {
- if (!view)
- return false;
- 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) => {
- if (!view)
- return false;
- 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;
- const 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);
- const 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);
- const 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) {
- var _a;
- 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 && ((_a = cellUnderMouse(view, startEvent)) == null ? void 0 : _a.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 event = _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;
- }
- }
- return null;
- }
- 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) {
- var _a;
- let totalWidth = 0;
- let fixedWidth = true;
- let nextDOM = colgroup.firstChild;
- const row = node.firstChild;
- if (!row)
- return;
- 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;
- (_a = nextDOM.parentNode) == null ? void 0 : _a.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) {
- plugin.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 && pluginState.activeHandle > -1 ? { class: "resize-cursor" } : {};
- },
- 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 && pluginState.activeHandle > -1) {
- return handleDecorations(state, pluginState.activeHandle);
- }
- },
- nodeViews: {}
- }
- });
- return plugin;
- }
- var ResizeState = class _ResizeState {
- constructor(activeHandle, dragging) {
- this.activeHandle = activeHandle;
- this.dragging = dragging;
- }
- apply(tr) {
- const state = this;
- const action = tr.getMeta(columnResizingPluginKey);
- if (action && action.setHandle != null)
- return new _ResizeState(action.setHandle, false);
- 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 = -1;
- }
- return new _ResizeState(handle, state.dragging);
- }
- return state;
- }
- };
- function handleMouseMove(view, event, handleWidth, cellMinWidth, lastColumnResizable) {
- const pluginState = columnResizingPluginKey.getState(view.state);
- if (!pluginState)
- return;
- 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", handleWidth);
- else if (right - event.clientX <= handleWidth)
- cell = edgeCell(view, event, "right", handleWidth);
- }
- if (cell != pluginState.activeHandle) {
- if (!lastColumnResizable && cell !== -1) {
- const $cell = view.state.doc.resolve(cell);
- const table = $cell.node(-1);
- const map = TableMap.get(table);
- const tableStart = $cell.start(-1);
- const col = map.colCount($cell.pos - tableStart) + $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 && pluginState.activeHandle > -1 && !pluginState.dragging)
- updateHandle(view, -1);
- }
- function handleMouseDown2(view, event, cellMinWidth) {
- const pluginState = columnResizingPluginKey.getState(view.state);
- if (!pluginState || 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 == null ? void 0 : 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)
- return;
- 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, handleWidth) {
- const offset = side == "right" ? -handleWidth : handleWidth;
- const found = view.posAtCoords({
- left: event.clientX + offset,
- 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];
- const attrs = table.nodeAt(pos).attrs;
- 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, { ...attrs, 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 && dom.nodeName != "TABLE") {
- dom = dom.parentNode;
- }
- if (!dom)
- return;
- updateColumnsOnResize(
- table,
- dom.firstChild,
- dom,
- cellMinWidth,
- col,
- width
- );
- }
- function zeroes(n) {
- return Array(n).fill(0);
- }
- 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] != map.map[index - 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_model4 = require("prosemirror-model");
- var import_prosemirror_state6 = require("prosemirror-state");
- function selectedRect(state) {
- const sel = state.selection;
- const $pos = selectionCell(state);
- const table = $pos.node(-1);
- const tableStart = $pos.start(-1);
- const map = TableMap.get(table);
- const rect = sel instanceof CellSelection ? map.rectBetween(
- sel.$anchorCell.pos - tableStart,
- sel.$headCell.pos - tableStart
- ) : map.findCell($pos.pos - tableStart);
- return { ...rect, tableStart, map, table };
- }
- 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];
- const 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;
- const pos = map.map[index];
- const cell = table.nodeAt(pos);
- const attrs = cell.attrs;
- 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(attrs, col - map.colCount(pos))
- );
- } else {
- const start = tr.mapping.slice(mapStart).map(tableStart + pos);
- tr.delete(start, start + cell.nodeSize);
- }
- row += attrs.rowspan;
- }
- }
- function deleteColumn(state, dispatch) {
- if (!isInTable(state))
- return false;
- if (dispatch) {
- const rect = selectedRect(state);
- const 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;
- const table = rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc;
- if (!table) {
- throw RangeError("No table found");
- }
- rect.table = table;
- rect.map = TableMap.get(table);
- }
- dispatch(tr);
- }
- return true;
- }
- function rowIsHeader(map, table, row) {
- var _a;
- const headerCell = tableNodeTypes(table.type.schema).header_cell;
- for (let col = 0; col < map.width; col++)
- if (((_a = table.nodeAt(map.map[col + row * map.width])) == null ? void 0 : _a.type) != headerCell)
- return false;
- return true;
- }
- function addRow(tr, { map, tableStart, table }, row) {
- var _a;
- 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];
- const attrs = table.nodeAt(pos).attrs;
- tr.setNodeMarkup(tableStart + pos, null, {
- ...attrs,
- rowspan: attrs.rowspan + 1
- });
- col += attrs.colspan - 1;
- } else {
- const type = refRow == null ? tableNodeTypes(table.type.schema).cell : (_a = table.nodeAt(map.map[index + refRow * map.width])) == null ? void 0 : _a.type;
- const node = type == null ? void 0 : type.createAndFill();
- if (node)
- cells.push(node);
- }
- }
- 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);
- const seen = /* @__PURE__ */ new Set();
- for (let col = 0, index = row * map.width; col < map.width; col++, index++) {
- const pos = map.map[index];
- if (seen.has(pos))
- continue;
- seen.add(pos);
- 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, {
- ...attrs,
- rowspan: attrs.rowspan - 1
- });
- col += attrs.colspan - 1;
- } else if (row < map.height && pos == map.map[index + map.width]) {
- const cell = table.nodeAt(pos);
- const attrs = cell.attrs;
- const copy = cell.type.create(
- { ...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 += 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;
- const table = rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc;
- if (!table) {
- throw RangeError("No table found");
- }
- rect.table = table;
- rect.map = TableMap.get(rect.table);
- }
- dispatch(tr);
- }
- return true;
- }
- function isEmpty(cell) {
- const c = cell.content;
- return c.childCount == 1 && c.child(0).isTextblock && c.child(0).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];
- const cell = rect.table.nodeAt(cellPos);
- if (seen[cellPos] || !cell)
- 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);
- }
- }
- }
- if (mergedPos == null || mergedCell == null) {
- return true;
- }
- tr.setNodeMarkup(mergedPos + rect.tableStart, null, {
- ...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) => {
- var _a;
- const sel = state.selection;
- let cellNode;
- let cellPos;
- if (!(sel instanceof CellSelection)) {
- cellNode = cellWrapping(sel.$from);
- if (!cellNode)
- return false;
- cellPos = (_a = cellAround(sel.$from)) == null ? void 0 : _a.pos;
- } else {
- if (sel.$anchorCell.pos != sel.$headCell.pos)
- return false;
- cellNode = sel.$anchorCell.nodeAfter;
- cellPos = sel.$anchorCell.pos;
- }
- if (cellNode == null || cellPos == null) {
- return false;
- }
- 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 = { ...baseAttrs, rowspan: 1 };
- if (baseAttrs.colspan > 1)
- baseAttrs = { ...baseAttrs, colspan: 1 };
- const rect = selectedRect(state), tr = state.tr;
- for (let i = 0; i < rect.right - rect.left; i++)
- attrs.push(
- colwidth ? {
- ...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) : void 0
- )
- );
- 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, {
- ...node.attrs,
- [name]: value
- });
- });
- else
- tr.setNodeMarkup($cell.pos, null, {
- ...$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);
- const lastChild = rowNode.lastChild;
- if (lastChild) {
- return rowEnd - 1 - 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;
- }
- }
- return null;
- }
- 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,
- // This piece of state is used to remember when a mouse-drag
- // cell-selection is happening, so that it can continue even as
- // transactions (which might move its anchor cell) come in.
- 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) {
- return tableEditingKey.getState(view.state) != null ? view.state.selection : null;
- },
- 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
- });
|