UNPKG

docxml

Version:

TypeScript (component) library for building and parsing a DOCX file

91 lines (90 loc) 4.43 kB
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _TableGridModel_instances, _TableGridModel_occupancy, _TableGridModel_info, _TableGridModel_getFirstAvailableColumnOnRow; function coord(x, y) { return `${x},${y}`; } /** * A conceptual description of the table that makes it easier to reason about it. */ export class TableGridModel { constructor(table) { _TableGridModel_instances.add(this); /** * A map of which col/row coordinates are filled by a cell. */ _TableGridModel_occupancy.set(this, new Map()); /** * The coordinate and size information about a cell. */ _TableGridModel_info.set(this, new Map()); table.children.forEach((row, rowIndex) => { row.children.forEach((cell) => { const colIndex = __classPrivateFieldGet(this, _TableGridModel_instances, "m", _TableGridModel_getFirstAvailableColumnOnRow).call(this, rowIndex); for (let y = rowIndex; y < rowIndex + cell.getRowSpan(); y++) { for (let x = colIndex; x < colIndex + cell.getColSpan(); x++) { const key = coord(x, y); if (__classPrivateFieldGet(this, _TableGridModel_occupancy, "f").has(key)) { // This should never happen so long as the colspans/rowspans make sense. throw new Error(`Cell ${x},${y} already occupied.`); } __classPrivateFieldGet(this, _TableGridModel_occupancy, "f").set(key, cell); } } if (!__classPrivateFieldGet(this, _TableGridModel_info, "f").has(cell)) { __classPrivateFieldGet(this, _TableGridModel_info, "f").set(cell, { row: rowIndex, column: colIndex, rowspan: cell.getRowSpan(), colspan: cell.getColSpan(), }); } }); }); } /** * Return the <td> node belonging to this column/row coordinate, taking all colspans/rowspans * into account. */ getNodeAtCell(column, row) { return __classPrivateFieldGet(this, _TableGridModel_occupancy, "f").get(coord(column, row)) || null; } /** * Get the number of columns in a row, even if some cells span multiple columns. */ getCellsInRow(row) { // TODO could be simplified if we knew the table is rectangular return (Array.from(__classPrivateFieldGet(this, _TableGridModel_occupancy, "f").keys()) .filter((key) => key.endsWith(`,${row}`)) .map((key) => key.split(',').map((n) => parseInt(n, 10))) .sort((a, b) => a[0] - b[0]) // TODO take into accoutn the edge case that .getNodeAtCell returns null .map(([x, y]) => this.getNodeAtCell(x, y))); } /** * Return the position and spanning of a given <td> node, keeping all colspans/rowspans of other * cels into account. */ getCellInfo(cell) { const info = __classPrivateFieldGet(this, _TableGridModel_info, "f").get(cell); if (!info) { throw new Error(`The given cell does not exist in this table`); } return info; } } _TableGridModel_occupancy = new WeakMap(), _TableGridModel_info = new WeakMap(), _TableGridModel_instances = new WeakSet(), _TableGridModel_getFirstAvailableColumnOnRow = function _TableGridModel_getFirstAvailableColumnOnRow(y) { const columnsOccupied = Array.from(__classPrivateFieldGet(this, _TableGridModel_occupancy, "f").keys()) .filter((key) => key.endsWith(`,${y}`)) .map((key) => parseInt(key.split(',')[0], 10)) .sort((a, b) => a - b); for (let i = 0; i < columnsOccupied.length; i++) { if (i !== columnsOccupied[i]) { return i; } } return columnsOccupied.length; };