\n\n \n \n \n ```\n\n 通过 `intlayerMarkdown` 插件进行全局配置(支持 MDX 自定义组件):\n\n ```ts fileName=\"main.ts\"\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n\n app.use(intlayerMarkdown, {\n components: {\n h1: (props) => h('h1', { style: { color: 'green' } }, props.children),\n MyButton: (props) => h('button', props), // MDX 组件\n },\n });\n ```\n\n > 如果未安装 `intlayerMarkdown` 插件,Intlayer 将使用默认编译器进行渲染。\n\n 您还可以使用 `.use()` 方法提供特定节点的局部覆盖:\n\n ```vue\n h('h1', { style: { color: 'red' } }, props.children),\n })\" />\n ```\n\n 您可以以字符串形式检索 Markdown:\n\n ```vue\n {{ myMarkdownContent.value }}\n {{ String(myMarkdownContent) }}\n {{ myMarkdownContent.toString() }}\n ```\n\n 您可以像这样访问您的 markdown 元数据:\n\n ```vue\n \n \n ```\n\n \n \n 默认情况下,Svelte 将 Markdown 呈现为 HTML 字符串。使用 `{@html}` 来渲染它。\n\n ```svelte fileName=\"App.svelte\"\n \n\n \n {@html $content.myMarkdownContent}\n \n ```\n\n > 如果未提供 `MarkdownProvider`,Intlayer 将使用默认编译器渲染 markdown。\n\n 您还可以使用 `.use()` 方法提供特定节点的局部覆盖:\n\n ```svelte\n {@html $content.myMarkdownContent.use({ ... })}\n ```\n\n 您可以以字符串形式检索 Markdown:\n\n ```svelte\n {$content.myMarkdownContent.value}\n {String($content.myMarkdownContent)}\n {$content.myMarkdownContent.toString()}\n ```\n\n 您可以像这样访问您的 markdown 元数据:\n\n ```svelte\n {$content.myMarkdownContent.metadata}\n {$content.myMarkdownContent.metadata.title}\n ```\n\n \n \n Preact 直接支持 JSX 中的 Markdown 节点。\n\n ```tsx fileName=\"App.tsx\"\n import { useIntlayer } from \"preact-intlayer\";\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n const AppContent = () => {\n const { myMarkdownContent } = useIntlayer(\"app\");\n return {myMarkdownContent}
;\n };\n\n const App = () => (\n {children}
,\n MyButton: (props) => , // MDX 组件\n }}\n >\n \n \n );\n ```\n\n > 如果未提供 `MarkdownProvider`,Intlayer 将使用默认的 Markdown 转 JSX 解析器渲染 markdown。\n\n 您还可以使用 `.use()` 方法提供特定节点的局部覆盖:\n\n ```tsx\n {myMarkdownContent.use({\n h1: ({ children }) => {children}
,\n })}\n ```\n\n 您可以以字符串形式检索 Markdown:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n 您可以像这样访问您的 markdown 元数据:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Solid 直接支持 JSX 中的 Markdown 节点。\n\n ```tsx fileName=\"App.tsx\"\n import { useIntlayer } from \"solid-intlayer\";\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n const AppContent = () => {\n const { myMarkdownContent } = useIntlayer(\"app\");\n return {myMarkdownContent}
;\n };\n\n const App = () => (\n {props.children}
,\n MyButton: (props) => , // MDX 组件\n }}\n >\n \n \n );\n ```\n\n > 如果未提供 `MarkdownProvider`,Intlayer 将使用默认的 Markdown 转 JSX 解析器渲染 markdown。\n\n 您还可以使用 `.use()` 方法提供特定节点的局部覆盖:\n\n ```tsx\n {myMarkdownContent.use({\n h1: (props) => {props.children}
,\n })}\n ```\n\n 您可以以字符串形式检索 Markdown:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n 您可以像这样访问您的 markdown 元数据:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Angular 使用 `[innerHTML]` 指令来呈现 Markdown 内容。\n\n ```typescript fileName=\"app.component.ts\"\n import { Component } from \"@angular/core\";\n import { useIntlayer } from \"angular-intlayer\";\n\n @Component({\n selector: \"app-root\",\n template: ``,\n })\n export class AppComponent {\n content = useIntlayer(\"app\");\n }\n ```\n\n > 如果未配置 IntlayerMarkdown 提供程序,Intlayer 将使用默认编译器进行渲染。\n\n 您还可以使用 `.use()` 方法提供特定节点的局部覆盖:\n\n ```typescript\n content().myMarkdownContent.use({\n h1: { class: \"text-3xl font-bold\" },\n })\n ```\n\n 您可以以字符串形式检索 Markdown:\n\n ```typescript\n content().myMarkdownContent.value\n String(content().myMarkdownContent)\n content().myMarkdownContent.toString()\n ```\n\n 您可以像这样访问您的 markdown 元数据:\n\n ```typescript\n content().myMarkdownContent.metadata\n content().myMarkdownContent.metadata.title\n ```\n\n \n\n\n### 2. 辅助实用程序(仅限 Markdown 字符串)\n\n这些实用程序渲染 **仅限原始 Markdown 字符串** 且独立于 `useIntlayer`。当您需要从词典以外的来源渲染 Markdown 时使用它们。\n\n\n \n \n #### `` 组件\n\n 使用特定选项渲染 Markdown 字符串。\n\n ```tsx\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n \n {\"# 我的标题\"}\n \n ```\n\n #### `useMarkdownRenderer()` 钩子\n\n 获取预配置的渲染器函数。\n\n ```tsx\n import { useMarkdownRenderer } from \"react-intlayer/markdown\";\n\n const renderMarkdown = useMarkdownRenderer({\n forceBlock: true,\n components: { h1: (props) => }\n });\n\n return renderMarkdown(\"# 我的标题\");\n ```\n\n #### `renderMarkdown()` 实用程序\n 组件外部渲染的独立实用程序。\n\n ```tsx\n import { renderMarkdown } from \"react-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# 我的标题\", { forceBlock: true });\n ```\n\n \n \n \n #### `` 组件\n\n 使用特定选项渲染 Markdown 字符串。\n\n ```tsx\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n \n {\"# 我的标题\"}\n \n ```\n\n #### `useMarkdownRenderer()` 钩子\n\n 获取预配置的渲染器函数。\n\n ```tsx\n import { useMarkdownRenderer } from \"next-intlayer/markdown\";\n\n const renderMarkdown = useMarkdownRenderer({\n forceBlock: true,\n components: { h1: (props) => }\n });\n\n return renderMarkdown(\"# 我的标题\");\n ```\n\n #### `renderMarkdown()` 实用程序\n 组件外部渲染的独立实用程序。\n\n ```tsx\n import { renderMarkdown } from \"next-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# 我的标题\", { forceBlock: true });\n ```\n\n \n \n\n #### `` 组件\n\n ```vue\n \n\n \n \n \n ```\n\n \n \n\n #### `` 组件\n\n ```svelte\n \n\n \n ```\n\n #### `useMarkdownRenderer()` 钩子\n\n ```svelte\n \n\n {@html render(\"# 我的标题\")}\n ```\n\n #### `renderMarkdown()` 实用程序\n\n ```svelte\n \n\n {@html renderMarkdown(\"# 我的标题\")}\n ```\n\n \n \n #### `` 组件\n\n ```tsx\n import { MarkdownRenderer } from \"preact-intlayer/markdown\";\n\n \n {\"# 我的标题\"}\n \n ```\n\n #### `useMarkdownRenderer()` 钩子\n\n ```tsx\n import { useMarkdownRenderer } from \"preact-intlayer/markdown\";\n\n const render = useMarkdownRenderer();\n\n return {render(\"# 我的标题\")}
;\n ```\n\n #### `renderMarkdown()` 实用程序\n\n ```tsx\n import { renderMarkdown } from \"preact-intlayer/markdown\";\n\n return {renderMarkdown(\"# 我的标题\")}
;\n ```\n\n \n \n #### `` 组件\n\n ```tsx\n import { MarkdownRenderer } from \"solid-intlayer/markdown\";\n\n \n {\"# 我的标题\"}\n \n ```\n\n #### `useMarkdownRenderer()` 钩子\n\n ```tsx\n import { useMarkdownRenderer } from \"solid-intlayer/markdown\";\n\n const render = useMarkdownRenderer();\n\n return {render(\"# 我的标题\")}
;\n ```\n\n #### `renderMarkdown()` 实用程序\n\n ```tsx\n import { renderMarkdown } from \"solid-intlayer/markdown\";\n\n return {renderMarkdown(\"# 我的标题\")}
;\n ```\n\n \n \n #### `IntlayerMarkdownService` 服务\n 使用服务呈现 Markdown 字符串。\n\n ```typescript\n import { IntlayerMarkdownService } from \"angular-intlayer/markdown\";\n\n export class MyComponent {\n constructor(private markdownService: IntlayerMarkdownService) {}\n\n renderMarkdown(markdown: string) {\n return this.markdownService.renderMarkdown(markdown);\n }\n }\n ```\n\n \n\n\n## 使用 `MarkdownProvider` 进行全局配置\n\n`MarkdownProvider`(或其框架对应的组件)为整个应用程序配置 Markdown 渲染管道。它适用于自动 `useIntlayer` 渲染和辅助实用程序。此处设置的选项为默认值 — `.use()` 在节点级别将其覆盖。\n\n\n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"react-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n ,\n a: ({ href, ...props }) => ,\n MyCustomJSXComponent: (props) => ,\n }}\n >\n {children}\n \n );\n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"react-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n // Use dynamic import to reduce the bundle size of your application\n const { renderMarkdown } = await import('react-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"next-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n ,\n a: ({ href, ...props }) => ,\n MyCustomJSXComponent: (props) => ,\n }}\n >\n {children}\n \n );\n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"next-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n // Use dynamic import to reduce the bundle size of your application\n const { renderMarkdown } = await import('next-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```typescript fileName=\"main.ts\"\n import { createApp } from \"vue\";\n import { intlayer } from \"vue-intlayer\";\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n import App from \"./App.vue\";\n\n const app = createApp(App);\n\n app.use(intlayer);\n app.use(intlayerMarkdown, {\n components: {\n h1: (props) =>\n h('h1', { style: { color: 'orange' }, ...props }, props.children),\n ComponentDemo: () => h('div', { style: { background: 'grey' } }, 'DEMO'),\n bold: (props) => h('strong', props),\n code: (props) => h('code', props),\n },\n });\n\n app.mount(\"#app\");\n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```typescript fileName=\"main.ts\"\n import { createApp } from \"vue\";\n import { intlayer } from \"vue-intlayer\";\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n import App from \"./App.vue\";\n\n const app = createApp(App);\n\n app.use(intlayer);\n app.use(intlayerMarkdown, {\n renderMarkdown: async (md) => {\n const { renderMarkdown } = await import('vue-intlayer/markdown');\n return renderMarkdown(md);\n },\n });\n\n app.mount(\"#app\");\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```svelte fileName=\"App.svelte\"\n \n\n \n \n \n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```svelte fileName=\"App.svelte\"\n \n\n {\n const { renderMarkdown } = await import('svelte-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n \n \n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {children}
,\n }}\n >\n {children}\n \n );\n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n const { renderMarkdown } = await import('preact-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n export const AppProvider = (props) => (\n {props.children}
,\n }}\n >\n {props.children}\n \n );\n ```\n\n\n > 支持 MDX — Markdown 内部使用的任何组件名称(例如 ``)都会根据 `components` 映射进行解析。\n\n 您还可以使用自己的 markdown 渲染器:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n export const AppProvider = (props) => (\n {\n const { renderMarkdown } = await import('solid-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {props.children}\n \n );\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n \n\n ```typescript fileName=\"app.module.ts\"\n import { NgModule } from '@angular/core';\n import { IntlayerMarkdownModule } from 'angular-intlayer/markdown';\n\n @NgModule({\n imports: [\n IntlayerMarkdownModule.forRoot({\n renderMarkdown: async (md) => {\n const { renderMarkdown } = await import('angular-intlayer/markdown');\n return renderMarkdown(md);\n }\n })\n ]\n })\n export class AppModule {}\n ```\n\n > 动态导入您的 Markdown 渲染器是减少应用程序Bundle 大小的好方法。\n\n \n\n\n## Suspense (悬念)\n\nIntlayer Markdown渲染器是动态加载的。虽然经过优化,但底层解析器块的大小约为55kb。同步加载会延迟初始页面渲染,并降低首次内容绘制(FCP)。\n\n为防止阻塞UI,Intlayer集成了React的Suspense API。它在后台获取解析器,并在下载期间抛出Promise。\n\n将渲染Intlayer Markdown的任何组件包装在``边界中。这会在下载块时显示本地化的后备状态,从而允许立即渲染DOM的其余部分。\n\n警告:如果不提供``边界,React将在根级别暂停或阻止整个组件树的渲染,直到55kb的块完全加载完毕。\n\n\n \n\n在Next.js App Router中,您可以为客户端组件使用React `Suspense`,或为服务器组件使用`loading.tsx`文件。\n\n**客户端组件:**\n\n```tsx fileName=\"components/MyComponent.tsx\"\n\"use client\";\nimport { useIntlayer } from \"next-intlayer\";\nimport { Suspense } from \"react\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n**带有`loading.tsx`的服务器组件:**\n\n```tsx fileName=\"app/loading.tsx\"\nexport default function Loading() {\n return Loading...
;\n}\n```\n\n```tsx fileName=\"app/page.tsx\"\nimport { useIntlayer } from \"next-intlayer/server\";\n\nconst MyPage = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n return {markdownContent}
;\n};\n\nexport default MyPage;\n```\n\n \n\n \n\n```tsx\nimport { useIntlayer } from \"react-intlayer\";\nimport { Suspense } from \"react\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n \n\nVue内置了``组件。将渲染Markdown内容的组件包装在``边界中。\n\n```vue fileName=\"MyComponent.vue\"\n\n\n\n \n \n \n Loading...
\n \n \n\n```\n\n \n \n\nSvelte没有Suspense API的等效项。使用`{#await}`块处理Markdown内容的异步渲染。\n\n```svelte fileName=\"MyComponent.svelte\"\n\n\n{#await $content.markdownContent}\n Loading...
\n{:then rendered}\n {@html rendered}\n{/await}\n```\n\n \n \n\nPreact通过`preact/compat`支持React的Suspense API。\n\n```tsx fileName=\"MyComponent.tsx\"\nimport { useIntlayer } from \"preact-intlayer\";\nimport { Suspense } from \"preact/compat\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n\nSolid有自己的来自`solid-js`的``组件。\n\n```tsx fileName=\"MyComponent.tsx\"\nimport { useIntlayer } from \"solid-intlayer\";\nimport { Suspense } from \"solid-js\";\n\nconst MyComponent = () => {\n const { markdownContent } = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n\nAngular没有Suspense API。使用Angular的可延迟视图(`@defer`)来处理延迟加载的Markdown内容(需要Angular 17+)。\n\n```typescript fileName=\"my.component.ts\"\nimport { Component } from \"@angular/core\";\nimport { useIntlayer } from \"angular-intlayer\";\n\n@Component({\n selector: \"app-my\",\n template: `\n @defer {\n \n } @loading {\n Loading...
\n }\n `,\n})\nexport class MyComponent {\n content = useIntlayer(\"my-markdown\");\n}\n```\n\n \n\n\n---\n\n## 服务端渲染 (SSR) 与 注水 (Hydration)\n\n与其他 Markdown 解析器(如 remark / rehype)相比,Intlayer Markdown 无依赖关系,且既可以在客户端运行,也可以在服务端运行。\n\n但是 Intlayer 针对服务端渲染 (SSR) 框架(如 Next.js App Router, React Router, Nuxt, SvelteKit 等)进行了解析优化。\n\nIntlayer 允许您在服务端将 Markdown 预解析为抽象语法树 (AST),而不是将原始 Markdown 字符串发送到客户端并在浏览器中解析(这会带来性能损失)。\n\n您可以在服务端使用框架的 Intlayer 包中的 `parseMarkdown` 函数来生成可序列化的 AST(`ParsedMarkdown` 对象),并将其直接传递给前端。所有 Intlayer 渲染工具(如 ``、`useMarkdownRenderer` 等)都会自动接受此 AST 对象并无缝渲染它。\n\n### 服务端/客户端架构中的示例\n\n\n \n\n ```tsx fileName=\"server.ts\"\n import { parseMarkdown } from \"react-intlayer/markdown\";\n\n // 1. 在服务端:将 markdown 解析为可序列化的 AST\n export const loader = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 将 AST 作为 JSON 返回给客户端\n return Response.json({ content: ast });\n };\n ```\n\n ```tsx fileName=\"client.tsx\"\n import { useLoaderData } from \"react-router\";\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n // 2. 在客户端:直接渲染 AST,无需重新解析\n export default function Page() {\n const { content } = useLoaderData();\n\n // 渲染器既接受原始字符串,也接受解析后的 AST\n return ;\n }\n ```\n\n \n \n\n ```tsx fileName=\"app/page.tsx\"\n import { parseMarkdown } from \"next-intlayer/markdown\";\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n export default async function Page() {\n // 1. 在服务端将 markdown 解析为可序列化的 AST\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 2. 直接渲染 AST\n // 在服务端组件(Server Component)中,这可以无缝工作,并在需要时\n // 直接将 AST 传递给底层的客户端组件。\n return ;\n }\n ```\n\n \n \n\n ```vue fileName=\"pages/index.vue\"\n \n\n \n \n \n \n ```\n\n \n \n\n ```typescript fileName=\"+page.server.ts\"\n import { parseMarkdown } from \"svelte-intlayer/markdown\";\n\n // 1. 在服务端:将 markdown 解析为可序列化的 AST\n export const load = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 将 AST 返回给客户端\n return { content: ast };\n };\n ```\n\n ```svelte fileName=\"+page.svelte\"\n \n\n \n \n ```\n\n \n \n\n Angular SSR 通常在初始加载期间在服务端解析数据,并在客户端进行注水。您可以使用解析器(resolvers)来传递 AST。\n\n ```typescript fileName=\"app.resolver.ts\"\n import { Injectable } from \"@angular/core\";\n import { Resolve } from \"@angular/router\";\n import { parseMarkdown, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Injectable({ providedIn: \"root\" })\n export class MarkdownResolver implements Resolve {\n resolve(): ParsedMarkdown {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n // 1. 在服务端:将 markdown 解析为可序列化的 AST\n return parseMarkdown(markdownString);\n }\n }\n ```\n\n ```typescript fileName=\"app.component.ts\"\n import { Component } from \"@angular/core\";\n import { ActivatedRoute } from \"@angular/router\";\n import { IntlayerMarkdownService, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Component({\n selector: \"app-root\",\n template: ``,\n })\n export class AppComponent {\n renderedMarkdown: string = \"\";\n\n constructor(\n private route: ActivatedRoute,\n private markdownService: IntlayerMarkdownService\n ) {\n // 2. 在客户端:直接渲染 AST,无需重新解析\n this.route.data.subscribe((data) => {\n this.renderedMarkdown = this.markdownService.renderMarkdown(\n data.markdownAst\n ) as string;\n });\n }\n }\n ```\n\n \n\n\n这种模式确保 Markdown 解析逻辑完全在服务端执行,从而显著减少客户端执行时间,并提高初始注水速度。\n\n## 选项参考\n\n这些选项可传递给`MarkdownProvider`、`MarkdownRenderer`、`useMarkdownRenderer`和`renderMarkdown`。\n\n| Option | Type | Default | 描述 |\n| :-------------------- | :---------- | :------ | :--------------------------------------------------------- |\n| `forceBlock` | `boolean` | `false` | 强制将输出包装在块级元素(例如``)中。 |\n| `forceInline` | `boolean` | `false` | 强制将输出包装在内联元素(例如`
`)中。 |\n| `tagfilter` | `boolean` | `true` | 启用GitHub标签过滤器以通过剥离危险的HTML标签来提高安全性。 |\n| `preserveFrontmatter` | `boolean` | `false` | 如果为`true`,则不会剥离Markdown字符串开头的frontmatter。 |\n| `components` | `Overrides` | `{}` | HTML标签到自定义组件的映射(例如`{ h1: MyHeading }`)。 |\n| `wrapper` | `Component` | `null` | 用于包装渲染Markdown的自定义组件。 |\n| `renderMarkdown` | `Function` | `null` | 自定义渲染函数,用于完全替换默认的Markdown编译器。 |\n","description":"了解如何使用 Intlayer 在您的多语言网站中声明和使用 Markdown 内容。按照本在线文档中的步骤将 Markdown 无缝集成到您的项目中。","url":"https://intlayer.org/zh/doc/concept/content/markdown","datePublished":"2025-02-07","dateModified":"2026-05-19","version":"8.11.0","keywords":"Markdown, 国际化, 文档, Intlayer, Next.js, JavaScript, React","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"开发者,内容经理"}}作者: Creation:2025-02-07Last update:2026-05-19
Markdown / 富文本内容
Intlayer 支持使用 Markdown 语法定义的富文本内容。这使您可以轻松编写和维护具有丰富格式的内容,例如博客、文章等。
声明 Markdown 内容
您可以使用 md 函数声明 Markdown 内容,或简单地将其作为字符串声明(如果它包含 Markdown 语法)。
渲染 Markdown
Intlayer 提供两种独立的方式来渲染 Markdown:
通过 useIntlayer
— Intlayer 会自动将 md 节点转换为框架的原生输出(JSX,VNode,HTML 字符串)。
- Frontmatter 被解析并作为
.metadata 暴露。您可以在两个级别上覆盖渲染 — 使用 MarkdownProvider(或框架等效物)进行全局覆盖,或使用 .use() 针对每个节点进行局部覆盖。两者可以结合使用;.use() 优先于 MarkdownProvider,而 MarkdownProvider 优先于默认渲染。
辅助实用程序 — <MarkdownRenderer />,useMarkdownRenderer() 和 renderMarkdown() 是独立的工具,仅接受原始 Markdown 字符串。它们独立于 useIntlayer,不与它返回的修饰节点一起工作。
Markdown 渲染支持 MDX — 在您的 Markdown 中直接按名称使用任何 JSX/框架组件。
1. 自动渲染(通过 useIntlayer)
2. 辅助实用程序(仅限 Markdown 字符串)
这些实用程序渲染 仅限原始 Markdown 字符串 且独立于 useIntlayer。当您需要从词典以外的来源渲染 Markdown 时使用它们。
使用 MarkdownProvider 进行全局配置
MarkdownProvider(或其框架对应的组件)为整个应用程序配置 Markdown 渲染管道。它适用于自动 useIntlayer 渲染和辅助实用程序。此处设置的选项为默认值 — .use() 在节点级别将其覆盖。
Suspense (悬念)
Intlayer Markdown渲染器是动态加载的。虽然经过优化,但底层解析器块的大小约为55kb。同步加载会延迟初始页面渲染,并降低首次内容绘制(FCP)。
为防止阻塞UI,Intlayer集成了React的Suspense API。它在后台获取解析器,并在下载期间抛出Promise。
将渲染Intlayer Markdown的任何组件包装在<Suspense>边界中。这会在下载块时显示本地化的后备状态,从而允许立即渲染DOM的其余部分。
警告:如果不提供<Suspense>边界,React将在根级别暂停或阻止整个组件树的渲染,直到55kb的块完全加载完毕。
服务端渲染 (SSR) 与 注水 (Hydration)
与其他 Markdown 解析器(如 remark / rehype)相比,Intlayer Markdown 无依赖关系,且既可以在客户端运行,也可以在服务端运行。
但是 Intlayer 针对服务端渲染 (SSR) 框架(如 Next.js App Router, React Router, Nuxt, SvelteKit 等)进行了解析优化。
Intlayer 允许您在服务端将 Markdown 预解析为抽象语法树 (AST),而不是将原始 Markdown 字符串发送到客户端并在浏览器中解析(这会带来性能损失)。
您可以在服务端使用框架的 Intlayer 包中的 parseMarkdown 函数来生成可序列化的 AST(ParsedMarkdown 对象),并将其直接传递给前端。所有 Intlayer 渲染工具(如 <MarkdownRenderer>、useMarkdownRenderer 等)都会自动接受此 AST 对象并无缝渲染它。
服务端/客户端架构中的示例
这种模式确保 Markdown 解析逻辑完全在服务端执行,从而显著减少客户端执行时间,并提高初始注水速度。
选项参考
这些选项可传递给MarkdownProvider、MarkdownRenderer、useMarkdownRenderer和renderMarkdown。
| Option | Type | Default | 描述 |
|---|
forceBlock | boolean | false | 强制将输出包装在块级元素(例如<div>)中。 |
forceInline | boolean | false | 强制将输出包装在内联元素(例如<span>)中。 |
tagfilter | boolean | true | 启用GitHub标签过滤器以通过剥离危险的HTML标签来提高安全性。 |
preserveFrontmatter | boolean | false | 如果为true,则不会剥离Markdown字符串开头的frontmatter。 |
components | Overrides | {} | HTML标签到自定义组件的映射(例如{ h1: MyHeading })。 |
wrapper | Component | null | 用于包装渲染Markdown的自定义组件。 |
renderMarkdown | Function | null | 自定义渲染函数,用于完全替换默认的Markdown编译器。 |