Skip to content

ResolveNumPrFromStyle drops child-style ilvl when numId is inherited via basedOn #180

Description

@skyeanything

Summary

ResolveNumPrFromStyle (src/officecli/Handlers/Word/WordHandler.StyleList.cs) resolves a paragraph's effective numbering by walking the basedOn style chain, but it treats numId and ilvl as a single unit. When a child style declares only w:ilvl and inherits w:numId from its basedOn parent, the walk skips the child (it has no numId) and returns the parent's (numId, ilvl) — silently discarding the child's ilvl.

Repro

A common Word-generated multilevel list linked to heading styles:

  • style 2 (heading 1): numPr = <w:ilvl val="0"/><w:numId val="1"/>
  • style 3 (heading 2): basedOn=2, numPr = <w:ilvl val="1"/>no numId, inherited from style 2
  • style 4 (heading 3): numPr = <w:ilvl val="2"/><w:numId val="1"/>

A paragraph with pStyle=3 should resolve to (numId=1, ilvl=1).
But officecli get <doc> /body --json reports numLevel=0 for it (the parent's ilvl), not 1.

Impact

Everything relying on ResolveNumPrFromStyle: paragraph numLevel emission (get /body), HtmlPreview rendering, Navigation counters. A downstream consumer that computes numbering values from numId+numLevel gets the wrong level, so all H1/H2 collapse onto one counter and values come out wrong.

Root cause

In the basedOn walk, the first style with a non-null numId is returned wholesale as (numId, ilvl). A child style that declares ilvl without numId is never consulted for its ilvl.

Confirmed still present on main (v1.0.131).

Suggested fix

Track numId and ilvl independently while walking the chain: remember the first-seen numId and the first-seen ilvl (they may come from different styles in the chain), break once numId is resolved, and return (resolvedNumId, resolvedIlvl ?? 0). The direct-numPr branch (step 1) has the same latent issue when a paragraph's own numPr carries ilvl but not numId.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions