---
title: "为 DOCX 导出自定义有序列表编号"
description: "定义可在 DOCX 导出中保留的多级有序列表编号格式，涵盖基础样式、标记模板、对齐、缩进和字体。"
canonical_url: "https://tiptap.zhcndoc.com/conversion/export/docx/ordered-list-numbering"
---

# 为 DOCX 导出自定义有序列表编号

定义可在 DOCX 导出中保留的多级有序列表编号格式，涵盖基础样式、标记模板、对齐、缩进和字体。

- **1. 激活试用或订阅**

  在你的账户中开始 [免费试用](https://cloud.tiptap.dev/v2?trial=true) 或 [订阅 Start
  套餐](https://cloud.tiptap.dev/v2/billing)。
- **2. 从私有注册表安装**

  要安装此前端扩展，请按照 [设置指南](https://tiptap.zhcndoc.com/guides/pro-extensions.md) 通过身份验证访问 Tiptap 的私有 npm 注册表。

`@tiptap-pro/extension-export-docx` 接受一个可选的 **编号格式定义** 注册表（多级标记样式、标记文本、对齐、缩进和字体），并通过外层 `<ol>` 上的一个属性按列表进行选择。具有匹配 id 的列表会按对应定义导出；没有对应定义的列表则按普通 `1. 2. 3.` 导出。

此功能为可选启用。未提供 `numberingFormats` 的使用者不会看到任何行为变化。

> **Interactive demo:** [ExportDocxOrderedListNumbering](https://embed-pro.tiptap.dev/preview/Extensions/ExportDocxOrderedListNumbering)

## 提供了什么

| 导出                                                                             | 包                                   | 用途                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OrderedListNumbering`                                                         | `@tiptap-pro/extension-convert-kit` | Tiptap 扩展，为 `orderedList` 添加 `numberingFormat` 属性，并提供 `setOrderedListNumberingFormat(id)` 和 `toggleOrderedListWithFormat(format?)` 命令，还会通过 `editor.storage.orderedListNumbering` 跟踪光标选区处的活动格式。由 `ConvertKit` 注册（通过 `orderedListNumbering: true`，或带有 `defaultFormat` / `formats` 的选项对象启用）。在粘贴、JSON、协作同步和程序化编辑中强制仅最外层编号。 |
| `generateNumberingFormatCss(formats, options?)`                                | `@tiptap-pro/extension-convert-kit` | 纯函数、无依赖，返回用于编辑器预览的 CSS 文本：相同的注册表，相同的视觉效果。                                                                                                                                                                                                                                                                              |
| `NumberingFormatDefinition`, `NumberingLevelDefinition`, `NumberingMarkerFont` | `@tiptap-pro/extension-convert-kit` | 你的注册表遵循的数据结构。结构上与 `ExportDocx` 的 `numberingFormats` 配置兼容。                                                                                                                                                                                                                                                              |
| `ExportDocx.configure({ numberingFormats })`                                   | `@tiptap-pro/extension-export-docx` | 将注册表传递给导出器，使 `.docx` 包含匹配的定义。                                                                                                                                                                                                                                                                                          |
| `LevelFormat`, `IRunOptions`, `PositiveUniversalMeasure`                       | `@tiptap-pro/extension-export-docx` | 从 `docx` 重新导出，因此你无需再添加第二个依赖项。                                                                                                                                                                                                                                                                                          |

面向最终用户的选择器 UI 并不属于这些包；这属于应用层关注点，取决于你的组件库。

## 快速开始

```ts
import { Editor } from '@tiptap/core'
import { ConvertKit, type NumberingFormatDefinition } from '@tiptap-pro/extension-convert-kit'
import { ExportDocx, LevelFormat } from '@tiptap-pro/extension-export-docx'

// 1. 定义你的注册表：单一事实来源，供下面两侧共用。
const MY_FORMATS: NumberingFormatDefinition[] = [
  {
    id: 'decimal-paren',
    levels: [
      { baseStyle: LevelFormat.DECIMAL, textTemplate: '%1)' },
      { baseStyle: LevelFormat.LOWER_LETTER, textTemplate: '%2)' },
      { baseStyle: LevelFormat.LOWER_ROMAN, textTemplate: '%3)' },
    ],
  },
  {
    id: 'outline',
    levels: [
      { baseStyle: LevelFormat.DECIMAL, textTemplate: '%1.' },
      { baseStyle: LevelFormat.DECIMAL, textTemplate: '%1.%2.' },
      { baseStyle: LevelFormat.DECIMAL, textTemplate: '%1.%2.%3.' },
    ],
  },
]

// 2. 通过 ConvertKit 选择启用。传入 `formats` 会生成编辑器预览 CSS，
//    并自动注入；同时用相同的注册表注册 ExportDocx，以便
//    .docx 包含匹配的定义。
const editor = new Editor({
  extensions: [
    ConvertKit.configure({
      // 默认关闭，因此不使用自定义编号的使用者可以保持干净的
      // orderedList schema。传入一个选项对象（或 `true`）即可启用。
      orderedListNumbering: { formats: MY_FORMATS },
    }),
    ExportDocx.configure({
      numberingFormats: MY_FORMATS,
      onCompleteExport: (blob) => {
        /* 下载 blob */
      },
    }),
  ],
})

// 3. 在当前选区以所选格式开始一个编号列表
//    （或者，当已经在列表中时，使用 setOrderedListNumberingFormat 更改其格式）。
editor.chain().focus().toggleOrderedListWithFormat('outline').run()
```

更喜欢自己管理样式表？那就省略 `formats`，改为从 [`generateNumberingFormatCss`](#generatenumberingformatcssformats-options) 注入 CSS。这两种方式会生成相同的标记。

## 启用有序列表编号

`OrderedListNumbering` 随 [`@tiptap-pro/extension-convert-kit`](https://tiptap.zhcndoc.com/conversion/import/docx/convertkit.md) 提供，但**默认关闭**，以便为不使用自定义编号的使用者保持 `orderedList` schema 的简洁。通过 `ConvertKit` 选择启用：

```ts
ConvertKit.configure({ orderedListNumbering: true })
```

不要传 `true`，而是传入一个选项对象来配置两件事：

```ts
ConvertKit.configure({
  orderedListNumbering: {
    // 新建有序列表时开始使用的格式 id。默认为 `null`（普通的 `1. 2. 3.`）。
    defaultFormat: 'outline',
    // 传给 ExportDocx 的相同定义。提供后，
    // 会据此生成并自动注入编辑器预览 CSS，
    // 因此屏幕上的标记会与导出结果一致，无需额外接线。
    formats: MY_FORMATS,
  },
})
```

| Option          | Default | Description                                                                                                                                                                     |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defaultFormat` | `null`  | 应用于新建有序列表的编号格式 id（`numberingFormat` 属性的默认值）。仅对最外层列表进行格式化；嵌套列表保持不变。                                                                                                              |
| `formats`       | `null`  | 用于生成并注入编辑器预览 CSS 的编号格式定义，与你传给 `ExportDocx.configure({ numberingFormats })` 的数组相同。使用相同格式配置的编辑器会共享一份预览样式表，而使用不同格式配置的编辑器则会获得各自独立的样式表，因此每个编辑器始终显示正确的标记；共享样式表只有在最后一个使用它的编辑器被销毁后才会移除。 |

在这里传入 `formats`，等同于你自己调用 [`generateNumberingFormatCss`](#generatenumberingformatcssformats-options) 并注入其结果：按你的设置选择最合适的方式即可。

## 应用格式

`setOrderedListNumberingFormat(id)` 命令会在当前选区最外层的有序列表祖先上设置 `numberingFormat` 属性。传入 `null` 可清除它（此时列表会作为普通的 `1. 2. 3.` 导出）。

```ts
editor.chain().focus().setOrderedListNumberingFormat('decimal-paren').run()
editor.chain().focus().setOrderedListNumberingFormat(null).run()
```

当选区不在有序列表中时，该命令返回 `false`。

### 以某种格式开始新列表

`setOrderedListNumberingFormat` 只会作用于选区**已经**位于其中的列表。要从非列表选区开始以所选格式创建编号列表，请使用 `toggleOrderedListWithFormat(format?)`。它会在一次调用中创建有序列表并应用格式，这正是“选择一种格式来开始编号列表”工具栏按钮的自然操作：

```ts
// 从段落开始：创建一个有序列表并设置其格式。
editor.chain().focus().toggleOrderedListWithFormat('outline').run()

// 省略格式可按配置的 `defaultFormat` 开始列表。
editor.chain().focus().toggleOrderedListWithFormat().run()
```

当选区已经位于有序列表中时，该命令会切换关闭该列表，与 `toggleOrderedList` 的行为一致。链式调用 `toggleOrderedList().setOrderedListNumberingFormat(format)` 会得到相同的最终状态；只是单个命令更方便，也会处理关闭切换的情况。

要在工具栏中反映当前激活的格式，请从扩展的 storage 中读取它；当选区和文档发生变化时，它会保持同步：

```ts
const activeFormatId = editor.storage.orderedListNumbering.activeNumberingFormat
// 一个格式 id，或者在选区不在有序列表中时为 `null`
```

## `NumberingFormatDefinition`

```ts
interface NumberingFormatDefinition {
  id: string
  levels: NumberingLevelDefinition[]
}
```

| 字段       | 类型                           | 描述                                                                     |
| -------- | ---------------------------- | ---------------------------------------------------------------------- |
| `id`     | `string`                     | 在你的 `numberingFormats[]` 中唯一。序列化到 orderedList 的 `numberingFormat` 属性中。 |
| `levels` | `NumberingLevelDefinition[]` | 每个嵌套深度对应一项。必须非空。当列表嵌套深度超过数组长度时，深度 `N` 会复用 `levels[N % levels.length]`。 |

## `NumberingLevelDefinition`

```ts
interface NumberingLevelDefinition {
  baseStyle: NumberingBaseStyle
  textTemplate: string
  startAt?: number
  alignment?: 'left' | 'center' | 'right'
  numberIndent?: number | string
  textIndent?: number | string
  markerFont?: NumberingMarkerFont
}
```

ConvertKit 的类型使用普通字符串字面量，因此该包不会引入 `docx`。这些字段在结构上与 `ExportDocx` 更严格（使用 `docx` 类型）的版本兼容，因此从 `@tiptap-pro/extension-export-docx` 传入 `LevelFormat.DECIMAL` 的效果与传入字符串 `'decimal'` 相同。

| 字段             | 默认值         | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseStyle`    | (必填)        | 计数器字形，对应于匹配的 docx [`LevelFormat`](https://docx.js.org/api/enums/LevelFormat.html) 值。拉丁/数字样式（`'decimal'`、`'decimalZero'`、`'upperLetter'`、`'lowerLetter'`、`'upperRoman'`、`'lowerRoman'`、`'none'`）以及许多区域样式（例如 `'hebrew1'`、`'thaiNumbers'`、`'hindiNumbers'`、`'japaneseCounting'`、`'koreanDigital'`、`'chineseCounting'`、`'ideographDigital'`）会映射到匹配的 CSS 计数器样式，因此预览会渲染其原生字形。没有对应 CSS 等价形式的样式（例如 `'chicago'`、`'ordinal'`、`'cardinalText'`），以及任何无法识别的字符串，都会在**仅编辑器预览中**回退为 `decimal`；导出的 `.docx` 始终会保留你设置的精确 `LevelFormat`。 |
| `textTemplate` | (必填)        | 使用 Word 的 `<w:lvlText>` 语法的标记文本（见下文）。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `startAt`      | `1`         | 初始计数值。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `alignment`    | `'left'`    | 数字区域内的标记文本对齐方式。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `numberIndent` | Word 的每级默认值 | 从页面边距到标记的距离。Twips 数值或 docx 风格的度量字符串（`'0.63cm'`、`'0.25in'`、`'18pt'`）。                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `textIndent`   | Word 的每级默认值 | 从页面边距到正文文本的距离。应大于 `numberIndent`。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `markerFont`   | 无           | 仅标记的 run 格式（见下文 [`NumberingMarkerFont`](#numberingmarkerfont)）。可随 DOCX 导出保留，并会在编辑器预览中由 `generateNumberingFormatCss` 反映。                                                                                                                                                                                                                                                                                                                                                                                              |

## `NumberingMarkerFont`

```ts
interface NumberingMarkerFont {
  font?: string | { name: string }
  size?: number | string
  bold?: boolean
  italics?: boolean
  color?: string
  underline?: unknown
}
```

| 字段          | 描述                                                         |
| ----------- | ---------------------------------------------------------- |
| `font`      | 字体族名称，或一个 docx 风格的 `{ name }` 对象。                          |
| `size`      | docx 的半磅值，使用数字表示（例如 `28` = 14pt），或 docx 度量字符串，例如 `'14pt'`。 |
| `bold`      | 设置为 `true` 可将标记渲染为粗体。                                      |
| `italics`   | 设置为 `true` 可将标记渲染为斜体。                                      |
| `color`     | 十六进制颜色值，可带或不带前导 `#`。                                       |
| `underline` | 任何真值都会在预览中应用 `text-decoration: underline`。                 |

与 `generateNumberingFormatCss` 所理解的 docx [`IRunOptions`](https://docx.js.org/api/interfaces/IRunOptions.html) 子集一致。你传递给 `ExportDocx` 的额外字段会在预览中被忽略，但仍会保留到 `.docx` 中。

## `textTemplate` 语法

- `%1` 到 `%9` 引用的是 1 基索引的嵌套深度上的计数器。因此，无论 `textTemplate` 属于哪一层，`%1` 始终表示“最外层的计数器”。
- 其他所有字符都会按字面量渲染。
- 以非数字结尾的孤立 `%`（例如 `"50%"`）会被保留。

要让每一层显示自己的计数器，请按层级使用递增的 `%N`。要让某一层包含父级计数器（法律式大纲），请把它们串联起来：在第 1 层使用 `'%1.%2.'` 时会渲染为 `'1.1.'`。

| 模板所在层级 N              | 渲染示例            |
| --------------------- | --------------- |
| 第 0 层的 `'%1.'`        | `1.`            |
| 第 1 层的 `'%2.'`        | `1.`（第 1 层的计数器） |
| 第 1 层的 `'%1.%2.'`     | `1.1.`          |
| 第 2 层的 `'%1.%2.%3.'`  | `1.1.1.`        |
| 第 0 层的 `'Article %1'` | `Article 1`     |
| 第 0 层的 `'§ %1 —'`     | `§ 1 —`         |
| 第 2 层的 `'(%3)'`       | `(1)`           |

## 架构约定：仅限最外层

`numberingFormat` 属性只应放在**最外层** `<ol>` 上。一个定义会声明整个多级列表的所有嵌套层级。`OrderedListNumbering` 会在解析时强制执行这一点：如果粘贴的 HTML 中，嵌套的 `<ol>` 上带有 `data-numbering-format`，该属性会被移除。

同一个最外层 `<ol>` 下的所有嵌套层级共享一个计数器作用域，并且子级会在父级递增时重新开始，就像 Word 的行为一样。

## 循环规则

`levels.length` 定义了循环周期。当列表嵌套深度超过 `levels.length - 1` 时，深度 `N` 会在 DOCX 导出和编辑器预览 CSS 中都复用 `levels[N % levels.length]`。提供九个层级可以覆盖 Word 的完整嵌套深度而不循环；如果更深的层级可以自然重复较浅的条目，则可提供更少的层级。

## 默认值与 Word 标准一致

当省略 `numberIndent` / `textIndent` 时，导出器和 CSS 辅助函数都会输出 Word 的标准多级列表默认值：

| 深度 | `textIndent`   | `numberIndent` | 悬挂缩进  |
| -- | -------------- | -------------- | ----- |
| 0  | `720` (0.50″)  | `360` (0.25″)  | `360` |
| 1  | `1140` (0.79″) | `780` (0.54″)  | `360` |
| 2  | `1440` (1.00″) | `1080` (0.75″) | `360` |
| 3  | `1740` (1.21″) | `1380` (0.96″) | `360` |
| 4  | `2040` (1.42″) | `1680` (1.17″) | `360` |
| 5  | `2340` (1.63″) | `1980` (1.38″) | `360` |
| 6  | `2640` (1.83″) | `2280` (1.58″) | `360` |
| 7  | `2940` (2.04″) | `2580` (1.79″) | `360` |
| 8  | `3240` (2.25″) | `2880` (2.00″) | `360` |

## `generateNumberingFormatCss(formats, options?)`

返回 CSS 文本，由你决定如何注入（例如 `<style>` 标签、CSS-in-JS 层、由构建流水线提供的样式表等）。该函数是纯函数且无依赖，可安全地在启动时或注册表发生变化时调用。

```ts
generateNumberingFormatCss(formats, {
  scope: '.tiptap.ProseMirror', // 默认
  maxDepth: 9, // 默认
})
```

| 选项         | 默认值                     | 描述                                                                        |
| ---------- | ----------------------- | ------------------------------------------------------------------------- |
| `scope`    | `'.tiptap.ProseMirror'` | 为每条生成的规则添加 CSS 选择器前缀作用域。传入空字符串可输出不带作用域的结果（适合注入到 Shadow DOM 或你自己的 CSS 层中）。 |
| `maxDepth` | `9`                     | 要生成规则的最大嵌套深度。较小的值会生成更小的样式表。                                               |

生成的 CSS 会将每个列表标记及其正文文本定位到与 Word 渲染的绝对位置一致，包括每一层嵌套深度的阶梯式缩进。如果你需要为主题定制覆盖某些内容（深色模式、RTL、字体缩放），可以把输出包裹在你自己的选择器或作用域中，并依赖级联规则。

## 解析规则

- 匹配的 id 会使用相应的定义来渲染该多级列表的每一层（包括所有嵌套的 `<ol>`）。
- 未匹配的 id（拼写错误、缺少属性、空的 `numberingFormats`）会渲染为普通的 `1. 2. 3.` 编号。
- 引用相同格式的同级多级列表会独立重新开始，每个都从各自的 `startAt` 开始。

## 已知限制

导出器刻意没有建模的 Word 功能：

| 功能                                         | 变通方案 / 范围                                   |
| ------------------------------------------ | ------------------------------------------- |
| 强制父级计数器引用无论基础样式如何都以阿拉伯数字显示（Word 的“法律编号”覆盖） | 为相同视觉输出定义一个所有层级都为 `DECIMAL` 的单独格式。          |
| 按层级自定义计数器重启                                | 始终使用 Word 的默认行为（子级会在父级递增时重新开始）。             |
| 标记文本后缀（标记与正文之间的制表符 / 空格 / 无）               | 始终为 `tab`（Word 的默认值）。                       |
| 在独立列表之间延续编号                                | 每个列表都会独立从其 `startAt` 开始。                    |
| 按条目覆盖标记                                    | 使用一个单独的列表从不同的计数值开始。                         |
| DOCX → 编辑器导入                               | 由 `@tiptap-pro/extension-import-docx` 单独处理。 |

## 另请参阅

- [编辑器扩展概览](https://tiptap.zhcndoc.com/conversion/export/docx/editor-extension.md): 基础 `ExportDocx` 配置。
- [样式](https://tiptap.zhcndoc.com/conversion/export/docx/styles.md): 段落样式、标题、列表段落样式的 `styleOverrides`。
- [REST API](https://tiptap.zhcndoc.com/conversion/export/docx/rest-api.md): 服务器端转换端点。
