docxml
Version:
TypeScript (component) library for building and parsing a DOCX file
102 lines (101 loc) • 3.16 kB
JavaScript
// 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 './Break.js';
import './FieldRangeEnd.js';
import './FieldRangeInstruction.js';
import './FieldRangeSeparator.js';
import './FieldRangeStart.js';
import './Image.js';
import './NonBreakingHyphen.js';
import './Symbol.js';
import './Tab.js';
import { Component } from '../classes/Component.js';
import { textPropertiesFromNode, textPropertiesToNode, } from '../properties/text-properties.js';
import { createChildComponentsFromNodes, registerComponent } from '../utilities/components.js';
import { create } from '../utilities/dom.js';
import { QNS } from '../utilities/namespaces.js';
import { evaluateXPathToMap } from '../utilities/xquery.js';
import { TextDeletion } from './TextDeletion.js';
/**
* A component that represents text. All inline formatting options, such as bold/italic/underline,
* are in fact different props or styles on the `<Text>` component.
*/
export class Text extends Component {
/**
* Creates an XML DOM node for this component instance.
*/
async toNode(ancestry) {
const asTextDeletion = ancestry.some((ancestor) => ancestor instanceof TextDeletion);
const anc = [this, ...ancestry];
return create(`
element ${QNS.w}r {
$rpr,
$children
}
`, {
rpr: textPropertiesToNode(this.props),
children: await Promise.all(this.children.map((child) => {
if (typeof child === 'string') {
return create(`element ${QNS.w}${asTextDeletion ? 'delText' : 't'} {
attribute xml:space { "preserve" },
$text
}`, {
text: child,
});
}
return child.toNode(anc);
})),
});
}
/**
* Asserts whether or not a given XML node correlates with this component.
*/
static matchesNode(node) {
return node.nodeName === 'w:r';
}
/**
* Instantiate this component from the XML in an existing DOCX file.
*/
static fromNode(node, context) {
const { children, rpr } = evaluateXPathToMap(`
map {
"rpr": ./${QNS.w}rPr,
"children": array{
./(
${QNS.w}br,
${QNS.w}tab,
${QNS.w}drawing,
${QNS.w}t/text(),
${QNS.w}delText/text(),
${QNS.w}fldChar,
${QNS.w}instrText
)
}
}
`, node);
return new Text(textPropertiesFromNode(rpr), ...createChildComponentsFromNodes(this.children, children, context));
}
}
Object.defineProperty(Text, "children", {
enumerable: true,
configurable: true,
writable: true,
value: [
'Break',
'FieldRangeEnd',
'FieldRangeInstruction',
'FieldRangeSeparator',
'FieldRangeStart',
'Image',
'NonBreakingHyphen',
'Symbol',
'Tab',
]
});
Object.defineProperty(Text, "mixed", {
enumerable: true,
configurable: true,
writable: true,
value: true
});
registerComponent(Text);