From 28b617dd738b0c3c5ec56359a2a8546285253212 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sun, 26 Jul 2026 14:41:23 +0800 Subject: [PATCH] test(ui-primitives): cover the fence pre-routing arms; drop the unreachable array probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI coverage flagged MarkdownText's pre route: the array-element probe (raw[0]) and the mixed-content fallbacks were unreachable — the markdown pipeline hands pre one code element whose children are one string (or none, for an empty fence). Simplify to the string check, annotate the isValidElement guard as representation-change armor, and pin both live arms: the empty fence keeps the stock
, a language-less fence renders
the plain CodeBlock arm.
---
 .../client/ui-primitives/src/markdown/MarkdownText.tsx | 10 +++++-----
 packages/client/ui-primitives/tests/markdown.spec.tsx  |  9 +++++++++
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx
index 79ebc5f1b2..775978a275 100644
--- a/packages/client/ui-primitives/src/markdown/MarkdownText.tsx
+++ b/packages/client/ui-primitives/src/markdown/MarkdownText.tsx
@@ -53,14 +53,14 @@ function buildComponents(streaming: boolean): Components {
     // plain arm — retokenizing a growing fence on every chunk is quadratic
     // main-thread work; the finalize swap highlights it once.
     pre: ({ children }) => {
+      /* v8 ignore next 2 -- the markdown pipeline always hands `pre` its single `code` element; the undefined arm guards a react-markdown representation change. */
       const child = isValidElement<{ className?: string; children?: unknown }>(children) ? children : undefined
       const raw = child?.props.children
-      const text = typeof raw === 'string' ? raw : Array.isArray(raw) && typeof raw[0] === 'string' ? raw[0] : undefined
-      // A fence whose content isn't one plain string (never produced by the
-      // markdown pipeline) keeps the stock 
 rather than guessing.
-      if (text === undefined) return 
{children}
+ // A fence whose content isn't one plain string (e.g. an empty fence) + // keeps the stock
 rather than guessing.
+      if (typeof raw !== 'string') return 
{children}
const lang = /language-([\w-]+)/.exec(child?.props.className ?? '')?.[1] - return + return }, } } diff --git a/packages/client/ui-primitives/tests/markdown.spec.tsx b/packages/client/ui-primitives/tests/markdown.spec.tsx index 1bd629a7d0..00de9683ff 100644 --- a/packages/client/ui-primitives/tests/markdown.spec.tsx +++ b/packages/client/ui-primitives/tests/markdown.spec.tsx @@ -64,6 +64,15 @@ describe('MarkdownText', () => { expect(screen.getByRole('link', { name: 'https://deepseek.com' })).toBeTruthy() }) + it('an empty fence keeps the stock pre; a language-less fence renders the plain CodeBlock arm', () => { + const empty = render() + expect(empty.container.querySelector('pre')?.outerHTML).toBe('
') + + const plain = render() + expect(plain.container.querySelector('pre.shiki')).toBeNull() + expect(plain.container.querySelector('pre code')?.textContent).toContain('no language here') + }) + it('streaming renders fences plain; the finalize swap highlights them', () => { const fence = '```ts\nconst answer = 42\n```' const live = render()