Skip to content

Commit 4aa6e9d

Browse files
committed
fix(rich-markdown-editor): unique widget key per duplicate embed URL
Key embed widgets by source + per-source occurrence index so two standalone links to the same URL render as two distinct players instead of collapsing into one, while keeping the key stable across unrelated edits (no iframe reload).
1 parent ef83130 commit 4aa6e9d

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/embed/link-embed.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ describe('LinkEmbed', () => {
3434
expect(iframe?.getAttribute('src')).toBe('https://www.youtube.com/embed/dQw4w9WgXcQ')
3535
})
3636

37+
it('renders one player per link when the same URL appears twice', () => {
38+
const view = editorWith(`${YOUTUBE_LINK}${YOUTUBE_LINK}`).view
39+
expect(view.dom.querySelectorAll('iframe')).toHaveLength(2)
40+
})
41+
3742
it('keeps the underlying document a plain markdown link (lossless round-trip)', () => {
3843
const markdown = editorWith(YOUTUBE_LINK).getMarkdown()
3944
expect(markdown).toContain('https://www.youtube.com/watch?v=dQw4w9WgXcQ')

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/embed/link-embed.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,24 @@ function getStandaloneLinkHref(node: ProseMirrorNode): string | null {
3535

3636
function buildDecorations(doc: ProseMirrorNode): DecorationSet {
3737
const decorations: Decoration[] = []
38+
/** Per-source occurrence count, so repeated embeds of the same URL get distinct, stable keys. */
39+
const sourceCounts = new Map<string, number>()
3840
doc.descendants((node, pos) => {
3941
if (node.type.name !== 'paragraph') return undefined
4042
const href = getStandaloneLinkHref(node)
4143
if (href) {
4244
const embedInfo = getEmbedInfo(href)
4345
if (embedInfo) {
44-
// Render the player just after the link paragraph, keyed by source so the iframe/video
45-
// DOM is reused across edits instead of reloading on every keystroke.
46+
// Key by source + occurrence index so the iframe/video DOM is reused across unrelated
47+
// edits (no reload on keystroke) while two links to the same URL still render as two
48+
// distinct widgets rather than collapsing into one.
49+
const source = `embed:${embedInfo.type}:${embedInfo.url}`
50+
const index = sourceCounts.get(source) ?? 0
51+
sourceCounts.set(source, index + 1)
4652
decorations.push(
4753
Decoration.widget(pos + node.nodeSize, () => createEmbedDom(embedInfo), {
4854
side: 1,
49-
key: `embed:${embedInfo.type}:${embedInfo.url}`,
55+
key: `${source}:${index}`,
5056
})
5157
)
5258
}

0 commit comments

Comments
 (0)