集成快照

文档历史记录记录您内容的每一次更改,以便您能够撤回错误、审核编辑或从任何时刻创建新草稿。

本页将向您介绍 历史 扩展的安装、配置和常见任务。

公共演示

编辑器内容在所有演示访问者之间共享。

访问专用注册表

版本历史扩展发布在 Tiptap 的私有 npm 注册表中。按 私有注册表指南 操作集成该扩展。如果您已经对您的 Tiptap 账户进行了身份验证,您可以直接跳转至 #安装

安装


npm install @tiptap-pro/extension-snapshot @hocuspocus/transformer

注意@hocuspocus/transformer 包用于将 Y.js 的二进制数据转换为 Tiptap JSON。同时也需要安装 Y.js 以支持协作。 如果尚未安装,请在项目中运行 npm install yjs。如果您使用 NPM,这应该会自动发生(因为它会自动解析对等依赖关系)。

设置

设置类型默认值
providerTiptapCollabProvidernull
onUpdatefunction() => {}

自动版本控制

自动版本控制功能会在固定间隔自动创建文档的新版本。这确保您拥有全面的更改历史,而无需手动干预。

您可以使用 toggleVersioning 命令切换此功能(默认:禁用)。

当您启用自动版本控制时,Tiptap 会在固定间隔(默认30秒,仅在文档发生更改时)创建新版本。这可能会创建许多版本,因此您可能想要增加间隔。 要自定义间隔,可以执行以下操作:

// 设置自动版本间隔(以秒为单位)
const ydoc = provider.configuration.document
ydoc.getMap<number>('__tiptapcollab__config').set('intervalSeconds', 900)

恢复到某个版本

当您恢复到以前的版本时:

  1. 如果有未保存的更改,Tiptap 会自动创建一个版本以保留这些更改。
  2. Tiptap 会在历史记录的顶部创建一个新版本,其内容来自您选择的版本。
  3. 所有用户可以从此新版本继续工作。

请注意,恢复仅影响 ydoc 中的 default 片段。当您恢复 Tiptap 内容时,评论不会更改(除非您在 TiptapCollabProvider 中指定了不同的 field)。

您可以集成 比较快照 扩展以突出不同版本之间的差异,确保您选择正确的版本进行恢复。

存储

KeyTypeDescription
currentVersionnumber当前版本。
lastSavedDate最近保存的时间戳。
latestVersionnumber最新版本。
providerTiptapCollabProvider协作提供者实例。
statusstring提供者的状态 - 可以是 connectingconnecteddisconnected
syncedboolean版本历史是否与服务器同步。
versioningEnabledboolean是否启用版本控制。
versionsarray<Version>存储在历史中的版本数组。每个版本包含 version(数字)、date(数字)、可选的 name(字符串)和可选的 meta(对象)。有关 meta 字段的详细信息,请参见 自动版本元数据

命令

命令描述
saveVersion使用给定的标题创建一个新版本
toggleVersioning为此文档切换自动版本控制
revertToVersion恢复到特定版本,可以使用可选标题创建新的恢复版本

示例

基本设置

const provider = new TiptapCollabProvider({
  // ...
})

const editor = new Editor({
  // ...
  extensions: [
    // ...
    Snapshot.configure({
      provider,
    }),
  ],
})

存储版本更新

在此示例中,我们检索版本更新的数据并将其保存到变量中。

let currentVersion = 0
let latestVersion = 0
let autoversioningEnabled = false
let versions = []

const provider = new TiptapCollabProvider({
  // ...
})

const editor = new Editor({
  // ...
  extensions: [
    // ...
    Snapshot.configure({
      provider,
      onUpdate(payload) {
        currentVersion = payload.currentVersion
        latestVersion = payload.version
        versions = payload.versions
        autoversioningEnabled = payload.versioningEnabled
      },
    }),
  ],
})

直接从存储访问版本数据

const provider = new TiptapCollabProvider({
  // ...
})

const editor = new Editor({
  // ...
  extensions: [
    // ...
    Snapshot.configure({
      provider,
    }),
  ],
})

const latestVersion = editor.storage.snapshot.latestVersion
const currentVersion = editor.storage.snapshot.currentVersion
const versions = editor.storage.snapshot.versions
const autoversioningEnabled = editor.storage.snapshot.versioningEnabled

手动创建新版本

editor.commands.saveVersion('我的新自定义版本')

使用元数据创建版本

您可以向版本附加任意元数据。这对于存储额外的上下文信息(如作者、标签或任何自定义数据)非常有用。

editor.commands.saveVersion('Release v1.0', false, {
  author: 'Jane Doe',
  tags: ['release', 'stable'],
})

saveVersion 命令接受三个参数:

参数类型默认值描述
namestringundefined版本的可选名称
forcebooleanfalse即使未检测到更改也创建版本
metaRecord<string, unknown>undefined附加到版本的任意元数据

自动版本元数据

每个版本的 meta 对象中自动包含一个 __tiptap 键。该元数据由服务器添加,提供有关版本创建方式及贡献者的上下文信息。

一个版本的 meta 字段示例如下:

{
  "__tiptap": {
    "trigger": "websocket",
    "changesBy": ["#user1"],
    "triggeredBy": "user1"
  },
  "wordCount": 81624434
}

__tiptap 对象包含以下字段:

字段类型描述
triggerstring版本的创建方式。可能的值包括:"websocket"(通过编辑器/提供者),"api"(通过 REST API),"autoVersioning"(自动版本控制功能创建),或 "revert"(恢复到以前版本时创建)。
changesBystring[]包含此版本更改的用户标识列表。
triggeredBystring触发版本创建的用户标识。

您通过 saveVersion 或 REST API 传递的任何自定义元数据都存储在 __tiptap 键的同一级 meta 顶层中。__tiptap 键为保留字段,不能被自定义元数据覆盖。

从服务器获取版本

您可以使用 fetchVersions 命令手动刷新服务器上的版本列表。这会更新扩展存储中的最新版本数据。

editor.commands.fetchVersions()

启用文档自动版本控制

editor.commands.enableVersioning()

禁用文档自动版本控制

editor.commands.disableVersioning()

通过版本 ID 恢复

editor.commands.revertToVersion(4)

使用自定义名称恢复版本 ID

在此示例中,编辑器命令帮助您回到版本 4。当您使用此命令时,它将带您回到版本 4 的状态,并且还将此旧版本保存为一个新版本,称为“恢复到版本”。这样,您可以继续从版本 4 开始工作,但它现在作为最新版本保存。

editor.commands.revertToVersion(4, '恢复到版本')

恢复、命名和备份

在此示例中,当您恢复到文档的版本 4 时,编辑器会自动创建两个新版本。第一个新版本记录并保存您在恢复之前文档的状态,作为备份。第二个新版本将文档恢复到版本 4,允许您从这里继续作为新的起点。

editor.commands.revertToVersion(4, '恢复到版本', '恢复之前的未版本化更改')

为编辑器实现版本预览

上述示例直接修改文档,并未提供版本的仅限于本地的预览。因此,您必须为此需求创建自己的前端解决方案。您可以利用 TiptapCloudProvider 的无状态消息系统请求特定版本的内容。

首先,附加一个监听器到提供程序:

const versions = await provider.listVersions()
// versions: Array<{ version: number, date: number, name?: string, meta?: Record<string, unknown> }>

获取缓存的版本列表

获取本地缓存的版本列表(不请求服务器):

const versions = provider.getVersions()

监听版本变更

使用回调函数订阅版本列表更新:

const onVersionsChange = (versions) => {
  console.log('版本已更新:', versions)
}

// 开始监听
provider.watchVersions(onVersionsChange)

// 停止监听
provider.unwatchVersions(onVersionsChange)

创建带元数据的版本

provider.createVersion('我的版本', false, {
  author: 'Jane Doe',
  tags: ['draft'],
})

为编辑器实现版本预览

上述示例直接修改文档,并不提供仅在本地对版本的预览。因此,您必须为此需求创建自己的前端解决方案。您可以使用 TiptapCollabProvider 上的 previewVersion 方法从服务器请求特定版本。

首先,附加一个监听器到提供程序:

// 导入 getPreviewContentFromVersionPayload 辅助函数(详情见下文)
import { watchPreviewContent } from '@tiptap-pro/extension-snapshot'

// 配置提供程序
const provider = new TiptapCollabProvider({ ... })

// 使用 watchPreviewContent 工具函数监听提供者上的内容更改
const unbindWatchContent = watchPreviewContent(provider, content => {
  // 设置编辑器内容
  editor.commands.setContent(content)
})

如果您想解绑监听器,可以调用返回的 unbindWatchContent 函数:

const unbindWatchContent = watchPreviewContent(provider, (content) => {
  // 设置编辑器内容
  editor.commands.setContent(content)
})

// 取消监听
unbindWatchContent()

配置完成后,您可以按如下方式触发 version.preview 请求:

// 向服务器请求特定版本的预览
provider.previewVersion(1)

// 您可以将此操作绑定到按钮点击或其他 UI 元素上以触发请求。

要超越预览并以可视化方式比较不同版本,比较快照 扩展提供了一种简单的方法来查看编辑器中任意两个版本之间的差异。

实用函数

getPreviewContentFromVersionPayload

此函数将来自协作提供程序的有效负载转换为 Tiptap JSON 内容。

参数描述
payload版本预览事件的 Hocuspocus 有效负载
field要解析的字段。默认值:default
const myContent = getPreviewContentFromVersionPayload(payload, 'default')

watchPreviewContent

此函数在您的提供程序上设置一个观察者,监控必要的事件以响应版本内容的更改。它还返回一个新函数,您可以用来取消观察这些事件。

参数描述
provider协作提供程序
callback被调用的回调函数,参数为 Tiptap JSON 内容
field被监视的字段 - 默认值为 default
const unwatchContent = watchPreviewContent(provider, editor.commands.setContent, 'default')

// 取消观察版本预览内容
unwatchContent()

可能的提供程序有效负载

以下是可以从提供程序发送或接收的有效负载列表:

外发

document.revert

请求将文档恢复到给定版本,带有可选的标题设置。

provider.createVersion('My custom version', false, { author: 'Jane Doe' })

version.create

创建一个带有可选标题的新版本。

provider.sendStateless(
  JSON.stringify({ action: 'version.create', name: '我的自定义版本' }),
)

versions.list

请求服务器上的全部版本列表。

const versions = await provider.listVersions()

内发

version.created

此无状态消息包含有关新创建版本的信息,包括任何附加的元数据。

provider.on('stateless', (data) => {
  const payload = JSON.parse(data.payload)

  if (payload.event === 'version.created') {
    const latestVersion = payload.version
    const name = payload.name // 可选版本名称
    const date = payload.date // 创建时间戳
    const meta = payload.meta // 可选元数据对象
  }
})

versions.list

listVersions 方法返回完整的版本列表。每个版本包含 versiondate,以及可选的 namemeta 字段。

const versions = await provider.listVersions()
// versions 是一个包含 { version: number, date: number, name?: string, meta?: object } 的数组

document.reverted

此无状态消息包含有关文档恢复的信息。

provider.on('stateless', (data) => {
  const payload = JSON.parse(data.payload)

  if (payload.event === 'document.reverted') {
    const currentVersion = payload.version
  }
})