# @diplodoc/mdx-extension 中文文档

规范地址：https://npmcn.com/package/%40diplodoc/mdx-extension/

版本：1\.10\.1
npm 元数据更新时间：2026-08-18T09:10:50.595Z
中文译文更新时间：2026-11-12T10:52:41.116Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40diplodoc/mdx-extension
原文对照：https://npmcn.com/package/%40diplodoc/mdx-extension/?lang=original
项目主页：https://github.com/diplodoc-platform/mdx-extension#readme
源码仓库：https://github.com/diplodoc-platform/mdx-extension

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.2 MB，162 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：3 个
- peer 依赖：react ^16\.14\.0 \|\| ^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0，react-dom ^16\.14\.0 \|\| ^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0
- 首次发布：2025-05-26T10:35:33.861Z
- 最新版本发布：2026-06-17T13:20:26.205Z
- 近 30 天下载量：6632（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：37（近 12 个月 7 个）

## 中文简介

[![npm version](https://img.shields.io/npm/v/@diplodoc/mdx-extension?logo=npm)](https://www.npmjs.com/package/@diplodoc/mdx-extension) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)

## 安装

```sh
npm install @diplodoc/mdx-extension
```

也可以使用：`pnpm add @diplodoc/mdx-extension`、`yarn add @diplodoc/mdx-extension`、`bun add @diplodoc/mdx-extension`

## README

# @diplodoc/mdx-扩展

[![npm version](https://img.shields.io/npm/v/@diplodoc/mdx-extension?logo=npm)](https://www.npmjs.com/package/@diplodoc/mdx-extension) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Diplodoc的标记下变压器的MDX扩展可以将MDX/JSX组件嵌入标记下的内容.

## 安装

```bash
npm install @diplodoc/mdx-extension
# or
yarn add @diplodoc/mdx-extension
```

## 特征

-   无缝地将JSX/MDX组件纳入下调内容
-   支持客户端(CSR)和服务器端(SSR)渲染
-   跟踪背景变化的背景支持
-   多个语法选项 :
    -   明确 `<MDX>...</MDX>` 标记
    -   JSX碎片 `<>...</>`
    -   直接反应组件使用 `<Component />`
-   MDX 输入验证的内置安全
-   对高级组件安装的门户支持 `withPortal`
-   通过同步组件加载支持 `idMdxComponentLoader`
-   缺失 MDX 引用的默认组件倒计时 `recmaDefaultComponent`

## 使用量

### 基本设置

首先,增加一个 `mdxPlugin()` 到您的 Diplodoc 变换插件 :

```typescript
import transform from '@diplodoc/transform';
import DefaultPlugins from '@diplodoc/transform/lib/plugins';
import {mdxPlugin} from '@diplodoc/mdx-extension';

const result = transform(markdownContent, {
  plugins: [...DefaultPlugins, mdxPlugin()],
});
```

### 使用默认组件倒置

这个 `recmaDefaultComponent` 插件为缺失的 MDX 组件引用提供优雅回落. 它不扔出错误,而是重定向到可配置的默认组件.

```typescript
import {mdxPlugin, recmaDefaultComponent} from '@diplodoc/mdx-extension';

const result = transform(markdownContent, {
  plugins: [
    ...DefaultPlugins,
    mdxPlugin({
      compileOptions: {
        recmaPlugins: [recmaDefaultComponent({componentName: 'DefaultComponent'})],
      },
    }),
  ],
});
```

示例默认组件 :

```tsx
const Components = {
  DefaultComponent: ({tagName, ...props}) => (
    <div style={{border: '1px dashed red'}}>Missing component: {tagName}</div>
  ),
};
```

### 启用 MDX 输入验证

这个 `validateMdx` 插件为 **矩形插件** (Rhype Compatible MDAST to JavaScript AST 编译器)通过分析生成的抽象语法树(AST)来验证MDX内容的安全性. 它通过限制允许的JavaScript构造和模式来阻止潜在不安全代码的执行.

启用 MDX 输入的安全验证 :

```typescript
import {mdxPlugin, validateMdx} from '@diplodoc/mdx-extension';

const result = transform(markdownContent, {
  plugins: [
    ...DefaultPlugins,
    mdxPlugin({
      compileOptions: {
        recmaPlugins: [validateMdx],
      },
    }),
  ],
});
```

#### 插件验证

这个 `validateMdx` 插件通过 :

1.  **限制 JSX 道具值** 只允许:
    
    -   字数(字符串、数字、布尔)
    -   标识符
    -   阵列表达式( 有有效的元素)
    -   对象表达式( 具有有效属性)
    -   二进制表达式( 有有效的操作)
    -   JSX的具体呼吁`_jsxs`, (中文(简体) ), `_jsx`(中文(简体) )
2.  **封锁危险道具** 包括:
    
    -   `dangerouslySetInnerHTML`
    -   `ref`
    -   事件处理器(从 `on[A-Z]`(中文(简体) )
    -   在不安全的 URL 协议中 `href`, (中文(简体) ), `src`, (中文(简体) ), `action` 道具(块) `javascript:` 财务报告和审定财务报表 `data:text/html`(中文(简体) )
3.  **限制组件类型** 仅改为:
    
    -   已建MDX组件(`_Fragment`, (中文(简体) ), `MDXLayout`, (中文(简体) ), `_createMdxContent`(中文(简体) )
    -   来自 `_components` 对象
    -   文体组件名称
4.  **取消不安全的 JavaScript 构造**数字 :
    
    -   函数声明(特定 MDX 函数除外)
    -   可变声明(具体模式除外)
    -   成员表达式(具体模式除外)
    -   调用表达式( 特定函数除外)
    -   新表达式( 只有 `Error` 允许)
    -   散开元素( 仅特定模式)
    -   逻辑表达式( 只有特定模式)
    -   Async/await、出产、转让、导入和函数表达式
5.  **执行深度限制** (最大深度50)防止过于复杂的AST
    

#### 为什么使用这个插件?

-   **警卫**: 防止在 MDX 内容中执行任意 JavaScript 代码
-   **服务器侧保护**: 屏蔽安全代码, 可以在 SSR 期间执行
-   **受控制环境**:确保只允许批准的模式
-   **早期错误检测**: 在执行前抛出可疑模式的验证错误

#### 校验错误

当插件检测出无效的图案时,它会抛出描述性错误,例如:

-   不可允许“ 危险” 的组件道具
-   这里不允许“ 组件标签类型... ”
-   "功能宣言在这里是不允许的"
-   "最大深度超过"

### 客户端渲染( CSR)

```tsx
import React, {Fragment, useMemo, useRef} from 'react';
import transform from '@diplodoc/transform';
import DefaultPlugins from '@diplodoc/transform/lib/plugins';
import {mdxPlugin, useMdx, isWithMdxArtifacts, validateMdx} from '@diplodoc/mdx-extension';

const Components = {
  CustomComponent: (props) => <div {...props}>Custom</div>,
};

const CONTENT = `
# Markdown Content

<CustomComponent style={{color: 'red'}} />

<MDX>
  <div>This will be rendered as MDX</div>
</MDX>
`;

function App() {
  const ref = useRef(null);

  const {html, mdxArtifacts} = useMemo(() => {
    const {result} = transform(CONTENT, {
      plugins: [
        ...DefaultPlugins,
        mdxPlugin({
          compileOptions: {
            recmaPlugins: [validateMdx],
          },
        }),
      ],
    });

    isWithMdxArtifacts(result);

    return result;
  }, []);

  const portals = useMdx({
    refCtr: ref,
    html,
    components: Components,
    mdxArtifacts,
  });

  return (
    <Fragment>
      <div ref={ref}></div>
      {portals}
    </Fragment>
  );
}
```

### 服务器端渲染( SSR)

```tsx
import React from 'react';
import transform from '@diplodoc/transform';
import DefaultPlugins from '@diplodoc/transform/lib/plugins';
import {mdxPlugin, useMdxSsr, getSsrRenderer, validateMdx} from '@diplodoc/mdx-extension';

const Components = {
  ServerComponent: (props) => <strong {...props}>Server Rendered</strong>,
};

const CONTENT = `
# Server Rendered Content

<ServerComponent />
`;

export async function getServerSideProps() {
  const render = await getSsrRenderer({
    components: Components,
    compileOptions: {
      recmaPlugins: [validateMdx],
    },
  });

  const {result} = transform(CONTENT, {
    plugins: [...DefaultPlugins, mdxPlugin({render})],
  });

  isWithMdxArtifacts(result);

  const {html, mdxArtifacts} = result;

  return {props: {html, mdxArtifacts}};
}

function ServerPage({html, mdxArtifacts}) {
  const ref = useRef(null);

  const portals = useMdxSsr({
    refCtr: ref,
    components: Components,
    mdxArtifacts,
    html,
  });

  const innerHtml = useMemo(() => {
    return {__html: html};
  }, [html]);

  return (
    <Fragment>
      <div ref={ref} dangerouslySetInnerHTML={innerHtml}></div>
      {portals}
    </Fragment>
  );
}
```

## 收集插件

收集插件在收集文物的同时提供处理和转换MDX内容的功能. 它同时以同步和同步两种版本出现.

### 同步收集插件

```typescript
import {getMdxCollectPlugin} from '@diplodoc/mdx-extension';

const plugin = getMdxCollectPlugin({
  tagNames: ['CustomComponent'], // Optional filter for specific tags
  pureComponents: PURE_COMPONENTS,
  compileOptions: {
    // MDX compilation options
  },
});

const transformedContent = plugin(originalContent);
```

### 一个同步收集插件

```typescript
import {getAsyncMdxCollectPlugin} from '@diplodoc/mdx-extension';

const asyncPlugin = getAsyncMdxCollectPlugin({
  tagNames: ['AsyncComponent'], // Optional filter for specific tags
  pureComponents: PURE_COMPONENTS,
  compileOptions: {
    // MDX compilation options
  },
});

const transformedContent = await asyncPlugin(originalContent);
```

## 占位符渲染器

占位器渲染器为MDX内容提供了两相渲染方法. 这对于您需要将解析与执行区分开来, 如延迟渲染, SSR 组件等, 或当您要在多个通道中处理 MDX 内容时, 都是有益的 .

### 如何运作

1.  **占位符生成**: 在初始MDX处理过程中 `getPlaceholderRenderer` 函数创建带有唯一ID的占位符 HTML 元素,并存储 MDX 的原始内容 `mdxArtifacts.idFragment`。 。 。 .
    
2.  **占位符渲染**: 后来 `createPlaceholderRender` 或者说 `createAsyncPlaceholderRender` 函数处理这些占位符,用实际制作的 HTML 取而代之,并将汇编的代码存储在 `idMdx` 财务报告和审定财务报表 `idTagName` 用于客户端水分.
    

### 使用量

```typescript
import {getPlaceholderRenderer, createPlaceholderRender} from '@diplodoc/mdx-extension';

// Create a placeholder renderer
const placeholderRenderer = getPlaceholderRenderer();

// Use it in mdxPlugin
const {result} = transform(content, {
  plugins: [
    ...DefaultPlugins,
    mdxPlugin({
      render: placeholderRenderer,
    }),
  ],
});

// Later, render the placeholders
const render = createPlaceholderRender({
  components: YOUR_COMPONENTS,
  // ... other options
});

const finalHtml = render(result.html, result.mdxArtifacts);
```

### 同步占位符渲染

用于同步渲染(例如,组件具有 `withInitialProps`),使用同步版本:

```typescript
import {createAsyncPlaceholderRender} from '@diplodoc/mdx-extension';

const asyncRender = createAsyncPlaceholderRender({
  components: YOUR_COMPONENTS,
  // ... other options
});

const finalHtml = await asyncRender(result.html, result.mdxArtifacts);
```

## Raw MDX 内容插件

这个 `remarkRawMdxContent` 插件是一个注释插件,在指定的组件内取出原始的MDX内容并保存为文本,防止被解析为MDX. 这对需要输出原始MDX/JSX作为文本内容的组件(例如代码示例,文档生成器)有用.

### 如何运作

插件处理 MDX JSX 元素并针对指定的标签名,取出打开和关闭标签之间的原始文本内容. 然后用一个包含该原始内容的单一文本节点来取而代之,保留了原始格式.

### 使用量

```typescript
import {remarkRawMdxContent} from '@diplodoc/mdx-extension';
import {unified} from 'unified';
import remarkParse from 'remark-parse';
import remarkMdx from 'remark-mdx';

const processor = unified()
  .use(remarkParse)
  .use(remarkMdx)
  .use(remarkRawMdxContent, {
    tagNames: ['CodeExample', 'RawContent'], // Specify which tags to process
  });

const tree = processor.parse(`# Example

<CodeExample>
  <Button>Click me</Button>
</CodeExample>`);

const transformedTree = processor.runSync(tree);
```

### 与 Diplodoc 变形合并

您可以使用插件作为您的 Diplodoc 变换管道的一部分 :

```typescript
import transform from '@diplodoc/transform';
import DefaultPlugins from '@diplodoc/transform/lib/plugins';
import {mdxPlugin, remarkRawMdxContent} from '@diplodoc/mdx-extension';

const result = transform(content, {
  plugins: [
    ...DefaultPlugins,
    mdxPlugin({
      compileOptions: {
        remarkPlugins: [[remarkRawMdxContent, {tagNames: ['CodeExample']}]],
      },
    }),
  ],
});
```

这将确保内部内容 `<CodeExample>` 标记保存为原始文本,而不是解析为MDX.

## API 参考

### `mdxPlugin(options?: { render?: MDXRenderer })`

允许MDX处理的主要插件功能.

#### 选项 :

-   `render`: 可选的渲染器功能,用于SSD `getSsrRenderer`
-   `tagNames?: string[]` - 可选的标签名称阵列以过滤将处理哪些组件

### `useMdx(options: UseMdxProps): React.Fragment`

用于客户端MDX处理的反应钩.

#### 选项 :

-   `refCtr`: 参考容器元素
-   `html`: 来自 Diplodoc 转换的 HTML 字符串
-   `components`: 要使用的反应组件对象
-   `mdxArtifacts`: MDX 变形器
-   `pureComponents?`: 不应被水合物(MDX Contiments)组件的可选对象
-   `contextList?`: 向 MDX 组件提供反射语境阵列
-   `idMdxComponentLoader?`: 自定义 mdx 组件加载器

### `useMdxSsr(options: UseMdxSsrProps): React.Fragment`

SSR处理过的MDX内容的回放钩.

#### 选项 :

-   `refCtr`: 参考容器元素
-   `html`: 来自 Diplodoc 转换的 HTML 字符串
-   `components`: 要使用的反应组件对象
-   `mdxArtifacts`: MDX 变形器
-   `pureComponents?`: 不应被水合物(MDX Contiments)组件的可选对象
-   `contextList?`: 向 MDX 组件提供反射语境阵列
-   `idMdxComponentLoader?`: 自定义 mdx 组件加载器

### `getRenderer(options: GetRenderProps)`

为客户端处理创建渲染器功能.

#### 选项 :

-   `compileOptions?`: MDX 编译选项(参见 [MDX 文档](https://mdxjs.com/packages/mdx/#compileoptions)(中文(简体) )

### `getSsrRenderer(options: GetSsrRendererProps)`

创建用于服务器侧处理的 SSR 渲染器功能.

#### 选项 :

-   `components`: 要使用的反应组件对象
-   `pureComponents?`: 不应被水合物(MDX Contiments)组件的可选对象
-   `compileOptions?`: MDX 编译选项(参见 [MDX 文档](https://mdxjs.com/packages/mdx/#compileoptions)(中文(简体) )
-   `contextList?`: 向 MDX 组件提供反应上下文阵列。 使用 `{ ctx, initValue }` 通过 SSR 初始值的格式

### `getAsyncSsrRenderer(options: GetAsyncSsrRendererProps)`

创建支持的同步 SSR 渲染器 `withInitialProps`。 。 。 .

#### 选项 :

-   `components`: 要使用的反应组件对象
-   `pureComponents?`: 不应被水合物(MDX Contiments)组件的可选对象
-   `compileOptions?`: MDX 编译选项(参见 [MDX 文档](https://mdxjs.com/packages/mdx/#compileoptions)(中文(简体) )
-   `contextList?`: 向 MDX 组件提供反应上下文阵列。 使用 `{ ctx, initValue }` 通过 SSR 初始值的格式

### `getMdxCollectPlugin(options: Options)`

创建用于处理 MDX 内容的同步收集插件.

#### 选项 :

-   `tagNames?: string[]` - 可选的标签名称阵列以过滤处理
-   `pureComponents?`: 应跳过客户端水合的组件
-   `compileOptions?`: MDX 编译选项

### `getAsyncMdxCollectPlugin(options: AsyncOptions)`

创建一个同步收集插件,支持带有初始道具的组件.

#### 选项 :

-   `tagNames?: string[]` - 可选的标签名称阵列以过滤处理
-   `pureComponents?`: 应跳过客户端水合的组件
-   `compileOptions?`: MDX 编译选项

### 州管理背景

#### `MdxStateCtx: Context<MdxStateCtxValue>`

提供对当前 MDX 状态的访问 :

```tsx
const state = useContext(MdxStateCtx);
```

#### `MdxSetStateCtx: Context<MdxSetStateCtxValue>`

提供状态设置函数( 只在 SSR 期间可用) :

```tsx
const setState = useContext(MdxSetStateCtx);
// Usage in SSR:
setState?.({key: value});
```

### 组件增强器

#### `withInitialProps: WithInitialProps`

环绕一个组件,以便在 SSR 期间获取初始道具.

**参数:**

-   `component`: 反射组件来包接
-   `getInitProps`: 接收道具和MDX状态的函数,返回道具(同步或sync)

#### `withPortal: WithPortalProps`

通过 React.createPortal 包成组件,允许更灵活的挂起.

**参数:**

-   `component`: 反射组件来包接
-   `fallback`: 可选倒置组件在挂载门户前显示

**用法 :**

```tsx
export const COMPONENTS = {
  Tabs: withPortal(TabsLocal, () => <Skeleton />),
};
```

使用时 `withPortal`本构成部分将:

1.  初始后退组件(如果提供)
2.  准备时创建挂载实际组件的门户
3.  卸载时清理门户

## 语法示例

### 明确的 MDX 标记

```markdown
<MDX>
  <MyComponent prop="value" />
</MDX>
```

### JSX 碎片

```markdown
<>

  <div>Fragment content</div>
</>
```

### 直接组件使用

```markdown
<Button onClick={() => console.log('click')}>
Click me
</Button>
```

## 高级特性

### 安全部门改革国家管理

库为服务器-Side渲染(SSR)期间管理状态提供两个上下文提供者:

-   **`MdxSetStateCtx`** - 提供更新MDX状态功能的背景。 此功能仅在SSD期间可用(`null` 在客户端。 如果您使用此上下文设置了组件状态,则会是:
    
    -   序列化为 `data-mdx-state` sSR 期间属性
    -   备查 `MdxStateCtx` 当组件生成时
-   **`MdxStateCtx`** - 提供一个访问当前 MDX 状态值的上下文
    

### 与初始道具同步 SSR

-   **`withInitialProps`** - 能够同步获取安全部门改革数据的更高级组件:
    
    -   将一个组件与此函数并用时 `getAsyncSsrRenderer`,则 `getInitialProps` 函数将调用
    -   接收组件道具和 MDX 状态作为参数
    -   可以返回静态或基于承诺的道具
-   **`getAsyncSsrRenderer`** - 一个同步的版本 `getSsrRenderer` 即:
    
    -   支持用包起来的组件 `withInitialProps`
    -   允许在 SSR 期间获取同步数据

示例用法:

```typescript
const getInitialProps: MDXGetInitialProps<CounterProps> = (props, mdxState) => {
  mdxState.initialValue = 10; // Set initial state
  return props;
};

export const SSR_COMPONENTS = {
  ...COMPONENTS,
  Counter: withInitialProps(Counter, getInitialProps),
};
```

### 纯元件

库支持纯组件:

-   只在安全部门改革期间做过一次
-   客户端跳过水合
-   可通过 `pureComponents` 选项
    -   `useMdx`
    -   `useMdxSsr`
    -   `getSsrRenderer`
    -   `getAsyncSsrRenderer`

示例

```typescript
export const PURE_COMPONENTS = {
  KatexFormula, // Will render once on server and not hydrate
  Label, // on client
  CompatTable,
  Alert,
};
```

### 同步组件加载

这个 `useMdx` 财务报告和审定财务报表 `useMdxSsr` 钩子支持可选 `idMdxComponentLoader` 能够同步加载 MDX 组件的参数:

```tsx
interface PageProps {
  html: string;
  mdxArtifacts?: MdxArtifacts;
  withLoader?: boolean;
}

const Page: FC<PageProps> = ({html, mdxArtifacts}) => {
  const [isSuccess, setSuccess] = React.useState(false);
  const [data, setData] = React.useState<IdMdxComponentLoader['data']>(undefined);

  useMdxSsr({
    // ...other options
    idMdxComponentLoader: {isSuccess, data},
  });

  useEffect(() => {
    (async () => {
      const idMdxComponent: Record<string, React.ComponentType<MDXProps>> = {};

      for (const [artifactId, code] of Object.entries(mdxArtifacts?.idMdx ?? {})) {
        const fn = await asyncExecuteCode(code);
        idMdxComponent[artifactId] = fn(runtime).default;
      }

      setData(idMdxComponent);
      setSuccess(true);
    })();
  }, [mdxArtifacts]);

  // ...rest of the component
};
```

### 汇编选项

所有渲染器的功能( A)`getSsrRenderer`, (中文(简体) ), `getAsyncSsrRenderer`, (中文(简体) ), `getRenderer`)接受可选的MDX编译选项:

```typescript
const renderer = await getAsyncSsrRenderer({
  components: SSR_COMPONENTS,
  pureComponents: PURE_COMPONENTS,
  compileOptions: {
    // MDX compilation options here
  },
});
```

这允许在保持库核心功能的同时,对MDX编译过程进行精细控制.

## 许可证

麻省理工学院

## 常见问题

### 如何安装 @diplodoc/mdx-extension？

在项目目录运行 npm install @diplodoc/mdx-extension，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^16\.14\.0 \|\| ^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0）、react-dom（^16\.14\.0 \|\| ^17\.0\.0 \|\| ^18\.0\.0 \|\| ^19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @diplodoc/mdx-extension 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @diplodoc/mdx-extension 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @diplodoc/mdx-extension 可以商用吗？

@diplodoc/mdx-extension 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @diplodoc/mdx-extension 的下载量有多少？

根据 npm 官方下载统计，@diplodoc/mdx-extension 在 2026/10/13 – 2026/11/11 这 30 天内被下载 6,632 次，日均约 221 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @diplodoc/mdx-extension 还在维护吗？

最新版本 1\.10\.1 发布于 2026/06/17（4 个月前）；至今共发布 37 个版本，其中过去 12 个月发布了 7 个；首次发布于 2025/05/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

