GrooveSeek

Semantic search over a Markdown knowledge base, served over MCP.

View the Project on GitHub alphabet-h/grooveseek

27. Detect docx headings from style names and their basedOn chain

Context and problem

Until this record the .docx parser decided a heading from the spelling of the style ID a paragraph names: <w:pStyle w:val="Heading1">, lowercased, had to start with heading and end in a number. A style ID is an identifier the writing application picks for each document, not a name. Word with a Japanese interface writes its built-in headings under the IDs 1 .. 6 and names them heading 1 .. heading 6 in word/styles.xml, so a document written that way had none of its headings recognised and was indexed as a single chunk. The test documents had no word/styles.xml and used Heading1-style IDs, which is why nothing showed it.

The question is what decides that a paragraph is a heading, and what a document without usable styles gets.

Decision drivers

Options considered

  1. What decides.
    • Names only, as Apache Tika and unstructured do: a style named heading N is a heading. Rejected: a custom style based on a heading style is not, and to its author it is a heading.
    • Names and the w:basedOn chain, with an outline level of 9 on a derived style cancelling the heading (pandoc’s rule, plus the cancellation). Taken.
    • The effective outline level as well, as docling does: any style with an outline level from 0 to 8 is a heading whatever its name. Rejected: body styles that carry an outline level exist, and docling had to answer an issue (#4106) about them.
  2. When the table and the spelling disagree.
    • A heading if either says so. Rejected: the cancellation, and a style whose name is not a heading’s, would be overruled whenever the ID happens to be spelled Heading... — two rules.
    • The table decides an ID it holds; the spelling decides only an ID it does not. Taken.
  3. A malformed styles part.
    • Use the styles that parsed before the break. Rejected: a style whose parent was lost ends its walk early and becomes body text that neither the whole table nor the spelling would give, and nothing shows which.
    • Ignore the whole part, read every paragraph by spelling, and say so on stderr. Taken.
  4. A styles part that the decompression budget cannot hold together with the parts already read.
    • Fail the document, as for docProps/core.xml. Rejected: a document indexed today would drop out of the index for a part it can do without.
    • Skip the part with a warning and fall back. Taken.

Decision

Consequences

References