@haklex/rich-diff 0.0.81 → 0.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,9 +1,8 @@
1
- import { ColorSchemeProvider, getVariantClass } from "@haklex/rich-editor";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { getVariantClass, ColorSchemeProvider } from "@haklex/rich-editor";
2
3
  import { RichRenderer } from "@haklex/rich-static-renderer";
3
4
  import { PortalThemeProvider } from "@haklex/rich-style-token";
4
5
  import { useMemo } from "react";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- //#region src/style.css.ts
7
6
  var root = "xcvddd0";
8
7
  var header = "xcvddd1";
9
8
  var headerCell = "xcvddd2";
@@ -15,479 +14,485 @@ var cellOld = "xcvddd7";
15
14
  var delete_ = "xcvddd8";
16
15
  var insert = "xcvddd9";
17
16
  var empty = "xcvddda";
18
- //#endregion
19
- //#region src/compute-diff.ts
20
- var CHAR_DIFF_MAX_MATRIX_CELLS = 5e4;
21
- var DELETE_MARK_STYLE = "background-color: color-mix(in srgb, var(--rc-alert-caution) 22%, transparent); text-decoration: line-through;";
22
- var INSERT_MARK_STYLE = "background-color: color-mix(in srgb, var(--rc-alert-tip) 22%, transparent);";
17
+ const CHAR_DIFF_MAX_MATRIX_CELLS = 5e4;
18
+ const DELETE_MARK_STYLE = "background-color: color-mix(in srgb, var(--rc-alert-caution) 22%, transparent); text-decoration: line-through;";
19
+ const INSERT_MARK_STYLE = "background-color: color-mix(in srgb, var(--rc-alert-tip) 22%, transparent);";
23
20
  function getNodeTypeKey(node) {
24
- const n = node;
25
- if (n.type === "heading") return `heading:${n.tag}`;
26
- if (n.type === "list") return `list:${n.listType}`;
27
- return n.type || "unknown";
21
+ const n = node;
22
+ if (n.type === "heading") return `heading:${n.tag}`;
23
+ if (n.type === "list") return `list:${n.listType}`;
24
+ return n.type || "unknown";
28
25
  }
29
26
  function nodesEqual(a, b) {
30
- return JSON.stringify(a) === JSON.stringify(b);
27
+ return JSON.stringify(a) === JSON.stringify(b);
31
28
  }
32
29
  function isTextNode(node) {
33
- const n = node;
34
- return n.type === "text" && typeof n.text === "string";
30
+ const n = node;
31
+ return n.type === "text" && typeof n.text === "string";
35
32
  }
36
33
  function getChildren(node) {
37
- const n = node;
38
- return Array.isArray(n.children) ? n.children : null;
34
+ const n = node;
35
+ return Array.isArray(n.children) ? n.children : null;
39
36
  }
40
37
  function appendStyle(baseStyle, extraStyle) {
41
- const normalizedBase = typeof baseStyle === "string" ? baseStyle.trim() : "";
42
- if (!normalizedBase) return extraStyle;
43
- return `${normalizedBase}${normalizedBase.endsWith(";") ? "" : ";"} ${extraStyle}`;
38
+ const normalizedBase = typeof baseStyle === "string" ? baseStyle.trim() : "";
39
+ if (!normalizedBase) return extraStyle;
40
+ return `${normalizedBase}${normalizedBase.endsWith(";") ? "" : ";"} ${extraStyle}`;
44
41
  }
45
42
  function cloneTextNode(node, text, markKind) {
46
- let { style } = node;
47
- if (markKind === "delete") style = appendStyle(style, DELETE_MARK_STYLE);
48
- else if (markKind === "insert") style = appendStyle(style, INSERT_MARK_STYLE);
49
- return {
50
- ...node,
51
- text,
52
- style
53
- };
43
+ let { style } = node;
44
+ if (markKind === "delete") {
45
+ style = appendStyle(style, DELETE_MARK_STYLE);
46
+ } else if (markKind === "insert") {
47
+ style = appendStyle(style, INSERT_MARK_STYLE);
48
+ }
49
+ const cloned = {
50
+ ...node,
51
+ text,
52
+ style
53
+ };
54
+ return cloned;
54
55
  }
55
56
  function cloneNodeWithChildren(node, children) {
56
- return {
57
- ...node,
58
- children
59
- };
57
+ return {
58
+ ...node,
59
+ children
60
+ };
60
61
  }
61
62
  function decorateSubtree(node, kind) {
62
- if (isTextNode(node)) return cloneTextNode(node, node.text, kind);
63
- const children = getChildren(node);
64
- if (!children) return node;
65
- return cloneNodeWithChildren(node, children.map((child) => decorateSubtree(child, kind)));
63
+ if (isTextNode(node)) {
64
+ return cloneTextNode(node, node.text, kind);
65
+ }
66
+ const children = getChildren(node);
67
+ if (!children) return node;
68
+ return cloneNodeWithChildren(
69
+ node,
70
+ children.map((child) => decorateSubtree(child, kind))
71
+ );
66
72
  }
67
73
  function reverseText(value) {
68
- return Array.from(value).reverse().join("");
74
+ return Array.from(value).reverse().join("");
69
75
  }
70
76
  function mergeTextOps(ops) {
71
- const merged = [];
72
- for (const op of ops) {
73
- if (!op.text) continue;
74
- const last = merged.at(-1);
75
- if (last && last.kind === op.kind) last.text += op.text;
76
- else merged.push({ ...op });
77
- }
78
- return merged;
77
+ const merged = [];
78
+ for (const op of ops) {
79
+ if (!op.text) continue;
80
+ const last = merged.at(-1);
81
+ if (last && last.kind === op.kind) {
82
+ last.text += op.text;
83
+ } else {
84
+ merged.push({ ...op });
85
+ }
86
+ }
87
+ return merged;
79
88
  }
80
89
  function diffMiddleChars(oldChars, newChars) {
81
- const m = oldChars.length;
82
- const n = newChars.length;
83
- if (m === 0 && n === 0) return [];
84
- if (m === 0) return [{
85
- kind: "insert",
86
- text: newChars.join("")
87
- }];
88
- if (n === 0) return [{
89
- kind: "delete",
90
- text: oldChars.join("")
91
- }];
92
- if (m * n > CHAR_DIFF_MAX_MATRIX_CELLS) return [{
93
- kind: "delete",
94
- text: oldChars.join("")
95
- }, {
96
- kind: "insert",
97
- text: newChars.join("")
98
- }];
99
- const dp = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }).fill(0));
100
- for (let i = 1; i <= m; i++) for (let j = 1; j <= n; j++) if (oldChars[i - 1] === newChars[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
101
- else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
102
- const reversedOps = [];
103
- let i = m;
104
- let j = n;
105
- while (i > 0 && j > 0) {
106
- if (oldChars[i - 1] === newChars[j - 1]) {
107
- const last = reversedOps.at(-1);
108
- if (last && last.kind === "equal") last.text += oldChars[i - 1];
109
- else reversedOps.push({
110
- kind: "equal",
111
- text: oldChars[i - 1]
112
- });
113
- i--;
114
- j--;
115
- continue;
116
- }
117
- if (dp[i - 1][j] >= dp[i][j - 1]) {
118
- const last = reversedOps.at(-1);
119
- if (last && last.kind === "delete") last.text += oldChars[i - 1];
120
- else reversedOps.push({
121
- kind: "delete",
122
- text: oldChars[i - 1]
123
- });
124
- i--;
125
- } else {
126
- const last = reversedOps.at(-1);
127
- if (last && last.kind === "insert") last.text += newChars[j - 1];
128
- else reversedOps.push({
129
- kind: "insert",
130
- text: newChars[j - 1]
131
- });
132
- j--;
133
- }
134
- }
135
- while (i > 0) {
136
- const last = reversedOps.at(-1);
137
- if (last && last.kind === "delete") last.text += oldChars[i - 1];
138
- else reversedOps.push({
139
- kind: "delete",
140
- text: oldChars[i - 1]
141
- });
142
- i--;
143
- }
144
- while (j > 0) {
145
- const last = reversedOps.at(-1);
146
- if (last && last.kind === "insert") last.text += newChars[j - 1];
147
- else reversedOps.push({
148
- kind: "insert",
149
- text: newChars[j - 1]
150
- });
151
- j--;
152
- }
153
- return mergeTextOps(reversedOps.reverse().map((op) => ({
154
- kind: op.kind,
155
- text: reverseText(op.text)
156
- })));
90
+ const m = oldChars.length;
91
+ const n = newChars.length;
92
+ if (m === 0 && n === 0) return [];
93
+ if (m === 0) return [{ kind: "insert", text: newChars.join("") }];
94
+ if (n === 0) return [{ kind: "delete", text: oldChars.join("") }];
95
+ if (m * n > CHAR_DIFF_MAX_MATRIX_CELLS) {
96
+ return [
97
+ { kind: "delete", text: oldChars.join("") },
98
+ { kind: "insert", text: newChars.join("") }
99
+ ];
100
+ }
101
+ const dp = Array.from(
102
+ { length: m + 1 },
103
+ () => Array.from({ length: n + 1 }).fill(0)
104
+ );
105
+ for (let i2 = 1; i2 <= m; i2++) {
106
+ for (let j2 = 1; j2 <= n; j2++) {
107
+ if (oldChars[i2 - 1] === newChars[j2 - 1]) {
108
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
109
+ } else {
110
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
111
+ }
112
+ }
113
+ }
114
+ const reversedOps = [];
115
+ let i = m;
116
+ let j = n;
117
+ while (i > 0 && j > 0) {
118
+ if (oldChars[i - 1] === newChars[j - 1]) {
119
+ const last = reversedOps.at(-1);
120
+ if (last && last.kind === "equal") {
121
+ last.text += oldChars[i - 1];
122
+ } else {
123
+ reversedOps.push({ kind: "equal", text: oldChars[i - 1] });
124
+ }
125
+ i--;
126
+ j--;
127
+ continue;
128
+ }
129
+ if (dp[i - 1][j] >= dp[i][j - 1]) {
130
+ const last = reversedOps.at(-1);
131
+ if (last && last.kind === "delete") {
132
+ last.text += oldChars[i - 1];
133
+ } else {
134
+ reversedOps.push({ kind: "delete", text: oldChars[i - 1] });
135
+ }
136
+ i--;
137
+ } else {
138
+ const last = reversedOps.at(-1);
139
+ if (last && last.kind === "insert") {
140
+ last.text += newChars[j - 1];
141
+ } else {
142
+ reversedOps.push({ kind: "insert", text: newChars[j - 1] });
143
+ }
144
+ j--;
145
+ }
146
+ }
147
+ while (i > 0) {
148
+ const last = reversedOps.at(-1);
149
+ if (last && last.kind === "delete") {
150
+ last.text += oldChars[i - 1];
151
+ } else {
152
+ reversedOps.push({ kind: "delete", text: oldChars[i - 1] });
153
+ }
154
+ i--;
155
+ }
156
+ while (j > 0) {
157
+ const last = reversedOps.at(-1);
158
+ if (last && last.kind === "insert") {
159
+ last.text += newChars[j - 1];
160
+ } else {
161
+ reversedOps.push({ kind: "insert", text: newChars[j - 1] });
162
+ }
163
+ j--;
164
+ }
165
+ const forwardOps = reversedOps.reverse().map((op) => ({ kind: op.kind, text: reverseText(op.text) }));
166
+ return mergeTextOps(forwardOps);
157
167
  }
158
168
  function diffTextByChar(oldText, newText) {
159
- const oldChars = Array.from(oldText);
160
- const newChars = Array.from(newText);
161
- let prefix = 0;
162
- while (prefix < oldChars.length && prefix < newChars.length && oldChars[prefix] === newChars[prefix]) prefix++;
163
- let oldSuffix = oldChars.length - 1;
164
- let newSuffix = newChars.length - 1;
165
- while (oldSuffix >= prefix && newSuffix >= prefix && oldChars[oldSuffix] === newChars[newSuffix]) {
166
- oldSuffix--;
167
- newSuffix--;
168
- }
169
- const ops = [];
170
- if (prefix > 0) ops.push({
171
- kind: "equal",
172
- text: oldChars.slice(0, prefix).join("")
173
- });
174
- ops.push(...diffMiddleChars(oldChars.slice(prefix, oldSuffix + 1), newChars.slice(prefix, newSuffix + 1)));
175
- if (oldSuffix < oldChars.length - 1) ops.push({
176
- kind: "equal",
177
- text: oldChars.slice(oldSuffix + 1).join("")
178
- });
179
- return mergeTextOps(ops);
169
+ const oldChars = Array.from(oldText);
170
+ const newChars = Array.from(newText);
171
+ let prefix = 0;
172
+ while (prefix < oldChars.length && prefix < newChars.length && oldChars[prefix] === newChars[prefix]) {
173
+ prefix++;
174
+ }
175
+ let oldSuffix = oldChars.length - 1;
176
+ let newSuffix = newChars.length - 1;
177
+ while (oldSuffix >= prefix && newSuffix >= prefix && oldChars[oldSuffix] === newChars[newSuffix]) {
178
+ oldSuffix--;
179
+ newSuffix--;
180
+ }
181
+ const ops = [];
182
+ if (prefix > 0) {
183
+ ops.push({
184
+ kind: "equal",
185
+ text: oldChars.slice(0, prefix).join("")
186
+ });
187
+ }
188
+ ops.push(
189
+ ...diffMiddleChars(
190
+ oldChars.slice(prefix, oldSuffix + 1),
191
+ newChars.slice(prefix, newSuffix + 1)
192
+ )
193
+ );
194
+ if (oldSuffix < oldChars.length - 1) {
195
+ ops.push({
196
+ kind: "equal",
197
+ text: oldChars.slice(oldSuffix + 1).join("")
198
+ });
199
+ }
200
+ return mergeTextOps(ops);
180
201
  }
181
202
  function splitTextNodeByCharDiff(oldNode, newNode) {
182
- const ops = diffTextByChar(oldNode.text, newNode.text);
183
- const oldNodes = [];
184
- const newNodes = [];
185
- let changed = false;
186
- for (const op of ops) {
187
- if (!op.text) continue;
188
- if (op.kind === "equal") {
189
- oldNodes.push(cloneTextNode(oldNode, op.text));
190
- newNodes.push(cloneTextNode(newNode, op.text));
191
- continue;
192
- }
193
- changed = true;
194
- if (op.kind === "delete") {
195
- oldNodes.push(cloneTextNode(oldNode, op.text, "delete"));
196
- continue;
197
- }
198
- newNodes.push(cloneTextNode(newNode, op.text, "insert"));
199
- }
200
- return {
201
- oldNodes: oldNodes.length > 0 ? oldNodes : [oldNode],
202
- newNodes: newNodes.length > 0 ? newNodes : [newNode],
203
- changed
204
- };
203
+ const ops = diffTextByChar(oldNode.text, newNode.text);
204
+ const oldNodes = [];
205
+ const newNodes = [];
206
+ let changed = false;
207
+ for (const op of ops) {
208
+ if (!op.text) continue;
209
+ if (op.kind === "equal") {
210
+ oldNodes.push(cloneTextNode(oldNode, op.text));
211
+ newNodes.push(cloneTextNode(newNode, op.text));
212
+ continue;
213
+ }
214
+ changed = true;
215
+ if (op.kind === "delete") {
216
+ oldNodes.push(cloneTextNode(oldNode, op.text, "delete"));
217
+ continue;
218
+ }
219
+ newNodes.push(cloneTextNode(newNode, op.text, "insert"));
220
+ }
221
+ return {
222
+ oldNodes: oldNodes.length > 0 ? oldNodes : [oldNode],
223
+ newNodes: newNodes.length > 0 ? newNodes : [newNode],
224
+ changed
225
+ };
205
226
  }
206
- /**
207
- * LCS-based structural alignment.
208
- *
209
- * Scoring:
210
- * exact match → +2 (always align)
211
- * type match → +1 (prefer align over skip)
212
- * type mismatch → not considered (never align different types)
213
- */
214
227
  function alignNodes(oldNodes, newNodes) {
215
- const m = oldNodes.length;
216
- const n = newNodes.length;
217
- const dp = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }).fill(0));
218
- for (let i = 1; i <= m; i++) for (let j = 1; j <= n; j++) {
219
- const skip = Math.max(dp[i - 1][j], dp[i][j - 1]);
220
- if (getNodeTypeKey(oldNodes[i - 1]) === getNodeTypeKey(newNodes[j - 1])) {
221
- const score = nodesEqual(oldNodes[i - 1], newNodes[j - 1]) ? 2 : 1;
222
- dp[i][j] = Math.max(skip, dp[i - 1][j - 1] + score);
223
- } else dp[i][j] = skip;
224
- }
225
- const ops = [];
226
- let i = m;
227
- let j = n;
228
- while (i > 0 && j > 0) {
229
- if (getNodeTypeKey(oldNodes[i - 1]) === getNodeTypeKey(newNodes[j - 1])) {
230
- const exact = nodesEqual(oldNodes[i - 1], newNodes[j - 1]);
231
- const score = exact ? 2 : 1;
232
- if (dp[i][j] === dp[i - 1][j - 1] + score) {
233
- ops.push(exact ? {
234
- kind: "equal",
235
- node: oldNodes[i - 1]
236
- } : {
237
- kind: "modify",
238
- oldNode: oldNodes[i - 1],
239
- newNode: newNodes[j - 1]
240
- });
241
- i--;
242
- j--;
243
- continue;
244
- }
245
- }
246
- if (dp[i - 1][j] >= dp[i][j - 1]) {
247
- ops.push({
248
- kind: "delete",
249
- node: oldNodes[i - 1]
250
- });
251
- i--;
252
- } else {
253
- ops.push({
254
- kind: "insert",
255
- node: newNodes[j - 1]
256
- });
257
- j--;
258
- }
259
- }
260
- while (i > 0) ops.push({
261
- kind: "delete",
262
- node: oldNodes[--i]
263
- });
264
- while (j > 0) ops.push({
265
- kind: "insert",
266
- node: newNodes[--j]
267
- });
268
- ops.reverse();
269
- return ops;
228
+ const m = oldNodes.length;
229
+ const n = newNodes.length;
230
+ const dp = Array.from(
231
+ { length: m + 1 },
232
+ () => Array.from({ length: n + 1 }).fill(0)
233
+ );
234
+ for (let i2 = 1; i2 <= m; i2++) {
235
+ for (let j2 = 1; j2 <= n; j2++) {
236
+ const skip = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
237
+ if (getNodeTypeKey(oldNodes[i2 - 1]) === getNodeTypeKey(newNodes[j2 - 1])) {
238
+ const score = nodesEqual(oldNodes[i2 - 1], newNodes[j2 - 1]) ? 2 : 1;
239
+ dp[i2][j2] = Math.max(skip, dp[i2 - 1][j2 - 1] + score);
240
+ } else {
241
+ dp[i2][j2] = skip;
242
+ }
243
+ }
244
+ }
245
+ const ops = [];
246
+ let i = m;
247
+ let j = n;
248
+ while (i > 0 && j > 0) {
249
+ const typeMatch = getNodeTypeKey(oldNodes[i - 1]) === getNodeTypeKey(newNodes[j - 1]);
250
+ if (typeMatch) {
251
+ const exact = nodesEqual(oldNodes[i - 1], newNodes[j - 1]);
252
+ const score = exact ? 2 : 1;
253
+ if (dp[i][j] === dp[i - 1][j - 1] + score) {
254
+ ops.push(
255
+ exact ? { kind: "equal", node: oldNodes[i - 1] } : {
256
+ kind: "modify",
257
+ oldNode: oldNodes[i - 1],
258
+ newNode: newNodes[j - 1]
259
+ }
260
+ );
261
+ i--;
262
+ j--;
263
+ continue;
264
+ }
265
+ }
266
+ if (dp[i - 1][j] >= dp[i][j - 1]) {
267
+ ops.push({ kind: "delete", node: oldNodes[i - 1] });
268
+ i--;
269
+ } else {
270
+ ops.push({ kind: "insert", node: newNodes[j - 1] });
271
+ j--;
272
+ }
273
+ }
274
+ while (i > 0) {
275
+ ops.push({ kind: "delete", node: oldNodes[--i] });
276
+ }
277
+ while (j > 0) {
278
+ ops.push({ kind: "insert", node: newNodes[--j] });
279
+ }
280
+ ops.reverse();
281
+ return ops;
270
282
  }
271
283
  function diffChildrenInline(oldChildren, newChildren) {
272
- const ops = alignNodes(oldChildren, newChildren);
273
- const nextOldChildren = [];
274
- const nextNewChildren = [];
275
- let changed = false;
276
- for (const op of ops) switch (op.kind) {
277
- case "equal":
278
- nextOldChildren.push(op.node);
279
- nextNewChildren.push(op.node);
280
- break;
281
- case "delete":
282
- changed = true;
283
- nextOldChildren.push(decorateSubtree(op.node, "delete"));
284
- break;
285
- case "insert":
286
- changed = true;
287
- nextNewChildren.push(decorateSubtree(op.node, "insert"));
288
- break;
289
- case "modify": {
290
- changed = true;
291
- if (isTextNode(op.oldNode) && isTextNode(op.newNode)) {
292
- const textDiff = splitTextNodeByCharDiff(op.oldNode, op.newNode);
293
- nextOldChildren.push(...textDiff.oldNodes);
294
- nextNewChildren.push(...textDiff.newNodes);
295
- break;
296
- }
297
- const nested = diffNodeInline(op.oldNode, op.newNode);
298
- if (nested) {
299
- nextOldChildren.push(nested.oldNode);
300
- nextNewChildren.push(nested.newNode);
301
- } else {
302
- nextOldChildren.push(decorateSubtree(op.oldNode, "delete"));
303
- nextNewChildren.push(decorateSubtree(op.newNode, "insert"));
304
- }
305
- break;
306
- }
307
- }
308
- return {
309
- oldChildren: nextOldChildren,
310
- newChildren: nextNewChildren,
311
- changed
312
- };
284
+ const ops = alignNodes(oldChildren, newChildren);
285
+ const nextOldChildren = [];
286
+ const nextNewChildren = [];
287
+ let changed = false;
288
+ for (const op of ops) {
289
+ switch (op.kind) {
290
+ case "equal": {
291
+ nextOldChildren.push(op.node);
292
+ nextNewChildren.push(op.node);
293
+ break;
294
+ }
295
+ case "delete": {
296
+ changed = true;
297
+ nextOldChildren.push(decorateSubtree(op.node, "delete"));
298
+ break;
299
+ }
300
+ case "insert": {
301
+ changed = true;
302
+ nextNewChildren.push(decorateSubtree(op.node, "insert"));
303
+ break;
304
+ }
305
+ case "modify": {
306
+ changed = true;
307
+ if (isTextNode(op.oldNode) && isTextNode(op.newNode)) {
308
+ const textDiff = splitTextNodeByCharDiff(op.oldNode, op.newNode);
309
+ nextOldChildren.push(...textDiff.oldNodes);
310
+ nextNewChildren.push(...textDiff.newNodes);
311
+ break;
312
+ }
313
+ const nested = diffNodeInline(op.oldNode, op.newNode);
314
+ if (nested) {
315
+ nextOldChildren.push(nested.oldNode);
316
+ nextNewChildren.push(nested.newNode);
317
+ } else {
318
+ nextOldChildren.push(decorateSubtree(op.oldNode, "delete"));
319
+ nextNewChildren.push(decorateSubtree(op.newNode, "insert"));
320
+ }
321
+ break;
322
+ }
323
+ }
324
+ }
325
+ return {
326
+ oldChildren: nextOldChildren,
327
+ newChildren: nextNewChildren,
328
+ changed
329
+ };
313
330
  }
314
331
  function diffNodeInline(oldNode, newNode) {
315
- if (getNodeTypeKey(oldNode) !== getNodeTypeKey(newNode)) return null;
316
- if (nodesEqual(oldNode, newNode)) return {
317
- oldNode,
318
- newNode,
319
- changed: false
320
- };
321
- const oldChildren = getChildren(oldNode);
322
- const newChildren = getChildren(newNode);
323
- if (!oldChildren || !newChildren) return null;
324
- const childDiff = diffChildrenInline(oldChildren, newChildren);
325
- if (!childDiff.changed) return {
326
- oldNode,
327
- newNode,
328
- changed: false
329
- };
330
- return {
331
- oldNode: cloneNodeWithChildren(oldNode, childDiff.oldChildren),
332
- newNode: cloneNodeWithChildren(newNode, childDiff.newChildren),
333
- changed: true
334
- };
332
+ if (getNodeTypeKey(oldNode) !== getNodeTypeKey(newNode)) return null;
333
+ if (nodesEqual(oldNode, newNode)) {
334
+ return { oldNode, newNode, changed: false };
335
+ }
336
+ const oldChildren = getChildren(oldNode);
337
+ const newChildren = getChildren(newNode);
338
+ if (!oldChildren || !newChildren) return null;
339
+ const childDiff = diffChildrenInline(oldChildren, newChildren);
340
+ if (!childDiff.changed) {
341
+ return { oldNode, newNode, changed: false };
342
+ }
343
+ return {
344
+ oldNode: cloneNodeWithChildren(oldNode, childDiff.oldChildren),
345
+ newNode: cloneNodeWithChildren(newNode, childDiff.newChildren),
346
+ changed: true
347
+ };
335
348
  }
336
349
  function diffModifiedNode(oldNode, newNode) {
337
- const nested = diffNodeInline(oldNode, newNode);
338
- if (nested) return {
339
- oldNode: nested.oldNode,
340
- newNode: nested.newNode
341
- };
342
- return {
343
- oldNode: decorateSubtree(oldNode, "delete"),
344
- newNode: decorateSubtree(newNode, "insert")
345
- };
350
+ const nested = diffNodeInline(oldNode, newNode);
351
+ if (nested) {
352
+ return { oldNode: nested.oldNode, newNode: nested.newNode };
353
+ }
354
+ return {
355
+ oldNode: decorateSubtree(oldNode, "delete"),
356
+ newNode: decorateSubtree(newNode, "insert")
357
+ };
346
358
  }
347
359
  function computeDiff(oldState, newState) {
348
- const ops = alignNodes(oldState.root.children, newState.root.children);
349
- const hunks = [];
350
- for (const op of ops) switch (op.kind) {
351
- case "equal": {
352
- const last = hunks.at(-1);
353
- if (last && last.type === "equal") last.nodes.push(op.node);
354
- else hunks.push({
355
- type: "equal",
356
- nodes: [op.node]
357
- });
358
- break;
359
- }
360
- case "modify":
361
- {
362
- const inline = diffModifiedNode(op.oldNode, op.newNode);
363
- hunks.push({
364
- type: "delete",
365
- nodes: [inline.oldNode]
366
- }, {
367
- type: "insert",
368
- nodes: [inline.newNode]
369
- });
370
- }
371
- break;
372
- case "delete":
373
- hunks.push({
374
- type: "delete",
375
- nodes: [decorateSubtree(op.node, "delete")]
376
- });
377
- break;
378
- case "insert":
379
- hunks.push({
380
- type: "insert",
381
- nodes: [decorateSubtree(op.node, "insert")]
382
- });
383
- break;
384
- }
385
- return hunks;
360
+ const ops = alignNodes(oldState.root.children, newState.root.children);
361
+ const hunks = [];
362
+ for (const op of ops) {
363
+ switch (op.kind) {
364
+ case "equal": {
365
+ const last = hunks.at(-1);
366
+ if (last && last.type === "equal") {
367
+ last.nodes.push(op.node);
368
+ } else {
369
+ hunks.push({ type: "equal", nodes: [op.node] });
370
+ }
371
+ break;
372
+ }
373
+ case "modify": {
374
+ {
375
+ const inline = diffModifiedNode(op.oldNode, op.newNode);
376
+ hunks.push(
377
+ { type: "delete", nodes: [inline.oldNode] },
378
+ { type: "insert", nodes: [inline.newNode] }
379
+ );
380
+ }
381
+ break;
382
+ }
383
+ case "delete": {
384
+ hunks.push({
385
+ type: "delete",
386
+ nodes: [decorateSubtree(op.node, "delete")]
387
+ });
388
+ break;
389
+ }
390
+ case "insert": {
391
+ hunks.push({
392
+ type: "insert",
393
+ nodes: [decorateSubtree(op.node, "insert")]
394
+ });
395
+ break;
396
+ }
397
+ }
398
+ }
399
+ return hunks;
386
400
  }
387
- //#endregion
388
- //#region src/RichDiff.tsx
389
401
  function buildRows(hunks) {
390
- const rows = [];
391
- let i = 0;
392
- while (i < hunks.length) {
393
- const hunk = hunks[i];
394
- if (hunk.type === "equal") {
395
- rows.push({
396
- left: hunk,
397
- right: hunk
398
- });
399
- i++;
400
- } else {
401
- const deletes = [];
402
- const inserts = [];
403
- while (i < hunks.length && hunks[i].type !== "equal") {
404
- if (hunks[i].type === "delete") deletes.push(hunks[i]);
405
- else inserts.push(hunks[i]);
406
- i++;
407
- }
408
- const maxLen = Math.max(deletes.length, inserts.length);
409
- for (let k = 0; k < maxLen; k++) rows.push({
410
- left: k < deletes.length ? deletes[k] : null,
411
- right: k < inserts.length ? inserts[k] : null
412
- });
413
- }
414
- }
415
- return rows;
402
+ const rows = [];
403
+ let i = 0;
404
+ while (i < hunks.length) {
405
+ const hunk = hunks[i];
406
+ if (hunk.type === "equal") {
407
+ rows.push({ left: hunk, right: hunk });
408
+ i++;
409
+ } else {
410
+ const deletes = [];
411
+ const inserts = [];
412
+ while (i < hunks.length && hunks[i].type !== "equal") {
413
+ if (hunks[i].type === "delete") deletes.push(hunks[i]);
414
+ else inserts.push(hunks[i]);
415
+ i++;
416
+ }
417
+ const maxLen = Math.max(deletes.length, inserts.length);
418
+ for (let k = 0; k < maxLen; k++) {
419
+ rows.push({
420
+ left: k < deletes.length ? deletes[k] : null,
421
+ right: k < inserts.length ? inserts[k] : null
422
+ });
423
+ }
424
+ }
425
+ }
426
+ return rows;
416
427
  }
417
428
  function wrapDoc(nodes) {
418
- return { root: {
419
- children: nodes,
420
- direction: "ltr",
421
- format: "",
422
- indent: 0,
423
- type: "root",
424
- version: 1
425
- } };
429
+ return {
430
+ root: {
431
+ children: nodes,
432
+ direction: "ltr",
433
+ format: "",
434
+ indent: 0,
435
+ type: "root",
436
+ version: 1
437
+ }
438
+ };
426
439
  }
427
- function HunkRenderer({ hunk, variant, theme, rendererConfig, extraNodes }) {
428
- return /* @__PURE__ */ jsx(RichRenderer, {
429
- extraNodes,
430
- rendererConfig,
431
- theme,
432
- value: useMemo(() => wrapDoc(hunk.nodes), [hunk.nodes]),
433
- variant
434
- });
440
+ function HunkRenderer({
441
+ hunk,
442
+ variant,
443
+ theme,
444
+ rendererConfig,
445
+ extraNodes
446
+ }) {
447
+ const doc = useMemo(() => wrapDoc(hunk.nodes), [hunk.nodes]);
448
+ return /* @__PURE__ */ jsx(
449
+ RichRenderer,
450
+ {
451
+ extraNodes,
452
+ rendererConfig,
453
+ theme,
454
+ value: doc,
455
+ variant
456
+ }
457
+ );
435
458
  }
436
- function RichDiff({ oldValue, newValue, variant = "article", theme = "light", rendererConfig, extraNodes, className }) {
437
- const hunks = useMemo(() => computeDiff(oldValue, newValue), [oldValue, newValue]);
438
- const rows = useMemo(() => buildRows(hunks), [hunks]);
439
- const rendererProps = {
440
- variant,
441
- theme,
442
- rendererConfig,
443
- extraNodes
444
- };
445
- const variantClass = getVariantClass(variant);
446
- return /* @__PURE__ */ jsx(PortalThemeProvider, {
447
- className: variantClass,
448
- theme,
449
- children: /* @__PURE__ */ jsx(ColorSchemeProvider, {
450
- colorScheme: theme,
451
- children: /* @__PURE__ */ jsx("div", {
452
- className: variantClass,
453
- style: {
454
- width: "100%",
455
- maxWidth: "100%"
456
- },
457
- children: /* @__PURE__ */ jsxs("div", {
458
- className: `${root} ${className ?? ""}`.trim(),
459
- children: [/* @__PURE__ */ jsxs("div", {
460
- className: header,
461
- children: [/* @__PURE__ */ jsx("div", {
462
- className: `${headerCell} ${headerOld}`,
463
- children: "Old"
464
- }), /* @__PURE__ */ jsx("div", {
465
- className: headerCell,
466
- children: "New"
467
- })]
468
- }), /* @__PURE__ */ jsx("div", {
469
- className: body,
470
- children: rows.map((row$1, i) => /* @__PURE__ */ jsxs("div", {
471
- className: row,
472
- children: [/* @__PURE__ */ jsx("div", {
473
- className: `${cell} ${cellOld} ${row$1.left ? row$1.left.type === "delete" ? delete_ : "" : empty}`.trim(),
474
- children: row$1.left && /* @__PURE__ */ jsx(HunkRenderer, {
475
- hunk: row$1.left,
476
- ...rendererProps
477
- })
478
- }), /* @__PURE__ */ jsx("div", {
479
- className: `${cell} ${row$1.right ? row$1.right.type === "insert" ? insert : "" : empty}`.trim(),
480
- children: row$1.right && /* @__PURE__ */ jsx(HunkRenderer, {
481
- hunk: row$1.right,
482
- ...rendererProps
483
- })
484
- })]
485
- }, i))
486
- })]
487
- })
488
- })
489
- })
490
- });
459
+ function RichDiff({
460
+ oldValue,
461
+ newValue,
462
+ variant = "article",
463
+ theme = "light",
464
+ rendererConfig,
465
+ extraNodes,
466
+ className
467
+ }) {
468
+ const hunks = useMemo(() => computeDiff(oldValue, newValue), [oldValue, newValue]);
469
+ const rows = useMemo(() => buildRows(hunks), [hunks]);
470
+ const rendererProps = { variant, theme, rendererConfig, extraNodes };
471
+ const variantClass = getVariantClass(variant);
472
+ return /* @__PURE__ */ jsx(PortalThemeProvider, { className: variantClass, theme, children: /* @__PURE__ */ jsx(ColorSchemeProvider, { colorScheme: theme, children: /* @__PURE__ */ jsx("div", { className: variantClass, style: { width: "100%", maxWidth: "100%" }, children: /* @__PURE__ */ jsxs("div", { className: `${root} ${className ?? ""}`.trim(), children: [
473
+ /* @__PURE__ */ jsxs("div", { className: header, children: [
474
+ /* @__PURE__ */ jsx("div", { className: `${headerCell} ${headerOld}`, children: "Old" }),
475
+ /* @__PURE__ */ jsx("div", { className: headerCell, children: "New" })
476
+ ] }),
477
+ /* @__PURE__ */ jsx("div", { className: body, children: rows.map((row$1, i) => /* @__PURE__ */ jsxs("div", { className: row, children: [
478
+ /* @__PURE__ */ jsx(
479
+ "div",
480
+ {
481
+ className: `${cell} ${cellOld} ${row$1.left ? row$1.left.type === "delete" ? delete_ : "" : empty}`.trim(),
482
+ children: row$1.left && /* @__PURE__ */ jsx(HunkRenderer, { hunk: row$1.left, ...rendererProps })
483
+ }
484
+ ),
485
+ /* @__PURE__ */ jsx(
486
+ "div",
487
+ {
488
+ className: `${cell} ${row$1.right ? row$1.right.type === "insert" ? insert : "" : empty}`.trim(),
489
+ children: row$1.right && /* @__PURE__ */ jsx(HunkRenderer, { hunk: row$1.right, ...rendererProps })
490
+ }
491
+ )
492
+ ] }, i)) })
493
+ ] }) }) }) });
491
494
  }
492
- //#endregion
493
- export { RichDiff, computeDiff };
495
+ export {
496
+ RichDiff,
497
+ computeDiff
498
+ };
@@ -1,2 +1 @@
1
- :root{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}:root.dark{--rc-text:#fafafa;--rc-text-secondary:#a1a1aa;--rc-text-tertiary:#71717a;--rc-text-quaternary:#52525b;--rc-bg:#09090b;--rc-bg-secondary:#18181b;--rc-bg-tertiary:#27272a;--rc-fill:#2a2a2f;--rc-fill-secondary:#222226;--rc-fill-tertiary:#1b1b1f;--rc-fill-quaternary:#131316;--rc-border:#27272a;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#e4e4e7;--rc-code-bg:#27272a;--rc-hr-border:#27272a;--rc-quote-border:#60a5fa;--rc-quote-bg:#1e3a5f;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}.pvevj00{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}.pvevj01{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#2563eb;--rc-quote-bg:#eff6ff;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.8;--rc-line-height-tight:1.4;--rc-font-family:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}.pvevj02{--rc-text:#000;--rc-text-secondary:#27272a;--rc-text-tertiary:#71717a;--rc-text-quaternary:#a1a1aa;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f4f4f5;--rc-fill:#e8e8ec;--rc-fill-secondary:#eeeeef;--rc-fill-tertiary:#f4f4f6;--rc-fill-quaternary:#f9f9fa;--rc-border:#f4f4f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#3f3f46;--rc-code-bg:#f4f4f5;--rc-hr-border:#e4e4e7;--rc-quote-border:#a1a1aa;--rc-quote-bg:#fafafa;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:none;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:2px;--rc-space-sm:4px;--rc-space-md:10px;--rc-space-lg:16px;--rc-space-xl:20px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:14px;--rc-font-size-small:12px;--rc-line-height:1.5;--rc-line-height-tight:1.3;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:3px;--rc-radius-md:6px;--rc-radius-lg:12px}.dark .pvevj00,[data-theme=dark] .pvevj00,.dark.pvevj00,[data-theme=dark].pvevj00,.dark .pvevj01,[data-theme=dark] .pvevj01,.dark.pvevj01,[data-theme=dark].pvevj01,.dark .pvevj02,[data-theme=dark] .pvevj02,.dark.pvevj02,[data-theme=dark].pvevj02{--rc-text:#fafafa;--rc-text-secondary:#a1a1aa;--rc-text-tertiary:#71717a;--rc-text-quaternary:#52525b;--rc-bg:#09090b;--rc-bg-secondary:#18181b;--rc-bg-tertiary:#27272a;--rc-fill:#2a2a2f;--rc-fill-secondary:#222226;--rc-fill-tertiary:#1b1b1f;--rc-fill-quaternary:#131316;--rc-border:#27272a;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#e4e4e7;--rc-code-bg:#27272a;--rc-hr-border:#27272a;--rc-quote-border:#60a5fa;--rc-quote-bg:#1e3a5f;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}.xcvddd0{border:1px solid var(--rc-border);border-radius:6px;font-size:14px;overflow:hidden}.xcvddd1{border-bottom:1px solid var(--rc-border);background:var(--rc-bg-secondary);grid-template-columns:1fr 1fr;display:grid}.xcvddd2{text-transform:uppercase;letter-spacing:.05em;color:var(--rc-text-secondary);padding:8px 16px;font-size:12px;font-weight:600}.xcvddd3{border-right:1px solid var(--rc-border)}.xcvddd4{flex-direction:column;display:flex}.xcvddd5{border-bottom:1px solid var(--rc-border);grid-template-columns:1fr 1fr;display:grid}.xcvddd5:last-child{border-bottom:none}.xcvddd6{min-height:32px;padding:4px 12px;overflow:hidden}.xcvddd7{border-right:1px solid var(--rc-border)}.xcvddd8{background-color:color-mix(in srgb, var(--rc-alert-caution) 15%, transparent)}.xcvddd9{background-color:color-mix(in srgb, var(--rc-alert-tip) 15%, transparent)}.xcvddda{background-color:var(--rc-bg-secondary)}.xcvddd8 .rich-content__body{opacity:.85}
2
- /*$vite$:1*/
1
+ :root{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}:root.dark{--rc-text: #fafafa;--rc-text-secondary: #a1a1aa;--rc-text-tertiary: #71717a;--rc-text-quaternary: #52525b;--rc-bg: #09090b;--rc-bg-secondary: #18181b;--rc-bg-tertiary: #27272a;--rc-fill: #2a2a2f;--rc-fill-secondary: #222226;--rc-fill-tertiary: #1b1b1f;--rc-fill-quaternary: #131316;--rc-border: #27272a;--rc-accent: #60a5fa;--rc-accent-light: #60a5fa20;--rc-link: #60a5fa;--rc-code-text: #e4e4e7;--rc-code-bg: #27272a;--rc-hr-border: #27272a;--rc-quote-border: #60a5fa;--rc-quote-bg: #1e3a5f;--rc-alert-info: #7db9e5;--rc-alert-warning: #da864a;--rc-alert-tip: #54da48;--rc-alert-caution: #e16973;--rc-alert-important: #9966e0;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.4), 0 4px 6px -4px rgba(0,0,0,.35);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.25), 0 4px 16px rgba(0,0,0,.4);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}.pvevj00{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.7;--rc-line-height-tight: 1.4;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}.pvevj01{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #2563eb;--rc-quote-bg: #eff6ff;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: 700px;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 4px;--rc-space-sm: 8px;--rc-space-md: 16px;--rc-space-lg: 24px;--rc-space-xl: 32px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 16px;--rc-font-size-small: 14px;--rc-line-height: 1.8;--rc-line-height-tight: 1.4;--rc-font-family: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm: 4px;--rc-radius-md: 8px;--rc-radius-lg: 12px}.pvevj02{--rc-text: #000;--rc-text-secondary: #27272a;--rc-text-tertiary: #71717a;--rc-text-quaternary: #a1a1aa;--rc-bg: #ffffff;--rc-bg-secondary: #fafafa;--rc-bg-tertiary: #f4f4f5;--rc-fill: #e8e8ec;--rc-fill-secondary: #eeeeef;--rc-fill-tertiary: #f4f4f6;--rc-fill-quaternary: #f9f9fa;--rc-border: #f4f4f5;--rc-accent: #2563eb;--rc-accent-light: #2563eb20;--rc-link: #2563eb;--rc-code-text: #3f3f46;--rc-code-bg: #f4f4f5;--rc-hr-border: #e4e4e7;--rc-quote-border: #a1a1aa;--rc-quote-bg: #fafafa;--rc-alert-info: #006bb7;--rc-alert-warning: #cc5500;--rc-alert-tip: #11cc00;--rc-alert-caution: #cc0011;--rc-alert-important: #5500cc;--rc-max-width: none;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.04), 0 4px 16px rgba(0,0,0,.08);--rc-space-xs: 2px;--rc-space-sm: 4px;--rc-space-md: 10px;--rc-space-lg: 16px;--rc-space-xl: 20px;--rc-font-family-sans: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif: "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-mono: "SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs: .625em;--rc-font-size-xs: .75em;--rc-font-size-sm: .8125em;--rc-font-size-md: .875em;--rc-font-size-lg: 1.25em;--rc-font-size-base: 14px;--rc-font-size-small: 12px;--rc-line-height: 1.5;--rc-line-height-tight: 1.3;--rc-font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm: 3px;--rc-radius-md: 6px;--rc-radius-lg: 12px}.dark .pvevj00,[data-theme=dark] .pvevj00,.dark.pvevj00,[data-theme=dark].pvevj00,.dark .pvevj01,[data-theme=dark] .pvevj01,.dark.pvevj01,[data-theme=dark].pvevj01,.dark .pvevj02,[data-theme=dark] .pvevj02,.dark.pvevj02,[data-theme=dark].pvevj02{--rc-text: #fafafa;--rc-text-secondary: #a1a1aa;--rc-text-tertiary: #71717a;--rc-text-quaternary: #52525b;--rc-bg: #09090b;--rc-bg-secondary: #18181b;--rc-bg-tertiary: #27272a;--rc-fill: #2a2a2f;--rc-fill-secondary: #222226;--rc-fill-tertiary: #1b1b1f;--rc-fill-quaternary: #131316;--rc-border: #27272a;--rc-accent: #60a5fa;--rc-accent-light: #60a5fa20;--rc-link: #60a5fa;--rc-code-text: #e4e4e7;--rc-code-bg: #27272a;--rc-hr-border: #27272a;--rc-quote-border: #60a5fa;--rc-quote-bg: #1e3a5f;--rc-alert-info: #7db9e5;--rc-alert-warning: #da864a;--rc-alert-tip: #54da48;--rc-alert-caution: #e16973;--rc-alert-important: #9966e0;--rc-shadow-top-bar: 0 8px 30px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);--rc-shadow-modal: 0 10px 15px -3px rgba(0,0,0,.4), 0 4px 6px -4px rgba(0,0,0,.35);--rc-shadow-menu: 0 1px 4px rgba(0,0,0,.25), 0 4px 16px rgba(0,0,0,.4)}.xcvddd0{border:1px solid var(--rc-border);border-radius:6px;overflow:hidden;font-size:14px}.xcvddd1{display:grid;grid-template-columns:1fr 1fr;border-bottom:1px solid var(--rc-border);background:var(--rc-bg-secondary)}.xcvddd2{padding:8px 16px;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--rc-text-secondary)}.xcvddd3{border-right:1px solid var(--rc-border)}.xcvddd4{display:flex;flex-direction:column}.xcvddd5{display:grid;grid-template-columns:1fr 1fr;border-bottom:1px solid var(--rc-border)}.xcvddd5:last-child{border-bottom:none}.xcvddd6{padding:4px 12px;min-height:32px;overflow:hidden}.xcvddd7{border-right:1px solid var(--rc-border)}.xcvddd8{background-color:color-mix(in srgb,var(--rc-alert-caution) 15%,transparent)}.xcvddd9{background-color:color-mix(in srgb,var(--rc-alert-tip) 15%,transparent)}.xcvddda{background-color:var(--rc-bg-secondary)}.xcvddd8 .rich-content__body{opacity:.85}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-diff",
3
- "version": "0.0.81",
3
+ "version": "0.0.83",
4
4
  "description": "Rich diff editor",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,9 +21,9 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@haklex/rich-editor": "0.0.81",
25
- "@haklex/rich-static-renderer": "0.0.81",
26
- "@haklex/rich-style-token": "0.0.81"
24
+ "@haklex/rich-editor": "0.0.83",
25
+ "@haklex/rich-style-token": "0.0.83",
26
+ "@haklex/rich-static-renderer": "0.0.83"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/react": "^19.2.14",