ConvertKit: DOCX 感知编辑器扩展
Beta 功能
ConvertKit 的 API、属性名称和捆绑扩展正在逐步稳定,但在正式可用之前仍可能会有 一些调整。如果你依赖 ConvertKit,请锁定准确的包版本,并在采用它之前先阅读 无法工作的内容 章节。
这会做什么
DOCX 文件包含了基础 Tiptap 扩展并不了解的格式元数据:段落间距(以 twips 为单位)、表格行高规则、图片裁剪百分比、单元格垂直对齐、各边框宽度。如果你用原生 Tiptap 渲染 DOCX 内容,这些信息会丢失或渲染错误。
ConvertKit 是一个单一扩展,用于配置你的编辑器以导入 DOCX 内容。 引入它后,你将获得:
- 28 个捆绑扩展已连接好,用于处理 Convert API 生成的一切内容。
- 自定义的 Paragraph、Heading、Image、Table、TableRow、TableCell 和 TableHeader 扩展,可接受 DOCX 特定属性。
- 在编辑器创建时注入的一小段 CSS 重置,用于规范浏览器默认样式,使 DOCX 间距值能够准确渲染。
- 每个捆绑扩展都可以单独配置或禁用。
安装
npm i @tiptap-pro/extension-convert-kit@^0.1.0工作原理
三个部分:
- 一组预配置扩展。 ConvertKit 注册了一组精选的 Tiptap 扩展(用于 marks 和 lists 的基础扩展,以及针对段落、标题、图片和表格的支持 DOCX 的自定义覆盖)。你可以在
ConvertKit.configure({…})中为任意槽位传入false来排除对应扩展。 - schema 节点上的 DOCX 属性。 支持 DOCX 的覆盖扩展会继承其基础对应项,并声明额外属性(段落间距、图片裁剪、表格单元格属性)。转换服务会生成这些属性;ConvertKit 的节点会将其渲染出来。
- 作用域化 CSS 重置。 ConvertKit 注入了一小段 CSS 重置,用于规范段落外边距、表格行高、单元格垂直对齐以及精确高度行的浏览器默认值,从而使 DOCX 间距值能够准确渲染。编辑器销毁时,这个重置会被移除。
import { Editor } from '@tiptap/core'
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
const editor = new Editor({
extensions: [ConvertKit],
})自定义或禁用特定子扩展:
new Editor({
extensions: [
ConvertKit.configure({
heading: { levels: [1, 2, 3] }, // 仅允许 H1–H3
codeBlock: false, // 完全移除 code-block 节点
table: false, // 替换为另一套表格栈
}),
],
})能工作
内置扩展
ConvertKit 在单个 @tiptap-pro/extension-convert-kit 包中捆绑了 28 个扩展。下面的列表是参考资料,方便你了解编辑器 schema 中会出现什么;这些扩展不需要单独安装或注册。
| Category | Extensions |
|---|---|
| Core | Document, Text, Paragraph, Heading |
| Marks | Bold, Italic, Underline, Strike, Code, Link |
| Blocks | Blockquote, HorizontalRule, HardBreak, CodeBlock, PageBreak |
| Lists | BulletList, OrderedList, ListItem, ListKeymap |
| Media | Image* |
| Styling | TextStyleKit (TextStyle, Color, BackgroundColor, FontFamily, FontSize, LineHeight), TextAlign, Highlight (multicolor), Superscript, Subscript |
| UI helpers | Dropcursor, Gapcursor |
| Tables | ConvertTableKit (Table*, TableRow*, TableCell*, TableHeader*) |
标有 * 的扩展是 Tiptap 基础扩展的自定义、支持 DOCX 的覆盖版本。请查看下一节了解它们新增了什么。
在 Tiptap 基础扩展之上新增的 DOCX 属性
| Extension | Added attributes | Source |
|---|---|---|
Paragraph | spacingBefore, spacingAfter, lineHeight, fontSize, indent, firstLineIndent, contextualSpacing | paragraph mark 上的 DOCX w:pPr + w:rPr |
Heading | same as Paragraph | paragraph mark 上的 DOCX w:pPr + w:rPr |
Image | cropTop, cropBottom, cropLeft, cropRight | drawings 上的 DOCX a:srcRect |
Table | width, indent (+ cellMinWidth: 1 default, vs Tiptap's 25) | DOCX w:tblW, w:tblInd, w:tblGrid |
TableRow | height, heightRule (exact / atLeast) | DOCX w:trHeight + w:hRule |
TableCell / TableHeader | background, verticalAlign, per-side border (width / style / color on top/bottom/left/right) | DOCX w:tcPr |
CSS 重置会规范什么
该重置作用于 .tiptap,并调整了几个区域;否则浏览器默认样式会与 DOCX 间距不对齐:
- 段落间距。 段落以及
*后代元素的上、下外边距会被清零,因此 DOCX 作者设置的间距值(其自身包含前后值)能够准确渲染,而不会叠加在浏览器默认外边距之上。 - 表格行高和单元格内边距。 默认值会被收紧,因此声明了特定行高的表格能够按那些高度实际渲染。
- 精确高度行会裁剪溢出内容。 具有
heightRule: "exact"的行会通过内部单元格包装器裁剪溢出内容;比声明行高更高的内容会被隐藏,这与 Word 的行为一致。 - 尾随换行伪影。 ProseMirror 的尾随换行会设置为零外边距和内边距,因此不会在段落末尾引入虚假的空白。
如果你需要覆盖其中任何一项,请在 .tiptap 内针对你自己的选择器进行设置——你的规则会覆盖重置。
一些小但重要的默认值
- 表格的
cellMinWidth: 1。Tiptap 默认是25,这会把 DOCX 的间距列(1–15 px 的窄列,用于布局)放大成可见的间隙。ConvertKit 将最小值上限限制为1px。 - 使用
types: ['paragraph', 'heading']配置textAlign,使 DOCX 段落两种对齐块都能传递过去。 - 使用
multicolor: true配置highlight,从而让 DOCXw:highlight的颜色原样传递。
将无法工作
这些是有意的限制
这些都不是 bug。它们是该功能明确记录的边界。如果你的工作流依赖下面任何一项, 那么这个功能并不适合你。
- 浮动表格。 DOCX
w:tblpPr(相对于锚点定位并带文字环绕的表格)会渲染为普通的纵向堆叠内联表格。定位元数据会被转换器丢弃。这是刻意为之;浮动布局的保真度不在范围内。 - 负表格缩进。 小于零的
w:tblInd值会保留在attrs.indent中,但在渲染时会被限制为0。Word 会把负缩进渲染到页面边距沟槽中;浏览器没有这个沟槽,因此渲染它们会把表格推到页面边缘之外。 - 精确行高溢出。 具有
heightRule: "exact"的行会通过.cell-content包装器的overflow: hidden裁剪溢出内容。比声明高度更高的内容不可见。 - 过宽表格宽度。 声明宽度超过容器的表格会以
max-width: 100%渲染。声明的宽度会保留在attrs.width中,但视觉上会被限制。 - 多页布局。 ConvertKit 不进行分页。如果你需要跨页表格、真实的页面容器、页眉/页脚,或者希望页面分隔符在视觉上生效,请将 ConvertKit 与 Pages extension 配合使用,并为表格扩展使用 PagesTableKit。
- 脚注、尾注、评论。 不会渲染。转换器会把它们作为段落输出或直接丢弃;ConvertKit 不会添加任何脚注/评论 UI。
你应该预期到
- 编辑器挂载期间会应用一个小型、作用域化的 CSS 重置,并在编辑器销毁时移除。同一页面上的多个由 ConvertKit 驱动的编辑器会共享这份重置(它只插入一次)。
- 在你的应用中,DOCX 导入内容会获得一致的渲染。带有非零 DOCX 裁剪的图片会真正裁剪显示;当列变窄时,具有
heightRule: "atLeast"的行会垂直增长;verticalAlign: "center"的单元格会将内容居中。 - 与其余 Tiptap Pro 扩展生态系统完全兼容。
@tiptap-pro/extension-import-docx和@tiptap-pro/extension-export-docx是天然的配套项;如果你需要分页,@tiptap-pro/extension-pages-tablekit可以叠加使用。 - 紧凑的默认排版。 CSS 重置会清零段落外边距并应用紧凑的行高。如果你用 ConvertKit 处理的内容不是从 DOCX 导入的,请在其上叠加你自己的排版规则——这份重置是有意设计的,而不是我们期望直接呈现为美观的默认样式。
不要预期到
- 超出节点属性级别的 DOCX 保真度。 ConvertKit 会接入 Convert API 生成的属性。如果转换器没有解析某个 DOCX 特性,ConvertKit 就无法渲染它。
- 表格的自动缩放手柄。 ConvertKit 的 Table 扩展继承自
@tiptap/extension-table,并支持标准的缩放行为,但默认的cellMinWidth: 1意味着手柄可以把列拖到 1 px 宽,这通常不是你在手动编辑时想要的。将 DOCX 导入与手动创作混合使用时,请覆盖table.cellMinWidth。
ConvertKit 不覆盖的内容
ConvertKit 会将 Convert API 产出的所有特性作为 Tiptap 节点和标记来处理。某些导入的 DOCX 内容超出了这一范围,仍然需要在应用层处理:
- 脚注和尾注引用。 导入 REST API 会返回脚注和尾注数据,但 编辑器扩展 不会展示这些内容,也没有任何 Tiptap 扩展可以渲染脚注标记或注释。参见 脚注和尾注。
- 多栏布局。 导入会为多栏章节生成
columns和column节点,但没有可用于渲染它们的编辑器扩展。参见 页面结构。 - 目录。 会被导入为
tableOfContents节点。除非你添加自定义扩展,否则会以普通内容形式渲染。参见 支持的功能。 - Word 样式。 样式名在导入时用于结构识别(标题、引用块、代码块)。文档样式目录中定义的视觉样式不会被应用。可将 ConvertKit 与 CSS 注入 配合,以保留样式目录;或者参见 Word 样式。
- 数学公式。 Convert API 不会解析 OMML。参见 数学公式。
- 字间距。 Convert API 会将字符间距按逐段标记提取为
textStyle.letterSpacing,但捆绑的TextStyleKit没有声明letterSpacing属性,因此该值在渲染时会被丢弃。CSS 注入 也不会提取它(只有导出侧编译才接受它)。若要渲染导入的字间距,请为TextStyle扩展一个letterSpacing属性,并在renderHTML中输出style="letter-spacing: …"。参见 字体族和字号。 - 页面布局。 页面大小、页边距、页眉和页脚属于文档级别的事项。ConvertKit 负责渲染内容;可将其与 Pages 扩展 配合使用,以实现分页布局。
如需了解如何扩展 ConvertKit 的内置扩展,以及如何使用 CSS 为转换后的内容设置样式,请参阅 转换后内容样式 指南。
配置参考
每个键都是可选的。若要排除某个扩展,请传入 false。若要把部分选项对象传递给底层扩展的 configure(),请传入对应对象。每个键的默认值都是 {}。
ConvertKit.configure({
document: Record<string, never> | false,
text: Record<string, never> | false,
paragraph: Partial<ParagraphOptions> | false,
heading: Partial<HeadingOptions> | false,
blockquote: Partial<BlockquoteOptions> | false,
bold: Partial<BoldOptions> | false,
italic: Partial<ItalicOptions> | false,
underline: Partial<UnderlineOptions> | false,
strike: Partial<StrikeOptions> | false,
code: Partial<CodeOptions> | false,
link: Partial<LinkOptions> | false,
bulletList: Partial<BulletListOptions> | false,
orderedList: Partial<OrderedListOptions> | false,
listItem: Partial<ListItemOptions> | false,
listKeymap: Partial<ListKeymapOptions> | false,
hardBreak: Partial<HardBreakOptions> | false,
horizontalRule: Partial<HorizontalRuleOptions> | false,
dropcursor: Partial<DropcursorOptions> | false,
gapcursor: Record<string, never> | false,
codeBlock: Partial<CodeBlockOptions> | false,
image: Partial<ImageOptions> | false,
textStyleKit: Partial<TextStyleKitOptions> | false,
textAlign: Partial<TextAlignOptions> | false, // 默认:{ types: ['paragraph', 'heading'] }
highlight: Partial<HighlightOptions> | false, // 默认:{ multicolor: true }
superscript: Partial<SuperscriptExtensionOptions> | false,
subscript: Partial<SubscriptExtensionOptions> | false,
pageBreak: Partial<PageBreakOptions> | false,
table: Partial<ConvertTableKitOptions> | false,
})相关
- PagesTableKit: 封装 ConvertKit 的 Table 扩展的配套包,提供与 Pages 扩展分页兼容的 CSS Grid NodeView。
- CSS 注入(导入): 将 ConvertKit 与 CSS 注入配合,以从 DOCX 样式目录中获得排版保真度。
- 编辑器扩展(导入 DOCX):
ImportDocx扩展如何调用 Convert API。