Storybook 中使用 Markdown Doc Block 导入并渲染外部 Markdown 文档 Storybook 中使用 Markdown Doc Block 导入并渲染外部 Markdown 文档【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook在本仓库Storybook 官方源码库的文档体系里docs/_snippets/storybook-custom-docs-markdown.md是一段承载把外部 Markdown 文件如 CHANGELOG.md无缝渲染进组件文档页这一核心用法的代码片段。本文以此为骨架结合 MDX 指南、Markdown Doc Block API 文档 与storybook/addon-docs的源码实现系统讲解MarkdownDoc Block 的使用姿势、?raw导入约定的必要性、底层渲染原理及 GFM 扩展配置读完你可以在自己的 Storybook 项目中把任何既有 Markdown 资产复用到文档站点中。场景与动机让既有 Markdown 资产活在文档中团队在长期迭代中往往会沉淀一批纯 Markdown 文档例如CHANGELOG.md、README.md、贡献指南或组件使用规范。它们与 Storybook 中基于 MDX 的组件文档并行存在维护成本高、内容易分叉。Storybook 在storybook/addon-docs中提供了名为Markdown的 Doc Block用来把这类纯 Markdown 内容原样导入并渲染到 MDX 页面内与Meta、Canvas、Controls等 Doc Block 组合成一篇完整的文档页。它适用的典型场景包括在文档页中内嵌项目的CHANGELOG.md让版本记录与组件文档同处一个站点复用已经写好的README.md避免同一份说明在两处重复维护将纯文本规范、工作流说明等插入到.mdx页面中作为附加章节。在 MDX 指南 Generate documentation from Markdown 一节中这一用法被官方推荐为扩展自定义文档的标准方式。最小可用示例把 CHANGELOG.md 渲染进文档页按照官方片段创建一个Changelog.mdx文件内容如下import { Meta, Markdown } from storybook/addon-docs/blocks; import Readme from ../../Changelog.md?raw; Meta titleChangelog / # Changelog Markdown{Readme}/Markdown逐行拆解这个示例中的关键要素片段作用import { Meta, Markdown } from storybook/addon-docs/blocks从storybook/addon-docs/blocks导入所需的两个 Doc BlockMeta负责文档在侧边栏中的定位与元信息Markdown负责渲染纯 Markdown 内容import Readme from ../../Changelog.md?raw以字符串形式加载项目中的Changelog.md原始内容。这里的../../是相对当前.mdx文件所在目录的路径指向你项目中的真实 Markdown 文件示例中为仓库根目录下的Changelog.mdMeta titleChangelog /通过titleprop 把文档节点放到侧边栏的任意层级不依赖任何组件 stories使其成为独立的文档专用docs-only页面Markdown{Readme}/Markdown把前面以?raw导入的字符串内容交给MarkdownDoc Block解析并渲染为页面的实际内容关于导入路径路径基于.mdx文件自身的物理位置进行解析因此实际书写时请替换为你项目中CHANGELOG.md或任意.md文件的真实相对位置。文件名也无需固定为Changelog.mdx可以按文档职责自由命名。为什么必须加?raw导入约定背后的原因代码中醒目地使用了?raw后缀这是本用法能否生效的关键。MDX 指南与 Markdown Doc Block API 文档 都强调了这一点?raw后缀让打包器把文件内容以纯文本字符串原样注入而不是当作模块被解析求值。如果直接写import ReadMe from ./README.md;不带?rawStorybook 在处理 MDX 时会尝试把它当作 MDX/JSX 语法处理从而引发错误。因此正确写法是// 错误写法会报错 import ReadMe from ./README.md; // 正确写法必须以 ?raw 结尾 import ReadMe from ./README.md?raw;从源码层面可以进一步印证这一约定在 code/addons/docs/src/blocks/blocks/Markdown.stories.tsx 中官方测试示例即通过import mdContent from ../examples/Markdown-content.md?raw方式加载真实 Markdown 文件并将其作为children传入Markdown组件验证原始字符串导入这条链路。这也说明该用法不仅在文档层面被推荐同时是组件实现所依赖的输入形式。MarkdownDoc Block 的 Props 与底层渲染实现MarkdownDoc Block 的完整 API 参见 doc-block-markdown.mdx其核心 Props 如下Prop类型说明childrenstring要解析和展示的、以 Markdown 语法格式化后的字符串通常来自?raw导入optionsobject透传给底层markdown-to-jsx库的配置项用于定制渲染行为children只接受字符串类型。阅读源码 code/addons/docs/src/blocks/blocks/Markdown.tsx 可以看到组件会先校验props.children若缺失则渲染null若类型不是字符串则抛出带引导性提示的错误并建议用模板字符串包裹即{\...}形式而不是把多行内容裸写在 标签内实际渲染委托给markdown-to-jsx提供的PureMarkdown组件并注入了一套默认的optionsforceBlock: true将根级文本强制按块级元素渲染避免裸文本直接输出overrides覆盖了code映射为CodeOrSourceMdx让行内代码与代码块呈现 Storybook 文档风格、a映射为AnchorMdx保证文档内链接行为一致以及各级标题HeadersMdx同时会把用户通过optionsprop 传入的overrides合并进来因此你可以按需继续定制任意 HTML 元素到 React 组件的映射。组件外层通过withMdxComponentOverride(Markdown, MarkdownImpl)包装允许 Storybook 在不同渲染场景下对Markdown进行组件级覆写。这些内部覆盖组件CodeOrSourceMdx、AnchorMdx、HeadersMdx定义于 code/addons/docs/src/blocks/blocks/mdx.tsx正是它们保证了导入的 Markdown 与页面内其余 MDX 内容在排版风格上保持一致。一个使用options的进阶示意由于options会被合并进底层markdown-to-jsx的配置你可以基于它调整渲染细节。例如把链接目标统一加上新窗口打开逻辑或自定义某个元素的样式映射import { Meta, Markdown } from storybook/addon-docs/blocks; import Readme from ./README.md?raw; Meta titleREADME / Markdown options{{ overrides: { h1: { props: { className: my-custom-heading } }, }, }} {Readme} /Markdown为什么不直接内联导入 Markdown你可能会问既然 MDX 本身支持 JSX 表达式为什么不直接把Readme作为表达式插入API 文档专门解释了这一问题。试看下面这段看起来可行的写法{/* 这种写法不可用仅用于演示问题 */} import ReadMe from ./README.md; {ReadMe}问题出在 MDX尤其是 MDX2/MDX3与纯 Markdown 之间存在语法差异MDX 对表达式与 JSX 标签的解析更加严格# A header { this is valid in a plain markdown file, but MDX2 will try to evaluate this as an expression } This is also valid, but MDX2 thinks this is a JSX component /上面两段在纯 Markdown 文件中都合法但一旦被 MDX 编译器处理{ ... }会被当作 JS 表达式求值、...会被当作 JSX 组件标签直接导致编译失败或渲染异常。此外MDX 会把换行包裹的字符串包进p等标签中造成同一份内容在.md与.mdx中渲染效果不一致。MarkdownDoc Block 的职责正是让纯 Markdown 按其本来的语义解析规避 MDX 对{}、尖括号等语法的干扰——这正是 Markdown.tsx 使用独立markdown-to-jsx渲染器而非 MDX 编译器的根本原因。进阶开启 GFM 以支持表格、脚注等扩展语法基础 CommonMark 不支持 GFMGitHub Flavored Markdown中的表格、删除线、脚注等语法。如果你的.md文件中包含 Markdown 表格且渲染不正确官方建议引入remark-gfm插件它并非默认依赖需要单独安装为开发依赖yarn add -D remark-gfm随后在.storybook/main.js|ts中通过addon-docs的options.mdxPluginOptions.mdxCompileOptions.remarkPlugins启用该插件完整写法可对照官方片段 storybook-main-config-remark-options.mdimport remarkGfm from remark-gfm; export default { framework: storybook/your-framework, // 替换为你实际使用的框架 stories: [../src/**/*.mdx, ../src/**/*.stories.(js|jsx|mjs|ts|tsx)], addons: [ { name: storybook/addon-docs, options: { mdxPluginOptions: { mdxCompileOptions: { remarkPlugins: [remarkGfm], }, }, }, }, ], };启用后Markdown 表格、任务列表等 GFM 语法即可在文档页中正确呈现。若你正在从旧版 Storybook 迁移到新版本 MDX官方在 mdx.mdx 的 Troubleshooting 一节还提供了迁移问题的排查建议与?path/story/...等文档内链接技巧可一并参考。总结MarkdownDoc Block 是 Storybook 复用既有纯 Markdown 文档的官方桥梁。其正确用法可归纳为三步用?raw后缀把.md内容导入为字符串 → 通过import { Markdown } from storybook/addon-docs/blocks引入组件 → 以Markdown{content}/Markdown形式渲染配合MetaDoc Block 即可将渲染结果挂载到侧边栏任意位置。需要支持表格等 GFM 语法时再通过.storybook/main.js中的remarkPlugins开启remark-gfm即可。进一步阅读MDX 与自定义文档总指南Markdown Doc Block API 参考Doc Blocks 创作文档总览Autodocs 自动化文档配置Markdown 组件源码实现Markdown 组件测试/演示 Stories【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考