Uniword includes a prevention layer (Docx::Reconciler) that runs automatically during serialization. It enforces cross-part invariants so structurally invalid DOCX output becomes impossible.
1. How It Works
The reconciler inspects the package’s parts and settings before serialization. If it detects an inconsistency — for example, footnote properties that reference a footnotes part that does not exist — it creates the missing part or injects the missing property automatically.
2. Three Reconciliation Groups
The Reconciler is organized into three mutually exclusive, collectively exhaustive (MECE) groups that together cover everything Word checks:
2.1. Group 1 — Document Body (profile-independent, always runs)
Intra-part correctness of word/document.xml:
| Check | Auto-fix |
|---|---|
Missing section properties |
Add |
|
Create minimal footnotes with separator entries |
|
Create |
|
Create minimal endnotes with separator entries |
|
Create |
Missing separator entry (id=-1) |
Inject separator |
Missing continuation entry (id=0) |
Inject continuation |
2.2. Group 2 — Support Parts (profile-dependent, runs when profile provided)
Intra-part content completeness of all parts except document.xml. Only runs when a Profile is provided.
| Part | What gets populated |
|---|---|
Theme |
Load default theme from profile |
Settings |
zoom, proofState, defaultTabStop, characterSpacingControl, compat, rsids, mathPr, themeFontLang, clrSchemeMapping, decimalSymbol, listSeparator, w14:docId, w15:docId |
Font table |
Profile-driven font entries with panose/charset/family/pitch/sig metadata |
Styles |
docDefaults (theme font refs, spacing), latentStyles (~376 exceptions), default styles (Normal, DefaultParagraphFont, TableNormal, NoList) |
Web settings |
optimizeForBrowser, allowPNG, namespace declarations |
App properties |
Template, Application, AppVersion, Company |
Core properties |
lastModifiedBy, creator, revision, UTC timestamps |
Document body |
Tracking attributes: w14:paraId, w14:textId, w:rsidR, w:rsidRDefault on paragraphs; w:rsidR on sectPr |
2.3. Group 3 — Package Consistency (profile-independent, always runs)
Cross-part correctness — relationships, content types, and references form a consistent graph:
| Check | Fix applied |
|---|---|
Content types |
Rebuild defaults (rels + xml only). Overrides only for parts that exist. |
Root rels rId ordering |
rId1=officeDocument, rId2=core-properties, rId3=extended-properties. Non-standard rels preserved. |
Document rels rId ordering |
rId1=styles, rId2=settings, rId3=webSettings, rId4=fontTable, rId5=theme. Non-standard rels preserved. |
3. Execution Order
The groups run in order:
Group 1 (body) → Group 2 (parts) → Group 3 (consistency)
Group 2 may create parts (e.g., theme) that Group 3 needs to reference. Group 1 runs first because body-level attributes are referenced by settings.
4. Profile Gating
Without a Profile, only Groups 1 and 3 run (backward compatible). With a profile, all three groups run, producing output that matches Microsoft Word’s expected format.
# Without profile: structural reconciliation only
doc.save("output.docx")
# With profile: full reconciliation including content population
profile = Uniword::Docx::Profile.load(:word_2024_en)
doc.save("output.docx", profile: profile)
5. When It Runs
The reconciler runs in Docx::Package#to_zip_content before the serialization phase. Every time a DOCX file is written, the prevention layer ensures the output is structurally valid.
|
The reconciler is NOT an extension point — it enforces built-in DOCX invariants. For customizable validation, use |
6. Relationship to Verification
The prevention layer is distinct from the verification system:
- Prevention Layer
-
Runs automatically during writes. Fixes known invariant violations silently. Cannot be disabled.
- Verification Pipeline
-
Runs on demand via
uniword verify. Reports issues across three layers (OPC, XSD, semantic). Can include custom rules.
Use the prevention layer to guarantee valid output. Use the verification pipeline to diagnose existing documents.
7. Structural Validation
Validation::StructuralValidator provides document-level integrity checks used by DocumentRoot#valid?:
-
Verifies the document body exists and contains at least one block element
-
Checks paragraph integrity (no nil runs within paragraphs)
-
Validates table structure (rows and cells present)
-
Detects broken internal references
This validator runs on demand via document.valid? and is separate from the automatic prevention layer.