Skip to content

Fix flattening of visually-nested DOCX lists that use a separate numbering definition - #2332

Open
changsheng (changsheng0804-blip) wants to merge 1 commit into
microsoft:mainfrom
changsheng0804-blip:fix/docx-nested-lists-separate-numbering
Open

Fix flattening of visually-nested DOCX lists that use a separate numbering definition#2332
changsheng (changsheng0804-blip) wants to merge 1 commit into
microsoft:mainfrom
changsheng0804-blip:fix/docx-nested-lists-separate-numbering

Conversation

@changsheng0804-blip

Copy link
Copy Markdown

Description

Fixes #2323.

When a Word document contains a visually-nested sub-list such as

1. Item 1
2. Item 2
   • Item 2.1
   • Item 2.2
3. Item 3
   a) Item 3.1
   b) Item 3.2

the current output flattens the a) / b) sub-list into the top level and renumbers its items (4., 5.).

Root cause: Word frequently stores such sub-lists as an independent top-level numbering definition (their own numId at ilvl 0); the visual nesting comes only from the level's left indent in numbering.xml. Since mammoth resolves nesting from ilvl, it emits the sub-items as siblings of the parent list, and the Markdown conversion faithfully flattens them. (Verified by inspecting the intermediate mammoth HTML and the document/numbering XML of the repro file from the issue: the sub-list paragraphs reference numId=3, ilvl=0 with left indent 1080, while the parent list level uses 720.)

Fix: a new _pre_process_nested_lists step in pre_process_docx rewrites such runs to continue the parent list at a deeper ilvl. A run is rewritten only when all of the following hold, keeping the heuristic conservative:

  • it starts at ilvl 0 with a numId different from the immediately preceding numbered paragraph (any non-list paragraph in between prevents the rewrite);
  • the indent of the new list's level 0 (from numbering.xml, w:left/w:start) is strictly greater than the indent of the preceding paragraph's list level;
  • the referenced numbering definitions exist.

Documents without a numbering.xml part, and any file in which preprocessing raises, are passed through unchanged (same fallback behavior as the existing math preprocessing step).

Test evidence

All run locally (Windows, Python 3.12 venv, pip install -e packages/markitdown[docx]):

  • The repro DOCX attached to Nested list in docx is not properly parsed in Markdown #2323 converts from the flattened form (4. Item 3.1 / 5. Item 3.2 at top level) to a properly nested list after this change.
  • Three new tests in packages/markitdown/tests/test_docx_nested_lists.py (self-contained; they build minimal DOCX files in memory instead of adding binary fixtures):
  • Existing vector tests: the failure set is byte-identical with and without this change (the failures in my minimal environment are missing optional converter dependencies, e.g. [xlsx]/[pptx], unrelated to DOCX); the test.docx conversion vector passes.
  • black --check (repo-pinned 23.7.0) passes on both changed files.

…ering definition

Word often renders sub-lists (e.g. 'a) ... b) ...' below a numbered item) as
an independent top-level numbering definition whose visual nesting comes only
from its indentation in numbering.xml. mammoth flattens such lists because
the paragraphs reference their own numbering definition at ilvl 0, so the
converted Markdown loses the nesting and renumbers the sub-items at the top
level.

The new _pre_process_nested_lists step rewrites such runs to continue the
parent list at a deeper ilvl when a list at ilvl 0 with a different numId
directly follows another list paragraph and its level-0 indent is strictly
greater than the preceding level's indent.

Fixes microsoft#2323
@changsheng0804-blip

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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.

Nested list in docx is not properly parsed in Markdown

1 participant