/** * Preservation & conformance support: the L1 comparator and the * package-level fidelity verdict. * * L1 ("semantic equivalence") is the minimum fidelity bar for every * round-trip: a reserialized part must compare equal to its source under * the rules below. The comparator is used by the conformance suite and by * unit tests across all modules. See PRESERVATION.md for the fidelity * ladder (L1/L2/L3) and the normative comparison rules (its §3 is the * source of truth for this module). * * Comparison semantics (normative summary): * - Elements match on (resolved namespace URI, localName); prefixes are * irrelevant. * - Attributes are compared as an unordered set keyed by * (namespace URI, localName) → value. Namespace declaration attributes * (xmlns, xmlns:*) are excluded — they matter only via resolution, so * declarations are compared by *effect*, not placement. * - Child normalization order: comments/PIs are dropped, then adjacent * text/CDATA nodes are coalesced (CDATA is not distinguished from * text), then whitespace-only runs are dropped UNLESS * xml:space="preserve" is in effect (nearest ancestor-or-self * declaration wins; "default" re-enables dropping). * - Non-whitespace text compares exactly (no trimming). * - The XML declaration, prolog, and epilog are ignored (document-level * compare). * * `comparePackages` lifts the ladder to whole OPC packages: per part it * reports `identical` (byte-equal — the L3 outcome), `equivalent` * (XML part, not byte-equal but L1-equal), or `different`. It reads the * two archives via the `zip` module (the bottom layer; `compareXml` * itself depends only on `xml`). */ import { XmlDocument, XmlElement } from '../xml/index.js'; /** Category of a reported difference. */ export type XmlDiffKind = 'element-name' | 'attribute-missing' | 'attribute-extra' | 'attribute-value' | 'text' | 'child-count' | 'node-kind'; /** One difference found by {@link compareXml}. */ export interface XmlDiff { /** * Path to the differing node in the EXPECTED tree, as slash-separated * qualified-by-namespace steps with 1-based indices among same-named * element siblings (XPath convention; the index is omitted when the * element has no same-named sibling), e.g. '/w:document/w:body/w:p[2]'. * Attribute diffs append '/@name'; text diffs append '/text()'. * Prefixes shown are those of the expected tree (display only — * matching is namespace-based). */ path: string; kind: XmlDiffKind; /** Human-readable, single-line description of the difference. */ message: string; /** Stringified expected-side value, when meaningful for the kind. */ expected?: string; /** Stringified actual-side value, when meaningful for the kind. */ actual?: string; } /** * Structurally compare two trees under the L1 rules. Returns all * differences found (empty array = L1-equal). Comparison continues past * differences where feasible so a diff report is complete enough to act * on; subtree recursion stops at a node whose name/kind already differs. * * Accepts documents (compared by root; declaration/prolog/epilog ignored) * or elements (attached elements resolve namespaces and xml:space through * their real ancestors — comparing subtrees of live documents is * supported and correct). */ export declare function compareXml(expected: XmlDocument | XmlElement, actual: XmlDocument | XmlElement): readonly XmlDiff[]; /** True when {@link compareXml} finds no differences. */ export declare function isL1Equal(expected: XmlDocument | XmlElement, actual: XmlDocument | XmlElement): boolean; /** * Assert L1 equality; throws `Error` whose message lists every diff * (path, kind, expected vs actual) — suitable for test failure output. */ export declare function assertL1Equal(expected: XmlDocument | XmlElement, actual: XmlDocument | XmlElement): void; /** * Per-part fidelity verdict: * - `identical` — byte-for-byte equal content (the L3 outcome); * - `equivalent` — an XML part (`.xml`/`.rels`) that is not byte-equal * but is L1-equal (the minimum bar for reserialized parts); * - `different` — anything else, including parts present on one side only. */ export type PartVerdict = 'identical' | 'equivalent' | 'different'; /** Verdict for one zip entry (part) of a compared package pair. */ export interface PackagePartComparison { /** Entry name as stored in the archive (no leading slash). */ readonly name: string; readonly verdict: PartVerdict; /** * L1 diffs for an XML part that compared structurally unequal. * Absent for identical/equivalent parts and for non-XML parts. */ readonly diffs?: readonly XmlDiff[]; /** Extra context: presence mismatch, parse failure, binary mismatch. */ readonly note?: string; } /** Result of {@link comparePackages}. */ export interface PackageComparison { /** True when every part's verdict is identical or equivalent. */ readonly equal: boolean; /** * One row per entry name: expected-package order first, then entries * that exist only in the actual package, in their own order. */ readonly parts: readonly PackagePartComparison[]; } /** * Compare two OOXML packages (zip archives) part by part and return a * per-part {@link PartVerdict}. Content is compared uncompressed: byte * equality first (→ `identical`); XML parts (`.xml`/`.rels`) that differ * in bytes are re-compared under L1 (→ `equivalent` when L1-equal, with * the diffs attached otherwise). Parts present in only one package are * `different` with an explanatory note. * * This is the checker behind the round-trip matrix: open→save untouched * must yield `identical` for every part (L3); open→edit→save must yield * `identical` for untouched parts and at least `equivalent` for edited * XML parts (L1). */ export declare function comparePackages(expected: Uint8Array, actual: Uint8Array): Promise; //# sourceMappingURL=index.d.ts.map