比较版本
BetaPilot program
使用 compareVersions 命令 比较两个 Yjs 版本更新并显示变化。
获取版本
首先使用 getVersions 方法获取版本。如果使用快照扩展,可以从 editor.storage.snapshot.versions 获取可用版本。数组中的每个项目都包含保存版本 ID 的 version 属性。将这些版本 ID 传给 getVersions。
有关如何保存快照和获取版本数据,请参阅快照指南。
import { getVersions } from '@tiptap-pro/compare'
import { TiptapCollabProvider } from '@tiptap-pro/provider'
const provider = new TiptapCollabProvider()
const { prevSnapshot: versionA, snapshot: versionB } = await getVersions({
provider,
// 从快照扩展获取的版本 ID
fromVersion: 1,
toVersion: 2,
})比较版本
将 Compare 扩展添加到要显示变化的编辑器中,然后将两个 Yjs 版本传给 compareVersions。
import { Editor } from '@tiptap/core'
import { Compare } from '@tiptap-pro/compare'
// 显示变化的编辑器
const editor = new Editor({
extensions: [
Compare,
// ...other extensions
],
})
editor.commands.compareVersions({
versionA,
versionB,
})compareVersions 命令会比较两个版本,并立即显示变化。
设置变更样式
当用户 ID 可用时,compareVersions 会将其添加到每项变化的元数据中。使用 renderDecorations 为每位用户设置颜色。
const colors = [
'#FAF594',
'#958DF1',
'#F98181',
'#70CFF8',
'#FBBC88',
'#94FADB',
'#B9F18D',
'#6EE7B7',
]
const colorMapping = new Map()
const getUserColor = (userId) => {
if (!colorMapping.has(userId)) {
colorMapping.set(userId, colors[(userId || '').length % colors.length])
}
return colorMapping.get(userId)
}
const getDiffUserColor = ({ userId, diffType }) =>
`${getUserColor(userId)}${diffType === 'removed' ? '50' : 'B0'}`
const getDecorationAttributes = ({ userId, backgroundColor, textColor }) => {
if (!userId) {
return {}
}
return {
'data-diff-user-id': userId,
style: `--diff-background-color: ${backgroundColor}; --diff-text-color: ${textColor}`,
}
}
const getAddedDecorationAttributes = (userId) =>
getDecorationAttributes({
userId,
backgroundColor: getDiffUserColor({ userId, diffType: 'added' }),
textColor: '#000',
})
const renderDecorations = ({ suggestion, defaultRenderDecorations }) => {
const userId = suggestion.metadata?.userId
const removedAttributes = getDecorationAttributes({
userId,
backgroundColor: getDiffUserColor({ userId, diffType: 'removed' }),
textColor: '#777',
})
const addedAttributes = getAddedDecorationAttributes(userId)
return defaultRenderDecorations({
attributes: addedAttributes,
subChangeAttributes: addedAttributes,
replacementAttributes: removedAttributes,
replacementSubChangeAttributes: removedAttributes,
})
}
const getNestedChangeAttributes = ({ nestedChange }) =>
getAddedDecorationAttributes(nestedChange.metadata?.userId)将自定义渲染器传给 compareVersions。
editor.commands.compareVersions({
versionA,
versionB,
displayOptions: { getNestedChangeAttributes, renderDecorations },
})将以下样式添加到样式表。这些样式使用 renderDecorations 设置的 CSS 变量,并在悬停时显示用户 ID。
[data-diff-user-id] {
cursor: pointer;
display: inline-block;
position: relative;
}
[data-diff-user-id]::before {
background-color: #fff;
border: 1px solid var(--black);
border-radius: 6px;
color: var(--black);
content: attr(data-diff-user-id);
font-size: 0.75rem;
font-weight: normal;
left: 0;
line-height: normal;
padding: 3px;
position: absolute;
text-align: center;
top: 105%;
visibility: hidden;
white-space: nowrap;
z-index: 1;
}
[data-diff-user-id]:hover::before {
visibility: visible;
}
/* Current, added, and nested content */
.diff-suggestion,
.diff-suggestion-nested-change {
background-color: var(--diff-background-color, rgb(226 255 232 / 69%));
color: var(--diff-text-color, var(--black));
}
strong .diff-suggestion-diff {
font-weight: normal;
}
em .diff-suggestion-diff {
font-style: normal;
}
code:not(pre code) .diff-suggestion-diff {
font-family: sans-serif;
}
.diff-suggestion-diff strong {
font-weight: bold;
}
.diff-suggestion-diff em {
font-style: italic;
}
.diff-suggestion-diff code:not(pre code) {
font-family: monospace;
}
.diff-suggestion.diff-suggestion--change-group,
.diff-suggestion-nested-change--block {
background-color: var(--diff-background-color, rgb(226 255 232 / 69%));
}
.diff-suggestion-sub-change,
.diff-suggestion-nested-change--inline {
background-color: var(--diff-background-color, rgb(226 255 232 / 69%));
}
/* Replacement content from the previous version */
.diff-suggestion-diff {
background-color: var(--diff-background-color, rgb(255 226 226 / 31%));
color: var(--diff-text-color, var(--black));
text-decoration: line-through;
}
.diff-suggestion-diff.diff-suggestion-diff--change-group {
background-color: var(--diff-background-color, rgb(255 226 226 / 31%));
}
.diff-suggestion-diff-sub-change {
background-color: var(--diff-background-color, rgb(255 226 226 / 31%));
}
.tiptap li:has(.diff-suggestion, .diff-suggestion-nested-change) {
display: list-item;
}
.diff-suggestion-diff:has(> :is(blockquote, h1, h2, h3, h4, h5, h6, hr, ol, p, pre, ul)) {
display: block;
width: 100%;
}
.diff-suggestion:is(blockquote, h1, h2, h3, h4, h5, h6, hr, ol, p, pre, ul),
.diff-suggestion-nested-change--block:is(blockquote, h1, h2, h3, h4, h5, h6, hr, ol, p, pre, ul) {
display: block;
width: 100%;
}