docxml
Version:
TypeScript (component) library for building and parsing a DOCX file
80 lines (79 loc) • 3.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.jsx = void 0;
const Component_js_1 = require("../classes/Component.js");
const Text_js_1 = require("../components/Text.js");
/**
* The JSX pragma with which you can write `<Paragraph>` instead of `new Paragraph({})`.
*
* Also exposed as the `jsx` prop on the (static) class as well as instance of this library's top-
* level API -- see also {@link Api}.
*/
async function jsx(component, props, ...children) {
const flattenedChildren = await children
// Flatten the children, which may themselves have been wrapped in an array because they
// contained invalid children.
// Moreover, any component might at this point still be only the promise thereof. Resolve all.
.reduce(async function flatten(flatPromise, childPromise) {
const child = await childPromise;
const flat = await flatPromise;
return Array.isArray(child)
? [...flat, ...(await child.reduce(flatten, Promise.resolve([])))]
: [...flat, child];
}, Promise.resolve([]));
return (flattenedChildren
// Add the node, if it is valid, or add the node split into pieces with the invalid children
// vertically inserted between
.reduce((nodes, child) => {
if (typeof child === 'string' && (0, Component_js_1.isComponentDefinition)(component) && !component.mixed) {
child = new Text_js_1.Text({}, child);
}
const isValid = !(0, Component_js_1.isComponentDefinition)(component) ||
(component.mixed && typeof child === 'string') ||
component.children.includes(child.constructor.name);
if (!isValid) {
if (child.constructor === Text_js_1.Text && component === Text_js_1.Text) {
Object.assign(child.props, props);
}
nodes.push(child);
}
else {
const lastQueuedItem = nodes[nodes.length - 1];
if (typeof lastQueuedItem === 'string' || lastQueuedItem instanceof Component_js_1.Component) {
// Queue this item as a simple object, so that its children can be changed
// in the next iteration.
nodes.push({
component,
props,
children: [child],
});
}
else {
lastQueuedItem.children.push(child);
}
}
return nodes;
}, [{ component, props, children: [] }])
// Instantiate the "queued" items (props/children that haven't been instantiated yet so that
// their children could be shuffled around).
.map((node) => {
if (typeof node === 'string') {
return node;
}
if (node instanceof Component_js_1.Component) {
return node;
}
if ((0, Component_js_1.isComponentDefinition)(component)) {
return new component(node.props || {}, ...(node.children || []));
}
else {
const x = component({ ...props, children: node.children || [] });
return x;
}
})
// Flatten again, no telling what came out of a ComponentFunction
.reduce((flat, thing) => (Array.isArray(thing) ? [...flat, ...thing] : [...flat, thing]), [])
// Remove empty Text components, they don't do anything
.filter((node) => !(node.constructor === Text_js_1.Text && !node.children.length)));
}
exports.jsx = jsx;