feat(web): shiki syntax highlighting for code surfaces
One highlighter for the client: a synchronous fine-grained shiki core (JS regex engine, no WASM) in ui-primitives with an explicit grammar allowlist (typescript, shellscript, json — aliases resolve, unknown languages take a geometry-identical plain arm). The shared CodeBlock component owns both arms; markdown fences, the run_code expanded program body (typescript), and the details panel Input (json) all route through it. Token colors live in a new ui-theme shiki.css sheet as --shiki-* custom properties (light/dark blocks), wired through the shell's base.css chain — tokens-only styling holds; shiki's generated span tree is the sanctioned innerHTML path (static output, no user HTML). jsdom specs pin token spans, aliases, both fallbacks, and the fence route; the built-bundle snapshot asserts the highlighted program under the code row.
This commit is contained in:
@@ -87,14 +87,9 @@ button.leading {
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
/* The code variant's expanded body is the run_code program: monospace on the
|
||||
markdown code-block fill so the program reads as code, not prose. */
|
||||
.root[data-variant='code'] .body {
|
||||
font-family: var(--ds-font-family-code);
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
padding: 6px 8px;
|
||||
margin-left: 22px;
|
||||
border-radius: 6px;
|
||||
background: var(--dsw-alias-markdown-code-block);
|
||||
/* The code variant's expanded body is the run_code program, rendered through
|
||||
the shared CodeBlock (shiki-highlighted TypeScript); only indentation is
|
||||
this row's concern. */
|
||||
.codeBody {
|
||||
margin: 4px 0 4px 22px;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { useState, type KeyboardEvent, type MouseEvent, type ReactNode } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import { StateDot } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { CodeBlock, StateDot } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import type { ToolRowState, ToolRowVariant } from '../contract/tool-call-model.ts'
|
||||
import css from './ToolRow.module.css'
|
||||
@@ -96,7 +96,9 @@ export function ToolRow({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{open && <div className={css.body}>{body}</div>}
|
||||
{open && (variant === 'code'
|
||||
? <CodeBlock code={body} lang="typescript" className={css.codeBody} />
|
||||
: <div className={css.body}>{body}</div>)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// share the store seat exists for) and derives the call material from the
|
||||
// session snapshot — no data of its own.
|
||||
|
||||
import { CodeBlock } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { shallowEqual } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { ConversationSnapshot, ToolResultNode } from '@deepseek-ai/dsh-client-runtime/client'
|
||||
import type { DetailsSlotProps } from '../contract/slots.ts'
|
||||
@@ -89,7 +90,7 @@ export function DetailsPanel({ useSession, useStore, closeDetails }: DetailsPane
|
||||
{material.argsRaw !== null && (
|
||||
<section className={css.section}>
|
||||
<div className={css.sectionLabel}>Input</div>
|
||||
<pre className={css.code}>{pretty(material.argsRaw)}</pre>
|
||||
<CodeBlock code={pretty(material.argsRaw)} lang="json" />
|
||||
</section>
|
||||
)}
|
||||
<section className={css.section}>
|
||||
|
||||
Reference in New Issue
Block a user