fix(docx-core): reconstruct permStart/permEnd paragraph-level markers on rebuild#440
Conversation
… on rebuild PR #109 introduced PARAGRAPH_LEVEL_TAGS + buildRunContentWithParagraphMarkers so commentRange*/bookmark* markers are emitted outside synthetic <w:r> wrappers on rebuild, but deferred the range-permission markers because they had no fixture coverage. Until now, w:permStart/w:permEnd inside a paragraph produced no atoms at all (not a leaf, not a tracked paragraph-level marker), so rebuild silently dropped document protection ranges from the output. The same OOXML placement rule (ECMA-376 edition 5, Part 1 § 17.13.5) applies to perm markers: valid as direct children of <w:p> and revision wrappers, never inside <w:r>. All handling is tag-list driven, so the fix is: - Add w:permStart/w:permEnd to PARAGRAPH_LEVEL_TAGS so they atomize inside <w:p> and re-emit at paragraph level via the existing marker-aware path. - Add them to SCAFFOLD_STRIP_TAGS so body-level (sibling-of-<w:p>) perm markers are stripped from the rebuild scaffold, consistent with bookmark/commentRange behavior, instead of surviving as orphans. - Extend buildSyntheticDocx with permSpanParagraphs / siblingPermBefore fixture options and add rebuild + scaffold-strip + inplace-regression tests. Inplace mode is unaffected: atomizeParagraphLevelMarkers stays false there. - Regenerate spec-compliance/CONFORMANCE.md from the updated § 17.13.5 registry prose. moveFromRange/moveToRange remain deferred — they collide with the synthetic emission in wrapWithMoveFrom/wrapWithMoveTo. Fixes: #111 Ref: #106, #109
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
LLM-Based Quality Gate
Overall: ✅ PASS (5 pass · 0 warn · 10 skipped · 15 total)
Full checklist questions
Estimated cost (this run): $0.0085 — 25,297 input + 338 output tokens (≈4 chars/token) on |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
The WARN is a false positive for this PR:
|
…s-rebuild-20260611
LLM-Based Quality Gate
Overall:
Full checklist questions
Estimated cost (this run): $0.0084 — 25,297 input + 341 output tokens (≈4 chars/token) on |
✅ Post-merge smoke passedMerged: Steps
Real-world fixtures
Visual evidence: skipped (range permissions are structurally invisible on a rendered page — nothing paints) Cleanup
|
Summary
Follow-up to #106 / PR #109, closing out the deferred range-permission markers. Fixes #111.
Until now,
w:permStart/w:permEndinside a paragraph produced no atoms at all (not a leaf tag, not a tracked paragraph-level marker), so rebuild mode silently dropped document-protection ranges from the output.The placement rule from PR #109 (ECMA-376 edition 5, Part 1 § 17.13.5 — valid as direct children of
<w:p>and revision wrappers, never inside<w:r>) applies identically to perm markers, and all handling is tag-list driven, so the fix is additive:atomizer.ts: addw:permStart/w:permEndtoPARAGRAPH_LEVEL_TAGS(atomized inside<w:p>, re-emitted bare via the existingbuildRunContentWithParagraphMarkerspath).documentReconstructor.ts: add them toSCAFFOLD_STRIP_TAGSso body-level (sibling-of-<w:p>) perm markers are stripped from the rebuild scaffold, consistent with bookmark/commentRange behavior.synthetic-docx-fixture.ts: newpermSpanParagraphs/siblingPermBeforeoptions.rebuild-auxiliary-merge.test.ts: three new tests — cross-paragraph span survives rebuild at paragraph level with matching ids and a valid parent (w:p/w:ins/w:del/w:moveFrom/w:moveTo); body-level markers are stripped; inplace mode unaffected (regression guard —atomizeParagraphLevelMarkersstays false there).[ECMA-PART1-17-13-5]+ regeneratedCONFORMANCE.md.moveFromRange/moveToRangeremain deferred — they collide with the synthetic emission inwrapWithMoveFrom/wrapWithMoveTo.Acceptance (from #111)
permStart/permEndsurvive rebuild at paragraph levelbuild,lint:workspaces,test:run,check:spec-coverage,check:conformance-citations,check:conformance-doc)