diff --git a/.changeset/fair-balloons-share.md b/.changeset/fair-balloons-share.md new file mode 100644 index 00000000..f3f6a75c --- /dev/null +++ b/.changeset/fair-balloons-share.md @@ -0,0 +1,5 @@ +--- +"streamdown": patch +--- + +Fix stale rendering when in-block markdown content changes during streaming updates. diff --git a/packages/streamdown/__tests__/components-rerender.test.tsx b/packages/streamdown/__tests__/components-rerender.test.tsx index c0ed0429..6bfbb1a1 100644 --- a/packages/streamdown/__tests__/components-rerender.test.tsx +++ b/packages/streamdown/__tests__/components-rerender.test.tsx @@ -422,6 +422,39 @@ describe("sameNodePosition edge cases", () => { expect(container.querySelector("ol")).toBeTruthy(); }); + + it("should re-render when only offset changes", () => { + const nodeV1 = { + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 2, column: 5, offset: 20 }, + }, + }; + const nodeV2 = { + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 2, column: 5, offset: 35 }, + }, + }; + + const { container, rerender } = render( + +
    +
  1. item
  2. +
+
+ ); + + rerender( + +
    +
  1. item
  2. +
+
+ ); + + expect(container.querySelector("ol")).toBeTruthy(); + }); }); describe("MemoParagraph block code unwrapping with data-block", () => { diff --git a/packages/streamdown/lib/components.tsx b/packages/streamdown/lib/components.tsx index 2449ca3a..8f0c33ad 100644 --- a/packages/streamdown/lib/components.tsx +++ b/packages/streamdown/lib/components.tsx @@ -42,6 +42,7 @@ const LANGUAGE_REGEX = /language-([^\s]+)/; interface MarkdownPoint { column?: number; line?: number; + offset?: number; } interface MarkdownPosition { end?: MarkdownPoint; @@ -74,8 +75,10 @@ function sameNodePosition(prev?: MarkdownNode, next?: MarkdownNode): boolean { return ( prevStart?.line === nextStart?.line && prevStart?.column === nextStart?.column && + prevStart?.offset === nextStart?.offset && prevEnd?.line === nextEnd?.line && - prevEnd?.column === nextEnd?.column + prevEnd?.column === nextEnd?.column && + prevEnd?.offset === nextEnd?.offset ); }