快照对比
本页演示 power-editor 的快照对比流程。
- 准备两份 Tiptap JSON 文档。
- 分别用
power-editor渲染源文档和目标文档。 - 通过
getJSON()读取两边编辑器内容。 - 使用
computeDiff()或diffTool.compareDiff()计算差异。 - 将最终审阅结果渲染到另一个
power-editor中。
说明
快照对比用于把两个编辑器快照转换为可审阅的差异结果,适合版本预览、草稿校对、审批确认和变更回放。
主编辑器中的 Diff Props
下面这些属性已经在主编辑器 power-editor 上可直接使用,既可以用于本页示例,也可以用于你自己的审阅页面。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
diffInlineBlockTypes | string[] | [] | 扩展按“行内内容 diff”处理的块级节点类型。适合外观像块节点、但内容仍应逐段比较的自定义节点。 |
diffContainerBlockTypes | string[] | [] | 扩展按“容器节点 diff”处理的块级节点类型。适合包装器、布局容器、多子节点结构。 |
diffInsertColor | string | "" | 插入变更主色。 |
diffDeleteColor | string | "" | 删除变更主色。 |
diffInsertColorSec | string | "" | 插入变更辅助色,常用于边框或装饰。 |
diffDeleteColorSec | string | "" | 删除变更辅助色。 |
diffInsertHoverColor | string | "" | 鼠标移入插入变更时的高亮色。 |
diffDeleteHoverColor | string | "" | 鼠标移入删除变更时的高亮色。 |
diffInsertHoverColorSec | string | "" | 插入变更 hover 状态的辅助色。 |
diffDeleteHoverColorSec | string | "" | 删除变更 hover 状态的辅助色。 |
推荐场景
- 自定义段落类节点时,优先补充到
diffInlineBlockTypes。 - 自定义容器、卡片、布局块时,优先补充到
diffContainerBlockTypes。 - 如果你的审阅界面有品牌色或深浅主题切换,建议同时配置普通态和 hover 态颜色。
源快照
目标快照
审阅结果
示例
在当前文档仓库中
本页在线示例直接引用源码文件,因为这里的 VitePress 就运行在同一个仓库里:
js
import { computeDiff } from "@/packages/editor/src/js/diffTool/index.js";
import { applyTrackedGroup } from "@/packages/editor/src/js/diffTool/apply.js";执行 yarn add @creatorsn/powereditor3 之后
发布到 npm 并安装后,不要再从上面的内部源码路径导入,而应该从包根入口导入:
js
import {
computeDiff,
diffTool,
applyTrackedGroup,
} from "@creatorsn/powereditor3";如果你只使用默认的对比流程,那么 computeDiff(sourceDoc, targetDoc) 就够用了。
如果你希望使用可配置写法,也可以这样写:
js
import { diffTool } from "@creatorsn/powereditor3";
const result = diffTool
.configure({
extendInlineDiffBlockTypes: ["customParagraphLike"],
extendContainerDiffBlockTypes: ["customContainerLike"],
})
.compareDiff(sourceDoc, targetDoc);使用 <power-editor> 暴露的方法
power-editor 组件实例同样暴露了 compareDiff()。如果你已经拿到了编辑器 ref,并且希望复用编辑器级别的配置入口,也可以直接这样调用:
vue
<script setup>
import { ref } from "vue";
const reviewEditorRef = ref(null);
function compareWithEditor(sourceDoc, targetDoc) {
return reviewEditorRef.value?.compareDiff?.(sourceDoc, targetDoc);
}
</script>本页主示例仍然使用直接调用 computeDiff() + applyTrackedGroup() 的方式,因为这样更便于看清整条 diff 处理链路。
vue
<script setup>
import { ref } from "vue";
import { computeDiff, applyTrackedGroup } from "@creatorsn/powereditor3";
const sourceEditorRef = ref(null);
const targetEditorRef = ref(null);
const reviewEditorRef = ref(null);
const reviewContent = ref({
type: "doc",
content: [],
});
const reviewChanges = ref([]);
function collectReviewChanges(reviewDoc) {
return [];
}
function compareSnapshots() {
const sourceJson = sourceEditorRef.value?.editor?.()?.getJSON();
const targetJson = targetEditorRef.value?.editor?.()?.getJSON();
const result = computeDiff(sourceJson, targetJson);
reviewContent.value = result.reviewDoc;
reviewChanges.value = collectReviewChanges(result.reviewDoc);
}
function applyChange(groupId, action) {
const editor = reviewEditorRef.value?.editor?.();
if (!editor) return;
applyTrackedGroup(editor, groupId, action);
reviewContent.value = editor.getJSON();
reviewChanges.value = collectReviewChanges(reviewContent.value);
}
</script>
<template>
<power-editor ref="sourceEditorRef" :model-value="sourceContent"></power-editor>
<power-editor ref="targetEditorRef" :model-value="targetContent"></power-editor>
<power-editor ref="reviewEditorRef" :model-value="reviewContent" :editable="false" :showToolBar="false"></power-editor>
<fv-button @click="compareSnapshots">执行对比</fv-button>
<fv-button @click="applyChange(reviewChanges[0]?.groupId, 'accept')">接受第一条变更</fv-button>
</template>说明事项
- 本示例中的
model-value使用的是 Tiptap JSON 文档,而不是 HTML 字符串。 - 段落行内内容现在支持
text、hardBreak、inlineEquation等多种行内原子节点。 computeDiff()会同时返回chunks和reviewDoc。diffTool.compareDiff()返回的数据结构与computeDiff()一致。reviewDoc可以直接交给power-editor渲染成最终对比结果。- 安装包之后,可以从
@creatorsn/powereditor3直接导入applyTrackedGroup()。