PagesTableKit:用于 Pages 扩展的表格

Available in Start planExperimentv0.2.0

实验性功能

PagesTableKit 是专为 Pages 扩展构建的。API 和渲染行为可能会在没有通知的情况下变更。如果你依赖它,请锁定确切的包版本。在采用之前,请先阅读 无法使用的内容 部分。

哪种设置适合我?

两种场景,一个编辑器栈

PagesTableKit 在两种场景下都很有用,它们的区别在于表格内容如何进入编辑器,而不是你如何配置编辑器。基础扩展是相同的;第二种场景会在此基础上额外添加 Import 扩展。

  • 仅 Pages 工作流。 你正在构建一个分页编辑器(适合打印的版式、信纸风格文档、报告),并且需要表格能够正确分页。内容为手动编写。
  • Pages + DOCX 导入工作流。 你正在导入 .docx 文件,并在分页编辑器中渲染它们。你需要表格既能分页,能忠实反映原始 DOCX 的格式(声明的宽度、行高、缩进)。

这两种场景使用相同的编辑器栈:ConvertKit(用于 schema)+ TableKit(用于分页安全的表格)+ Pages(用于布局)。场景 B 额外添加 ImportDocx。下面每一节都会标明它适用于哪个场景。

安装

npm i @tiptap-pro/extension-convert-kit \
      @tiptap-pro/extension-pages-tablekit \
      @tiptap-pro/extension-pages

对于场景 B,还需要安装:

npm i @tiptap-pro/extension-import-docx

如何配置

PagesTableKit 提供了一个单独的 TableKit 扩展,它将 Table、TableRow、TableCell 和 TableHeader 扩展打包在一起。请只注册一次,而不是分别手动接入这四个扩展。

场景 A:仅 Pages(不导入 DOCX)

注册 ConvertKit(并禁用其内置的表格栈)、PagesTableKit 中的 TableKit,以及 Pages

import { Editor } from '@tiptap/core'
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
import { TableKit } from '@tiptap-pro/extension-pages-tablekit'
import { Pages } from '@tiptap-pro/extension-pages'

const editor = new Editor({
  extensions: [
    ConvertKit.configure({ table: false }), // 禁用 ConvertKit 的表格
    TableKit,
    Pages.configure({
      /* 页面格式、边距等 */
    }),
  ],
})

ConvertKit 提供文档的节点和标记 schema;PagesTableKit 的 TableKit 提供分页安全的表格。ConvertKit 内置的 ConvertTableKit 不是分页安全的,这就是我们在这里将其禁用的原因。

场景 B:Pages + DOCX 导入

在同一套栈的基础上再添加 ImportDocx 扩展。保持禁用 ConvertKit 的表格;PagesTableKit 的 TableKit 接受与 ConvertKit 表格相同的 DOCX 单元格属性,因此导入的表格会随着分页正确渲染。

import { Editor } from '@tiptap/core'
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
import { ImportDocx } from '@tiptap-pro/extension-import-docx'
import { TableKit } from '@tiptap-pro/extension-pages-tablekit'
import { Pages } from '@tiptap-pro/extension-pages'

const editor = new Editor({
  extensions: [
    ConvertKit.configure({ table: false }),
    TableKit,
    ImportDocx.configure({
      /* appId, token, … */
    }),
    Pages.configure({
      /* 页面格式、边距等 */
    }),
  ],
})

支持的内容

通用行为(两种场景都适用)

  • 分页安全的表格渲染。 表格位于页面内容区域内,不会在水平方向溢出。
  • 保留列比例。 当每个单元格都带有 colwidth 时,列会按比例缩小以适配页面。10 % / 40 % / 50 % 的列分配在任何页面宽度下都会渲染为 10 / 40 / 50。
  • 行高行为。
    • heightRule: "exact":行会按声明的高度渲染,并裁剪溢出的内容。
    • heightRule: "atLeast"(或未设置):当内容或更窄的列本会导致裁剪时,行会在垂直方向增长。
  • 实时更新。 增加、删除或重新排序单元格的编辑会立即重新布局该行。

仅 DOCX 专属行为(场景 B)

当你的文档内容由 DOCX 导入器生成时,这些额外行为会自动启用。你不需要单独配置它们;如果转换器输出了该属性,PagesTableKit 就会遵守它。

  • 遵守已声明的 DOCX 宽度。 如果 DOCX 表格作者设定的宽度大于页面,它会按比例缩小到内容区域,而不是溢出。
  • DOCX 行高。 使用 w:trHeightw:hRule="exact" 时会裁剪;w:hRule="atLeast"(或缺失)时会增长。
  • 保留窄的间距列。 DOCX 间距列(1–15 px)不会被放大成可见宽度。
  • 负值 DOCX 缩进。 DOCX 中的负值 w:tblInd(Word 会把它渲染到纸张边缘的槽位/留白处)会保留到 attrs.indent 中,但会在视觉上被钳制为 0,防止表格推到页面边缘之外。
  • 单元格背景、垂直对齐、每侧边框。 会从 DOCX 导入直接传递过来,无需额外处理。

不支持的内容

这些是有意设定的限制

这些不是 bug。它们是该功能明确且文档化的边界。如果你的工作流依赖下面任何一项,这个功能就不是合适的工具。

通用限制(两种场景都适用)

  • 不带 Pages 扩展的编辑器。 PagesTableKit 是为 Pages 的分页布局设计的;它依赖 Pages 将行限制在页面内。在标准编辑器中,行无法正确渲染,过宽的表格会在水平方向溢出。请改用普通表格扩展。
  • 手动编写且混合使用 colwidth / 不使用 colwidth 的行。每个单元格都带有列宽时,才会触发按比例收缩行为。如果某些单元格带宽度而某些没有,列的渲染比例可能与你预期不同。
  • 列宽拖拽控制柄。 支持来自 @tiptap/extension-table 的拖拽调整大小,但最终渲染宽度可能会按比例而不是你拖到的精确像素值呈现,尤其是在每个单元格已经带有列宽时。

仅 DOCX 限制(场景 B)

  • 浮动表格。 DOCX w:tblpPr(相对于锚点并带文本环绕定位的表格)不会被导入器转换;浮动表格会按普通的纵向堆叠表格渲染。
  • 与 Microsoft Word 表格布局的像素级一致。 Word 使用专有的布局算法,将固定和比例尺寸与内容测量混合在一起。对于使用 Word“自动调整为内容”设置创建的表格,可能会出现细微差异。

已知问题

行必须能放进单个页面

当表格行放不下当前页面时,Pages 会将整行作为一个原子单元移到下一页。这与 Microsoft Word 不同,Word 会在视觉上把很高的行跨页拆分。PagesTableKit 目前不支持行中间的分页拆分。

如果某一行的高度大于页面内容区域,那么即使把它移到下一页,它也仍然放不下:编辑器会继续尝试把它往后移动,并陷入无限循环。最终会导致无限分页循环和损坏的编辑器。

如何避免。 保持行高小于页面内容区域。尤其注意:

  • heightRule: "atLeast" 的行:其内容可能无限增长。
  • 继承了非常高的精确高度行的 DOCX 导入:这些行是为比目标页面格式更大的纸张编写的。
  • 单元格内嵌套的表格:这可能导致外层行比页面更高。

行内分页拆分在路线图中。ETA:待定。

预期会发生什么

通用(两种场景都适用)

  • 表格位于页面内容区域内;精确高度行会裁剪,atLeast 行会增长。
  • 每次事务都会生效;增加或删除单元格会立即重新布局该行。
  • 超大的表格(成千上万行)在编辑时可能会带来明显的布局开销。如果遇到这种情况,可以考虑手动对大表格分页,或将其拆分到多个文档中。

仅 DOCX(场景 B)

  • 导入时,DOCX 表格会保留其声明的宽度、行高、缩进、背景颜色以及每侧边框。
  • 过宽的 DOCX 表格(Word 模板中常见的全宽表格)会在视觉上缩小以适配页面,而不是溢出。
  • 渲染前不需要对导入的 DOCX JSON 做后处理;扩展会直接读取导入器生成的属性。

不要指望

通用(两种场景都适用)

  • Pages 的替代品。 PagesTableKit 只负责表格。分页、页面容器、页眉和页脚都是 Pages 的职责。
  • 来自你自定义 DOM 代码的列宽变更。 列宽来自 ProseMirror 文档。请通过 @tiptap/extension-table 的命令(或你自己的事务)来改变它们,而不是直接写入 dom.style

仅 DOCX(场景 B)

  • 往返一致性(round-trip identity)。 通过 Convert 管道导入再导出 DOCX 不能保证字节级完全一致。导入时会丢弃不支持的 DOCX 功能(浮动、某些表格样式)。

配置参考

PagesTableKit 导出一个单独的 TableKit 扩展,将 Table、TableRow、TableCell 和 TableHeader 打包在一起。

import { TableKit } from '@tiptap-pro/extension-pages-tablekit'

// 使用默认值
TableKit,

每个打包的扩展都可以配置(或用 false 禁用),通过 TableKit.configure()

TableKit.configure({
  table: { cellMinWidth: 1 }, // 来自 @tiptap/extension-table 的 Table 选项
  tableRow: {
    /* TableRow 选项 */
  },
  tableCell: {
    /* TableCell 选项 */
  },
  tableHeader: false, // 完全禁用表头扩展
})

PagesTableKit 没有任何独有的配置项;每个键都会透传到其底层扩展的标准选项。

相关内容