Components / Text Outputs
Code Block
代码块:语言标 + 行号 + 复制按钮(1.2s Copied 回执)。优先级 P1,已移植(1:1 aicss.dev)。
① 活体演示
组件内 Copy 按钮真实可用(clipboard API + 回退)。四态:running(围栏未闭合、流式中)/ ok(渲染完成)/ error(run 失败中断,语言标染 danger)/ empty(无代码围栏)。
empty 态:组件不渲染(回答里无代码围栏)
② 对比台
左:wb-ui 活体;右:aicss.dev 原站截图存档(2026-08-13 采集,可滚动)。
wb-ui 活体
aicss.dev 原站截图(design/reference/aicss/code-block/screenshot.png)

③ 真实字段说明
字段真源:packages/contracts/workbench-events.mjs:36-77;reducer apps/web/index.html:6782。没有独立的代码块事件——代码围栏(```lang)存在于 assistant 文本内,由 markdown 渲染层解析(契约 3.D.4)。
| 事件 type | 字段 | 驱动行为 |
|---|---|---|
workbench.assistant.completed | payload.text | 终稿 markdown;``` 围栏 → 本组件(lang 取围栏语言标) |
workbench.assistant.delta | payload.text | 流式累积;围栏未闭合时 running 态 |
workbench.run.status | payload.status | failed/cancelled → error 态(围栏中断) |
| (回答无代码围栏) | — | empty 态:组件不渲染 |
脱敏样本(真实解析器输出,assistant 终稿事件;文件:fixtures/thinking-state.ndjson)——本组件消费其 text 内的代码围栏:
{"type":"workbench.assistant.completed","text":"Done — scratch note written and edited."}
④ 用在 workbench 哪个位置
接入点:apps/web/index.html:4624 renderMarkdownSafe(text) 的代码围栏(fence)渲染分支——轮 3b 在 ?ui=next 灰度下把 fence 输出换成本组件(含复制按钮,契约 3.D.4)。下游消费方:renderAssistantAnswer(:4857) 与时间线 narration。只换 fence 的 HTML 模板,不动 markdown 解析与转义逻辑(escapeHtml 路径保持)。
⑤ 复制即用代码
引入 tokens + 组件 CSS/JS。全部相对路径、零依赖。
<link rel="stylesheet" href="design/wb-ui/lib/tokens.css"> <link rel="stylesheet" href="design/wb-ui/lib/components/code-block.css"> <script src="design/wb-ui/lib/components/code-block.js"></script>
// markdown fence → 组件(lang/code 来自围栏解析)
var h = WbUI.codeBlock.render(el, { lang: "ts", code: fenceBody });
h.set("ok"); // 围栏闭合
h.setCode(newCode); // 流式中重渲染
h.set("error"); // run failed/cancelled 中断
Ported from aicss.dev/components/code-block, fetched 2026-08-13. Internal use only(上游无 license 声明,对外使用前须确认授权——docs/86 R1)。