注入内容 REST API

要在服务器端注入内容到文档中,请使用本文档中描述的 PATCH 端点。此功能支持版本历史记录,跟踪更改以及通过此端点添加的内容。

更新文档的端点还允许 JSON 更新以修改您在协作服务器上的文档,包括本地部署和云端:

  • 在任何文档服务器端添加 jsonbinarybase64 内容。
  • 使用 UniqueID 扩展 向特定节点注入内容。
  • 用户仍然可以实时协作,因为内容在注入过程中。
  • 跟踪用户和注入内容的更改,完全兼容 快照

用例

内容注入 REST API 可以实现一些方便但复杂的用例:

  • 文档内容的实时翻译。
  • 在服务器端以编程方式标记或操作文档内容。
  • 集成服务器端组件,例如执行 SQL 查询并显示结果。
  • 版本历史集成和无冲突的并发编辑合并。

创建文档

要在 Tiptap Collab 服务器上初始化新文档,请使用 POST 方法和以下端点:

POST /api/documents/:identifier?format=:format

服务器将为成功创建返回 HTTP 状态码 204,如果文档已存在则返回 409(必须先删除才能覆盖),如果操作失败则返回 422

format 参数接受与更新端点相同的值(binarybase64json)。

更新文档

要在协作服务器上更新现有文档,您可以使用 PATCH 方法和以下 API 端点:

PATCH /api/documents/:identifier?format=:format

此端点接受 Yjs 更新消息并将其应用到指定文档。

查询参数

参数类型默认值描述
formatstring更新的格式:jsonbinary(Yjs 的 Y.encodeStateAsUpdate)或 base64(以 Base64 编码的二进制状态)。
modestringdefault更新策略:default 合并节点,append 仅追加,node 将匹配的节点替换为负载内容,attrs 替换匹配节点的属性,delete 删除匹配的节点(不需要负载)。请参阅模式
nodeAttributeNamestring将更新限制为具有此名称属性的节点。与 nodeAttributeValue 一起使用。
nodeAttributeValuestring将更新限制为具有此值属性的节点。与 nodeAttributeName 一起使用。您可以传递多个值:?nodeAttributeValue=a&nodeAttributeValue=b
checksumstring仅当文档的当前状态与此校验和匹配时才应用更新(在获取文档响应中作为 x-FRAGMENTNAME-checksum 返回)。否则返回 409 Checksum mismatch
userstring与更改关联的用户 ID。
skipVersioning1如果传递,此更改不会触发自动版本控制。
fragmentstringdefault要更新的 Yjs 片段。您可以通过传递多个值来更新多个片段(当 format=json 时):?fragment=a&fragment=b
mergeAttributes0 | 10仅与 mode=attrs 一起使用。当为 1 时,请求负载中未包含的属性将被保留。当为 0(默认)时,缺失的属性将被删除。
multiUpdatestrue仅与 mode=attrsformat=json 一起使用。允许在单个请求中更新具有不同属性值的多个节点。请求体必须是 { where, attrs } 对象的 JSON 数组。请参阅多重更新

成功更新后,服务器将返回 HTTP 状态 204。如果文档不存在,将返回 404,如果负载无效或无法应用更新,将返回 422

示例: 更新文档的 curl 命令

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \\
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA' \\
--data '@yjsUpdate.binary'

通过 JSON 更新

通过 JSON 更新时,服务器计算当前文档状态与提供的 JSON 之间的差异,然后内部计算所需的 Yjs 更新以达到目标状态。

To ensure precise updates, especially for node-specific changes, it is recommended to use the nodeAttributeName and nodeAttributeValue parameters. These can be generated by Tiptap's UniqueID Extension or a custom implementation. Note that this only works for top level nodes when using mode=default.

省略这些参数可能会导致覆盖在获取文档和发出更新调用之间所做的任何更新。get document 调用返回一个头 x-${fragmentName}-checksum,可以通过将其传递给更新调用作为 ?checksum=${checksum} 来检测冲突。如果自上次获取以来文档已被更新,更新将以 409 Checksum mismatch. 状态失败。

模式

mode 参数控制内容如何应用到文档:

默认模式

将负载中的节点合并到文档中。这是未指定模式时的默认行为。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Merged content" }]
    }
  ]
}'

追加模式

将节点追加到文档的 JSON 表示中,而不更改现有节点。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=append' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "This paragraph is appended at the end" }]
    }
  ]
}'

节点模式

将匹配 nodeAttributeName/nodeAttributeValue 的节点替换为负载中的节点。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=node&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "paragraph",
  "attrs": { "id": "abc-123" },
  "content": [{ "type": "text", "text": "This replaces the entire matched node" }]
}'

属性模式

将匹配节点的所有属性替换为请求负载(仅发送属性对象)。有关 mergeAttributes 的详细信息,请参阅仅更新节点属性

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "textAlign": "center",
  "indent": 2
}'

删除模式

删除匹配 nodeAttributeName/nodeAttributeValue 的节点。不需要负载。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=delete&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: YOUR_SECRET'

有用的参数组合

跟踪谁做了更改

将用户 ID 与注入的内容关联,用于审计跟踪和版本历史。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&user=bot-user-1' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Injected by bot" }]
    }
  ]
}'

跳过自动版本控制

注入内容而不创建新的版本快照。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&skipVersioning=1' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Silent update" }]
    }
  ]
}'

更新特定片段

定位特定的 Yjs 片段而不是默认片段,或同时更新多个片段。

# 更新单个片段
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&fragment=sidebar' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Sidebar content" }]
    }
  ]
}'
# 使用相同内容更新多个片段
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&fragment=header&fragment=footer' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Shared content" }]
    }
  ]
}'

使用校验和的安全冲突更新

仅当自上次获取以来文档未更改时才应用更新。

# 1. 获取文档并记录校验和头(x-default-checksum)。当使用 ?format=json 获取文档时,该头存在。如果您想获取不同片段的校验和,请发送 &fragment=customfragmentname
# 2. 在更新调用中使用该校验和
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&checksum=THE_CHECKSUM_VALUE' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "Only applied if document unchanged" }]
    }
  ]
}'

合并属性而不删除现有属性

更新匹配节点上的特定属性,同时保留所有其他现有属性。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&nodeAttributeName=id&nodeAttributeValue=abc-123&mergeAttributes=1' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "textAlign": "center"
}'

完整示例

示例: 使用 JSON 更新文档

// 定义文档名称、密钥和应用程序 ID
const docName = '' // 如有必要,请进行 URI 编码
const secret = ''
const appId = ''; // Your document server ID from the Cloud dashboard;

// 构建基本 URL
const url = `https://${appId}.collab.tiptap.cloud`

// 获取当前文档的 JSON 表示
const docJson = await axios.get(`${url}/api/documents/${docName}?format=json`, {
    headers: {
    Authorization: secret
  },
})

// 提取文档的 JSON 内容
const tiptapJson = docJson.data
const nodes = tiptapJson.content

// 使用唯一标识符查找并记录特定节点
const query = nodes.find(n => n.attrs?.identifier === 'fe5c0789-85d9-4877-a2c3-bccf5d874866').content[0].text
const resultTable = nodes.find(n => n.attrs?.identifier === '246368b6-0746-4ca1-a16f-8d964aff4041')

console.log(`Query: ${query}`)
console.log(JSON.stringify(resultTable.content))

// 向结果表节点附加新内容
resultTable.content.push({
  // 新表行内容在此
  {
    "type": "tableRow",
    "content": [
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "Jan"
              }
            ]
          }
        ]
      },
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "Thurau"
              }
            ]
          }
        ]
      },
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "jan@janthurau.de"
              }
            ]
          }
        ]
      }
    ]
  }
})

// 将更新后的 JSON 发送回服务器以应用更改
await axios.patch(`${url}/api/documents/${docName}?format=json`, tiptapJson, {
  headers: {
    Authorization: secret
  }
})

仅更新节点属性

如果您只想更新节点的属性,可以使用 ?mode=attrs 查询参数。这将仅更新节点的属性,而不更新其内容。 在此模式下,nodeAttributeNamenodeAttributeValue 参数适用于任何(不仅仅是顶层)节点。

默认情况下,匹配节点上的所有属性都会被替换——未包含在负载中的属性将被删除。要保留现有属性并仅更新负载中指定的属性,请传递 ?mergeAttributes=1

不指定节点过滤器(nodeAttributeNamenodeAttributeValue)将导致所有节点被更新。

curl --location --request PATCH '/api/documents/:identifier?format=json&nodeAttributeName=id&nodeAttributeValue=12&mode=attrs' \
--data '{
  "indent": 12,
  "textAlign": "right"
}'

多重更新

当使用 mode=attrs 时,您可以通过传递 multiUpdates=true 在单个请求中更新具有不同属性值的多个节点。您不是在查询参数中使用 nodeAttributeName/nodeAttributeValue 来定位节点,而是在请求体中提供一个更新对象数组。每个对象指定一个 where 子句来匹配节点以及要应用的 attrs

where 子句中的所有条件使用 AND 逻辑连接——节点必须匹配每个指定的属性才能被更新。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&multiUpdates=true' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '[
  {
    "where": {
      "id": "id123"
    },
    "attrs": {
      "textAlign": "center"
    }
  },
  {
    "where": {
      "name": "customname"
    },
    "attrs": {
      "indent": 2
    }
  }
]'

您可以将 multiUpdates 与其他参数如 userskipVersioningfragmentmergeAttributes 结合使用:

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&multiUpdates=true&user=bot-user-1&mergeAttributes=1' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '[
  {
    "where": {
      "id": "node-1",
      "type": "heading"
    },
    "attrs": {
      "level": 2
    }
  },
  {
    "where": {
      "id": "node-2"
    },
    "attrs": {
      "textAlign": "right"
    }
  }
]'

文档字段

这些端点允许您读取和更新文档上的自定义 Yjs 字段。当您使用自定义 Yjs 类型(例如 Y.getMap('configuration'))并希望通过 API 获取或更新值时,这非常有用。

获取文档字段

GET /api/documents/:identifier/fields?field=:field&type=:type

返回自定义 Yjs 字段的当前值。

查询参数

参数类型默认值描述
fieldstring自定义字段的名称。
typestring自定义字段的 Yjs 类型。支持的值:maparray。传递错误的类型将返回不正确的结果。注意,调用此端点将在文档上创建该类型(如果它不存在)。为相同的字段名称切换类型将产生意外的副作用。
curl --location 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: YOUR_SECRET'

更新文档字段

PATCH /api/documents/:identifier/fields?field=:field&type=:type
PUT /api/documents/:identifier/fields?field=:field&type=:type

更新文档上的自定义 Yjs 字段。

  • PATCH 将请求体合并到现有字段值中 —— 仅更新您发送的键,保留现有键。
  • PUT 完全替换字段 —— 请求体中不存在的键将被删除。

查询参数

参数类型默认值描述
fieldstring自定义字段的名称。
typestring自定义字段的 Yjs 类型。目前仅支持 map 类型进行更新。
userstring要与更改关联的用户 ID。
skipVersioning1如果传入,此更改不会触发自动版本控制。

示例:使用 PATCH 合并值

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "key": "newValue",
  "array": [1, 2, 3],
  "object": {
    "id": 62,
    "position": ""
  },
  "arrayOfObjects": [
    { "id": 61 }
  ]
}'

示例:使用 PUT 替换所有值

curl --location --request PUT 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "key": "newValue"
}'

任何未包含在 PUT 请求体中的现有键都将从字段中删除。