ReadonlydeadlineReadonlyoriginalReadonlyprofileReadonlyschemasReadonlyunpackedReadonlyverboseReadonlyxmlParts whose schema the engine could not load, or whose XSD call threw,
in the walk that finished last. Each validateAgainstXsd owns its
count, resets the instance at entry and publishes its count at exit,
even on a throw, so a nested walk cannot erase the outer count (#943).
A call outside every walk's active calls (a direct call, or a late
task after its call settled) counts on the instance, and a walk still
running replaces that count when it publishes its own: the failure is
not the walk's, and its own outcome reports it.
xsdWalk.parts.length === xsdWalk.eligible only proves every eligible
part was offered to the engine; this counter is what proves the engine
actually answered for it. A schema that fails to compile still counts as
a completed walk, which is why the top-level validate() also requires
this to be 0 before reporting schemaCompleted: true.
Engine trace owned by one validateAgainstXsd walk on this instance.
Published at entry so a lone walk is observable while running; the
walk that finishes last publishes its own trace again, even on a
throw, so nested walks do not mix their parts or counts (#943).
DOCXSchemaValidator.validate resets it at entry. mergeResults drops
it, so the public validate() copies it off the instance afterwards.
The named checks this validator executed, in the order they ran.
Reset at the entry of every validate().
Delete _rels/*.rels parts whose <Relationships> element has zero
children. Mirrors what Word does on save — see
validateNoEmptyRelsParts for the spec citation.
Returns the count of files deleted. The deleted files are also
removed from this.xmlFiles so subsequent passes (and validation
re-runs in the same instance) don't see them.
Subclass entry point. Returns merged result of all checks.
Reports every mismatched r:id it finds, under every profile: this
method knows nothing about the registered Word checks, so a caller
composing it directly gets the full legacy finding set (#612). A full
DOCXSchemaValidator.validate() run hands the story reference
elements its Word rule already reported back to that rule
(withoutRepeatedHeaderFooterFindings in docx.ts), through the
structured story reference identity this method registers on each
headerReference/footerReference mismatch (#616) and on each such
rels-id-missing (#619), and the same hand-off pairs a dangling
c:chart/o:OLEObject r:id with word-part-reference-relationship
(#705), a wne:toolbarData with word-attached-toolbar-relationship
(#716) and a refused w:hyperlink with word-hyperlink-relationship
(#1089). A full non-lenient PPTXSchemaValidator.validate() run hands
a slide master's p:sldLayoutId to sldlayout-missing-rid the same
way (#1093). Each pairing reads the registered identity, never the
message prose.
Validate one part against the schema the routing picks for it. The
schema walk calls it for each part it validates, so a subclass that
overrides it sees every one. Only the first base call the walk's own
active call makes for this part claims the root its eligibility check
read, once (#902, #941). Each call owns its roots: the claiming call
takes that one entry from its walk at claim time, while every other
call starts empty and reads afresh (#910, #926). A nested call or walk
cannot replace the root the claiming call routes by (#949). The call's
scope stops serving reads once the call is done — after
_validateSingleFileXsd and the --original baseline read — so a
task that outlives it reads afresh (#964).
Every XML part should NOT begin with a UTF-8 BOM (U+FEFF, bytes EF BB
BF). XML 1.0 §4.3.3 permits the BOM and Microsoft Office emits it
routinely, so this is reported at warning severity under EVERY
profile — it never fails a document on its own. The finding stays
visible in result.issues so callers who care about canonical bytes can
audit it.
Profile-aware check: every _rels/*.rels part must contain at
least one <Relationship> child. Per OPC §9.3 / ISO 29500-2, a
relationship part exists because its source part has outgoing
relationships — an empty <Relationships/> is non-canonical and
Word strips them on save.
Severity:
strict → error (spec-purist: flag the non-canonical state).lenient → warning (real-world unpack→pack pipelines and
third-party writers routinely emit empty rels parts; visible
but doesn't fail validation).This is the canonical example of a "strict-only" gap surfaced by
the comparison against Word's own save output: jubarte / our pack
helper preserves empty rels sidecars from the input, while Word
strips them. The repaired-file regression of the
sample-document.id-overflow.docx fixture surfaces here.
Well-formedness of every XML part, checked on the ORIGINAL BYTES.
libxml2 parses bytes, so the part's own BOM and encoding declaration
decide how it decodes (a UTF-16 part read as a UTF-8 string is garbage)
and every diagnostic carries a 1-based line/column. Parsing runs
WITHOUT XML_PARSE_RECOVER so content @xmldom silently recovers from
(a bare &, an unquoted attribute value) is reported instead of
accepted, and WITH XML_PARSE_NONET | XML_PARSE_NO_XXE so external
entities are never fetched. See src/lib/xml-syntax.ts.
Codes: xml-syntax (not well-formed), xml-undeclared-prefix
(undeclared namespace prefix), xml-encoding (declared encoding
unsupported / bytes do not decode in it).
StaticassertEagerly verify that the wasm-backed XSD engine is loadable and that XSD validation is available on this host. Call this once at program startup if you want loud failures when the engine is broken — otherwise the per-file pipeline silently turns the same condition into per-file validation errors that look like document corruption.
Throws an Error prefixed with XSD engine unavailable when validation
cannot be performed. Returns silently on success.
Successor of the libxmljs2-era assertLibxmljsAvailable, retired with
the native addon (no Node 26 / ABI-147 prebuild, no source build).
The run's wall-clock budget, when it has one (#630).