代码块元信息提取:用 Shiki transformer 而非 remark 插件
给代码块加文件名显示时,remark 方案写入的属性会被 Astro 的 Shiki 渲染丢弃,改用 shikiConfig.transformers 在最终 HTML 上挂 data-meta。
背景
想让代码围栏支持 title="reading-time.js" 这样的元信息,在代码块头部显示文件名。Astro 的 Markdown 管线里有两个可能的挂载点:remark(AST 阶段)和 Shiki transformer(渲染阶段)。
备选方案
- remark 插件:遍历 AST,往
node.data.hProperties写data-meta; - 前端正则解析:从渲染后的 class 里反推语言与元信息;
- shikiConfig.transformers 的
pre(node)钩子:从this.options.meta.__raw取围栏 meta,写到最终<pre>上。
决定
采用方案 3。
取舍
- 方案 1 看似标准,实测无效:Astro 用 Shiki 重新生成
<pre>,remark 写的自定义属性整体丢失;这也提醒我们——在管线中段写属性,必须确认下游不会重绘同一个节点。 - 方案 2 拿不到 title 元信息,只能拿到语言,能力不足。
- 方案 3 的 transformer 直接作用在最终输出上,稳定;语言名顺便从 Shiki 的
data-language属性读取,省一次解析。 - 附带收益:
wrap: false让长代码横向滚动,不再折行。
决策回顾
followUp:
- date: 2026-10-25 note: 同一 transformer 模式后来复用到了练习题、对比卡片等更多围栏的数据传递上,方案经住了扩展考验。 retrospective: 合适。transformer 是 Shiki 官方扩展点,稳定性与可维护性都好于在 remark 层对抗渲染管线。
决策回顾
当初的选择是否合适 合适。transformer 是 Shiki 官方扩展点,稳定性与可维护性都好于在 remark 层对抗渲染管线。
- 同一 transformer 模式后来复用到了练习题、对比卡片等更多围栏的数据传递上,方案经住了扩展考验。