自定义asciinema代码成功失败分析
很好,我们可以总结一下为什么之前失败,而现在成功了:
1️⃣ 之前失败的原因
-
使用
type: 'jsx', value: '<AsciinemaPlayer … />'-
MDX loader 不会执行字符串形式的 JSX。
-
它只会把它当作文本节点渲染到页面上。
-
结果页面显示
<AsciinemaPlayer … />字符串,而不是 React 组件。
-
-
尝试在 AST 中放 React 元素对象 (
React.createElement)-
Remark 插件本质上只生成 AST 节点。
-
MDX loader 不认识
data.reactElement,无法把 React 对象渲染成元素。 -
所以即便在 AST 中放了
React.createElement(BrowserOnly, …),页面也不会显示。
-
-
BrowserOnly 也无效
-
BrowserOnly 只是一个 React 组件,它需要在 React 渲染阶段被调用。
-
之前的插件生成的内容根本没有变成 React 组件节点,MDX loader 只是当成文本。
-
2️⃣ 为什么现在成功了
-
生成了
mdxJsxFlowElement节点-
MDX v2 loader 识别
mdxJsxFlowElementAST 节点,并直接转换为 React 元素。 -
这样生成的 AST 相当于在 Markdown 中写了 JSX:
mdx<AsciinemaPlayer file="…" autoplay={true}>
<span>5, 开始</span>
</AsciinemaPlayer> -
MDX loader 会在编译阶段把它变成可渲染的 React 组件。
-
-
属性和 children 都是标准 AST 节点
-
attributes使用mdxJsxAttribute,MDX loader 会解析true/false/number/string。 -
children使用mdxJsxTextElement+text节点,MDX loader 会转换为 React 子元素。
-
-
完全遵循 MDX AST 规范
-
不生成额外的
data.reactElement或type: 'jsx', value: ''。 -
因此 MDX loader 可以完整渲染,最终页面显示播放器,而不是字符串。
-
3️⃣ 核心总结
| 方案 | 原因 | 结果 |
|---|---|---|
type: 'jsx', value: '<… />' | 只是文本,不会被编译执行 | 页面显示字符串 <… /> |
data.reactElement = React.createElement(...) | MDX loader 不识别 React 对象 | 页面显示空或无效果 |
mdxJsxFlowElement + mdxJsxAttribute/children | 完全符合 MDX AST 规范 | 页面成功渲染为 React 组件 |
✅ 结论:
在 Remark 插件中生成 JSX,必须生成标准 MDX AST 节点 (mdxJsxFlowElement),才能被 MDX loader 渲染成 React 组件。
Markdown → Remark → MDX → React 渲染 流程
-
Markdown 解 析为 Remark AST
-
Markdown 文件被解析成树形结构(AST)。
-
每个 code block、段落、标题等都是 AST 节点。
-
-
Remark 插件处理 AST
-
插件遍历 AST,找到目标节点(比如
code节点)。 -
插件可以修改节点类型或内容。
-
关键:要生成 JSX,必须生成 MDX AST 节点(
mdxJsxFlowElement),而不是 React 对象或普通文本。
-
-
Remark AST → MDX AST
-
MDX loader 会把 AST 转换成 MDX AST,其中
mdxJsxFlowElement节点会被标记为 JSX 组件节点。 -
属性用
mdxJsxAttribute,子节点用mdxJsxTextElement。
-
-
MDX AST → Babel/React 编译
-
MDX loader 将 MDX AST 转为 React 组件代码。
-
JSX 节点会变成
React.createElement(Component, props, children)。
-
-
React 渲染
-
最终 React 渲染生成真实 DOM。
-
你的
<AsciinemaPlayer>会被调用,BrowserOnly和asciinema-player执行,生成播放器 DOM。
-
关键点总结
-
失败原因:生成的只是文本或 React 对象,MDX loader 不执行。
-
成功原因:生成了标准 MDX AST 节点,MDX loader 会正常编译成 React 元素。
-
经验:Remark 插件想在 MDX 中生成组件,必须遵循 MDX AST 规范,直接生成
mdxJsxFlowElement才行。
这也是为什么你现在在 Markdown 中写 code block 就可以直接显示播放器,而不再显示字符串。