Harden streaming markdown rendering#768
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @blove's task in 2m 40s —— View job PR Review
SummaryThe dependency bump is clean — Fenced code test (line 55): Nested inline test (line 65): Only the Blockquote No correctness bugs, no security issues, no type-safety problems, no subscription leaks. The |
| grow(content); | ||
| expect(el.querySelectorAll('pre code')).toHaveLength(1); | ||
| expect(el.querySelector('pre code')?.className).toBe('language-ts'); | ||
| expect(el.querySelector('p')?.textContent ?? '').not.toContain('```'); |
There was a problem hiding this comment.
Weak assertion — checks only the first <p>. querySelector returns a single element, so if the parser leaks ``` into a second paragraph this passes silently. Either widen to all paragraphs or assert on the whole element:
| expect(el.querySelector('p')?.textContent ?? '').not.toContain('```'); | |
| expect([...el.querySelectorAll('p')].some((p) => p.textContent?.includes('```'))).toBe(false); |
Alternatively: expect(el.textContent).not.toContain('```') — simpler, catches leakage anywhere.
| expect(el.querySelector('em')?.textContent).toContain('em and'); | ||
| expect(el.querySelector('strong')?.textContent).toContain('strong and code'); | ||
| expect(el.querySelector('strong code')?.textContent).toBe('code'); | ||
| expect(el.textContent).not.toContain('**strong'); |
There was a problem hiding this comment.
Only the **strong opener is checked. The opening *em delimiter could still leak without being caught here. Consider also asserting:
| expect(el.textContent).not.toContain('**strong'); | |
| expect(el.textContent).not.toContain('**strong'); | |
| expect(el.textContent).not.toContain('*em'); |
| const quote = el.querySelector('blockquote'); | ||
| expect(quote).toBeTruthy(); | ||
| const paragraph = quote?.querySelector('p'); | ||
| expect(paragraph?.textContent).toBe('hellowor'); |
There was a problem hiding this comment.
'hellowor' (no space) pins the parser's hard-break behavior for blockquote continuations. This is correct for 0.5.5 and the <br> check below confirms it intentionally, but a short comment would make the why obvious for future readers:
| expect(paragraph?.textContent).toBe('hellowor'); | |
| // Continuation `> wor` joins via <br>, not a space — check textContent has no space | |
| expect(paragraph?.textContent).toBe('hellowor'); |
Summary
Why
The upstream parser fix keeps streamed blockquote paragraphs nested in their owning blockquote and preserves open-line nested preview updates. The chat package should consume that release and cover nearby streaming surfaces so future parser changes do not regress table or blockquote rendering.
Validation
git diff --checknpx vitest run src/lib/streaming/streaming-markdown.torture.spec.ts src/lib/streaming/streaming-markdown.table-stream.spec.ts --config vite.config.mts --reporter=verbosenpx nx build chat