Skip to content

fix(converter): handle legal numbering continuation pattern#93

Merged
JSv4 merged 4 commits intomainfrom
feature/fix-legal-numbering-continuation
Dec 23, 2025
Merged

fix(converter): handle legal numbering continuation pattern#93
JSv4 merged 4 commits intomainfrom
feature/fix-legal-numbering-continuation

Conversation

@JSv4
Copy link
Copy Markdown
Owner

@JSv4 JSv4 commented Dec 23, 2025

Summary

  • Fix incorrect multi-level list numbering when items continue a flat sequence at different indentation levels
  • Documents with items like 1., 2., 3. at level 0 followed by item at level 1 (with start=4) now render as "4." instead of "3.4"
  • Fix inconsistent indentation across list items at the same level
  • Add documentation for OOXML corner cases

The Problem

In the NVCA-Model-COI document, a numbered list had:

  • Items 1-3 at ilvl=0 with format %1. → displayed correctly as "1.", "2.", "3."
  • Item 4 at ilvl=1 with format %1.%2 and start=4 → was displaying as "3.4" instead of "4."

Microsoft Word shows "4." because it detects this as a "continuation pattern" - a flat list that happens to use different indentation levels.

Additionally, items 2-4 had different indentation than item 1 (0.5in vs 0.25in wrapper width) due to a mutation bug.

The Fix

1. Continuation Pattern Detection

Added "continuation pattern" detection in ListItemRetriever.cs:

  1. Detection: A paragraph at ilvl > 0 is in a continuation pattern when:

    • It's the first paragraph at this level AND
    • The level's start value equals the parent level's counter + 1
    • OR it inherits continuation status from a previous paragraph at the same level
  2. Handling: When detected, uses level 0's format string with the current level's counter value

2. Numbering Definition Mutation Fix

Fixed mutation bug in FormattingAssembler.cs:

  • The code was modifying the original numbering definition's pPr element by calling .Remove() on its child elements
  • This caused subsequent list items using the same numbering level to lose their tab definitions
  • Fixed by cloning numberingParaProps before modifying

3. Tab Width Calculation Fix

Updated WmlToHtmlConverter.cs to check accumulated properties (pt:pPr) first for indentation and tabs, falling back to direct properties (w:pPr) if not found.

Changes

  • Docxodus/ListItemRetriever.cs - Added ContinuationInfo class and detection/handling logic
  • Docxodus/FormattingAssembler.cs - Clone numberingParaProps before mutation; use effective level for properties
  • Docxodus/WmlToHtmlConverter.cs - Check pt:pPr first for tabs and indentation
  • docs/ooxml_corner_cases.md - New documentation for OOXML edge cases
  • CLAUDE.md - Added section on documenting corner cases
  • CHANGELOG.md - Added entry for this fix

Test plan

  • Build succeeds with no warnings
  • All 1178 tests pass
  • NVCA document now renders item 4 as "4." instead of "3.4"
  • All 4 list items have consistent 0.25in wrapper width

JSv4 added 4 commits December 22, 2025 23:46
Fix incorrect multi-level list numbering when items continue a flat
sequence at different indentation levels. Documents with items like
1., 2., 3. at level 0 followed by item at level 1 (with start=4) now
render as "4." instead of "3.4".

The fix adds "continuation pattern" detection in ListItemRetriever.cs:
- Detects when a deeper-level item continues a flat list sequence
  (start value equals parent counter + 1)
- When detected, uses level 0's format string with current counter
- Tracks continuation state per level with inheritance
- Resets deeper level tracking when going to shallower levels

Also adds:
- docs/ooxml_corner_cases.md for documenting OOXML edge cases
- CLAUDE.md section on documenting corner cases
…ontinuation patterns

When a list item is detected as a "continuation pattern" (deeper-level
item that continues a flat sequence), the converter now uses level 0's
properties for:
- Run properties (rPr) - fixes underline appearing incorrectly
- Paragraph properties (pPr) - fixes tab stops and indentation

Changes:
- FormattingAssembler.cs: Use GetEffectiveLevel() in NormalizeListItemsTransform,
  ParaStyleParaPropsStack, and AnnotateParagraph functions
- ListItemRetriever.cs: Made ContinuationInfo class internal for cross-file access
- Updated CHANGELOG.md and docs/ooxml_corner_cases.md with fix details
Added two tests to verify the continuation pattern fix:
- HC050_ContinuationPattern_RendersCorrectNumber: Verifies items at ilvl=1
  with start=4 render as "4." instead of "3.4"
- HC051_ContinuationPattern_UsesLevel0Formatting: Verifies continuation items
  use level 0's run properties (no underline when level 1 has underline)

These tests create programmatic documents with multi-level numbered lists
to verify the fix handles the edge case correctly.
…tting

Clone numberingParaProps before removing non-indent elements to avoid
mutating the original numbering definition. This was causing subsequent
list items using the same numbering level to lose their tab definitions,
resulting in inconsistent wrapper span widths (0.5in instead of 0.25in).

Also updated CalculateSpanWidthTransform to check accumulated properties
(pt:pPr) first for indentation and tabs, falling back to direct properties
(w:pPr) if not found.
@JSv4 JSv4 merged commit fa9facd into main Dec 23, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant