Skip to content

SD-3229 - fix: enhance TOC entry processing and bookmark handling#3515

Draft
chittolinag wants to merge 5 commits into
mainfrom
gabriel/sd-3229-bug-mixed-source-toc-update-replaces-entries-with-no-table
Draft

SD-3229 - fix: enhance TOC entry processing and bookmark handling#3515
chittolinag wants to merge 5 commits into
mainfrom
gabriel/sd-3229-bug-mixed-source-toc-update-replaces-entries-with-no-table

Conversation

@chittolinag
Copy link
Copy Markdown
Contributor

Issue

Clicking Update table of contents on a mixed-source TOC (one that combines \t custom-style mappings with \f TC-field identifiers) destructively rebuilt the entries: auto-numbered heading prefixes disappeared, hyperlink anchors switched from the existing body _Toc… bookmarks to synthetic UUID names, multi-run Section rows collapsed into a single text node, the pageReference field downgraded to a plain text run with a tocPageNumber mark, the TOC2 left tab stop was dropped, and heading character marks (bold/underline/Times New Roman Bold) leaked into Article rows. In the worst case the rebuild produced the "No table of contents entries found." placeholder when sources weren't being collected at all. (SD-3229)

Proposed solution

  • Fix the TOC SWITCH_PATTERN so unquoted switch arguments (\f C) parse with their identifier instead of as a bare flag.
  • Hoist embedded w:bookmarkStart / w:bookmarkEnd out of the synthesized sd:tableOfContentsEntry atom so the entry stays valid and the bookmark remains visible to the bookmark map.
  • Bridge the v3 sd:tableOfContentsEntry translator into the v2 importer pipeline so TC fields actually materialize as PM tableOfContentsEntry nodes.
  • Teach collectTocSources to honor \t custom-style mappings, capture the source paragraph's existing _Toc… body bookmark (so the rebuilt entry reuses it), and pick up the rendered list-marker prefix + the body title marks for TC entries.
  • Rewrite buildTocEntryParagraphs to emit the importer-equivalent shape — multi-run entries, real pageReference PM node, level-2 left tab stop alongside the right tab stop, and the existing body bookmark as anchor.
  • Match Word's mark-propagation rules per ECMA-376 §17.16.5.68: heading-driven entries (\o/\u/\t) get plain text and inherit typography from the linked TOC{n} paragraph style; TC-field titles inherit only bold/italic/underline (no textStyle) so the TOC{n} font isn't overridden.
  • Update toc.update mode pageNumbers to walk pageReference subtrees, and syncTocBookmarks to skip sources with an existing body anchor so the rebuild doesn't litter the document with duplicate synthetic bookmarks.
  • Added unit + end-to-end regression tests covering the new entry shape and the mark-propagation rules.

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 26, 2026

SD-3229

@github-actions
Copy link
Copy Markdown
Contributor

Status: PASS

The two files in scope don't touch real OOXML elements/attributes — they only wire up a handler for the SuperDoc-internal synthetic node sd:tableOfContentsEntry (the sd: prefix is SuperDoc's own namespace, not an ECMA-376 one).

  • docxImporter.js just imports tableOfContentsEntryEntity and registers it in the handler list (line 261). No new element/attribute parsing, no defaults touched.
  • tableOfContentsEntryImporter.js is a one-liner bridge: generateV2HandlerEntity('tableOfContentsEntryNodeHandler', translator) against the existing v3 translator. No XML semantics live here.

The sd:tableOfContentsEntry atom is synthesized upstream by tc-preprocessor.js (out of scope) from w:instrText/w:fldChar runs that ECMA-376 §17.16 already specifies — those handlers aren't changed by this PR, so there's nothing to validate against the spec in the two files listed.

No spec violations detected.

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants