@pixerate/editor 0.21.0 → 0.22.0
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/README.md +20 -11
- package/dist/agent/index.cjs +8 -8
- package/dist/agent/index.d.cts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +2 -2
- package/dist/canvas/index.cjs +1269 -13
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +432 -6
- package/dist/canvas/index.d.ts +432 -6
- package/dist/canvas/index.js +1264 -8
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-U6NDQFOK.cjs → chunk-6M3BCTBD.cjs} +427 -138
- package/dist/chunk-6M3BCTBD.cjs.map +1 -0
- package/dist/{chunk-TVRC4KVT.cjs → chunk-AA4ZEVCC.cjs} +845 -90
- package/dist/chunk-AA4ZEVCC.cjs.map +1 -0
- package/dist/{chunk-LA7PEGU3.cjs → chunk-CL37JGFW.cjs} +4 -4
- package/dist/{chunk-LA7PEGU3.cjs.map → chunk-CL37JGFW.cjs.map} +1 -1
- package/dist/{chunk-A7DKIA72.js → chunk-DENSCKFC.js} +642 -69
- package/dist/chunk-DENSCKFC.js.map +1 -0
- package/dist/{chunk-4QPLEUL2.cjs → chunk-GVSMRPHB.cjs} +1046 -54
- package/dist/chunk-GVSMRPHB.cjs.map +1 -0
- package/dist/{chunk-KYRZDWM4.js → chunk-JJDLPEWL.js} +2 -2
- package/dist/{chunk-3TYMNULT.js → chunk-MJZBNWG7.js} +807 -52
- package/dist/chunk-MJZBNWG7.js.map +1 -0
- package/dist/{chunk-CYFJCKC4.js → chunk-QGHGJ56O.js} +997 -5
- package/dist/chunk-QGHGJ56O.js.map +1 -0
- package/dist/{chunk-GVW4P7BG.js → chunk-RU52I7QO.js} +305 -16
- package/dist/chunk-RU52I7QO.js.map +1 -0
- package/dist/{chunk-JYRIOFEN.cjs → chunk-SAZRENEZ.cjs} +647 -74
- package/dist/chunk-SAZRENEZ.cjs.map +1 -0
- package/dist/{controller-OUdxPY-X.d.ts → controller-B7GIybc4.d.cts} +139 -7
- package/dist/{controller-OUdxPY-X.d.cts → controller-B7GIybc4.d.ts} +139 -7
- package/dist/extensions/index.cjs +14 -4
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +3 -3
- package/dist/extensions/index.d.ts +3 -3
- package/dist/extensions/index.js +13 -3
- package/dist/{index-k3mFbPx_.d.cts → index-CCr_z9kF.d.cts} +3 -3
- package/dist/{index-Ng1pG7JE.d.ts → index-Ck6ajwXh.d.ts} +3 -3
- package/dist/index.cjs +250 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -8
- package/dist/index.d.ts +294 -8
- package/dist/index.js +241 -7
- package/dist/index.js.map +1 -1
- package/dist/{registry-iAHbqkYt.d.cts → registry-GJI4gToU.d.cts} +15 -4
- package/dist/{registry-iAHbqkYt.d.ts → registry-GJI4gToU.d.ts} +15 -4
- package/dist/serializers/index.cjs +3 -3
- package/dist/serializers/index.d.cts +1 -1
- package/dist/serializers/index.d.ts +1 -1
- package/dist/serializers/index.js +2 -2
- package/dist/spreadsheet/index.cjs +7 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +33 -4
- package/dist/spreadsheet/index.d.ts +33 -4
- package/dist/spreadsheet/index.js +6 -2
- package/dist/{track-changes-G8JcWB8b.d.cts → track-changes-BSF58RK0.d.cts} +92 -9
- package/dist/{track-changes-G8JcWB8b.d.ts → track-changes-BSF58RK0.d.ts} +92 -9
- package/dist/{types-DMe0vFB1.d.cts → types-CJ4U-HHI.d.cts} +1 -1
- package/dist/{types-DMe0vFB1.d.ts → types-CJ4U-HHI.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3TYMNULT.js.map +0 -1
- package/dist/chunk-4QPLEUL2.cjs.map +0 -1
- package/dist/chunk-A7DKIA72.js.map +0 -1
- package/dist/chunk-CYFJCKC4.js.map +0 -1
- package/dist/chunk-GVW4P7BG.js.map +0 -1
- package/dist/chunk-JYRIOFEN.cjs.map +0 -1
- package/dist/chunk-TVRC4KVT.cjs.map +0 -1
- package/dist/chunk-U6NDQFOK.cjs.map +0 -1
- /package/dist/{chunk-KYRZDWM4.js.map → chunk-JJDLPEWL.js.map} +0 -0
|
@@ -246,10 +246,31 @@ var _state = require('@tiptap/pm/state');
|
|
|
246
246
|
|
|
247
247
|
|
|
248
248
|
|
|
249
|
+
|
|
250
|
+
|
|
249
251
|
var _model = require('@tiptap/pm/model');
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
250
262
|
var _transform = require('@tiptap/pm/transform');
|
|
251
263
|
var INSERTION_MARK_NAME = "insertion";
|
|
252
264
|
var DELETION_MARK_NAME = "deletion";
|
|
265
|
+
var FORMAT_CHANGE_MARK_NAME = "formatChange";
|
|
266
|
+
var BLOCK_CHANGE_ATTRIBUTE = "blockChange";
|
|
267
|
+
var REVIEW_MARK_NAMES = /* @__PURE__ */ new Set([
|
|
268
|
+
INSERTION_MARK_NAME,
|
|
269
|
+
DELETION_MARK_NAME,
|
|
270
|
+
FORMAT_CHANGE_MARK_NAME,
|
|
271
|
+
"comment",
|
|
272
|
+
"bookmark"
|
|
273
|
+
]);
|
|
253
274
|
var TRACK_CHANGES_SKIP_META = "trackChangesSkip";
|
|
254
275
|
var TrackChangesStore = (_class2 = class {
|
|
255
276
|
|
|
@@ -281,6 +302,14 @@ var trackChangesPluginKey = new (0, _state.PluginKey)("trackChanges");
|
|
|
281
302
|
function changeAttributes(mark) {
|
|
282
303
|
return mark.attrs;
|
|
283
304
|
}
|
|
305
|
+
function parseJSON(value, fallback) {
|
|
306
|
+
if (!value) return fallback;
|
|
307
|
+
try {
|
|
308
|
+
return JSON.parse(value);
|
|
309
|
+
} catch (e2) {
|
|
310
|
+
return fallback;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
284
313
|
var sharedAttributes = () => ({
|
|
285
314
|
changeId: {
|
|
286
315
|
default: null,
|
|
@@ -367,75 +396,537 @@ var TrackedDeletion = _core.Mark.create({
|
|
|
367
396
|
];
|
|
368
397
|
}
|
|
369
398
|
});
|
|
399
|
+
var TrackedFormatChange = _core.Mark.create({
|
|
400
|
+
name: FORMAT_CHANGE_MARK_NAME,
|
|
401
|
+
inclusive: false,
|
|
402
|
+
addOptions() {
|
|
403
|
+
return {
|
|
404
|
+
HTMLAttributes: {
|
|
405
|
+
class: "pixerate-format-change underline decoration-dotted decoration-2 decoration-sky-500 underline-offset-4"
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
},
|
|
409
|
+
addStorage() {
|
|
410
|
+
return { markdown: { serialize: { open: "", close: "" }, parse: {} } };
|
|
411
|
+
},
|
|
412
|
+
addAttributes() {
|
|
413
|
+
return {
|
|
414
|
+
...sharedAttributes(),
|
|
415
|
+
before: {
|
|
416
|
+
default: [],
|
|
417
|
+
parseHTML: (el) => parseJSON(el.getAttribute("data-format-before"), []),
|
|
418
|
+
renderHTML: (attrs) => ({ "data-format-before": JSON.stringify(_nullishCoalesce(attrs.before, () => ( []))) })
|
|
419
|
+
},
|
|
420
|
+
after: {
|
|
421
|
+
default: [],
|
|
422
|
+
parseHTML: (el) => parseJSON(el.getAttribute("data-format-after"), []),
|
|
423
|
+
renderHTML: (attrs) => ({ "data-format-after": JSON.stringify(_nullishCoalesce(attrs.after, () => ( []))) })
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
},
|
|
427
|
+
parseHTML() {
|
|
428
|
+
return [{ tag: 'span[data-change-type="format"]', priority: 100 }];
|
|
429
|
+
},
|
|
430
|
+
renderHTML({ HTMLAttributes }) {
|
|
431
|
+
return [
|
|
432
|
+
"span",
|
|
433
|
+
_core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
|
|
434
|
+
"data-change-type": "format"
|
|
435
|
+
}),
|
|
436
|
+
0
|
|
437
|
+
];
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
var MARK_LABELS = {
|
|
441
|
+
bold: "Bold",
|
|
442
|
+
italic: "Italic",
|
|
443
|
+
underline: "Underline",
|
|
444
|
+
strike: "Strikethrough",
|
|
445
|
+
code: "Code",
|
|
446
|
+
link: "Link",
|
|
447
|
+
highlight: "Highlight",
|
|
448
|
+
subscript: "Subscript",
|
|
449
|
+
superscript: "Superscript",
|
|
450
|
+
textStyle: "Text style"
|
|
451
|
+
};
|
|
452
|
+
var TEXT_STYLE_LABELS = {
|
|
453
|
+
fontSize: "Font size",
|
|
454
|
+
fontFamily: "Font",
|
|
455
|
+
color: "Color",
|
|
456
|
+
backgroundColor: "Background color",
|
|
457
|
+
lineHeight: "Line height"
|
|
458
|
+
};
|
|
459
|
+
var BLOCK_LABELS = {
|
|
460
|
+
paragraph: "Paragraph",
|
|
461
|
+
codeBlock: "Code block",
|
|
462
|
+
blockquote: "Quote",
|
|
463
|
+
bulletList: "Bulleted list",
|
|
464
|
+
orderedList: "Numbered list",
|
|
465
|
+
taskList: "Task list",
|
|
466
|
+
listItem: "List item",
|
|
467
|
+
taskItem: "Task item"
|
|
468
|
+
};
|
|
469
|
+
function humanize(name) {
|
|
470
|
+
const words = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").toLowerCase();
|
|
471
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
472
|
+
}
|
|
473
|
+
function stableStringify(value) {
|
|
474
|
+
if (value === void 0) return "null";
|
|
475
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
476
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
477
|
+
const obj = value;
|
|
478
|
+
return `{${Object.keys(obj).filter((k) => obj[k] !== void 0).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`;
|
|
479
|
+
}
|
|
480
|
+
var sameValue = (a, b) => stableStringify(a) === stableStringify(b);
|
|
481
|
+
function markLabels(mark, other) {
|
|
482
|
+
if (mark.type === "textStyle") {
|
|
483
|
+
const attrs = _nullishCoalesce(mark.attrs, () => ( {}));
|
|
484
|
+
const otherAttrs = _nullishCoalesce(_optionalChain([other, 'optionalAccess', _2 => _2.attrs]), () => ( {}));
|
|
485
|
+
const keys = Array.from(/* @__PURE__ */ new Set([...Object.keys(attrs), ...Object.keys(otherAttrs)])).filter(
|
|
486
|
+
(key) => other ? !sameValue(attrs[key], otherAttrs[key]) : attrs[key] != null
|
|
487
|
+
);
|
|
488
|
+
return keys.length ? keys.map((key) => _nullishCoalesce(TEXT_STYLE_LABELS[key], () => ( humanize(key)))) : ["Text style"];
|
|
489
|
+
}
|
|
490
|
+
return [_nullishCoalesce(MARK_LABELS[mark.type], () => ( humanize(mark.type)))];
|
|
491
|
+
}
|
|
492
|
+
function diffFormatting(before, after) {
|
|
493
|
+
const summary = { added: [], removed: [], changed: [] };
|
|
494
|
+
const push = (list, labels) => labels.forEach((label) => {
|
|
495
|
+
if (!list.includes(label)) list.push(label);
|
|
496
|
+
});
|
|
497
|
+
after.forEach((mark) => {
|
|
498
|
+
const old = before.find((m) => m.type === mark.type);
|
|
499
|
+
if (!old) push(summary.added, markLabels(mark));
|
|
500
|
+
else if (!sameValue(_nullishCoalesce(old.attrs, () => ( {})), _nullishCoalesce(mark.attrs, () => ( {})))) push(summary.changed, markLabels(mark, old));
|
|
501
|
+
});
|
|
502
|
+
before.forEach((mark) => {
|
|
503
|
+
if (!after.some((m) => m.type === mark.type)) push(summary.removed, markLabels(mark));
|
|
504
|
+
});
|
|
505
|
+
return summary;
|
|
506
|
+
}
|
|
507
|
+
function mergeSummary(target, source) {
|
|
508
|
+
["added", "removed", "changed"].forEach(
|
|
509
|
+
(key) => source[key].forEach((label) => {
|
|
510
|
+
if (!target[key].includes(label)) target[key].push(label);
|
|
511
|
+
})
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
function describeFormatChange(summary) {
|
|
515
|
+
const parts = [];
|
|
516
|
+
if (summary.added.length) parts.push(`Formatted: ${summary.added.join(", ")}`);
|
|
517
|
+
if (summary.removed.length) parts.push(`Removed formatting: ${summary.removed.join(", ")}`);
|
|
518
|
+
if (summary.changed.length) parts.push(`Changed formatting: ${summary.changed.join(", ")}`);
|
|
519
|
+
return parts.join("; ") || "Formatted";
|
|
520
|
+
}
|
|
521
|
+
function blockLabel(type, attrs) {
|
|
522
|
+
if (type === "heading" && _optionalChain([attrs, 'optionalAccess', _3 => _3.level])) return `Heading ${attrs.level}`;
|
|
523
|
+
return _nullishCoalesce(BLOCK_LABELS[type], () => ( humanize(type)));
|
|
524
|
+
}
|
|
525
|
+
var containerLabels = (wrappers) => wrappers.filter((w) => w.type !== "listItem" && w.type !== "taskItem").map((w) => blockLabel(w.type, w.attrs));
|
|
526
|
+
var isPrefix = (a, b) => a.every((label, i) => b[i] === label);
|
|
527
|
+
function describeBlockChange(previous, current, ignoredAttributes = ["id"]) {
|
|
528
|
+
const parts = [];
|
|
529
|
+
const before = blockLabel(previous.type, previous.attrs);
|
|
530
|
+
const after = blockLabel(current.type, current.attrs);
|
|
531
|
+
if (before !== after) {
|
|
532
|
+
parts.push(`Changed ${before} to ${after}`);
|
|
533
|
+
} else {
|
|
534
|
+
const keys = Array.from(
|
|
535
|
+
/* @__PURE__ */ new Set([...Object.keys(_nullishCoalesce(previous.attrs, () => ( {}))), ...Object.keys(_nullishCoalesce(current.attrs, () => ( {})))])
|
|
536
|
+
).filter(
|
|
537
|
+
(key) => key !== BLOCK_CHANGE_ATTRIBUTE && !ignoredAttributes.includes(key) && !(current.type === "heading" && key === "level") && !sameValue(_optionalChain([previous, 'access', _4 => _4.attrs, 'optionalAccess', _5 => _5[key]]), _optionalChain([current, 'access', _6 => _6.attrs, 'optionalAccess', _7 => _7[key]]))
|
|
538
|
+
);
|
|
539
|
+
keys.forEach((key) => {
|
|
540
|
+
if (key === "textAlign") {
|
|
541
|
+
parts.push(`Changed alignment to ${humanize(String(_nullishCoalesce(_optionalChain([current, 'access', _8 => _8.attrs, 'optionalAccess', _9 => _9.textAlign]), () => ( "default"))))}`);
|
|
542
|
+
} else {
|
|
543
|
+
parts.push(`Changed ${humanize(key).toLowerCase()} of ${after}`);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
const oldTypes = previous.wrappers.map((w) => w.type).join("/");
|
|
548
|
+
const newTypes = current.wrappers.map((w) => w.type).join("/");
|
|
549
|
+
if (oldTypes !== newTypes) {
|
|
550
|
+
const was = containerLabels(previous.wrappers);
|
|
551
|
+
const now = containerLabels(current.wrappers);
|
|
552
|
+
const last = (list) => list[list.length - 1];
|
|
553
|
+
if (was.length === 0 && now.length > 0) parts.push(`Wrapped in ${last(now)}`);
|
|
554
|
+
else if (now.length === 0 && was.length > 0) parts.push(`Removed from ${last(was)}`);
|
|
555
|
+
else if (now.length > was.length && isPrefix(was, now)) parts.push(`Indented in ${last(now)}`);
|
|
556
|
+
else if (now.length < was.length && isPrefix(now, was)) parts.push(`Outdented from ${last(was)}`);
|
|
557
|
+
else if (was.length && now.length) parts.push(`Changed ${last(was)} to ${last(now)}`);
|
|
558
|
+
else parts.push("Changed nesting");
|
|
559
|
+
}
|
|
560
|
+
return parts.join("; ") || `Changed ${after}`;
|
|
561
|
+
}
|
|
562
|
+
function truncate(text, max = 40) {
|
|
563
|
+
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
564
|
+
}
|
|
370
565
|
function toDoc(source) {
|
|
371
566
|
if (!source) return null;
|
|
372
|
-
if (_optionalChain([source, 'access',
|
|
567
|
+
if (_optionalChain([source, 'access', _10 => _10.state, 'optionalAccess', _11 => _11.doc])) return source.state.doc;
|
|
373
568
|
if (source.doc && typeof source.doc.descendants === "function") return source.doc;
|
|
374
569
|
if (typeof source.descendants === "function") return source;
|
|
375
570
|
return null;
|
|
376
571
|
}
|
|
572
|
+
function stripBlockChange(attrs) {
|
|
573
|
+
const copy = { ...attrs };
|
|
574
|
+
delete copy[BLOCK_CHANGE_ATTRIBUTE];
|
|
575
|
+
return copy;
|
|
576
|
+
}
|
|
577
|
+
function blockSnapshot(doc, pos) {
|
|
578
|
+
const $pos = doc.resolve(pos);
|
|
579
|
+
const node = $pos.nodeAfter;
|
|
580
|
+
const wrappers = [];
|
|
581
|
+
for (let depth = 1; depth <= $pos.depth; depth++) {
|
|
582
|
+
const wrapper = $pos.node(depth);
|
|
583
|
+
wrappers.push({ type: wrapper.type.name, attrs: stripBlockChange(wrapper.attrs) });
|
|
584
|
+
}
|
|
585
|
+
return { type: node.type.name, attrs: stripBlockChange(node.attrs), wrappers };
|
|
586
|
+
}
|
|
587
|
+
function sameBlock(a, b, ignored) {
|
|
588
|
+
if (a.type !== b.type) return false;
|
|
589
|
+
const filter = (attrs) => Object.fromEntries(
|
|
590
|
+
Object.entries(_nullishCoalesce(attrs, () => ( {}))).filter(
|
|
591
|
+
([key]) => key !== BLOCK_CHANGE_ATTRIBUTE && !ignored.has(key)
|
|
592
|
+
)
|
|
593
|
+
);
|
|
594
|
+
if (!sameValue(filter(a.attrs), filter(b.attrs))) return false;
|
|
595
|
+
if (a.wrappers.length !== b.wrappers.length) return false;
|
|
596
|
+
return a.wrappers.every((w, i) => w.type === b.wrappers[i].type);
|
|
597
|
+
}
|
|
598
|
+
var isMarkChange = (type) => type === INSERTION_MARK_NAME || type === DELETION_MARK_NAME || type === FORMAT_CHANGE_MARK_NAME;
|
|
377
599
|
function getTrackedChanges(source) {
|
|
378
600
|
const doc = toDoc(source);
|
|
379
601
|
if (!doc) return [];
|
|
380
602
|
const byKey = /* @__PURE__ */ new Map();
|
|
603
|
+
const add = (key, type, attrs, from, to, text) => {
|
|
604
|
+
let change = byKey.get(key);
|
|
605
|
+
if (!change) {
|
|
606
|
+
change = {
|
|
607
|
+
id: attrs.changeId,
|
|
608
|
+
type,
|
|
609
|
+
author: {
|
|
610
|
+
id: attrs.authorId,
|
|
611
|
+
name: attrs.authorName,
|
|
612
|
+
...attrs.authorColor ? { color: attrs.authorColor } : {}
|
|
613
|
+
},
|
|
614
|
+
createdAt: attrs.createdAt,
|
|
615
|
+
from,
|
|
616
|
+
to,
|
|
617
|
+
ranges: [],
|
|
618
|
+
text: "",
|
|
619
|
+
description: ""
|
|
620
|
+
};
|
|
621
|
+
byKey.set(key, change);
|
|
622
|
+
}
|
|
623
|
+
const last = change.ranges[change.ranges.length - 1];
|
|
624
|
+
if (last && last.to === from) {
|
|
625
|
+
last.to = to;
|
|
626
|
+
} else {
|
|
627
|
+
change.ranges.push({ from, to });
|
|
628
|
+
}
|
|
629
|
+
change.to = to;
|
|
630
|
+
change.text += text;
|
|
631
|
+
return change;
|
|
632
|
+
};
|
|
381
633
|
doc.descendants((node, pos) => {
|
|
634
|
+
const block = _optionalChain([node, 'access', _12 => _12.attrs, 'optionalAccess', _13 => _13[BLOCK_CHANGE_ATTRIBUTE]]);
|
|
635
|
+
if (_optionalChain([block, 'optionalAccess', _14 => _14.changeId]) && node.isTextblock) {
|
|
636
|
+
const change = add(
|
|
637
|
+
`block:${block.changeId}`,
|
|
638
|
+
"block",
|
|
639
|
+
block,
|
|
640
|
+
pos,
|
|
641
|
+
pos + node.nodeSize,
|
|
642
|
+
node.textContent
|
|
643
|
+
);
|
|
644
|
+
if (!change.block) {
|
|
645
|
+
change.block = { previous: block.previous, current: blockSnapshot(doc, pos) };
|
|
646
|
+
}
|
|
647
|
+
}
|
|
382
648
|
if (!node.isInline) return;
|
|
383
649
|
node.marks.forEach((mark) => {
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
650
|
+
const markType = mark.type.name;
|
|
651
|
+
if (!isMarkChange(markType)) return;
|
|
386
652
|
const attrs = changeAttributes(mark);
|
|
387
653
|
if (!attrs.changeId) return;
|
|
388
|
-
const
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
createdAt: attrs.createdAt,
|
|
402
|
-
from: pos,
|
|
403
|
-
to: end,
|
|
404
|
-
ranges: [],
|
|
405
|
-
text: ""
|
|
406
|
-
};
|
|
407
|
-
byKey.set(key, change);
|
|
654
|
+
const type = markType === FORMAT_CHANGE_MARK_NAME ? "format" : markType;
|
|
655
|
+
const change = add(
|
|
656
|
+
`${type}:${attrs.changeId}`,
|
|
657
|
+
type,
|
|
658
|
+
attrs,
|
|
659
|
+
pos,
|
|
660
|
+
pos + node.nodeSize,
|
|
661
|
+
node.isText ? _nullishCoalesce(node.text, () => ( "")) : ""
|
|
662
|
+
);
|
|
663
|
+
if (type === "format") {
|
|
664
|
+
const summary = diffFormatting(_nullishCoalesce(mark.attrs.before, () => ( [])), _nullishCoalesce(mark.attrs.after, () => ( [])));
|
|
665
|
+
if (!change.format) change.format = { added: [], removed: [], changed: [] };
|
|
666
|
+
mergeSummary(change.format, summary);
|
|
408
667
|
}
|
|
409
|
-
const last = change.ranges[change.ranges.length - 1];
|
|
410
|
-
if (last && last.to === pos) {
|
|
411
|
-
last.to = end;
|
|
412
|
-
} else {
|
|
413
|
-
change.ranges.push({ from: pos, to: end });
|
|
414
|
-
}
|
|
415
|
-
change.to = end;
|
|
416
|
-
change.text += text;
|
|
417
668
|
});
|
|
418
669
|
});
|
|
419
|
-
|
|
670
|
+
const changes = Array.from(byKey.values());
|
|
671
|
+
changes.forEach((change) => {
|
|
672
|
+
switch (change.type) {
|
|
673
|
+
case "insertion":
|
|
674
|
+
change.description = change.text ? `Inserted "${truncate(change.text)}"` : "Inserted content";
|
|
675
|
+
break;
|
|
676
|
+
case "deletion":
|
|
677
|
+
change.description = change.text ? `Deleted "${truncate(change.text)}"` : "Deleted content";
|
|
678
|
+
break;
|
|
679
|
+
case "format":
|
|
680
|
+
change.description = describeFormatChange(change.format);
|
|
681
|
+
break;
|
|
682
|
+
case "block":
|
|
683
|
+
change.description = describeBlockChange(change.block.previous, change.block.current);
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
return changes.sort((a, b) => a.from - b.from || a.to - b.to);
|
|
420
688
|
}
|
|
421
689
|
function getTrackedChangeAt(state, pos = state.selection.from, changes = getTrackedChanges(state.doc)) {
|
|
422
690
|
const { from, to } = state.selection;
|
|
423
|
-
const exact = changes.find((c) =>
|
|
691
|
+
const exact = changes.find((c) => {
|
|
692
|
+
const [start, end] = selectionRange(c);
|
|
693
|
+
return start === from && end === to;
|
|
694
|
+
});
|
|
424
695
|
if (exact) return exact;
|
|
425
|
-
|
|
696
|
+
const inline = changes.filter((c) => c.type !== "block");
|
|
697
|
+
const blocks = changes.filter((c) => c.type === "block");
|
|
698
|
+
return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(inline.find((c) => c.ranges.some((r) => r.from < pos && pos < r.to)), () => ( inline.find((c) => c.ranges.some((r) => r.from <= pos && pos <= r.to)))), () => ( blocks.find((c) => c.ranges.some((r) => r.from < pos && pos < r.to)))), () => ( null));
|
|
699
|
+
}
|
|
700
|
+
function selectionRange(change) {
|
|
701
|
+
return change.type === "block" ? [change.from + 1, change.to - 1] : [change.from, change.to];
|
|
426
702
|
}
|
|
427
703
|
function isTrackChangesEnabled(source) {
|
|
428
|
-
const state = _nullishCoalesce(_optionalChain([source, 'optionalAccess',
|
|
704
|
+
const state = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _15 => _15.state]), () => ( source));
|
|
429
705
|
if (!state || typeof state.plugins === "undefined") return false;
|
|
430
|
-
return _nullishCoalesce(_optionalChain([trackChangesPluginKey, 'access',
|
|
706
|
+
return _nullishCoalesce(_optionalChain([trackChangesPluginKey, 'access', _16 => _16.getState, 'call', _17 => _17(state), 'optionalAccess', _18 => _18.enabled]), () => ( false));
|
|
431
707
|
}
|
|
432
708
|
function getTrackChangesStore(editor) {
|
|
433
|
-
return _nullishCoalesce(_optionalChain([editor, 'optionalAccess',
|
|
709
|
+
return _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _19 => _19.storage, 'optionalAccess', _20 => _20.trackChanges, 'optionalAccess', _21 => _21.store]), () => ( null));
|
|
710
|
+
}
|
|
711
|
+
function marksFromJSON(schema, marks) {
|
|
712
|
+
const result = [];
|
|
713
|
+
(_nullishCoalesce(marks, () => ( []))).forEach((json) => {
|
|
714
|
+
try {
|
|
715
|
+
if (schema.marks[json.type]) result.push(schema.markFromJSON(json));
|
|
716
|
+
} catch (e3) {
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
return result;
|
|
720
|
+
}
|
|
721
|
+
function decideFormat(tr, changes, decision) {
|
|
722
|
+
const schema = tr.doc.type.schema;
|
|
723
|
+
const formatType = schema.marks[FORMAT_CHANGE_MARK_NAME];
|
|
724
|
+
if (!formatType) return;
|
|
725
|
+
const ids = new Set(changes.map((c) => c.id));
|
|
726
|
+
const segments = [];
|
|
727
|
+
changes.forEach(
|
|
728
|
+
(change) => change.ranges.forEach(
|
|
729
|
+
({ from, to }) => tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
730
|
+
if (!node.isInline) return true;
|
|
731
|
+
const mark = formatType.isInSet(node.marks);
|
|
732
|
+
if (mark && ids.has(mark.attrs.changeId)) {
|
|
733
|
+
segments.push({ from: Math.max(pos, from), to: Math.min(pos + node.nodeSize, to), node, mark });
|
|
734
|
+
}
|
|
735
|
+
return false;
|
|
736
|
+
})
|
|
737
|
+
)
|
|
738
|
+
);
|
|
739
|
+
segments.forEach(({ from, to, node, mark }) => {
|
|
740
|
+
tr.removeMark(from, to, formatType);
|
|
741
|
+
if (decision === "accept") return;
|
|
742
|
+
const before = _nullishCoalesce(mark.attrs.before, () => ( []));
|
|
743
|
+
const after = _nullishCoalesce(mark.attrs.after, () => ( []));
|
|
744
|
+
const involved = new Set([...before, ...after].map((m) => m.type));
|
|
745
|
+
node.marks.forEach((current) => {
|
|
746
|
+
if (involved.has(current.type.name)) tr.removeMark(from, to, current);
|
|
747
|
+
});
|
|
748
|
+
marksFromJSON(schema, before).forEach((restored) => tr.addMark(from, to, restored));
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
var LIST_ITEM_TYPES = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
752
|
+
function listItemAt(tr, contentPos) {
|
|
753
|
+
const $pos = tr.doc.resolve(contentPos);
|
|
754
|
+
const itemDepth = $pos.depth - 1;
|
|
755
|
+
if (itemDepth < 2) return null;
|
|
756
|
+
if (!LIST_ITEM_TYPES.has($pos.node(itemDepth).type.name) || $pos.index(itemDepth) !== 0) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
return { $pos, itemDepth };
|
|
760
|
+
}
|
|
761
|
+
function sinkItem(tr, contentPos) {
|
|
762
|
+
const info = listItemAt(tr, contentPos);
|
|
763
|
+
if (!info) return false;
|
|
764
|
+
const { $pos, itemDepth } = info;
|
|
765
|
+
const list = $pos.node(itemDepth - 1);
|
|
766
|
+
const index = $pos.index(itemDepth - 1);
|
|
767
|
+
const itemType = $pos.node(itemDepth).type;
|
|
768
|
+
if (index === 0 || list.child(index - 1).type !== itemType) return false;
|
|
769
|
+
const nodeBefore = list.child(index - 1);
|
|
770
|
+
const nestedBefore = _optionalChain([nodeBefore, 'access', _22 => _22.lastChild, 'optionalAccess', _23 => _23.type]) === list.type;
|
|
771
|
+
const inner = _model.Fragment.from(nestedBefore ? itemType.create() : null);
|
|
772
|
+
const slice = new (0, _model.Slice)(
|
|
773
|
+
_model.Fragment.from(itemType.create(null, _model.Fragment.from(list.type.create(null, inner)))),
|
|
774
|
+
nestedBefore ? 3 : 1,
|
|
775
|
+
0
|
|
776
|
+
);
|
|
777
|
+
const before = $pos.before(itemDepth);
|
|
778
|
+
const after = $pos.after(itemDepth);
|
|
779
|
+
tr.step(
|
|
780
|
+
new (0, _transform.ReplaceAroundStep)(before - (nestedBefore ? 3 : 1), after, before, after, slice, 1, true)
|
|
781
|
+
);
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
function outdentItem(tr, contentPos) {
|
|
785
|
+
const info = listItemAt(tr, contentPos);
|
|
786
|
+
if (!info) return false;
|
|
787
|
+
const { $pos, itemDepth } = info;
|
|
788
|
+
const listDepth = itemDepth - 1;
|
|
789
|
+
if (listDepth < 2 || !LIST_ITEM_TYPES.has($pos.node(listDepth - 1).type.name)) return false;
|
|
790
|
+
const itemType = $pos.node(itemDepth).type;
|
|
791
|
+
let range = new (0, _model.NodeRange)(
|
|
792
|
+
tr.doc.resolve($pos.before(itemDepth)),
|
|
793
|
+
tr.doc.resolve($pos.after(itemDepth)),
|
|
794
|
+
listDepth
|
|
795
|
+
);
|
|
796
|
+
const end = range.end;
|
|
797
|
+
const endOfList = range.$to.end(range.depth);
|
|
798
|
+
if (end < endOfList) {
|
|
799
|
+
tr.step(
|
|
800
|
+
new (0, _transform.ReplaceAroundStep)(
|
|
801
|
+
end - 1,
|
|
802
|
+
endOfList,
|
|
803
|
+
end,
|
|
804
|
+
endOfList,
|
|
805
|
+
new (0, _model.Slice)(_model.Fragment.from(itemType.create(null, range.parent.copy())), 1, 0),
|
|
806
|
+
1,
|
|
807
|
+
true
|
|
808
|
+
)
|
|
809
|
+
);
|
|
810
|
+
range = new (0, _model.NodeRange)(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth);
|
|
811
|
+
}
|
|
812
|
+
const target = _transform.liftTarget.call(void 0, range);
|
|
813
|
+
if (target == null) return false;
|
|
814
|
+
tr.lift(range, target);
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
function restoreWrappers(tr, contentPos, wrappers) {
|
|
818
|
+
const schema = tr.doc.type.schema;
|
|
819
|
+
const step = (fn) => {
|
|
820
|
+
const index = tr.steps.length;
|
|
821
|
+
const result = fn();
|
|
822
|
+
contentPos = tr.mapping.slice(index).map(contentPos);
|
|
823
|
+
return result !== false && tr.steps.length > index;
|
|
824
|
+
};
|
|
825
|
+
const chain = () => {
|
|
826
|
+
const $pos = tr.doc.resolve(contentPos);
|
|
827
|
+
const types = [];
|
|
828
|
+
for (let depth = 1; depth < $pos.depth; depth++) types.push($pos.node(depth).type.name);
|
|
829
|
+
return types;
|
|
830
|
+
};
|
|
831
|
+
const target = wrappers.map((w) => w.type);
|
|
832
|
+
for (let guard = 0; guard < 24; guard++) {
|
|
833
|
+
const current = chain();
|
|
834
|
+
if (current.join("/") === target.join("/")) return;
|
|
835
|
+
if (current.length === target.length) {
|
|
836
|
+
const index = current.findIndex((type2, i) => type2 !== target[i]);
|
|
837
|
+
const type = schema.nodes[target[index]];
|
|
838
|
+
if (type && LIST_ITEM_TYPES.has(type.name) === LIST_ITEM_TYPES.has(current[index])) {
|
|
839
|
+
const $pos = tr.doc.resolve(contentPos);
|
|
840
|
+
if (step(() => tr.setNodeMarkup($pos.before(index + 1), type, wrappers[index].attrs))) {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
let common = 0;
|
|
846
|
+
while (common < current.length && common < target.length && current[common] === target[common]) {
|
|
847
|
+
common++;
|
|
848
|
+
}
|
|
849
|
+
if (current.length > common) {
|
|
850
|
+
if (step(() => outdentItem(tr, contentPos))) continue;
|
|
851
|
+
const $from2 = tr.doc.resolve(contentPos);
|
|
852
|
+
const range2 = $from2.blockRange(tr.doc.resolve($from2.end()));
|
|
853
|
+
const lift = range2 ? _transform.liftTarget.call(void 0, range2) : null;
|
|
854
|
+
if (!range2 || lift == null || !step(() => tr.lift(range2, lift))) return;
|
|
855
|
+
continue;
|
|
856
|
+
}
|
|
857
|
+
const missing = wrappers.slice(current.length);
|
|
858
|
+
if (missing.length >= 2 && LIST_ITEM_TYPES.has(missing[1].type) && step(() => sinkItem(tr, contentPos))) {
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
const types = missing.map((w) => ({ type: schema.nodes[w.type], attrs: w.attrs }));
|
|
862
|
+
if (types.some((t) => !t.type)) return;
|
|
863
|
+
const $from = tr.doc.resolve(contentPos);
|
|
864
|
+
const range = $from.blockRange(tr.doc.resolve($from.end()));
|
|
865
|
+
if (!range) return;
|
|
866
|
+
const start = range.start;
|
|
867
|
+
step(() => tr.wrap(range, types));
|
|
868
|
+
const wrapper = tr.doc.nodeAt(start);
|
|
869
|
+
if (!wrapper) return;
|
|
870
|
+
const end = start + wrapper.nodeSize;
|
|
871
|
+
if (_optionalChain([tr, 'access', _24 => _24.doc, 'access', _25 => _25.resolve, 'call', _26 => _26(end), 'access', _27 => _27.nodeAfter, 'optionalAccess', _28 => _28.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, end)) {
|
|
872
|
+
step(() => tr.join(end));
|
|
873
|
+
}
|
|
874
|
+
if (_optionalChain([tr, 'access', _29 => _29.doc, 'access', _30 => _30.resolve, 'call', _31 => _31(start), 'access', _32 => _32.nodeBefore, 'optionalAccess', _33 => _33.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, start)) {
|
|
875
|
+
step(() => tr.join(start));
|
|
876
|
+
}
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function decideBlocks(tr, changes, decision) {
|
|
881
|
+
const ids = new Set(changes.map((c) => c.id));
|
|
882
|
+
const items = [];
|
|
883
|
+
tr.doc.descendants((node, pos) => {
|
|
884
|
+
const record = _optionalChain([node, 'access', _34 => _34.attrs, 'optionalAccess', _35 => _35[BLOCK_CHANGE_ATTRIBUTE]]);
|
|
885
|
+
if (node.isTextblock && _optionalChain([record, 'optionalAccess', _36 => _36.changeId]) && ids.has(record.changeId)) {
|
|
886
|
+
items.push({ contentPos: pos + 1, record });
|
|
887
|
+
}
|
|
888
|
+
return !node.isTextblock;
|
|
889
|
+
});
|
|
890
|
+
const schema = tr.doc.type.schema;
|
|
891
|
+
const startIndex = tr.steps.length;
|
|
892
|
+
items.reverse().forEach(({ contentPos: original, record }) => {
|
|
893
|
+
const contentPos = tr.mapping.slice(startIndex).map(original);
|
|
894
|
+
const $pos = tr.doc.resolve(contentPos);
|
|
895
|
+
if (!$pos.parent.isTextblock || $pos.parentOffset !== 0) return;
|
|
896
|
+
const pos = $pos.before();
|
|
897
|
+
if (decision === "accept") {
|
|
898
|
+
tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, null);
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
const previous = record.previous;
|
|
902
|
+
const type = previous && schema.nodes[previous.type];
|
|
903
|
+
if (!type) {
|
|
904
|
+
tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, null);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const attrs = { ...previous.attrs, [BLOCK_CHANGE_ATTRIBUTE]: null };
|
|
908
|
+
try {
|
|
909
|
+
tr.setNodeMarkup(pos, type, attrs);
|
|
910
|
+
} catch (e4) {
|
|
911
|
+
try {
|
|
912
|
+
tr.setBlockType(pos + 1, pos + 1, type, attrs);
|
|
913
|
+
} catch (e5) {
|
|
914
|
+
tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, null);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
try {
|
|
918
|
+
restoreWrappers(tr, tr.mapping.slice(startIndex).map(original), _nullishCoalesce(previous.wrappers, () => ( [])));
|
|
919
|
+
} catch (e6) {
|
|
920
|
+
}
|
|
921
|
+
});
|
|
434
922
|
}
|
|
435
923
|
function applyDecision(tr, changes, decision) {
|
|
436
924
|
const schema = tr.doc.type.schema;
|
|
925
|
+
const format = changes.filter((c) => c.type === "format");
|
|
926
|
+
if (format.length) decideFormat(tr, format, decision);
|
|
437
927
|
const deletions = [];
|
|
438
928
|
changes.forEach((change) => {
|
|
929
|
+
if (change.type !== "insertion" && change.type !== "deletion") return;
|
|
439
930
|
const markType = schema.marks[change.type];
|
|
440
931
|
if (!markType) return;
|
|
441
932
|
const keep = change.type === "insertion" === (decision === "accept");
|
|
@@ -450,6 +941,8 @@ function applyDecision(tr, changes, decision) {
|
|
|
450
941
|
deletions.sort((a, b) => b.from - a.from).forEach(({ from, to }) => {
|
|
451
942
|
tr.delete(tr.mapping.map(from), tr.mapping.map(to));
|
|
452
943
|
});
|
|
944
|
+
const blocks = changes.filter((c) => c.type === "block");
|
|
945
|
+
if (blocks.length) decideBlocks(tr, blocks, decision);
|
|
453
946
|
}
|
|
454
947
|
function resolveTrackedChanges(doc, view = "accepted") {
|
|
455
948
|
if (view === "all") return doc;
|
|
@@ -468,14 +961,27 @@ function hasInlineContent(fragment) {
|
|
|
468
961
|
});
|
|
469
962
|
return found;
|
|
470
963
|
}
|
|
471
|
-
function acceptSlice(slice,
|
|
472
|
-
|
|
964
|
+
function acceptSlice(slice, schema) {
|
|
965
|
+
const insertion = schema.marks[INSERTION_MARK_NAME];
|
|
966
|
+
const deletion = schema.marks[DELETION_MARK_NAME];
|
|
967
|
+
const format = schema.marks[FORMAT_CHANGE_MARK_NAME];
|
|
473
968
|
const mapFragment = (fragment) => {
|
|
474
969
|
const children = [];
|
|
475
970
|
fragment.forEach((child) => {
|
|
476
971
|
if (child.isInline) {
|
|
477
972
|
if (deletion && deletion.isInSet(child.marks)) return;
|
|
478
|
-
|
|
973
|
+
let marks = child.marks;
|
|
974
|
+
if (insertion) marks = insertion.removeFromSet(marks);
|
|
975
|
+
if (format) marks = format.removeFromSet(marks);
|
|
976
|
+
children.push(marks === child.marks ? child : child.mark(marks));
|
|
977
|
+
} else if (_optionalChain([child, 'access', _37 => _37.attrs, 'optionalAccess', _38 => _38[BLOCK_CHANGE_ATTRIBUTE]])) {
|
|
978
|
+
children.push(
|
|
979
|
+
child.type.create(
|
|
980
|
+
{ ...child.attrs, [BLOCK_CHANGE_ATTRIBUTE]: null },
|
|
981
|
+
mapFragment(child.content),
|
|
982
|
+
child.marks
|
|
983
|
+
)
|
|
984
|
+
);
|
|
479
985
|
} else {
|
|
480
986
|
children.push(child.copy(mapFragment(child.content)));
|
|
481
987
|
}
|
|
@@ -484,6 +990,13 @@ function acceptSlice(slice, insertion, deletion) {
|
|
|
484
990
|
};
|
|
485
991
|
return new (0, _model.Slice)(mapFragment(slice.content), slice.openStart, slice.openEnd);
|
|
486
992
|
}
|
|
993
|
+
function stripMarks(fragment) {
|
|
994
|
+
const children = [];
|
|
995
|
+
fragment.forEach((child) => {
|
|
996
|
+
children.push(child.isInline ? child.mark(_model.Mark.none) : child.copy(stripMarks(child.content)));
|
|
997
|
+
});
|
|
998
|
+
return _model.Fragment.fromArray(children);
|
|
999
|
+
}
|
|
487
1000
|
function newAttributes(ctx) {
|
|
488
1001
|
return {
|
|
489
1002
|
changeId: ctx.generateId(),
|
|
@@ -493,6 +1006,15 @@ function newAttributes(ctx) {
|
|
|
493
1006
|
createdAt: ctx.now()
|
|
494
1007
|
};
|
|
495
1008
|
}
|
|
1009
|
+
function baseAttributes(attrs) {
|
|
1010
|
+
return {
|
|
1011
|
+
changeId: attrs.changeId,
|
|
1012
|
+
authorId: attrs.authorId,
|
|
1013
|
+
authorName: attrs.authorName,
|
|
1014
|
+
authorColor: _nullishCoalesce(attrs.authorColor, () => ( null)),
|
|
1015
|
+
createdAt: attrs.createdAt
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
496
1018
|
function adjacentAttributes(doc, from, to, type, ctx) {
|
|
497
1019
|
const candidates = [doc.resolve(from).nodeBefore, doc.resolve(to).nodeAfter];
|
|
498
1020
|
for (const node of candidates) {
|
|
@@ -540,27 +1062,191 @@ function shouldSkip(tr) {
|
|
|
540
1062
|
!!tr.getMeta("y-sync$") || // Housekeeping appended by other plugins (e.g. trailing nodes).
|
|
541
1063
|
!!tr.getMeta("appendedTransaction");
|
|
542
1064
|
}
|
|
1065
|
+
function formattingOf(marks, ctx) {
|
|
1066
|
+
return marks.filter((m) => !REVIEW_MARK_NAMES.has(m.type.name) && !ctx.ignoredMarks.has(m.type.name)).map((m) => m.toJSON());
|
|
1067
|
+
}
|
|
1068
|
+
function mergeRanges(ranges) {
|
|
1069
|
+
const sorted = ranges.filter((r) => r.to > r.from).sort((a, b) => a.from - b.from);
|
|
1070
|
+
const merged = [];
|
|
1071
|
+
sorted.forEach((range) => {
|
|
1072
|
+
const last = merged[merged.length - 1];
|
|
1073
|
+
if (last && range.from <= last.to) last.to = Math.max(last.to, range.to);
|
|
1074
|
+
else merged.push({ ...range });
|
|
1075
|
+
});
|
|
1076
|
+
return merged;
|
|
1077
|
+
}
|
|
1078
|
+
function trackFormatting(tr, ranges, oldDoc, back, inserted, ctx) {
|
|
1079
|
+
const format = ctx.format;
|
|
1080
|
+
const doc = tr.doc;
|
|
1081
|
+
let changed = false;
|
|
1082
|
+
let batch = null;
|
|
1083
|
+
mergeRanges(ranges).forEach(({ from: a, to: b }) => {
|
|
1084
|
+
const segments = [];
|
|
1085
|
+
doc.nodesBetween(a, b, (node, pos, parent) => {
|
|
1086
|
+
if (!node.isInline) return true;
|
|
1087
|
+
const s = Math.max(a, pos);
|
|
1088
|
+
const e = Math.min(b, pos + node.nodeSize);
|
|
1089
|
+
if (e <= s || !parent || !parent.type.allowsMarkType(format)) return false;
|
|
1090
|
+
if (ctx.insertion.isInSet(node.marks)) return false;
|
|
1091
|
+
if (inserted.some((r) => s < r.to && e > r.from)) return false;
|
|
1092
|
+
const os = back.map(s, 1);
|
|
1093
|
+
const oe = back.map(e, -1);
|
|
1094
|
+
if (oe - os !== e - s) return false;
|
|
1095
|
+
oldDoc.nodesBetween(os, oe, (oldNode, oldPos) => {
|
|
1096
|
+
if (!oldNode.isInline) return true;
|
|
1097
|
+
const ss = Math.max(os, oldPos);
|
|
1098
|
+
const ee = Math.min(oe, oldPos + oldNode.nodeSize);
|
|
1099
|
+
if (ee > ss && !ctx.insertion.isInSet(oldNode.marks)) {
|
|
1100
|
+
segments.push({ from: s + (ss - os), to: s + (ee - os), oldNode, node });
|
|
1101
|
+
}
|
|
1102
|
+
return false;
|
|
1103
|
+
});
|
|
1104
|
+
return false;
|
|
1105
|
+
});
|
|
1106
|
+
segments.forEach(({ from, to, oldNode, node }) => {
|
|
1107
|
+
const existing = format.isInSet(oldNode.marks);
|
|
1108
|
+
const original = existing ? _nullishCoalesce(existing.attrs.before, () => ( [])) : formattingOf(oldNode.marks, ctx);
|
|
1109
|
+
const current = formattingOf(node.marks, ctx);
|
|
1110
|
+
if (sameValue(original, current)) {
|
|
1111
|
+
if (existing || format.isInSet(node.marks)) {
|
|
1112
|
+
tr.removeMark(from, to, format);
|
|
1113
|
+
changed = true;
|
|
1114
|
+
}
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
let attrs;
|
|
1118
|
+
if (existing && existing.attrs.authorId === ctx.author.id && existing.attrs.changeId) {
|
|
1119
|
+
attrs = baseAttributes(changeAttributes(existing));
|
|
1120
|
+
} else {
|
|
1121
|
+
if (!batch) {
|
|
1122
|
+
const description = describeFormatChange(diffFormatting(original, current));
|
|
1123
|
+
const neighbours = [doc.resolve(from).nodeBefore, doc.resolve(to).nodeAfter];
|
|
1124
|
+
for (const neighbour of neighbours) {
|
|
1125
|
+
const mark = neighbour && format.isInSet(neighbour.marks);
|
|
1126
|
+
if (mark && mark.attrs.authorId === ctx.author.id && mark.attrs.changeId && describeFormatChange(diffFormatting(_nullishCoalesce(mark.attrs.before, () => ( [])), _nullishCoalesce(mark.attrs.after, () => ( [])))) === description) {
|
|
1127
|
+
batch = baseAttributes(changeAttributes(mark));
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
batch = _nullishCoalesce(batch, () => ( newAttributes(ctx)));
|
|
1132
|
+
}
|
|
1133
|
+
attrs = batch;
|
|
1134
|
+
}
|
|
1135
|
+
tr.addMark(from, to, format.create({ ...attrs, before: original, after: current }));
|
|
1136
|
+
changed = true;
|
|
1137
|
+
});
|
|
1138
|
+
});
|
|
1139
|
+
return changed;
|
|
1140
|
+
}
|
|
1141
|
+
function trackBlocks(tr, pending, ctx) {
|
|
1142
|
+
let changed = false;
|
|
1143
|
+
let batch = null;
|
|
1144
|
+
pending.forEach(({ previous, existing }, contentPos) => {
|
|
1145
|
+
if (contentPos < 0 || contentPos > tr.doc.content.size) return;
|
|
1146
|
+
const $pos = tr.doc.resolve(contentPos);
|
|
1147
|
+
const node = $pos.parent;
|
|
1148
|
+
if (!node.isTextblock || $pos.parentOffset !== 0 || $pos.depth === 0) return;
|
|
1149
|
+
if (!node.type.spec.attrs || !(BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs)) return;
|
|
1150
|
+
const pos = $pos.before();
|
|
1151
|
+
const original = _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _39 => _39.previous]), () => ( previous));
|
|
1152
|
+
const current = blockSnapshot(tr.doc, pos);
|
|
1153
|
+
if (sameBlock(original, current, ctx.ignoredAttributes)) {
|
|
1154
|
+
if (node.attrs[BLOCK_CHANGE_ATTRIBUTE]) {
|
|
1155
|
+
tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, null);
|
|
1156
|
+
changed = true;
|
|
1157
|
+
}
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
const base = existing && existing.authorId === ctx.author.id && existing.changeId ? baseAttributes(existing) : batch = _nullishCoalesce(batch, () => ( newAttributes(ctx)));
|
|
1161
|
+
const value = { ...base, previous: original };
|
|
1162
|
+
if (!sameValue(node.attrs[BLOCK_CHANGE_ATTRIBUTE], value)) {
|
|
1163
|
+
tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, value);
|
|
1164
|
+
changed = true;
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
return changed;
|
|
1168
|
+
}
|
|
1169
|
+
function collectBlockChanges(step, docBefore, docAfter, rest, pending, ctx) {
|
|
1170
|
+
const record = (oldPos, newPos) => {
|
|
1171
|
+
const key = rest.map(newPos + 1);
|
|
1172
|
+
if (pending.has(key)) return;
|
|
1173
|
+
const oldNode = docBefore.nodeAt(oldPos);
|
|
1174
|
+
const previous = blockSnapshot(docBefore, oldPos);
|
|
1175
|
+
if (sameBlock(previous, blockSnapshot(docAfter, newPos), ctx.ignoredAttributes)) return;
|
|
1176
|
+
pending.set(key, {
|
|
1177
|
+
previous,
|
|
1178
|
+
existing: _nullishCoalesce(oldNode.attrs[BLOCK_CHANGE_ATTRIBUTE], () => ( null))
|
|
1179
|
+
});
|
|
1180
|
+
};
|
|
1181
|
+
if (step instanceof _transform.AttrStep) {
|
|
1182
|
+
const node = docBefore.nodeAt(step.pos);
|
|
1183
|
+
if (_optionalChain([node, 'optionalAccess', _40 => _40.isTextblock]) && step.attr !== BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(step.attr)) {
|
|
1184
|
+
record(step.pos, step.pos);
|
|
1185
|
+
}
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
const map = step.getMap();
|
|
1189
|
+
const back = map.invert();
|
|
1190
|
+
const start = map.map(step.from, -1);
|
|
1191
|
+
const end = map.map(step.to, 1);
|
|
1192
|
+
docAfter.nodesBetween(start, end, (node, pos) => {
|
|
1193
|
+
if (!node.isTextblock) return true;
|
|
1194
|
+
const oldContent = back.map(pos + 1);
|
|
1195
|
+
if (oldContent < 1 || oldContent > docBefore.content.size) return false;
|
|
1196
|
+
const $old = docBefore.resolve(oldContent);
|
|
1197
|
+
if ($old.parent.isTextblock && $old.parentOffset === 0 && $old.parent.content.size === node.content.size) {
|
|
1198
|
+
record($old.before(), pos);
|
|
1199
|
+
}
|
|
1200
|
+
return false;
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
543
1203
|
function trackTransactions(transactions, oldState, newState, ctx) {
|
|
544
1204
|
const maps = [];
|
|
545
1205
|
transactions.forEach((t) => maps.push(...t.mapping.maps));
|
|
546
1206
|
const inserted = [];
|
|
547
1207
|
const restores = [];
|
|
1208
|
+
const formatRanges = [];
|
|
1209
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
548
1210
|
let mapIndex = 0;
|
|
549
1211
|
const single = transactions.length === 1 && transactions[0].steps.length === 1;
|
|
550
1212
|
transactions.forEach((t) => {
|
|
551
1213
|
const skip = shouldSkip(t);
|
|
552
1214
|
t.steps.forEach((step, i) => {
|
|
553
1215
|
const index = mapIndex + i;
|
|
554
|
-
if (skip
|
|
555
|
-
const { from, to, slice } = step;
|
|
1216
|
+
if (skip) return;
|
|
556
1217
|
const rest = new (0, _transform.Mapping)(maps.slice(index + 1));
|
|
1218
|
+
const docBefore = t.docs[i];
|
|
1219
|
+
if (step instanceof _transform.AddMarkStep || step instanceof _transform.RemoveMarkStep) {
|
|
1220
|
+
const name = step.mark.type.name;
|
|
1221
|
+
if (ctx.format && !REVIEW_MARK_NAMES.has(name) && !ctx.ignoredMarks.has(name)) {
|
|
1222
|
+
formatRanges.push({ from: rest.map(step.from, 1), to: rest.map(step.to, -1) });
|
|
1223
|
+
}
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
if (step instanceof _transform.ReplaceAroundStep || step instanceof _transform.AttrStep) {
|
|
1227
|
+
if (ctx.trackBlocks) {
|
|
1228
|
+
const docAfter = _nullishCoalesce(t.docs[i + 1], () => ( t.doc));
|
|
1229
|
+
collectBlockChanges(step, docBefore, docAfter, rest, blocks, ctx);
|
|
1230
|
+
}
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
if (!(step instanceof _transform.ReplaceStep)) return;
|
|
1234
|
+
const { from, to, slice } = step;
|
|
1235
|
+
if (to > from && slice.size === to - from) {
|
|
1236
|
+
const deleted = docBefore.slice(from, to);
|
|
1237
|
+
if (slice.openStart === deleted.openStart && slice.openEnd === deleted.openEnd && stripMarks(slice.content).eq(stripMarks(deleted.content))) {
|
|
1238
|
+
if (ctx.format && !slice.content.eq(deleted.content)) {
|
|
1239
|
+
formatRanges.push({ from: rest.map(from, 1), to: rest.map(to, -1) });
|
|
1240
|
+
}
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
557
1244
|
if (slice.size > 0 && hasInlineContent(slice.content)) {
|
|
558
1245
|
const start = rest.map(from, 1);
|
|
559
1246
|
const end = rest.map(from + slice.size, -1);
|
|
560
1247
|
if (end > start) inserted.push({ from: start, to: end });
|
|
561
1248
|
}
|
|
562
1249
|
if (to > from) {
|
|
563
|
-
const docBefore = t.docs[i];
|
|
564
1250
|
const deleted = docBefore.slice(from, to);
|
|
565
1251
|
if (!hasInlineContent(deleted.content)) return;
|
|
566
1252
|
const $from = docBefore.resolve(from);
|
|
@@ -577,12 +1263,22 @@ function trackTransactions(transactions, oldState, newState, ctx) {
|
|
|
577
1263
|
});
|
|
578
1264
|
mapIndex += t.steps.length;
|
|
579
1265
|
});
|
|
580
|
-
if (inserted.length === 0 && restores.length === 0)
|
|
1266
|
+
if (inserted.length === 0 && restores.length === 0 && formatRanges.length === 0 && blocks.size === 0) {
|
|
1267
|
+
return null;
|
|
1268
|
+
}
|
|
581
1269
|
const tr = newState.tr;
|
|
582
1270
|
let changed = false;
|
|
1271
|
+
if (formatRanges.length && ctx.format) {
|
|
1272
|
+
const back = new (0, _transform.Mapping)(maps).invert();
|
|
1273
|
+
changed = trackFormatting(tr, formatRanges, oldState.doc, back, inserted, ctx) || changed;
|
|
1274
|
+
}
|
|
1275
|
+
if (blocks.size) {
|
|
1276
|
+
changed = trackBlocks(tr, blocks, ctx) || changed;
|
|
1277
|
+
}
|
|
583
1278
|
inserted.forEach(({ from, to }) => {
|
|
584
1279
|
tr.removeMark(from, to, ctx.deletion);
|
|
585
1280
|
tr.removeMark(from, to, ctx.insertion);
|
|
1281
|
+
if (ctx.format) tr.removeMark(from, to, ctx.format);
|
|
586
1282
|
const attrs = _nullishCoalesce(adjacentAttributes(tr.doc, from, to, ctx.insertion, ctx), () => ( newAttributes(ctx)));
|
|
587
1283
|
tr.addMark(from, to, ctx.insertion.create(attrs));
|
|
588
1284
|
changed = true;
|
|
@@ -596,7 +1292,7 @@ function trackTransactions(transactions, oldState, newState, ctx) {
|
|
|
596
1292
|
const sizeBefore = tr.doc.content.size;
|
|
597
1293
|
try {
|
|
598
1294
|
tr.replace(pos, pos, marked.slice);
|
|
599
|
-
} catch (
|
|
1295
|
+
} catch (e7) {
|
|
600
1296
|
return;
|
|
601
1297
|
}
|
|
602
1298
|
changed = true;
|
|
@@ -608,7 +1304,7 @@ function trackTransactions(transactions, oldState, newState, ctx) {
|
|
|
608
1304
|
if (cursor !== null) {
|
|
609
1305
|
try {
|
|
610
1306
|
tr.setSelection(_state.TextSelection.create(tr.doc, cursor));
|
|
611
|
-
} catch (
|
|
1307
|
+
} catch (e8) {
|
|
612
1308
|
}
|
|
613
1309
|
}
|
|
614
1310
|
tr.setMeta(TRACK_CHANGES_SKIP_META, true);
|
|
@@ -618,12 +1314,25 @@ function buildSnapshot(state, author) {
|
|
|
618
1314
|
const plugin = trackChangesPluginKey.getState(state);
|
|
619
1315
|
const changes = getTrackedChanges(state.doc);
|
|
620
1316
|
return {
|
|
621
|
-
enabled: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess',
|
|
622
|
-
author: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess',
|
|
1317
|
+
enabled: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _41 => _41.enabled]), () => ( false)),
|
|
1318
|
+
author: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _42 => _42.author]), () => ( author)),
|
|
623
1319
|
changes,
|
|
624
|
-
currentChangeId: _nullishCoalesce(_optionalChain([getTrackedChangeAt, 'call',
|
|
1320
|
+
currentChangeId: _nullishCoalesce(_optionalChain([getTrackedChangeAt, 'call', _43 => _43(state, state.selection.from, changes), 'optionalAccess', _44 => _44.id]), () => ( null))
|
|
625
1321
|
};
|
|
626
1322
|
}
|
|
1323
|
+
function allowTrackingInCodeBlocks(schema) {
|
|
1324
|
+
const marks = [schema.marks[INSERTION_MARK_NAME], schema.marks[DELETION_MARK_NAME]].filter(
|
|
1325
|
+
Boolean
|
|
1326
|
+
);
|
|
1327
|
+
Object.values(schema.nodes).forEach((type) => {
|
|
1328
|
+
const markSet = type.markSet;
|
|
1329
|
+
if (!type.isTextblock || !type.spec.code || markSet === null) return;
|
|
1330
|
+
const missing = marks.filter((mark) => !markSet.includes(mark));
|
|
1331
|
+
if (missing.length) {
|
|
1332
|
+
type.markSet = [...markSet, ...missing];
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
627
1336
|
var TrackChanges = _core.Extension.create({
|
|
628
1337
|
name: "trackChanges",
|
|
629
1338
|
addOptions() {
|
|
@@ -633,7 +1342,15 @@ var TrackChanges = _core.Extension.create({
|
|
|
633
1342
|
now: () => Date.now(),
|
|
634
1343
|
generateId: () => createReviewId("change"),
|
|
635
1344
|
insertionHTMLAttributes: {},
|
|
636
|
-
deletionHTMLAttributes: {}
|
|
1345
|
+
deletionHTMLAttributes: {},
|
|
1346
|
+
formatChangeHTMLAttributes: {},
|
|
1347
|
+
blockChangeClass: "pixerate-block-change border-l-2 border-amber-400 pl-2 dark:border-amber-500",
|
|
1348
|
+
trackFormatting: true,
|
|
1349
|
+
trackBlocks: true,
|
|
1350
|
+
trackCodeBlocks: true,
|
|
1351
|
+
blockTypes: ["paragraph", "heading", "codeBlock"],
|
|
1352
|
+
ignoredMarks: [],
|
|
1353
|
+
ignoredBlockAttributes: ["id"]
|
|
637
1354
|
};
|
|
638
1355
|
},
|
|
639
1356
|
addStorage() {
|
|
@@ -646,14 +1363,43 @@ var TrackChanges = _core.Extension.create({
|
|
|
646
1363
|
})
|
|
647
1364
|
};
|
|
648
1365
|
},
|
|
1366
|
+
addGlobalAttributes() {
|
|
1367
|
+
if (_optionalChain([this, 'access', _45 => _45.options, 'optionalAccess', _46 => _46.trackBlocks]) === false) return [];
|
|
1368
|
+
const blockClass = _nullishCoalesce(_optionalChain([this, 'access', _47 => _47.options, 'optionalAccess', _48 => _48.blockChangeClass]), () => ( ""));
|
|
1369
|
+
return [
|
|
1370
|
+
{
|
|
1371
|
+
types: _nullishCoalesce(_optionalChain([this, 'access', _49 => _49.options, 'optionalAccess', _50 => _50.blockTypes]), () => ( ["paragraph", "heading", "codeBlock"])),
|
|
1372
|
+
attributes: {
|
|
1373
|
+
[BLOCK_CHANGE_ATTRIBUTE]: {
|
|
1374
|
+
default: null,
|
|
1375
|
+
keepOnSplit: false,
|
|
1376
|
+
parseHTML: (el) => parseJSON(el.getAttribute("data-block-change"), null),
|
|
1377
|
+
renderHTML: (attrs) => {
|
|
1378
|
+
const value = attrs[BLOCK_CHANGE_ATTRIBUTE];
|
|
1379
|
+
if (!value) return {};
|
|
1380
|
+
return {
|
|
1381
|
+
"data-block-change": JSON.stringify(value),
|
|
1382
|
+
...blockClass ? { class: blockClass } : {}
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
];
|
|
1389
|
+
},
|
|
649
1390
|
addExtensions() {
|
|
650
|
-
const insertionAttrs = _nullishCoalesce(_optionalChain([this, 'access',
|
|
651
|
-
const deletionAttrs = _nullishCoalesce(_optionalChain([this, 'access',
|
|
1391
|
+
const insertionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _51 => _51.options, 'optionalAccess', _52 => _52.insertionHTMLAttributes]), () => ( {}));
|
|
1392
|
+
const deletionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _53 => _53.options, 'optionalAccess', _54 => _54.deletionHTMLAttributes]), () => ( {}));
|
|
1393
|
+
const formatAttrs = _nullishCoalesce(_optionalChain([this, 'access', _55 => _55.options, 'optionalAccess', _56 => _56.formatChangeHTMLAttributes]), () => ( {}));
|
|
652
1394
|
return [
|
|
653
1395
|
Object.keys(insertionAttrs).length ? TrackedInsertion.configure({ HTMLAttributes: insertionAttrs }) : TrackedInsertion,
|
|
654
|
-
Object.keys(deletionAttrs).length ? TrackedDeletion.configure({ HTMLAttributes: deletionAttrs }) : TrackedDeletion
|
|
1396
|
+
Object.keys(deletionAttrs).length ? TrackedDeletion.configure({ HTMLAttributes: deletionAttrs }) : TrackedDeletion,
|
|
1397
|
+
Object.keys(formatAttrs).length ? TrackedFormatChange.configure({ HTMLAttributes: formatAttrs }) : TrackedFormatChange
|
|
655
1398
|
];
|
|
656
1399
|
},
|
|
1400
|
+
onBeforeCreate() {
|
|
1401
|
+
if (this.options.trackCodeBlocks) allowTrackingInCodeBlocks(this.editor.schema);
|
|
1402
|
+
},
|
|
657
1403
|
addCommands() {
|
|
658
1404
|
const decide = (decision, id) => ({ state, tr, dispatch }) => {
|
|
659
1405
|
const all = getTrackedChanges(state.doc);
|
|
@@ -669,9 +1415,11 @@ var TrackChanges = _core.Extension.create({
|
|
|
669
1415
|
const changes = getTrackedChanges(state.doc);
|
|
670
1416
|
if (changes.length === 0) return false;
|
|
671
1417
|
const { from } = state.selection;
|
|
672
|
-
const
|
|
1418
|
+
const start = (c) => selectionRange(c)[0];
|
|
1419
|
+
const target = direction === 1 ? _nullishCoalesce(changes.find((c) => start(c) > from), () => ( changes[0])) : _nullishCoalesce([...changes].reverse().find((c) => start(c) < from), () => ( changes[changes.length - 1]));
|
|
673
1420
|
if (dispatch) {
|
|
674
|
-
|
|
1421
|
+
const [anchor, head] = selectionRange(target);
|
|
1422
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, anchor, head)).scrollIntoView();
|
|
675
1423
|
}
|
|
676
1424
|
return true;
|
|
677
1425
|
};
|
|
@@ -702,6 +1450,8 @@ var TrackChanges = _core.Extension.create({
|
|
|
702
1450
|
addProseMirrorPlugins() {
|
|
703
1451
|
const options = this.options;
|
|
704
1452
|
const store = this.storage.store;
|
|
1453
|
+
const ignoredMarks = new Set(_nullishCoalesce(options.ignoredMarks, () => ( [])));
|
|
1454
|
+
const ignoredAttributes = new Set(_nullishCoalesce(options.ignoredBlockAttributes, () => ( [])));
|
|
705
1455
|
let editorView = null;
|
|
706
1456
|
let pending = null;
|
|
707
1457
|
let flushTimer = null;
|
|
@@ -734,9 +1484,9 @@ var TrackChanges = _core.Extension.create({
|
|
|
734
1484
|
},
|
|
735
1485
|
appendTransaction: (transactions, oldState, newState) => {
|
|
736
1486
|
const plugin = trackChangesPluginKey.getState(oldState);
|
|
737
|
-
const tracking = !!_optionalChain([plugin, 'optionalAccess',
|
|
1487
|
+
const tracking = !!_optionalChain([plugin, 'optionalAccess', _57 => _57.enabled]);
|
|
738
1488
|
if (!tracking && !pending) return null;
|
|
739
|
-
if (_optionalChain([editorView, 'optionalAccess',
|
|
1489
|
+
if (_optionalChain([editorView, 'optionalAccess', _58 => _58.composing]) && transactions.some((t) => t.docChanged)) {
|
|
740
1490
|
if (tracking) {
|
|
741
1491
|
if (!pending) pending = { oldState, transactions: [] };
|
|
742
1492
|
pending.transactions.push(...transactions);
|
|
@@ -751,21 +1501,21 @@ var TrackChanges = _core.Extension.create({
|
|
|
751
1501
|
pending = null;
|
|
752
1502
|
}
|
|
753
1503
|
if (!tracking && trs === transactions) return null;
|
|
754
|
-
const author = _nullishCoalesce(_optionalChain([plugin, 'optionalAccess',
|
|
1504
|
+
const author = _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _59 => _59.author]), () => ( options.author));
|
|
755
1505
|
return trackTransactions(trs, fromState, newState, {
|
|
756
1506
|
author,
|
|
757
1507
|
now: options.now,
|
|
758
1508
|
generateId: options.generateId,
|
|
759
1509
|
insertion: newState.schema.marks[INSERTION_MARK_NAME],
|
|
760
|
-
deletion: newState.schema.marks[DELETION_MARK_NAME]
|
|
1510
|
+
deletion: newState.schema.marks[DELETION_MARK_NAME],
|
|
1511
|
+
format: options.trackFormatting !== false ? newState.schema.marks[FORMAT_CHANGE_MARK_NAME] : void 0,
|
|
1512
|
+
trackBlocks: options.trackBlocks !== false,
|
|
1513
|
+
ignoredMarks,
|
|
1514
|
+
ignoredAttributes
|
|
761
1515
|
});
|
|
762
1516
|
},
|
|
763
1517
|
props: {
|
|
764
|
-
transformPasted: (slice, view) => acceptSlice(
|
|
765
|
-
slice,
|
|
766
|
-
view.state.schema.marks[INSERTION_MARK_NAME],
|
|
767
|
-
view.state.schema.marks[DELETION_MARK_NAME]
|
|
768
|
-
),
|
|
1518
|
+
transformPasted: (slice, view) => acceptSlice(slice, view.state.schema),
|
|
769
1519
|
handleDOMEvents: {
|
|
770
1520
|
compositionend: () => {
|
|
771
1521
|
if (pending) scheduleFlush();
|
|
@@ -827,7 +1577,7 @@ function plainTextToSlice(text, schema) {
|
|
|
827
1577
|
}
|
|
828
1578
|
try {
|
|
829
1579
|
nodes.push(_model.Node.fromJSON(schema, nodeJson));
|
|
830
|
-
} catch (
|
|
1580
|
+
} catch (e9) {
|
|
831
1581
|
}
|
|
832
1582
|
});
|
|
833
1583
|
return _model.Slice.maxOpen(_model.Fragment.fromArray(nodes));
|
|
@@ -929,7 +1679,7 @@ function getEditorText(editor, options = {}) {
|
|
|
929
1679
|
if (typeof editor.getText === "function") {
|
|
930
1680
|
try {
|
|
931
1681
|
return editor.getText({ blockSeparator: "\n" });
|
|
932
|
-
} catch (
|
|
1682
|
+
} catch (e10) {
|
|
933
1683
|
return editor.getText();
|
|
934
1684
|
}
|
|
935
1685
|
}
|
|
@@ -938,10 +1688,10 @@ function getEditorText(editor, options = {}) {
|
|
|
938
1688
|
function extractMentionsFromDoc(docOrEditor) {
|
|
939
1689
|
if (!docOrEditor) return [];
|
|
940
1690
|
const mentions = [];
|
|
941
|
-
const doc = _optionalChain([docOrEditor, 'optionalAccess',
|
|
1691
|
+
const doc = _optionalChain([docOrEditor, 'optionalAccess', _60 => _60.state, 'optionalAccess', _61 => _61.doc]) || (typeof _optionalChain([docOrEditor, 'optionalAccess', _62 => _62.descendants]) === "function" ? docOrEditor : null);
|
|
942
1692
|
if (doc && typeof doc.descendants === "function") {
|
|
943
1693
|
doc.descendants((node) => {
|
|
944
|
-
if (_optionalChain([node, 'access',
|
|
1694
|
+
if (_optionalChain([node, 'access', _63 => _63.type, 'optionalAccess', _64 => _64.name]) === "mention" && node.attrs) {
|
|
945
1695
|
mentions.push({
|
|
946
1696
|
id: node.attrs.id || "",
|
|
947
1697
|
label: node.attrs.label || "",
|
|
@@ -1109,25 +1859,25 @@ function preprocessMarkdownMentions(content, optionsOrMentionables = []) {
|
|
|
1109
1859
|
if (!rawHandle) return match;
|
|
1110
1860
|
const lowerHandle = rawHandle.toLowerCase();
|
|
1111
1861
|
const entity = allMentionables.find((e) => {
|
|
1112
|
-
if (_optionalChain([e, 'access',
|
|
1113
|
-
if (_optionalChain([e, 'access',
|
|
1114
|
-
if (_optionalChain([e, 'access',
|
|
1115
|
-
if (_optionalChain([e, 'access',
|
|
1862
|
+
if (_optionalChain([e, 'access', _65 => _65.label, 'optionalAccess', _66 => _66.toLowerCase, 'call', _67 => _67()]) === lowerHandle) return true;
|
|
1863
|
+
if (_optionalChain([e, 'access', _68 => _68.handle, 'optionalAccess', _69 => _69.toLowerCase, 'call', _70 => _70()]) === lowerHandle) return true;
|
|
1864
|
+
if (_optionalChain([e, 'access', _71 => _71.name, 'optionalAccess', _72 => _72.toLowerCase, 'call', _73 => _73()]) === lowerHandle) return true;
|
|
1865
|
+
if (_optionalChain([e, 'access', _74 => _74.id, 'optionalAccess', _75 => _75.toLowerCase, 'call', _76 => _76()]) === lowerHandle) return true;
|
|
1116
1866
|
if (e.type === "agent" && `agent${(e.handle || e.label || "").toLowerCase()}` === lowerHandle) return true;
|
|
1117
|
-
if (_optionalChain([e, 'access',
|
|
1867
|
+
if (_optionalChain([e, 'access', _77 => _77.aliases, 'optionalAccess', _78 => _78.some, 'call', _79 => _79(
|
|
1118
1868
|
(a) => a.toLowerCase() === lowerHandle || e.type === "agent" && `agent${a.toLowerCase()}` === lowerHandle
|
|
1119
1869
|
)])) {
|
|
1120
1870
|
return true;
|
|
1121
1871
|
}
|
|
1122
1872
|
return false;
|
|
1123
1873
|
});
|
|
1124
|
-
let id = _optionalChain([entity, 'optionalAccess',
|
|
1125
|
-
let label = _optionalChain([entity, 'optionalAccess',
|
|
1126
|
-
let type = _optionalChain([entity, 'optionalAccess',
|
|
1127
|
-
let avatarUrl = _optionalChain([entity, 'optionalAccess',
|
|
1128
|
-
let color = _optionalChain([entity, 'optionalAccess',
|
|
1874
|
+
let id = _optionalChain([entity, 'optionalAccess', _80 => _80.id]);
|
|
1875
|
+
let label = _optionalChain([entity, 'optionalAccess', _81 => _81.label]) || _optionalChain([entity, 'optionalAccess', _82 => _82.handle]) || rawHandle;
|
|
1876
|
+
let type = _optionalChain([entity, 'optionalAccess', _83 => _83.type]);
|
|
1877
|
+
let avatarUrl = _optionalChain([entity, 'optionalAccess', _84 => _84.avatarUrl]);
|
|
1878
|
+
let color = _optionalChain([entity, 'optionalAccess', _85 => _85.color]) || _optionalChain([entity, 'optionalAccess', _86 => _86.hexColor]);
|
|
1129
1879
|
if (!entity) {
|
|
1130
|
-
const customResolved = _optionalChain([resolveMention, 'optionalCall',
|
|
1880
|
+
const customResolved = _optionalChain([resolveMention, 'optionalCall', _87 => _87(rawHandle)]);
|
|
1131
1881
|
if (customResolved) {
|
|
1132
1882
|
id = _nullishCoalesce(customResolved.id, () => ( id));
|
|
1133
1883
|
label = _nullishCoalesce(_nullishCoalesce(customResolved.label, () => ( customResolved.handle)), () => ( label));
|
|
@@ -1287,8 +2037,8 @@ function sanitizeEmbeddedHtml(html, stripDisallowed = false) {
|
|
|
1287
2037
|
}
|
|
1288
2038
|
var defaultHtmlInline = md.renderer.rules.html_inline;
|
|
1289
2039
|
var defaultHtmlBlock = md.renderer.rules.html_block;
|
|
1290
|
-
md.renderer.rules.html_inline = (tokens, idx, options, env, self) => _optionalChain([env, 'optionalAccess',
|
|
1291
|
-
md.renderer.rules.html_block = (tokens, idx, options, env, self) => _optionalChain([env, 'optionalAccess',
|
|
2040
|
+
md.renderer.rules.html_inline = (tokens, idx, options, env, self) => _optionalChain([env, 'optionalAccess', _88 => _88.allowUnsafeHtml]) ? defaultHtmlInline(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
|
|
2041
|
+
md.renderer.rules.html_block = (tokens, idx, options, env, self) => _optionalChain([env, 'optionalAccess', _89 => _89.allowUnsafeHtml]) ? defaultHtmlBlock(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
|
|
1292
2042
|
function preprocessMarkdownFileLinks(content) {
|
|
1293
2043
|
if (!content) return "";
|
|
1294
2044
|
return content.replace(
|
|
@@ -1304,23 +2054,23 @@ function preprocessMarkdownFileLinks(content) {
|
|
|
1304
2054
|
function markdownToTipTapHtml(markdown, options) {
|
|
1305
2055
|
if (!markdown) return "<p></p>";
|
|
1306
2056
|
let content = markdown;
|
|
1307
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
2057
|
+
if (_optionalChain([options, 'optionalAccess', _90 => _90.preprocessFileLinks])) {
|
|
1308
2058
|
content = preprocessMarkdownFileLinks(content);
|
|
1309
2059
|
}
|
|
1310
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
2060
|
+
if (_optionalChain([options, 'optionalAccess', _91 => _91.preprocessMentions]) || _optionalChain([options, 'optionalAccess', _92 => _92.mentionables]) || _optionalChain([options, 'optionalAccess', _93 => _93.preprocessOptions])) {
|
|
1311
2061
|
const mentionOpts = options.preprocessOptions || {
|
|
1312
2062
|
mentionables: options.mentionables
|
|
1313
2063
|
};
|
|
1314
2064
|
content = preprocessMarkdownMentions(content, mentionOpts);
|
|
1315
2065
|
}
|
|
1316
|
-
return md.render(content, { allowUnsafeHtml: _optionalChain([options, 'optionalAccess',
|
|
2066
|
+
return md.render(content, { allowUnsafeHtml: _optionalChain([options, 'optionalAccess', _94 => _94.allowUnsafeHtml]) });
|
|
1317
2067
|
}
|
|
1318
2068
|
function getEditorMarkdown(editor, options = {}) {
|
|
1319
2069
|
if (!editor) return "";
|
|
1320
|
-
const markdown = _optionalChain([editor, 'access',
|
|
1321
|
-
if (typeof _optionalChain([markdown, 'optionalAccess',
|
|
1322
|
-
const doc = _optionalChain([editor, 'access',
|
|
1323
|
-
if (doc && typeof _optionalChain([markdown, 'access',
|
|
2070
|
+
const markdown = _optionalChain([editor, 'access', _95 => _95.storage, 'optionalAccess', _96 => _96.markdown]);
|
|
2071
|
+
if (typeof _optionalChain([markdown, 'optionalAccess', _97 => _97.getMarkdown]) === "function") {
|
|
2072
|
+
const doc = _optionalChain([editor, 'access', _98 => _98.state, 'optionalAccess', _99 => _99.doc]);
|
|
2073
|
+
if (doc && typeof _optionalChain([markdown, 'access', _100 => _100.serializer, 'optionalAccess', _101 => _101.serialize]) === "function") {
|
|
1324
2074
|
const resolved = resolveTrackedChanges(doc, _nullishCoalesce(options.trackedChanges, () => ( "accepted")));
|
|
1325
2075
|
if (resolved !== doc) return markdown.serializer.serialize(resolved);
|
|
1326
2076
|
}
|
|
@@ -1363,5 +2113,10 @@ function getEditorMarkdown(editor, options = {}) {
|
|
|
1363
2113
|
|
|
1364
2114
|
|
|
1365
2115
|
|
|
1366
|
-
|
|
1367
|
-
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
exports.createReviewId = createReviewId; exports.CommentStore = CommentStore; exports.createCommentStore = createCommentStore; exports.formatReviewTime = formatReviewTime; exports.INSERTION_MARK_NAME = INSERTION_MARK_NAME; exports.DELETION_MARK_NAME = DELETION_MARK_NAME; exports.FORMAT_CHANGE_MARK_NAME = FORMAT_CHANGE_MARK_NAME; exports.BLOCK_CHANGE_ATTRIBUTE = BLOCK_CHANGE_ATTRIBUTE; exports.TRACK_CHANGES_SKIP_META = TRACK_CHANGES_SKIP_META; exports.TrackChangesStore = TrackChangesStore; exports.trackChangesPluginKey = trackChangesPluginKey; exports.TrackedInsertion = TrackedInsertion; exports.TrackedDeletion = TrackedDeletion; exports.TrackedFormatChange = TrackedFormatChange; exports.describeFormatChange = describeFormatChange; exports.describeBlockChange = describeBlockChange; exports.getTrackedChanges = getTrackedChanges; exports.getTrackedChangeAt = getTrackedChangeAt; exports.isTrackChangesEnabled = isTrackChangesEnabled; exports.getTrackChangesStore = getTrackChangesStore; exports.resolveTrackedChanges = resolveTrackedChanges; exports.TrackChanges = TrackChanges; exports.MENTION_REGEX = MENTION_REGEX; exports.MARKDOWN_MENTION_SPLIT_REGEX = MARKDOWN_MENTION_SPLIT_REGEX; exports.stripMarkdownCode = stripMarkdownCode; exports.extractMentions = extractMentions; exports.parseMentionSegments = parseMentionSegments; exports.preprocessMarkdownMentions = preprocessMarkdownMentions; exports.escapeHtml = escapeHtml; exports.plainTextToTipTapHtml = plainTextToTipTapHtml; exports.plainTextToSlice = plainTextToSlice; exports.htmlToPlainText = htmlToPlainText; exports.getEditorText = getEditorText; exports.extractMentionsFromDoc = extractMentionsFromDoc; exports.sanitizeHtml = sanitizeHtml; exports.preprocessMarkdownFileLinks = preprocessMarkdownFileLinks; exports.markdownToTipTapHtml = markdownToTipTapHtml; exports.getEditorMarkdown = getEditorMarkdown;
|
|
2122
|
+
//# sourceMappingURL=chunk-AA4ZEVCC.cjs.map
|