重现步骤
在线示例链接:暂无(最小复现见下方代码,使用 @ant-design/x-markdown 的 streaming 模式)
步骤:
-
以流式模式(streaming={{ hasNextChunk: true }})渲染如下 markdown —— 围栏代码块(fenced code block)前缩进了 2 个空格(例如位于列表项内;CommonMark 允许 fence 前有 0-3 个空格):
const input = ' ```js\nconst a = [1,2];\n ```';
<XMarkdown input={input} streaming={{ hasNextChunk: true }} />
-
观察流式输出:[1,2] 中的 [ 没有被当作代码块内容保护,触发了链接识别器挂起;最终输出丢失 closing fence 的末尾字符(实测输出以 `` 结尾,缺少 3 个反引号)。
-
若 opening fence 缩进、closing fence 顶格( ```js ... ```),feedFenceState 会把顶格的 closing fence 误认为新的 opening,inFenced 永久为 true,之后所有内容都走代码块路径。
当前行为
feedFenceState(packages/x-markdown/src/XMarkdown/hooks/useStreaming.ts)只在行首为列 0 时识别 opening fence(lineFenceLen === 0 && (char === '' || char === '~'))。行首任意前导空格会先命中 else 分支置 lineFenceRunEnded = true,反引号不再累积,缩进的 fence 完全不可见。后果(影响流式中间态;最终渲染交给 marked` 仍是正确的):
- 缩进代码块的内容不被
isInCodeBlock 保护,按普通文本运行 per-char token 识别器,[、<、$ 开头的内容被挂起为未完成 token(闪烁 / 占位符抖动);
- 之后顶格的 closing fence 被当作新的 opening,
inFenced latch 为 true 且无法退出,后续所有内容走 commitCache + code 路径,不再做任何 token 识别。
预期行为
与 CommonMark / marked 一致:fence 前允许 0-3 个空格(例如列表项内嵌套的代码块),流式状态下同样应正确识别 opening 与 closing fence,流式中间态与最终渲染一致。
上下文
缩进的围栏代码块(如列表项内的代码块)是常见 markdown 写法。当前流式模式下这类内容会闪烁、被吞,或导致后续内容渲染路径错误,与最终(非流式)渲染结果不一致。
版本
@ant-design/x-markdown 2.9.0(npm 发布版)与 main 分支 b529d8e9(2026-07-31)均存在。
真实流式渲染 Bug 现场对比图:
(左侧为无缩进正常状态,右侧为带缩进触发挂起 Bug 的状态)

重现步骤
在线示例链接:暂无(最小复现见下方代码,使用
@ant-design/x-markdown的 streaming 模式)步骤:
以流式模式(
streaming={{ hasNextChunk: true }})渲染如下 markdown —— 围栏代码块(fenced code block)前缩进了 2 个空格(例如位于列表项内;CommonMark 允许 fence 前有 0-3 个空格):观察流式输出:
[1,2]中的[没有被当作代码块内容保护,触发了链接识别器挂起;最终输出丢失 closing fence 的末尾字符(实测输出以``结尾,缺少 3 个反引号)。若 opening fence 缩进、closing fence 顶格(
```js ... ```),feedFenceState会把顶格的 closing fence 误认为新的 opening,inFenced永久为true,之后所有内容都走代码块路径。当前行为
feedFenceState(packages/x-markdown/src/XMarkdown/hooks/useStreaming.ts)只在行首为列 0 时识别 opening fence(lineFenceLen === 0 && (char === '' || char === '~'))。行首任意前导空格会先命中 else 分支置lineFenceRunEnded = true,反引号不再累积,缩进的 fence 完全不可见。后果(影响流式中间态;最终渲染交给marked` 仍是正确的):isInCodeBlock保护,按普通文本运行 per-char token 识别器,[、<、$开头的内容被挂起为未完成 token(闪烁 / 占位符抖动);inFencedlatch 为true且无法退出,后续所有内容走commitCache+ code 路径,不再做任何 token 识别。预期行为
与 CommonMark /
marked一致:fence 前允许 0-3 个空格(例如列表项内嵌套的代码块),流式状态下同样应正确识别 opening 与 closing fence,流式中间态与最终渲染一致。上下文
缩进的围栏代码块(如列表项内的代码块)是常见 markdown 写法。当前流式模式下这类内容会闪烁、被吞,或导致后续内容渲染路径错误,与最终(非流式)渲染结果不一致。
版本
@ant-design/x-markdown2.9.0(npm 发布版)与main分支b529d8e9(2026-07-31)均存在。真实流式渲染 Bug 现场对比图:

(左侧为无缩进正常状态,右侧为带缩进触发挂起 Bug 的状态)