-
Notifications
You must be signed in to change notification settings - Fork 191
refactor(painters/dom): unify SDT container rendering (SD-2838) #3322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
harbournick
merged 38 commits into
luccas/sd-2838-unify-paragraph-rendering
from
luccas/sd-2838-unify-sdt-rendering
May 26, 2026
Merged
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
0a463ac
refactor(painters/dom): consolidate SDT container helpers into sdt/ m…
luccas-harbour 3284962
fix(painters/dom): continue nested table SDT chrome
luccas-harbour 85e77a2
fix(painters/dom): suppress idless table SDT chrome
luccas-harbour c1d92bd
fix(painters/dom): inherit table container SDT chrome
luccas-harbour 78f8f04
fix(painters/dom): keep nested SDT chrome active
luccas-harbour b1ace96
fix(painters/dom): suppress nested table SDT chrome
luccas-harbour ad6d6cc
fix(painters/dom): continue partial nested SDT chrome
luccas-harbour 2bd9f2a
fix(painters/dom): preserve nested table SDT ancestor
luccas-harbour ae03e40
fix(painters/dom): allow nested SDT label overflow
luccas-harbour 685ceb4
fix(painters/dom): scope nested SDT overflow to rendered content
luccas-harbour e44f2ec
fix(painters/dom): use rendered SDT lock mode
luccas-harbour 944f988
fix(painters/dom): preserve ancestor SDT key
luccas-harbour 28c5950
fix(painters/dom): merge idless SDT siblings
luccas-harbour 308a3ed
test(painters/dom): cover SDT chrome gaps
luccas-harbour 8e1627a
refactor(painters/dom): share SDT container keys
luccas-harbour 913f86f
fix(painters/dom): drop unused table block local
luccas-harbour 160108b
fix(painters/dom): skip media for SDT boundaries
luccas-harbour 5c6753a
fix(painters/dom): preserve SDT ancestor chain
luccas-harbour cdad4c1
fix(painters/dom): defer SDT overflow to rendered chrome
luccas-harbour 8f2b80c
fix(painters/dom): continue split SDT paragraph chrome
luccas-harbour 738fcd3
refactor(painters/dom): extract SDT helpers from renderer
luccas-harbour 22ce0ff
refactor(painters/dom): unify image block rendering
luccas-harbour 8a2059c
fix(painters/dom): invalidate table image visual edits
luccas-harbour 01c2e2f
docs(layout-engine): flag SdtMetadata identity invariant for pm-adapter
luccas-harbour 112234f
refactor(painters/dom): drop unused block version derivation
luccas-harbour 6871e02
fix(layout-resolved): invalidate inline image visual edits
luccas-harbour b0be9c8
fix(layout-resolved): hash raw inline image clip paths
luccas-harbour b512cb9
refactor(painters/dom): extract image rendering helpers into modules
luccas-harbour 815af26
fix(layout-resolved): avoid image hyperlink hash collisions
luccas-harbour f823bb2
fix(painters/dom): keep table images block display
luccas-harbour e586394
test(painters/dom): cover unified drawing image rendering
luccas-harbour 9491a08
refactor(painters/dom): share image clip path reader
luccas-harbour 9d2871f
refactor(painters/dom): share inline style applier
luccas-harbour 6e71691
docs(painters/dom): preserve image transform rationale
luccas-harbour 6100449
refactor(painters/dom): share image hyperlink anchor type
luccas-harbour 77c811e
refactor(painters/dom): co-locate image utils under images/
luccas-harbour dabfe32
docs(layout-resolved): clarify deriveBlockVersion no longer duplicated
luccas-harbour f2e4dcb
Merge pull request #3328 from superdoc-dev/luccas/sd-2838-unify-image…
harbournick File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
packages/layout-engine/contracts/src/sdt-container.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import type { SdtMetadata } from './index.js'; | ||
| import { | ||
| getSdtContainerKey, | ||
| getSdtContainerKeyForBlock, | ||
| getSdtContainerMetadata, | ||
| hasExplicitSdtContainerKey, | ||
| } from './sdt-container.js'; | ||
|
|
||
| describe('SDT container key helpers', () => { | ||
| it('uses the first renderable container metadata', () => { | ||
| const containerSdt: SdtMetadata = { type: 'documentSection', id: 'section-1' }; | ||
|
|
||
| expect(getSdtContainerMetadata({ type: 'structuredContent', scope: 'inline', id: 'inline-1' }, containerSdt)).toBe( | ||
| containerSdt, | ||
| ); | ||
| }); | ||
|
|
||
| it('derives explicit keys for block content controls and document sections', () => { | ||
| expect(getSdtContainerKey({ type: 'structuredContent', scope: 'block', id: 'sdt-1' })).toBe( | ||
| 'structuredContent:sdt-1', | ||
| ); | ||
| expect(getSdtContainerKey({ type: 'documentSection', sdBlockId: 'section-block-1' })).toBe( | ||
| 'documentSection:section-block-1', | ||
| ); | ||
| }); | ||
|
|
||
| it('derives stable object keys for id-less containers', () => { | ||
| const sharedSdt: SdtMetadata = { type: 'structuredContent', scope: 'block', alias: 'Shared' }; | ||
| const firstKey = getSdtContainerKey(sharedSdt); | ||
|
|
||
| expect(firstKey).toMatch(/^idlessSdt:/); | ||
| expect(getSdtContainerKey(sharedSdt)).toBe(firstKey); | ||
| expect(hasExplicitSdtContainerKey(sharedSdt)).toBe(false); | ||
| }); | ||
|
|
||
| it('derives keys from any block-like object with SDT attrs', () => { | ||
| const sdt: SdtMetadata = { type: 'structuredContent', scope: 'block', id: 'media-sdt' }; | ||
|
|
||
| expect(getSdtContainerKeyForBlock({ attrs: { sdt } })).toBe('structuredContent:media-sdt'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| import type { SdtMetadata } from './index.js'; | ||
|
|
||
| type SdtBlockCandidate = { | ||
| attrs?: { | ||
| sdt?: SdtMetadata | null; | ||
| containerSdt?: SdtMetadata | null; | ||
| } | null; | ||
| }; | ||
|
|
||
| const idlessSdtContainerKeys = new WeakMap<SdtMetadata, string>(); | ||
| let nextIdlessSdtContainerKey = 0; | ||
|
|
||
| function getIdlessSdtContainerKey(metadata: SdtMetadata): string { | ||
| const existingKey = idlessSdtContainerKeys.get(metadata); | ||
| if (existingKey) return existingKey; | ||
|
|
||
| // AIDEV-NOTE: Id-less SDT grouping relies on pm-adapter sharing the same | ||
| // SdtMetadata object across sibling blocks in one container. Do not replace | ||
| // this with alias/title matching; separate controls can share display text. | ||
| const key = `idlessSdt:${++nextIdlessSdtContainerKey}`; | ||
| idlessSdtContainerKeys.set(metadata, key); | ||
| return key; | ||
| } | ||
|
|
||
| export function isSdtContainerMetadata(sdt: SdtMetadata | null | undefined): boolean { | ||
| if (!sdt) return false; | ||
| if (sdt.type === 'documentSection') return true; | ||
| if (sdt.type === 'structuredContent' && sdt.scope === 'block') return true; | ||
| return false; | ||
| } | ||
|
|
||
| export function getSdtContainerMetadata( | ||
| sdt?: SdtMetadata | null, | ||
| containerSdt?: SdtMetadata | null, | ||
| ): SdtMetadata | null { | ||
| if (isSdtContainerMetadata(sdt)) return sdt ?? null; | ||
| if (isSdtContainerMetadata(containerSdt)) return containerSdt ?? null; | ||
| return null; | ||
| } | ||
|
|
||
| export function getSdtContainerKey(sdt?: SdtMetadata | null, containerSdt?: SdtMetadata | null): string | null { | ||
| const metadata = getSdtContainerMetadata(sdt, containerSdt); | ||
| if (!metadata) return null; | ||
|
|
||
| if (metadata.type === 'structuredContent') { | ||
| if (metadata.scope !== 'block') return null; | ||
| if (metadata.id) return `structuredContent:${metadata.id}`; | ||
| return getIdlessSdtContainerKey(metadata); | ||
| } | ||
|
|
||
| if (metadata.type === 'documentSection') { | ||
| const sectionId = metadata.id ?? metadata.sdBlockId; | ||
| if (sectionId) return `documentSection:${sectionId}`; | ||
| return getIdlessSdtContainerKey(metadata); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| export function hasExplicitSdtContainerKey(sdt?: SdtMetadata | null, containerSdt?: SdtMetadata | null): boolean { | ||
| const metadata = getSdtContainerMetadata(sdt, containerSdt); | ||
| if (!metadata) return false; | ||
|
|
||
| if (metadata.type === 'structuredContent') { | ||
| return metadata.scope === 'block' && Boolean(metadata.id); | ||
| } | ||
|
|
||
| if (metadata.type === 'documentSection') { | ||
| return Boolean(metadata.id ?? metadata.sdBlockId); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| export function getSdtContainerKeyForBlock(block?: SdtBlockCandidate | null): string | null { | ||
| if (!block) return null; | ||
| return getSdtContainerKey(block.attrs?.sdt, block.attrs?.containerSdt); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 0 additions & 40 deletions
40
packages/layout-engine/layout-resolved/src/sdtContainerKey.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.