Skip to content

Commit 9fb3038

Browse files
Jing-yilinclaude
andcommitted
A picture still being written draws nothing, not an <img> with no source
remend 1.4 (#204) rewrites a half-written image to `![alt](streamdown:incomplete-image)` where 1.3 dropped it. DOMPurify strips that source, so the chat showed a broken picture until the closing bracket arrived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 9d196b9 commit 9fb3038

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

‎canvas/src/markdown.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ describe("renderMarkdown", () => {
1515
expect(renderMarkdown("run `bun test")).toContain("<code>bun test</code>");
1616
});
1717

18+
it("draws no picture until its source has arrived whole", () => {
19+
expect(renderMarkdown("see ![shot](https://x.dev/a")).not.toContain("<img");
20+
expect(renderMarkdown("see ![shot](https://x.dev/a.png)")).toContain(
21+
'src="https://x.dev/a.png"',
22+
);
23+
});
24+
1825
it("is a table only once the delimiter row has arrived", () => {
1926
expect(renderMarkdown("| a | b |")).not.toContain("<table");
2027
expect(renderMarkdown("| a | b |\n| - | - |")).toContain("<table");

‎canvas/src/markdown.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
import DOMPurify from "dompurify";
1111
import { Marked } from "marked";
12-
import remend from "remend";
12+
import remend, { INCOMPLETE_IMAGE_PLACEHOLDER } from "remend";
1313

1414
// The agent links what it made as `file:///…`, which DOMPurify drops and an http page could not
1515
// follow anyway. Relative to the project's page, `file/<path>` is the project's server
@@ -21,6 +21,11 @@ const md = new Marked({
2121
token.href = `file${url.pathname}${url.search}${url.hash}`;
2222
}
2323
},
24+
// A picture a delta cut open comes out of remend under a source only Streamdown draws, which
25+
// DOMPurify drops, leaving an `<img>` with none. Nothing is drawn until the rest arrives.
26+
renderer: {
27+
image: ({ href }) => (href === INCOMPLETE_IMAGE_PLACEHOLDER ? "" : false),
28+
},
2429
});
2530

2631
export function renderMarkdown(text: string): string {

0 commit comments

Comments
 (0)