Skip to content

SD-2440 - fix: toc not loading on paragraphs#2706

Open
chittolinag wants to merge 3 commits intomainfrom
gabriel/sd-2440-bug-import-fails-on-field-based-list-of-tablesfigures-toc
Open

SD-2440 - fix: toc not loading on paragraphs#2706
chittolinag wants to merge 3 commits intomainfrom
gabriel/sd-2440-bug-import-fails-on-field-based-list-of-tablesfigures-toc

Conversation

@chittolinag
Copy link
Copy Markdown
Contributor

@chittolinag chittolinag commented Apr 2, 2026

Issue

Importing documents where the TOC field sits inline inside a paragraph crashed because the converter always emitted block tableOfContents nodes that expect paragraph parents. When that type of document is imported, SuperDoc crashes completely.

Solution

Detect when the parent disallows block nodes and encode the TOC as a new inline tableOfContentsInline node with proper exporter/schema support plus translator tests locking encode/decode behavior. We now are loading that type of document properly, however the TOC is not 100% well formatted - but we'll tackle that separately.

@linear
Copy link
Copy Markdown

linear bot commented Apr 2, 2026

@chittolinag chittolinag changed the title fix: toc not loading on paragraphs SD-2440 - fix: toc not loading on paragraphs Apr 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Status: PASS

The OOXML field character handling in this PR is spec-compliant.

The inline TOC decodes to the standard complex field structure defined in ECMA-376 §17.16.2:

w:fldChar (begin) → w:instrText (preserve) → w:fldChar (separate) → [content] → w:fldChar (end)

All three pieces check out:

  • w:fldCharType values begin, separate, end are the exact three valid values per §17.16.18
  • xml:space="preserve" on w:instrText matches the spec's own examples (§17.16.23) — preserving whitespace in field codes like TOC \h is correct
  • Field sequence is valid — separate is optional per spec, but including it (as the code does) is correct when there's result content following it

The only difference from the block variant is that the runs are returned as a flat array for injection into an existing paragraph rather than being wrapped in w:p elements. That's the right behavior for inline fields — the surrounding paragraph context is owned by the parent, not this node.

@chittolinag chittolinag marked this pull request as ready for review April 2, 2026 19:03
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac0874bd59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +75 to +79
const inlineContentNodes = tocContent.flatMap((n) => {
const exported = exportSchemaToJson({ ...params, node: n });
if (!exported) return [];
return Array.isArray(exported) ? exported : [exported];
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Decode TOC children only in the active branch

In decode, tocContent is exported once into inlineContentNodes before we know whether the node is inline, and block TOCs then export the same children again into blockContentNodes (next line). This double pass is not just extra work: child decoders are stateful/mutating in this codebase (for example hyperlink decode removes link marks and can append relationships), so the second pass can serialize different output than the first and lose field content metadata in block TOCs. Move the export call inside each branch so each child is decoded exactly once.

Useful? React with 👍 / 👎.

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