From 057be3722a29cdbab46b631f5e209d5c4bee64dc Mon Sep 17 00:00:00 2001 From: Jules Youngberg Date: Fri, 12 Jun 2026 11:23:41 -0700 Subject: [PATCH 1/3] fix(streamdown): re-render for offset changes in components --- .../__tests__/components-rerender.test.tsx | 33 +++++++++++++++++++ packages/streamdown/lib/components.tsx | 5 ++- 2 files changed, 37 insertions(+), 1 deletion(-) 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 ); } From 7899ea9125c186076cd879d752c0c20486219550 Mon Sep 17 00:00:00 2001 From: Jules Youngberg Date: Fri, 12 Jun 2026 12:28:56 -0700 Subject: [PATCH 2/3] add changeset --- .changeset/fair-balloons-share.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fair-balloons-share.md diff --git a/.changeset/fair-balloons-share.md b/.changeset/fair-balloons-share.md new file mode 100644 index 00000000..0d971813 --- /dev/null +++ b/.changeset/fair-balloons-share.md @@ -0,0 +1,5 @@ +--- +"streamdown": patch +--- + +Compare position.start.offset and position.end.offset in sameNodePosition so mid-block markdown updates aren't skipped by React.memo. From ab93808357b9897934174ff990ed2ad6a352f27b Mon Sep 17 00:00:00 2001 From: Jules Youngberg Date: Fri, 12 Jun 2026 12:53:17 -0700 Subject: [PATCH 3/3] update changeset --- .changeset/fair-balloons-share.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/fair-balloons-share.md b/.changeset/fair-balloons-share.md index 0d971813..f3f6a75c 100644 --- a/.changeset/fair-balloons-share.md +++ b/.changeset/fair-balloons-share.md @@ -2,4 +2,4 @@ "streamdown": patch --- -Compare position.start.offset and position.end.offset in sameNodePosition so mid-block markdown updates aren't skipped by React.memo. +Fix stale rendering when in-block markdown content changes during streaming updates.