docxml
Version:
TypeScript (component) library for building and parsing a DOCX file
131 lines (130 loc) • 5.51 kB
TypeScript
import { type DocumentXml } from '../files/DocumentXml.js';
import { type FooterXml, type HeaderXml } from '../files/HeaderFooterXml.js';
import { type RelationshipsXml } from '../files/RelationshipsXml.js';
import { Archive } from './Archive.js';
/**
* An ancestor of a component at serialization time, or the {@link DocumentXml} instance that is the
* parent of the top-most component.
*
* Having this ancestry allows context-aware serialization.
*/
export declare type ComponentAncestor = DocumentXml | HeaderXml | FooterXml | AnyComponent;
/**
* Any component instance, uncaring of which one or which props/children it has. Knows nothing,
* assumes everything.
*/
export declare type AnyComponent = Component<{
[key: string]: unknown;
}, AnyComponent | string>;
/**
* Utility type to retrieve the prop types of an Component
*/
export declare type ComponentProps<ComponentGeneric extends Component | unknown> = ComponentGeneric extends Component<infer P, any> ? P : {
[key: string]: never;
};
/**
* Utility type to retrieve the children types of an Component
*/
export declare type ComponentChild<ComponentGeneric extends Component | unknown> = ComponentGeneric extends Component<any, infer C> ? C : never;
/**
* Contains references to things that ancestor nodes might want to communicate to their children.
*
* When you are a node inside another node you are within it's "context". You are also within the
* "context" of all ancestor nodes. Nodes can block, change or pass context through so children see
* the context the way the nearest ancestor decides.
*/
export declare type ComponentContext = {
/** The Archive that nodes in this context can read from. */
archive: Archive;
/** Relationships that the nodes in this context can reference. */
relationships: RelationshipsXml | null;
};
/**
* A secret property with which we can test wether or not a Class (or "Function" in JS land)
* extends from Component
*/
declare const IS_COMPONENT: unique symbol;
/**
* The interface to which a class definition of an XML component must adhere -- ie.
* it must have a `children` and `mixed` static properties.
*/
export interface ComponentDefinition<C extends AnyComponent | unknown = AnyComponent> {
new (props: ComponentProps<C>, ...children: ComponentChild<C>[]): C;
children: string[];
mixed: boolean;
matchesNode(node: Node): boolean;
fromNode(node: Node, context: ComponentContext): null | C;
[IS_COMPONENT]: true;
}
/**
* A custom function which which native components can be composed into something more easily
* reusable.
*/
export declare type ComponentFunction<PropsGeneric extends {
[key: string]: unknown;
} = {
[key: string]: never;
}, ChildGeneric extends AnyComponent | string = never> = (props: PropsGeneric & {
children?: ChildGeneric | ChildGeneric[];
}) => AnyComponent;
/**
* A component serializes to a string, or to an XML DOM node.
*/
declare type ComponentNode = string | Node;
/**
* A component may serialize to one string/node, or multiple.
*/
export declare type ComponentNodes = ComponentNode | ComponentNode[];
export declare function isComponentDefinition(Def: ComponentDefinition | any): Def is ComponentDefinition;
export declare abstract class Component<PropsGeneric extends {
[key: string]: unknown;
} = {
[key: string]: never;
}, ChildGeneric extends AnyComponent | string = never> {
static [IS_COMPONENT]: 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.
*/
static readonly children: string[];
/**
* 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.
*/
static readonly mixed: boolean;
/**
* The props given to this component instance.
*/
readonly props: PropsGeneric;
/**
* The children given to this component instance.
*/
readonly children: ChildGeneric[];
constructor(props: PropsGeneric, ...children: ChildGeneric[]);
/**
* 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: RelationshipsXml): void;
static matchesNode(_node: Node): boolean;
static fromNode(_node: Node, _context: ComponentContext): null | AnyComponent;
protected childrenToNode(ancestry: Array<ComponentAncestor>): Promise<ComponentNode[]>;
/**
* 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: Array<ComponentAncestor>): ComponentNodes | Promise<ComponentNodes>;
}
export {};