分栏视图

将修订记录并排显示:左窗格显示删除内容,右窗格显示新增内容。两个窗格都可以编辑,并会保持对应块对齐。

安装

首先,联系我们加入分栏视图试点计划。

独立产品

修订记录和 Tiptap Compare 是与分栏视图不同的产品,需要单独购买。

请先设置私有注册表,然后安装:

npm install @tiptap-pro/extension-split-view @tiptap-pro/extension-tracked-changes

连接编辑器

主编辑器是编辑器内容的事实来源。再创建两个编辑器,分别显示分栏视图的左右窗格。将 TrackedChanges 扩展添加到三个编辑器,并将 SplitView 添加到对应窗格的两个编辑器。

import { Editor } from '@tiptap/core'
import { TrackedChanges } from '@tiptap-pro/extension-tracked-changes'
import { SplitView, createSplitView } from '@tiptap-pro/extension-split-view'

const mainEditor = new Editor({
  extensions: [
    // ... other extensions
    TrackedChanges,
  ],
    content: '<p>从这里开始写作。</p>',
})

const beforeEditor = new Editor({
  extensions: [
    // ... other extensions
    TrackedChanges,
    SplitView,
  ],
})

const afterEditor = new Editor({
  extensions: [
    // ... other extensions
    TrackedChanges,
    SplitView,
  ],
})

let manager = createSplitView({ mainEditor, beforeEditor, afterEditor })

内容由主编辑器管理。createSplitView() 将两个窗格连接到主编辑器。编辑以及接受/拒绝操作会在三个编辑器之间同步。

排列窗格

打开分栏视图时隐藏主编辑器。为两个窗格设置相同的顶部内边距,并使用共享的滚动容器。

<div id="main" hidden></div>
<div id="split">
  <div id="before"></div>
  <div id="after"></div>
</div>
#split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  overflow: auto;
}

#split[hidden] {
  display: none;
}

灰色间隔块用于填充高度差或缺失的块。两个间隔块会使用到下一个块的两个间距中较大者作为底部外边距,该间距根据你的 CSS 测量。高度为零的间隔块只增加间距,不显示灰色方框。间隔块永远不会保存到文档中。

切换视图

销毁管理器以停止同步并移除窗格过滤;编辑器本身仍然保持存活。

manager.destroy()
document.querySelector('#split')?.setAttribute('hidden', '')
document.querySelector('#main')?.removeAttribute('hidden')

要返回分栏视图,请重新连接。两个窗格会接收主编辑器的当前文档。

document.querySelector('#main')?.setAttribute('hidden', '')
document.querySelector('#split')?.removeAttribute('hidden')
manager = createSplitView({ mainEditor, beforeEditor, afterEditor })

组件卸载时销毁三个编辑器。每个编辑器都有自己的撤销历史;分栏视图不提供共享撤销。

API 参考

SplitView

将它与 TrackedChanges 一起安装在两个窗格中。无需配置;在 createSplitView() 连接编辑器之前它保持非活动状态。

createSplitView(options): SplitViewManager

返回一个 SplitViewManager。传入三个不同且已挂载、schema 相同的编辑器。一个编辑器只能属于一个活动管理器。

OptionTypeDescription
mainEditorEditor提供初始文档。
beforeEditorEditor显示删除内容和未变化内容。
afterEditorEditor显示新增内容和未变化内容。
createSpacer(options: SplitViewSpacerOptions) => HTMLElement可选的自定义间隔元素。

其他类型的建议(例如格式变化)会在两个窗格中继续显示。三个编辑器都保留完整文档,包括在某个窗格中隐藏的内容。再次连接相同编辑器前,请先销毁现有管理器。

管理器方法

MethodReturnsDescription
getMainEditor()Editor | undefined返回主编辑器。
getBeforeEditor()Editor | undefined返回 Before 窗格。
getAfterEditor()Editor | undefined返回 After 窗格。
update()void在自定义布局或 CSS 发生变化后安排对齐。
destroy()void停止同步、移除间隔块和过滤并释放资源。可以安全地调用两次。

销毁后 getter 会返回 undefined。销毁任何已连接的编辑器也会销毁管理器。内容变化、调整大小、图片加载和字体加载都会自动更新对齐。

设置间隔块样式

默认间隔块是带有 tiptap-split-view-spacer 类的 div。可以使用 CSS 设置其背景:

#split {
  --tiptap-split-view-spacer-background: #eee;
}

如需自定义元素,请提供 createSpacer:

manager.destroy()
manager = createSplitView({
  mainEditor,
  beforeEditor,
  afterEditor,
  createSpacer({ document }) {
    const spacer = document.createElement('div')
    spacer.style.background = '#eee'
    return spacer
  },
})

SplitViewSpacerOptions 包含 document: Document 和 side: 'original' | 'modified'。createSpacer 回调应返回 HTMLElement;管理器会控制其高度、外边距和可见性。自定义元素不会自动获得默认类名。