UNPKG

docxml

Version:

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

96 lines (95 loc) 3.46 kB
// Import without assignment ensures Deno does not tree-shake this component. To avoid circular // definitions, components register themselves in a side-effect of their module. import './Row.js'; import './RowAddition.js'; import './RowDeletion.js'; import { checkForForbiddenParameters, isValidNumber } from '../utilities/parameter-checking.js'; import { Component } from '../classes/Component.js'; import { tablePropertiesFromNode, tablePropertiesToNode, } from '../properties/table-properties.js'; import { createChildComponentsFromNodes, registerComponent } from '../utilities/components.js'; import { create } from '../utilities/dom.js'; import { twip } from '../utilities/length.js'; import { QNS } from '../utilities/namespaces.js'; import { TableGridModel } from '../utilities/tables.js'; import { evaluateXPathToMap } from '../utilities/xquery.js'; /** * A component that represents a table. */ export class Table extends Component { constructor(tableProps, ...tableChildren) { checkForForbiddenParameters(tableProps, isValidNumber, true); super(tableProps, ...tableChildren); /** * A conceptual description of how the cells, columns, rows and spans of this table make sense. * * Exposed so it can be accessed by {@link Row} and {@link Cell} descendants, but not meant * to be used otherwise. */ Object.defineProperty(this, "model", { enumerable: true, configurable: true, writable: true, value: new TableGridModel(this) }); } /** * Creates an XML DOM node for this component instance. */ async toNode(ancestry) { const node = create(` element ${QNS.w}tbl { $tablePropertiesNode, if (exists($columnWidths)) then element ${QNS.w}tblGrid { for $columnWidth in array:flatten($columnWidths) return element ${QNS.w}gridCol { attribute ${QNS.w}w { $columnWidth } } } else (), $children } `, { tablePropertiesNode: tablePropertiesToNode(this.props), columnWidths: this.props.columnWidths?.length ? this.props.columnWidths.map((width) => Math.round(width.twip)) : null, children: await this.childrenToNode(ancestry), }); return node; } /** * Asserts whether or not a given XML node correlates with this component. */ static matchesNode(node) { return node.nodeName === 'w:tbl'; } /** * Instantiate this component from the XML in an existing DOCX file. */ static fromNode(node, context) { const { children, tblpr, ...props } = evaluateXPathToMap(` map { "tblpr": ./${QNS.w}tblPr, "columnWidths": array { ./${QNS.w}tblGrid/${QNS.w}gridCol/@${QNS.w}w/number() }, "children": array{ ./(${QNS.w}tr) } } `, node); return new Table({ columnWidths: props.columnWidths.map((size) => twip(size)), ...tablePropertiesFromNode(tblpr), }, ...createChildComponentsFromNodes(this.children, children, context)); } } Object.defineProperty(Table, "children", { enumerable: true, configurable: true, writable: true, value: ['Row', 'RowAddition', 'RowDeletion'] }); Object.defineProperty(Table, "mixed", { enumerable: true, configurable: true, writable: true, value: false }); registerComponent(Table);