@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.
Files changed (70) hide show
  1. package/README.md +20 -11
  2. package/dist/agent/index.cjs +8 -8
  3. package/dist/agent/index.d.cts +2 -2
  4. package/dist/agent/index.d.ts +2 -2
  5. package/dist/agent/index.js +2 -2
  6. package/dist/canvas/index.cjs +1269 -13
  7. package/dist/canvas/index.cjs.map +1 -1
  8. package/dist/canvas/index.d.cts +432 -6
  9. package/dist/canvas/index.d.ts +432 -6
  10. package/dist/canvas/index.js +1264 -8
  11. package/dist/canvas/index.js.map +1 -1
  12. package/dist/{chunk-U6NDQFOK.cjs → chunk-6M3BCTBD.cjs} +427 -138
  13. package/dist/chunk-6M3BCTBD.cjs.map +1 -0
  14. package/dist/{chunk-TVRC4KVT.cjs → chunk-AA4ZEVCC.cjs} +845 -90
  15. package/dist/chunk-AA4ZEVCC.cjs.map +1 -0
  16. package/dist/{chunk-LA7PEGU3.cjs → chunk-CL37JGFW.cjs} +4 -4
  17. package/dist/{chunk-LA7PEGU3.cjs.map → chunk-CL37JGFW.cjs.map} +1 -1
  18. package/dist/{chunk-A7DKIA72.js → chunk-DENSCKFC.js} +642 -69
  19. package/dist/chunk-DENSCKFC.js.map +1 -0
  20. package/dist/{chunk-4QPLEUL2.cjs → chunk-GVSMRPHB.cjs} +1046 -54
  21. package/dist/chunk-GVSMRPHB.cjs.map +1 -0
  22. package/dist/{chunk-KYRZDWM4.js → chunk-JJDLPEWL.js} +2 -2
  23. package/dist/{chunk-3TYMNULT.js → chunk-MJZBNWG7.js} +807 -52
  24. package/dist/chunk-MJZBNWG7.js.map +1 -0
  25. package/dist/{chunk-CYFJCKC4.js → chunk-QGHGJ56O.js} +997 -5
  26. package/dist/chunk-QGHGJ56O.js.map +1 -0
  27. package/dist/{chunk-GVW4P7BG.js → chunk-RU52I7QO.js} +305 -16
  28. package/dist/chunk-RU52I7QO.js.map +1 -0
  29. package/dist/{chunk-JYRIOFEN.cjs → chunk-SAZRENEZ.cjs} +647 -74
  30. package/dist/chunk-SAZRENEZ.cjs.map +1 -0
  31. package/dist/{controller-OUdxPY-X.d.ts → controller-B7GIybc4.d.cts} +139 -7
  32. package/dist/{controller-OUdxPY-X.d.cts → controller-B7GIybc4.d.ts} +139 -7
  33. package/dist/extensions/index.cjs +14 -4
  34. package/dist/extensions/index.cjs.map +1 -1
  35. package/dist/extensions/index.d.cts +3 -3
  36. package/dist/extensions/index.d.ts +3 -3
  37. package/dist/extensions/index.js +13 -3
  38. package/dist/{index-k3mFbPx_.d.cts → index-CCr_z9kF.d.cts} +3 -3
  39. package/dist/{index-Ng1pG7JE.d.ts → index-Ck6ajwXh.d.ts} +3 -3
  40. package/dist/index.cjs +250 -16
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +294 -8
  43. package/dist/index.d.ts +294 -8
  44. package/dist/index.js +241 -7
  45. package/dist/index.js.map +1 -1
  46. package/dist/{registry-iAHbqkYt.d.cts → registry-GJI4gToU.d.cts} +15 -4
  47. package/dist/{registry-iAHbqkYt.d.ts → registry-GJI4gToU.d.ts} +15 -4
  48. package/dist/serializers/index.cjs +3 -3
  49. package/dist/serializers/index.d.cts +1 -1
  50. package/dist/serializers/index.d.ts +1 -1
  51. package/dist/serializers/index.js +2 -2
  52. package/dist/spreadsheet/index.cjs +7 -3
  53. package/dist/spreadsheet/index.cjs.map +1 -1
  54. package/dist/spreadsheet/index.d.cts +33 -4
  55. package/dist/spreadsheet/index.d.ts +33 -4
  56. package/dist/spreadsheet/index.js +6 -2
  57. package/dist/{track-changes-G8JcWB8b.d.cts → track-changes-BSF58RK0.d.cts} +92 -9
  58. package/dist/{track-changes-G8JcWB8b.d.ts → track-changes-BSF58RK0.d.ts} +92 -9
  59. package/dist/{types-DMe0vFB1.d.cts → types-CJ4U-HHI.d.cts} +1 -1
  60. package/dist/{types-DMe0vFB1.d.ts → types-CJ4U-HHI.d.ts} +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-3TYMNULT.js.map +0 -1
  63. package/dist/chunk-4QPLEUL2.cjs.map +0 -1
  64. package/dist/chunk-A7DKIA72.js.map +0 -1
  65. package/dist/chunk-CYFJCKC4.js.map +0 -1
  66. package/dist/chunk-GVW4P7BG.js.map +0 -1
  67. package/dist/chunk-JYRIOFEN.cjs.map +0 -1
  68. package/dist/chunk-TVRC4KVT.cjs.map +0 -1
  69. package/dist/chunk-U6NDQFOK.cjs.map +0 -1
  70. /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', _2 => _2.state, 'optionalAccess', _3 => _3.doc])) return source.state.doc;
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 type = mark.type.name;
385
- if (type !== INSERTION_MARK_NAME && type !== DELETION_MARK_NAME) return;
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 key = `${type}:${attrs.changeId}`;
389
- const end = pos + node.nodeSize;
390
- const text = node.isText ? _nullishCoalesce(node.text, () => ( "")) : "";
391
- let change = byKey.get(key);
392
- if (!change) {
393
- change = {
394
- id: attrs.changeId,
395
- type,
396
- author: {
397
- id: attrs.authorId,
398
- name: attrs.authorName,
399
- ...attrs.authorColor ? { color: attrs.authorColor } : {}
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
- return Array.from(byKey.values()).sort((a, b) => a.from - b.from || a.to - b.to);
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) => c.from === from && c.to === to);
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
- return _nullishCoalesce(_nullishCoalesce(changes.find((c) => c.ranges.some((r) => r.from < pos && pos < r.to)), () => ( changes.find((c) => c.ranges.some((r) => r.from <= pos && pos <= r.to)))), () => ( null));
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', _4 => _4.state]), () => ( source));
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', _5 => _5.getState, 'call', _6 => _6(state), 'optionalAccess', _7 => _7.enabled]), () => ( false));
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', _8 => _8.storage, 'optionalAccess', _9 => _9.trackChanges, 'optionalAccess', _10 => _10.store]), () => ( null));
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, insertion, deletion) {
472
- if (!insertion && !deletion) return slice;
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
- children.push(insertion ? child.mark(insertion.removeFromSet(child.marks)) : child);
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 || !(step instanceof _transform.ReplaceStep)) return;
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) return null;
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 (e2) {
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 (e3) {
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', _11 => _11.enabled]), () => ( false)),
622
- author: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _12 => _12.author]), () => ( author)),
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', _13 => _13(state, state.selection.from, changes), 'optionalAccess', _14 => _14.id]), () => ( null))
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', _15 => _15.options, 'optionalAccess', _16 => _16.insertionHTMLAttributes]), () => ( {}));
651
- const deletionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _17 => _17.options, 'optionalAccess', _18 => _18.deletionHTMLAttributes]), () => ( {}));
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 target = direction === 1 ? _nullishCoalesce(changes.find((c) => c.from > from), () => ( changes[0])) : _nullishCoalesce([...changes].reverse().find((c) => c.from < from), () => ( changes[changes.length - 1]));
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
- tr.setSelection(_state.TextSelection.create(tr.doc, target.from, target.to)).scrollIntoView();
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', _19 => _19.enabled]);
1487
+ const tracking = !!_optionalChain([plugin, 'optionalAccess', _57 => _57.enabled]);
738
1488
  if (!tracking && !pending) return null;
739
- if (_optionalChain([editorView, 'optionalAccess', _20 => _20.composing]) && transactions.some((t) => t.docChanged)) {
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', _21 => _21.author]), () => ( options.author));
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 (e4) {
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 (e5) {
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', _22 => _22.state, 'optionalAccess', _23 => _23.doc]) || (typeof _optionalChain([docOrEditor, 'optionalAccess', _24 => _24.descendants]) === "function" ? docOrEditor : null);
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', _25 => _25.type, 'optionalAccess', _26 => _26.name]) === "mention" && node.attrs) {
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', _27 => _27.label, 'optionalAccess', _28 => _28.toLowerCase, 'call', _29 => _29()]) === lowerHandle) return true;
1113
- if (_optionalChain([e, 'access', _30 => _30.handle, 'optionalAccess', _31 => _31.toLowerCase, 'call', _32 => _32()]) === lowerHandle) return true;
1114
- if (_optionalChain([e, 'access', _33 => _33.name, 'optionalAccess', _34 => _34.toLowerCase, 'call', _35 => _35()]) === lowerHandle) return true;
1115
- if (_optionalChain([e, 'access', _36 => _36.id, 'optionalAccess', _37 => _37.toLowerCase, 'call', _38 => _38()]) === lowerHandle) return true;
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', _39 => _39.aliases, 'optionalAccess', _40 => _40.some, 'call', _41 => _41(
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', _42 => _42.id]);
1125
- let label = _optionalChain([entity, 'optionalAccess', _43 => _43.label]) || _optionalChain([entity, 'optionalAccess', _44 => _44.handle]) || rawHandle;
1126
- let type = _optionalChain([entity, 'optionalAccess', _45 => _45.type]);
1127
- let avatarUrl = _optionalChain([entity, 'optionalAccess', _46 => _46.avatarUrl]);
1128
- let color = _optionalChain([entity, 'optionalAccess', _47 => _47.color]) || _optionalChain([entity, 'optionalAccess', _48 => _48.hexColor]);
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', _49 => _49(rawHandle)]);
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', _50 => _50.allowUnsafeHtml]) ? defaultHtmlInline(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
1291
- md.renderer.rules.html_block = (tokens, idx, options, env, self) => _optionalChain([env, 'optionalAccess', _51 => _51.allowUnsafeHtml]) ? defaultHtmlBlock(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
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', _52 => _52.preprocessFileLinks])) {
2057
+ if (_optionalChain([options, 'optionalAccess', _90 => _90.preprocessFileLinks])) {
1308
2058
  content = preprocessMarkdownFileLinks(content);
1309
2059
  }
1310
- if (_optionalChain([options, 'optionalAccess', _53 => _53.preprocessMentions]) || _optionalChain([options, 'optionalAccess', _54 => _54.mentionables]) || _optionalChain([options, 'optionalAccess', _55 => _55.preprocessOptions])) {
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', _56 => _56.allowUnsafeHtml]) });
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', _57 => _57.storage, 'optionalAccess', _58 => _58.markdown]);
1321
- if (typeof _optionalChain([markdown, 'optionalAccess', _59 => _59.getMarkdown]) === "function") {
1322
- const doc = _optionalChain([editor, 'access', _60 => _60.state, 'optionalAccess', _61 => _61.doc]);
1323
- if (doc && typeof _optionalChain([markdown, 'access', _62 => _62.serializer, 'optionalAccess', _63 => _63.serialize]) === "function") {
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
- 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.TRACK_CHANGES_SKIP_META = TRACK_CHANGES_SKIP_META; exports.TrackChangesStore = TrackChangesStore; exports.trackChangesPluginKey = trackChangesPluginKey; exports.TrackedInsertion = TrackedInsertion; exports.TrackedDeletion = TrackedDeletion; 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;
1367
- //# sourceMappingURL=chunk-TVRC4KVT.cjs.map
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