Skip to content

fix(layout-adapter): preserve nested block content-control ancestry (#3745)#3753

Open
caio-pizzol wants to merge 6 commits into
mainfrom
caio/it-1188-nested-sdt-container-chain
Open

fix(layout-adapter): preserve nested block content-control ancestry (#3745)#3753
caio-pizzol wants to merge 6 commits into
mainfrom
caio/it-1188-nested-sdt-container-chain

Conversation

@caio-pizzol

@caio-pizzol caio-pizzol commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Nested block content controls (a w:sdt whose content holds another block w:sdt) were flattened during layout conversion: the inner control's content was dropped, and the outer control's identity was lost on whatever survived. This is the first step of #3752, which fixes it end to end.

This step records the real structure. handleStructuredContentBlockNode now threads an ordered outer-to-inner container chain and stamps it (attrs.sdtContainers) on every emitted block - paragraphs, tables, images, and drawings - while attrs.sdt stays each block's nearest control. The inner content is recovered and the outer/inner relationship is preserved in the data.

Rendering catches up in the linked follow-ups. Resolved layout (FU2) carries the key chain - including image/drawing fragments, which resolveFragmentSdtContainerKey skips today - and busts paint reuse when it changes; that keeps a control's fragments in one run. The painter (FU3) then applies container chrome to image/drawing fragments and draws depth-aware boxes so the outer box wraps the inner. Until both land, a drawing inside a control can still split its box. Editor lock enforcement is unchanged and stays on the PM tree.

Scope: data model and content recovery only - no nested chrome yet. The matching documentSection nested-SDT drop is tracked in #3752 and lands with the shared-traversal cleanup.

Builds on and incorporates @tom-material's fix from #3746, which identified the failing path. Supersedes #3746. Refs #3745.

Verified: imported a real Word file with a directly-nested block SDT through the importer and toFlowBlocks; the inner subtree is recovered and every block carries its outer-to-inner chain (inner blocks: [outer, inner]). Opened as draft pending CI.

tom-material and others added 3 commits June 16, 2026 19:52
Stamp an ordered outer-to-inner SDT container chain (attrs.sdtContainers) on
every emitted block - paragraphs, tables, images, and drawings - so a nested
block content control keeps its outer control's identity. attrs.sdt stays each
block's nearest control. Data-model step of the nested-SDT fix; resolved layout
and the painter consume the chain in follow-ups.

Refs #3745
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol caio-pizzol marked this pull request as ready for review June 19, 2026 10:34
@caio-pizzol caio-pizzol requested a review from a team as a code owner June 19, 2026 10:34

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

Copy link
Copy Markdown

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: bec8863d8c

ℹ️ 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 +173 to +174
if (nearest && target.attrs.sdt == null) target.attrs.sdt = nearest;
if (chain.length > 0) target.attrs.sdtContainers = chain as SdtMetadata[];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wire nested SDT ancestry into paint grouping

When this stamps the outer-to-inner chain only into attrs.sdtContainers, the production render path still ignores it: resolveFragmentSdtContainerKey derives the painter's sdtContainerKey only from attrs.sdt / attrs.containerSdt, and rg sdtContainers shows no runtime consumer outside these new tests. For a nested block SDT, the inner paragraph now has attrs.sdt set to the inner control, so the outer control is still lost for resolved-layout boundaries and DomPainter chrome even though the chain was preserved on the FlowBlock.

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