/** * Namespace-aware XML parser and serializer for OOXML parts. * * Parses to a **mutable tree** that the higher layers treat as the single * source of truth (lens architecture): models read from and mutate this * tree in place, and the serializer writes it back out. Unknown elements * and attributes therefore survive round-trips automatically. * * Fidelity rules (see CONTRACTS.md §2): * - The XML declaration's version/encoding/standalone values are preserved * verbatim (except encoding is rewritten to "UTF-8" on serialize when the * input was not UTF-8, since the serializer always emits UTF-8). * - Attribute order and namespace declarations are preserved exactly; * xmlns/xmlns:* declarations are ordinary members of `attributes`. * - Text is stored fully decoded; the serializer applies standard escaping * (& < > in text plus CR as ; & < > " in attribute values plus * TAB/CR/LF as character references). * - CDATA stays CDATA; comments and processing instructions are preserved * in place, including in the document prolog/epilog. * - Line endings are normalized on input per XML 1.0 (\r\n and lone \r * become \n) — a CR that must survive round-trips is always written as * the character reference, which is exactly what Office does. * * Security (OOXML never needs more): * - Any DOCTYPE declaration is rejected with {@link XmlParseError}. * - Only the five built-in entities (amp, lt, gt, apos, quot) and numeric * character references are recognized; any other entity reference is a * parse error. * - Input encodings: UTF-8 (with or without BOM) and UTF-16 LE/BE with BOM. * - Characters outside the XML 1.0 Char production (controls below U+0020 * other than tab/LF/CR, unpaired surrogates, U+FFFE/U+FFFF) are rejected * both when parsed literally (matching the existing rejection of the * equivalent character references) and when serialized (they have no * well-formed representation; silently substituting U+FFFD or emitting * raw control bytes would corrupt the output). * * Performance notes: the parser is a single pass over the decoded string. * It tokenizes with `indexOf`/`charCodeAt` (no regular expressions), slices * text in bulk, and only walks character-by-character inside runs that * actually contain entities or carriage returns. Line/column information * for errors is computed lazily, only when an error is thrown. */ /** The implicit namespace bound to the `xml` prefix. */ export declare const XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"; /** The implicit namespace of xmlns/xmlns:* declarations themselves. */ export declare const XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"; /** Error thrown on malformed, unsupported, or forbidden (DOCTYPE) input. */ export declare class XmlParseError extends Error { /** Character offset into the decoded input where the error occurred. */ readonly offset: number; /** 1-based line number of the error. */ readonly line: number; /** 1-based column number of the error. */ readonly column: number; constructor(message: string, offset: number, line: number, column: number); } /** * The `` declaration, with attribute values stored verbatim as * written in the source (e.g. standalone: 'yes'). */ export interface XmlDeclaration { version: string; encoding: string | null; standalone: string | null; } /** One attribute: ordered position within the owner element is preserved. */ export interface XmlAttribute { /** Prefix before the colon, or null for unprefixed attributes. */ prefix: string | null; /** Local name (full name for unprefixed attributes). */ localName: string; /** Fully decoded value (entities and char refs resolved). */ value: string; } /** Any node that can appear in an element's `children`. */ export type XmlNode = XmlElement | XmlText | XmlCdata | XmlComment | XmlProcessingInstruction; /** Character data node. `text` is fully decoded. */ export declare class XmlText { readonly kind: "text"; text: string; /** @internal Maintained by tree mutation methods — do not assign. */ _parent: XmlElement | null; constructor(text: string); /** Owner element; maintained by tree mutation methods. */ get parent(): XmlElement | null; } /** * CDATA section. Serialized back as CDATA. For L1 comparison and for * `XmlElement.text()`, CDATA is equivalent to text. */ export declare class XmlCdata { readonly kind: "cdata"; text: string; /** @internal Maintained by tree mutation methods — do not assign. */ _parent: XmlElement | null; constructor(text: string); get parent(): XmlElement | null; } /** * Comment node; `text` is the content between ``. XML has no * escape for `--` inside a comment, so text containing `--` or ending with * `-` is rejected (here and again at serialization, since the field is * mutable). */ export declare class XmlComment { readonly kind: "comment"; text: string; /** @internal Maintained by tree mutation methods — do not assign. */ _parent: XmlElement | null; constructor(text: string); get parent(): XmlElement | null; } /** * Processing instruction node (``). The target must be a * valid name (no `?`), and the data must not contain `?>` (which would * terminate the PI early — there is no escape). Both are enforced here and * again at serialization. */ export declare class XmlProcessingInstruction { readonly kind: "pi"; target: string; data: string; /** @internal Maintained by tree mutation methods — do not assign. */ _parent: XmlElement | null; constructor(target: string, data: string); get parent(): XmlElement | null; } /** * Element node. The heart of the lens architecture: higher-level models * hold references to XmlElements and mutate them in place. * * Namespace model: xmlns declarations are stored as ordinary attributes * (order preserved); {@link XmlElement.namespaceUri} and * {@link XmlElement.resolvePrefix} compute in-scope resolution by walking * the parent chain. Parent links are maintained by the mutation methods — * nodes must be attached/detached only via appendChild/insertBefore/ * removeChild so that resolution stays correct. */ export declare class XmlElement { readonly kind: "element"; /** Namespace prefix, or null when unprefixed. */ prefix: string | null; /** Local name (after the colon). */ localName: string; /** @internal Maintained by tree mutation methods — do not assign. */ _parent: XmlElement | null; /** @internal Mutate only through the attribute methods. */ _attributes: XmlAttribute[]; /** @internal Mutate only through appendChild/insertBefore/removeChild. */ _children: XmlNode[]; /** * Create a detached element. `prefix` defaults to null. No namespace * declaration is added implicitly — callers declare xmlns attributes * explicitly (matching how OOXML parts declare everything on the root). */ constructor(localName: string, prefix?: string | null); /** Owner element, or null for a root/detached element. */ get parent(): XmlElement | null; /** Qualified name as written: `prefix:localName` or `localName`. */ get name(): string; /** Ordered attribute list, including xmlns/xmlns:* declarations. */ get attributes(): readonly XmlAttribute[]; /** Ordered child nodes. Mutate only via the methods below. */ get children(): readonly XmlNode[]; /** * Resolved namespace URI of this element (in-scope resolution of its * prefix, walking the parent chain), or null when unprefixed and no * default namespace is in scope. */ namespaceUri(): string | null; /** * Resolve a prefix against the namespace declarations in scope at this * element. `null` resolves the default namespace. Returns null when the * prefix is not bound (or was un-declared with an empty value). The * `xml` and `xmlns` prefixes resolve to their fixed URIs without * declarations. */ resolvePrefix(prefix: string | null): string | null; /** * Find a prefix bound to `namespaceUri` in scope at this element * (nearest non-shadowed declaration wins). Returns null when the default * namespace is bound to it, undefined when no in-scope binding exists. */ lookupPrefix(namespaceUri: string): string | null | undefined; /** * Return an in-scope, non-shadowed **prefix** bound to `namespaceUri`, * declaring a new `xmlns:*` attribute on this element when none exists. * Uses `preferred` when it is free; otherwise generates `ns1`, `ns2`, … * (The default namespace is never returned — attributes require a real * prefix; callers placing elements in a default namespace do not need * this helper.) */ ensurePrefix(namespaceUri: string, preferred?: string): string; /** * Attribute value by qualified name exactly as written (e.g. 'w:val' or * 'val'). Undefined when absent. */ getAttribute(qualifiedName: string): string | undefined; /** * Namespace-aware attribute lookup. Per XML-Namespaces, unprefixed * attributes are in **no** namespace: pass `namespaceUri === null` for * them. Prefixed attributes match when their prefix resolves (in scope) * to `namespaceUri`. Namespace declarations themselves live in * {@link XMLNS_NAMESPACE} (the default declaration under local name * 'xmlns'). */ getAttributeNs(namespaceUri: string | null, localName: string): string | undefined; /** * Set an attribute by qualified name: updates the existing attribute in * place (preserving its position) or appends a new one at the end. */ setAttribute(qualifiedName: string, value: string): void; /** * Namespace-aware set: updates the first attribute matching * (namespaceUri, localName) in place, or appends a new attribute using an * in-scope prefix for the namespace ({@link ensurePrefix} — a new * `xmlns:*` declaration is added on this element when needed). * `namespaceUri === null` writes an unprefixed attribute. */ setAttributeNs(namespaceUri: string | null, localName: string, value: string): void; /** Remove an attribute by qualified name; true when one was removed. */ removeAttribute(qualifiedName: string): boolean; /** Namespace-aware removal; true when a matching attribute was removed. */ removeAttributeNs(namespaceUri: string | null, localName: string): boolean; /** Child elements only, in document order. */ elements(): readonly XmlElement[]; /** * First child element matching (namespaceUri, localName), compared on * resolved namespace. `namespaceUri === null` matches elements in no * namespace. */ find(namespaceUri: string | null, localName: string): XmlElement | undefined; /** All child elements matching (namespaceUri, localName), in order. */ findAll(namespaceUri: string | null, localName: string): readonly XmlElement[]; /** Concatenated text of all descendant text and CDATA nodes, in order. */ text(): string; /** * The effective `xml:space` value at this element: the nearest * ancestor-or-self declaration of 'preserve' or 'default' wins; * null when none is in effect. */ xmlSpace(): 'preserve' | 'default' | null; /** True when `xml:space="preserve"` is in effect at this element. */ preservesSpace(): boolean; /** Append `node` as the last child; detaches it from any prior parent. */ appendChild(node: XmlNode): void; /** * Insert `node` immediately before `reference` (which must be a child of * this element; throws otherwise). `reference === null` appends. */ insertBefore(node: XmlNode, reference: XmlNode | null): void; /** Remove a direct child; true when it was found and removed. */ removeChild(node: XmlNode): boolean; /** Deep clone of this element; the clone is detached (parent null). */ clone(): XmlElement; /** @internal Guard against inserting an element into its own subtree. */ private assertInsertable; } /** * A parsed XML document: optional declaration, optional prolog/epilog misc * nodes (comments/PIs outside the root — rare in OOXML but preserved), and * exactly one root element. */ export declare class XmlDocument { /** Declaration, or null when the source had none. Preserved verbatim. */ declaration: XmlDeclaration | null; /** Comments/PIs before the root element, in order. */ prolog: readonly (XmlComment | XmlProcessingInstruction)[]; /** The single root element. */ root: XmlElement; /** Comments/PIs after the root element, in order. */ epilog: readonly (XmlComment | XmlProcessingInstruction)[]; constructor(root: XmlElement, declaration?: XmlDeclaration | null); } /** * Parse a complete XML document. * * `Uint8Array` input is decoded per its BOM (UTF-8 default; UTF-16 LE/BE * with BOM supported); string input is used as-is (a leading U+FEFF is * stripped). Throws {@link XmlParseError} on malformed input, on any * DOCTYPE, on undefined entity references, and on unsupported encodings. * The input bytes are never mutated. */ export declare function parseXml(input: Uint8Array | string): XmlDocument; /** * Escape text content: `&` `<` `>` plus CR as ` `. Throws `Error` on * characters outside the XML 1.0 Char production (controls below U+0020 * other than tab/LF/CR, unpaired surrogates, U+FFFE/U+FFFF) — such * characters have no representation in well-formed XML, not even as * character references, so emitting them would corrupt the output. */ export declare function escapeText(value: string): string; /** * Escape an attribute value: `&` `<` `>` `"` plus tab/CR/LF as char refs. * Throws `Error` on non-XML characters — same policy as {@link escapeText}. */ export declare function escapeAttribute(value: string): string; /** * Serialize a document to UTF-8 bytes. * * Emits the declaration verbatim when present (encoding rewritten to * "UTF-8" if the source declared a different one), attributes in stored * order with their stored prefixes, namespace declarations exactly where * they appear in `attributes`, CDATA as CDATA, and standard escaping * elsewhere. No pretty-printing, no whitespace insertion, no BOM. */ export declare function serializeXml(document: XmlDocument): Uint8Array; /** Serialize any single node (fragment) to a string. Same rules as {@link serializeXml}. */ export declare function serializeNode(node: XmlNode): string; //# sourceMappingURL=index.d.ts.map