mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-12-19 22:27:52 +08:00
180 lines
6.1 KiB
Markdown
180 lines
6.1 KiB
Markdown
|
# Backend Document Manipulation
|
||
|
|
||
|
Backend Document Manipulation allows developers to programmatically modify documents stored on the Collaboration server (On premises and Cloud).
|
||
|
|
||
|
This feature provides flexibility in document management, enabling updates through JSON, which is a simpler alternative to using Yjs methods directly.
|
||
|
|
||
|
This functionality is available via API calls and is included from the start for users with a Business or Enterprise plan.
|
||
|
|
||
|
The feature is fully compliant with Version history, and allows to track changes from users, as well as the Backend Document Manipulation feature.
|
||
|
|
||
|
###To update an existing document on the Tiptap Collab server, you can use the PATCH method with the following API endpoint: Use Cases
|
||
|
|
||
|
Backend Document Manipulation enables a variety of use cases, such as:
|
||
|
|
||
|
- Live translation of document content.
|
||
|
- Server-side components, like executing an SQL query and displaying results.
|
||
|
- Automatic typo and grammar corrections.
|
||
|
- Version history integration and conflict-free merging of concurrent edits.
|
||
|
|
||
|
This powerful feature set allows for extensive customization and automation of document handling on the Tiptap platform, catering to a wide range of collaborative editing scenarios.
|
||
|
|
||
|
## Update Document
|
||
|
|
||
|
To update an existing document on the Collaboration server, you can use the `PATCH` method with the following API endpoint:
|
||
|
|
||
|
```bash
|
||
|
PATCH /api/documents/:identifier?format=:format
|
||
|
```
|
||
|
|
||
|
This endpoint accepts a Yjs update message and applies it to the specified document. The `format` query parameter specifies the format of the update and can be one of the following:
|
||
|
|
||
|
- `binary`: Directly using Yjs's `Y.encodeStateAsUpdate` method.
|
||
|
- `base64`: The binary state encoded as a Base64 string.
|
||
|
- `json`: Updates the document using JSON format (with some caveats, see below).
|
||
|
|
||
|
Upon successful update, the server will return HTTP status `204`. If the document does not exist, it will return `404`, and if the payload is invalid or the update cannot be applied, it will return `422`.
|
||
|
|
||
|
Example `curl` command to update a document:
|
||
|
|
||
|
```bash
|
||
|
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.txt'
|
||
|
```
|
||
|
|
||
|
### Update via JSON
|
||
|
|
||
|
When updating via JSON, the server computes the difference between the current document state and the provided JSON, then internally calculates the required Yjs update to reach the target state.
|
||
|
|
||
|
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](https://tiptap.dev/docs/editor/api/extensions/unique-id) or a custom implementation.
|
||
|
|
||
|
- `nodeAttributeName`: Configured as `attributeName` in the UniqueID extension.
|
||
|
- `nodeAttributeValue`: The unique value generated for the node to be updated.
|
||
|
|
||
|
From version 3.3.0 onwards, you can use `?mode=append` to append nodes to the document's JSON representation without altering existing content.
|
||
|
|
||
|
Omitting these parameters may result in overwriting any updates made between fetching the document and issuing the update call.
|
||
|
|
||
|
Here is an example of how to update a document using JSON:
|
||
|
|
||
|
```typescript
|
||
|
// Define the document name, secret, and application ID
|
||
|
const docName = ''
|
||
|
const secret = ''
|
||
|
const appId = '';
|
||
|
|
||
|
// Construct the base URL
|
||
|
const url = `https://${appId}.collab.tiptap.dev`
|
||
|
|
||
|
// Fetch the current document's JSON representation
|
||
|
const docJson = await axios.get(`${url}/api/documents/${docName}?format=json`, {
|
||
|
headers: {
|
||
|
Authorization: secret
|
||
|
},
|
||
|
})
|
||
|
|
||
|
// Extract the document's JSON content
|
||
|
const tiptapJson = docJson.data
|
||
|
const nodes = tiptapJson.content
|
||
|
|
||
|
// Find and log specific nodes using their unique identifiers
|
||
|
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))
|
||
|
|
||
|
// Append new content to the result table node
|
||
|
resultTable.content.push({
|
||
|
// New table row content here
|
||
|
{
|
||
|
"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"
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
})
|
||
|
|
||
|
// Send the updated JSON back to the server to apply the changes
|
||
|
await axios.patch(`${url}/api/documents/${docName}?format=json`, tiptapJson, {
|
||
|
headers: {
|
||
|
Authorization: secret
|
||
|
}
|
||
|
})
|
||
|
```
|
||
|
|
||
|
## Create Document
|
||
|
|
||
|
To seed a new document on the Tiptap Collab server, use the `POST` method with the following endpoint:
|
||
|
|
||
|
```bash
|
||
|
POST /api/documents/:identifier?format=:format
|
||
|
```
|
||
|
|
||
|
The server will return HTTP status `204` for successful creation, `409` if the document already exists (you must delete it first to overwrite), and `422` if the action failed.
|
||
|
|
||
|
The `format` parameter accepts the same values as the update endpoint (`binary`, `base64`, or `json`).
|