docxml
Version:
TypeScript (component) library for building and parsing a DOCX file
100 lines (99 loc) • 3.33 kB
JavaScript
var _a;
/**
* A secret property with which we can test wether or not a Class (or "Function" in JS land)
* extends from Component
*/
const IS_COMPONENT = Symbol();
// deno-lint-ignore no-explicit-any
export function isComponentDefinition(Def) {
return Def && typeof Def === 'function' && Def[IS_COMPONENT] === true;
}
export class Component {
constructor(props, ...children) {
/**
* The props given to this component instance.
*/
Object.defineProperty(this, "props", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
/**
* The children given to this component instance.
*/
Object.defineProperty(this, "children", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.props = props;
this.children = children;
}
/**
* An event hook with which this component can ensure that the correct relationship type is
* recorded to the relationship XML.
*
* For example;
*
* - Create a relationship to a {@link Hyperlink} external target
* - Create a relationship from the {@link Image} component to its image file binary.
*
* You'll want to use {@link RelationshipsXml} to create a relationship and store its
* identifier somewhere, before using it in {@link Component.toNode}.
*
* this.#relationshipId = relationships.add(RelationshipType.hyperlink, this.props.url);
*/
ensureRelationship(_relationships) {
// no-op
}
static matchesNode(_node) {
return false;
}
static fromNode(_node, _context) {
throw new Error('Not implemented');
}
async childrenToNode(ancestry) {
const anc = [this, ...ancestry];
const nodes = await Promise.all(this.children.map((child) => (typeof child === 'string' ? child : child.toNode(anc))));
return nodes.reduce((flat, s) => (Array.isArray(s) ? flat.concat(s) : [...flat, s]), []);
}
/**
* Create a DOM node for this XML component, one that can be stringified to schema-valid OOXML.
*
* By default, an XML component would serialize to its children and string contents -- like a
* fragment. Most components have an override to use specific OOXML elememnts, such as <w:p>.
*/
toNode(ancestry) {
return this.childrenToNode(ancestry);
}
}
_a = IS_COMPONENT;
// eslint-disable-next-line @typescript-eslint/prefer-as-const
Object.defineProperty(Component, _a, {
enumerable: true,
configurable: true,
writable: true,
value: true
});
/**
* Informs the JSX pragma which child components are allowed in this component.
* The JSX pragma can use this to attempt repairs at invalidly nested children.
*/
Object.defineProperty(Component, "children", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
/**
* Informs the JSX pragma on wether or not this component can contain text (string)
* children. The JSX pragma can use this to attempt repairs at invalidly nested children.
*/
Object.defineProperty(Component, "mixed", {
enumerable: true,
configurable: true,
writable: true,
value: false
});