将 DOCX 默认样式作为 CSS 注入
Available in Start planBetav0.10.0
Beta 功能
本页上的 API、属性名称和行为正在逐步稳定,但在正式可用之前仍可能继续 调整。如果你依赖此功能,请锁定确切的包版本,并在采用前阅读 哪些不会工作 这一节。
这会做什么
DOCX 文件包含一个样式目录:这些命名定义(Heading1、Normal、Quote 等)告诉 Word 正文、标题、超链接和列表应当如何显示。DOCX 中的每个段落或文本片段,要么继承自这些命名样式之一,要么在行内覆盖单独的属性。
如果没有这个功能,Tiptap Convert API 会把这些样式扁平化为按节点设置的属性。你会看到 fontSize、color 和 spacing 作为行内属性应用到每个段落上,但 Word 用作事实来源的可复用命名样式会被丢弃。
此功能会将命名样式目录提取为一个 CSS 对象(以 CSS 选择器为键),并且既可以直接返回给你,也可以将其作为带作用域的 <style> 标签注入到页面中。结果就是:文档的基础排版通过 CSS 级联规则来呈现,而不是在每个节点上使用行内属性,因此你的编辑器在视觉上与原始 DOCX 保持一致,同时又不会使文档模型膨胀。
安装
npm i @tiptap-pro/extension-import-docx@^0.10.0它如何工作
一个四步流程:
- 在导入请求中选择启用。 扩展要求 Convert API 在
cssStyles.enabled为true时包含样式目录。 - 转换服务提取。 转换器读取 DOCX 的样式定义,解析继承链(
basedOn),将 OOXML 属性翻译为 CSS 等价物,并在导入响应中返回一个cssStyles对象。 - 扩展构建 CSS 规则。 将
cssStyles对象编译为 CSS 字符串,并按你配置的选择器进行作用域隔离(默认.tiptap)。 - 自动注入或交给你处理。 如果
autoInject: true,扩展会把作用域隔离的<style>元素追加到document.head。如果autoInject: false,你会在onImport回调中收到原始的cssStyles对象,并由你决定如何处理。
import { ImportDocx } from '@tiptap-pro/extension-import-docx'
ImportDocx.configure({
appId: 'your-app-id',
token: 'your-jwt',
cssStyles: {
enabled: true, // 每次导入都提取样式
autoInject: true, // 自动以作用域 <style> 标签的形式注入
selector: '.tiptap', // 将规则作用域限定在该选择器下
},
})或者在每次调用时控制:
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 导出页面。
配置参考
ImportDocx.configure({
cssStyles: {
enabled?: boolean, // 默认:false。打开提取。
autoInject?: boolean, // 默认:false。将 <style> 标签追加到 document.head。
selector?: string, // 默认:'.tiptap'。注入规则的作用域。
},
})按次调用覆盖:
editor.chain().importDocx({
file,
cssStyles: { enabled, autoInject, selector }, // 任意子集
onImport(context) { /* context.cssStyles 在此处可用 */ },
})REST API 查询参数(若你直接调用 /import/docx):
POST /import/docx?extractCssStyles=true
相关
- CSS to DOCX (导出):反向方向。将你的编辑器 CSS 重新编译为 DOCX 样式定义。
- ConvertKit:配套扩展包,为 Paragraph、Heading、Table 等添加 DOCX 感知属性。
- REST API: CSS 样式提取:原始的
extractCssStyles参数和完整响应结构。