---
title: "将 DOCX 默认样式作为 CSS 注入"
description: "从 DOCX 文件中提取默认样式作为 CSS，并在导入时将它们注入到你的 Tiptap 编辑器中。"
canonical_url: "https://tiptap.zhcndoc.com/conversion/import/docx/css-injection"
---

# 将 DOCX 默认样式作为 CSS 注入

从 DOCX 文件中提取默认样式作为 CSS，并在导入时将它们注入到你的 Tiptap 编辑器中。

> **Beta 功能:**
>
> 本页上的 API、属性名称和行为正在逐步稳定，但在正式可用之前仍可能继续
> 调整。如果你依赖此功能，请锁定确切的包版本，并在采用前阅读 **哪些不会工作**
> 这一节。

- **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 注册表进行身份验证。

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

## 这会做什么

DOCX 文件包含一个样式目录：这些命名定义（`Heading1`、`Normal`、`Quote` 等）告诉 Word 正文、标题、超链接和列表应当如何显示。DOCX 中的每个段落或文本片段，要么继承自这些命名样式之一，要么在行内覆盖单独的属性。

如果没有这个功能，Tiptap Convert API 会把这些样式扁平化为按节点设置的属性。你会看到 fontSize、color 和 spacing 作为行内属性应用到每个段落上，但 Word 用作事实来源的可复用命名样式会被丢弃。

此功能会将命名样式目录提取为一个 **CSS 对象**（以 CSS 选择器为键），并且既可以直接返回给你，也可以将其作为带作用域的 `<style>` 标签注入到页面中。结果就是：文档的基础排版通过 CSS 级联规则来呈现，而不是在每个节点上使用行内属性，因此你的编辑器在视觉上与原始 DOCX 保持一致，同时又不会使文档模型膨胀。

## 安装

```bash
npm i @tiptap-pro/extension-import-docx@^0.10.0
```

## 它如何工作

一个四步流程：

1. **在导入请求中选择启用。** 扩展要求 Convert API 在 `cssStyles.enabled` 为 `true` 时包含样式目录。
2. **转换服务提取。** 转换器读取 DOCX 的样式定义，解析继承链（`basedOn`），将 OOXML 属性翻译为 CSS 等价物，并在导入响应中返回一个 `cssStyles` 对象。
3. **扩展构建 CSS 规则。** 将 `cssStyles` 对象编译为 CSS 字符串，并按你配置的选择器进行作用域隔离（默认 `.tiptap`）。
4. **自动注入或交给你处理。** 如果 `autoInject: true`，扩展会把作用域隔离的 `<style>` 元素追加到 `document.head`。如果 `autoInject: false`，你会在 `onImport` 回调中收到原始的 `cssStyles` 对象，并由你决定如何处理。

```ts
import { ImportDocx } from '@tiptap-pro/extension-import-docx'

ImportDocx.configure({
  token: 'your-jwt',
  cssStyles: {
    enabled: true,      // 每次导入都提取样式
    autoInject: true,   // 自动以作用域 <style> 标签的形式注入
    selector: '.tiptap', // 将规则作用域限定在该选择器下
  },
})
```

或者在每次调用时控制：

```ts
editor
  .chain()
  .importDocx({
    file,
    cssStyles: { enabled: true, autoInject: false },
    onImport(context) {
      // `context.cssStyles` 是原始对象；你可以按自己的方式处理
      console.log(context.cssStyles)
    },
  })
  .run()
```

## 何者可用

**选择器（16 个）：** 该功能只会把命名样式提取并映射到下列这些 CSS 选择器。

| 类型      | 选择器                                            |
| ------- | ---------------------------------------------- |
| 块级      | `p`, `h1`–`h6`, `blockquote`, `ul li`, `ol li` |
| 行内 / 标记 | `strong`, `em`, `u`, `s`, `a`, `code`          |

**CSS 属性（11 个）：** 上述每个选择器都可以接收这些属性的任意子集，具体取决于 DOCX 样式里定义了哪些。

| 属性                | DOCX 来源                            | 备注                                                               |
| ----------------- | ---------------------------------- | ---------------------------------------------------------------- |
| `fontSize`        | `w:sz`（半磅）                         | 转换为 `Npx`（`halfPoints / 2`）                                      |
| `color`           | `w:color`                          | 十六进制；跳过 `"auto"`                                                 |
| `fontFamily`      | `w:rFonts`                         | 优先使用 `@w:ascii`，其次是 `hAnsi`，再其次是 `cs`                            |
| `fontWeight`      | `w:b`                              | `"bold"` 或 `"normal"`                                            |
| `fontStyle`       | `w:i`                              | `"italic"` 或 `"normal"`                                          |
| `textDecoration`  | `w:u` + `w:strike`                 | 组合（例如 `"underline line-through"`）                                |
| `backgroundColor` | `w:shd[@fill]`                     | 十六进制；跳过 `"auto"`                                                 |
| `textAlign`       | `w:jc`                             | `left` / `center` / `right` / `justify`（DOCX `both` → `justify`） |
| `marginTop`       | `w:spacing[@before]`               | Twips → `Npt`                                                    |
| `marginBottom`    | `w:spacing[@after]`                | Twips → `Npt`                                                    |
| `lineHeight`      | `w:spacing[@line]` + `[@lineRule]` | `auto` → 无单位倍数；`exact`/`atLeast` → `Npt`                         |

**其他行为：**

- **继承链。** `basedOn` 引用会通过迭代解析，并进行循环检测，因此子样式会包含其从父样式继承的全部内容。
- **本地化文档。** 使用非英语版 Word 创建的 DOCX 文件（例如西班牙语 `Título1`、德语 `Überschrift1`）会映射回其规范名称（`heading 1`），因此选择器分配仍然可用。
- **失败是不可见的。** 如果提取因任何原因抛出异常（styles.xml 损坏、属性意外），它会返回 `{}`，导入会正常继续；该功能绝不会阻止可工作的导入。

## 什么不会工作

> **这些是有意为之的限制:**
>
> 这些并不是 bug。它们是该功能明确且已文档化的边界。如果你的工作流依赖下面任何一项，那么此功能并不是合适的工具。

- **伪类。** `:hover`、`:focus`、`:first-child` 等。DOCX 样式模型没有对应概念；不会提取任何此类内容。
- **任意选择器。** 上表中的 16 个选择器就是完整映射。任何用途落在该映射之外的 DOCX 样式（`TableGrid`、`TOC1`、`FootnoteText`、自定义用户样式）都会被丢弃。
- **字母间距。** 导出端编译器支持，但在导入时**不会**提取。
- **超出选择器本身的特异性。** 注入的规则会以你的选择器为作用域（例如 `.tiptap h1 { … }`）。它们不会考虑与你自己的样式表之间的级联顺序；你必须确保你的 CSS 不会意外覆盖它们，反之亦然。
- **行内覆盖。** 如果某个特定段落或文本片段在 Word 中行内覆盖了其样式（例如某个 `<w:r>` 直接设置了 `w:color`），这些覆盖仍会通过 Tiptap 节点上的属性渲染，而不是通过注入的样式表。你无法通过编辑注入的 CSS 来“取消覆盖”行内格式。
- **非文本样式。** 表格样式（`w:tblStyle`）、编号样式（`w:numId`），以及诸如页码之类的字符样式都不在映射范围内。

## 你可以期待

- 在每次成功导入且 `autoInject: true` 时，都会有一个附加到 `document.head` 的带作用域 `<style>` 元素。后续导入会替换前一个元素，因此任意时刻只会有一个处于活动状态。
- 无论 `autoInject` 设置如何，你都可以在 `onImport` 回调的上下文中获取原始 `cssStyles` 对象。你可以完全忽略自动注入，自己应用这些样式：把它们写入文件、发送到主题系统，或任何对你的应用最合适的方式。
- 样式会限定在你的编辑器范围内（默认 `.tiptap`，可通过 `cssStyles.selector` 配置）。只有当你把选择器设为全局选择器（例如 `body`）时，才会泄漏到页面的其他部分。
- 静默失败模式。如果 DOCX 没有样式目录，或者所有命名样式都落在 16 个选择器映射之外，`cssStyles` 会返回空，并且不会注入任何样式标签。

## 不要期待

- **像素级 Word 还原。** Word 使用内建布局引擎，其段落间距语义与 CSS 不同（例如折叠外边距、上下文相关的前后间距）。提取出的 CSS 是对 DOCX *样式定义* 的忠实翻译，而不是对 Word 布局输出的复现。
- **对实时编辑的动态更新。** 样式只会在每次导入时注入一次。如果用户之后在 Tiptap 中编辑文档，注入的样式不会重新计算；它们描述的是导入文档的基础样式，而不是当前编辑器状态。
- **跨文档合并。** 每次导入都会替换之前的 `<style>` 标签。连续导入两个 DOCX 文件时，你只能得到第二个文档的样式。如果你需要合并，可以从 `onImport` 中读取两个 `cssStyles` 对象并自行合并。
- **往返保证。** 提取再导出的循环并不是无损的；反向方向及其自身注意事项请参见 [CSS to DOCX](https://tiptap.zhcndoc.com/conversion/export/docx/css-to-docx.md) 导出页面。

## Configuration Reference

```ts
ImportDocx.configure({
  cssStyles: {
    enabled?: boolean,     // Default: false. Enable extraction.
    autoInject?: boolean,  // Default: false. Append <style> tags to document.head.
    selector?: string,     // Default: '.tiptap'. Scope of the injected rules.
  },
})
```

Override on a per-call basis:

```ts
editor.chain().importDocx({
  file,
  cssStyles: { enabled, autoInject, selector }, // any subset
  onImport(context) { /* context.cssStyles available here */ },
})
```

REST API query parameters (if you call `/import/docx` directly):

```
POST /import/docx?extractCssStyles=true
```

## 相关

- [CSS to DOCX (导出)](https://tiptap.zhcndoc.com/conversion/export/docx/css-to-docx.md)：反向方向。将你的编辑器 CSS 重新编译为 DOCX 样式定义。
- [ConvertKit](https://tiptap.zhcndoc.com/conversion/import/docx/convertkit.md)：配套扩展包，为 Paragraph、Heading、Table 等添加 DOCX 感知属性。
- [REST API: CSS 样式提取](https://tiptap.zhcndoc.com/conversion/import/docx/rest-api.md#css-style-extraction-experimental)：原始的 `extractCssStyles` 参数和完整响应结构。
