fix(x-markdown): 识别带 0-3 个前导空格的围栏代码块(缩进 fence) - #2018
Conversation
…aces feedFenceState only recognised an opening fence at column 0, so an indented fence (e.g. inside a list item) was invisible: the leading whitespace ended the fence run before the backticks accumulated, and a later top-of-column closing fence was re-consumed as a new opening, latching inFenced forever. Track leading spaces consumed per line (0-3, per CommonMark) and let the fence run start after them. A 4th space or any non-fence character still ends the run, so indented code and plain text are unaffected.
📝 WalkthroughWalkthrough本次变更修复流式 Markdown 围栏代码块的缩进识别。解析器现在支持 0 至 3 个前导空格,并区分 4 个空格缩进的代码内容。新增测试覆盖反引号、波浪线、列表嵌套和尾随空格。 Changes流式围栏缩进识别
Estimated code review effort: 2 (Simple) | ~15 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/x-markdown/src/XMarkdown/__tests__/hooks.test.tsx`:
- Around line 301-305: 修正测试夹具“4-space indent is indented code, not a
fence”:在该用例的 input 和 output 中为 code 行及末尾围栏都添加 4 个前导空格,确保整个字符串保持连续的 4 空格缩进代码块。
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e1828e82-a91d-4b4e-a055-5306e2735380
📒 Files selected for processing (2)
packages/x-markdown/src/XMarkdown/__tests__/hooks.test.tsxpackages/x-markdown/src/XMarkdown/hooks/useStreaming.ts
| { | ||
| title: '4-space indent is indented code, not a fence', | ||
| input: ' ```js\ncode\n```', | ||
| output: ' ```js\ncode\n```', | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
修正 4 空格测试夹具。
当前首行有 4 个空格,因此不会开启 fence。但末尾的无缩进围栏可能被解析为新的 opening fence。code 行也没有 4 个空格,因此该字符串不是连续的 4 空格缩进代码块。
请让代码行和末尾围栏也使用 4 个空格,或移除末尾的无缩进围栏。
建议修正
- input: ' ```js\ncode\n```',
- output: ' ```js\ncode\n```',
+ input: ' ```js\n code\n ```',
+ output: ' ```js\n code\n ```',该建议依据 PR objective 对“保持 4 个空格缩进代码块及普通缩进文本的原有行为”的要求。
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { | |
| title: '4-space indent is indented code, not a fence', | |
| input: ' ```js\ncode\n```', | |
| output: ' ```js\ncode\n```', | |
| }, | |
| { | |
| title: '4-space indent is indented code, not a fence', | |
| input: ' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/x-markdown/src/XMarkdown/__tests__/hooks.test.tsx` around lines 301
- 305, 修正测试夹具“4-space indent is indented code, not a fence”:在该用例的 input 和 output
中为 code 行及末尾围栏都添加 4 个前导空格,确保整个字符串保持连续的 4 空格缩进代码块。
🤔 这个变动的性质是?
🔗 相关 Issue
fix #2017
💡 需求背景和解决方案
问题:
feedFenceState(packages/x-markdown/src/XMarkdown/hooks/useStreaming.ts)只在行首为列 0 时识别围栏代码块(fenced code block)。CommonMark 允许 fence 前有 0-3 个空格(例如列表项内嵌套的代码块),但前导空格会先命中 else 分支置lineFenceRunEnded = true,反引号不再累积——缩进的 opening fence 不可见,之后顶格的 closing fence 被误认为新的 opening,inFenced永久 latch。流式中间态下缩进代码块内容不受isInCodeBlock保护,[/</$开头的内容被挂起(闪烁 / 占位符抖动),且最终输出可能丢失 closing fence 的字符。方案:在
FenceState中新增lineFenceIndent(当前行已消费的前导空格数),feedFenceState在 fence run 开始前容忍 0-3 个空格;第 4 个空格或任何非 fence 字符仍会结束 run(4 空格缩进代码块、普通缩进文本不受影响)。lineFenceIndent随其他行内状态在\n时重置。验证:
inFenced=true,修复版全部正确开合;无缩进对照与 4 空格缩进代码(非 fence)行为不变。useStreaming(流式模式,hasNextChunk: true)下,```js\nconst a = [1,2];\n ```原始版输出丢失 closing fence(以``结尾),修复版输出与输入逐字一致。fencedCodeTestCases(2/3 空格缩进开合、缩进波浪线、列表项内 fence、closing 后带尾随空格、4 空格反向用例),本地 jest 全量通过(102/102,含存量 4 个 fence 回归用例)。📝 更新日志
feedFenceStatenot recognizing fenced code blocks with 0-3 leading spaces (e.g. inside list items) during streaming, which caused incomplete-token churn and a stuck fence state.Summary by CodeRabbit