@pixerate/editor 0.22.0 → 0.24.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 (188) hide show
  1. package/README.md +175 -2
  2. package/THIRD_PARTY_NOTICES.md +139 -0
  3. package/dist/agent/index.cjs +87 -111
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +70 -211
  6. package/dist/agent/index.d.ts +70 -211
  7. package/dist/agent/index.js +78 -102
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +2075 -86
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +608 -186
  14. package/dist/canvas/index.d.ts +608 -186
  15. package/dist/canvas/index.js +2060 -71
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/{chunk-DENSCKFC.js → chunk-3CN2WD3X.js} +1730 -189
  22. package/dist/chunk-3CN2WD3X.js.map +1 -0
  23. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  24. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  25. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  26. package/dist/chunk-664LQYFJ.js +115 -0
  27. package/dist/chunk-664LQYFJ.js.map +1 -0
  28. package/dist/chunk-7DWMJCAT.js +453 -0
  29. package/dist/chunk-7DWMJCAT.js.map +1 -0
  30. package/dist/chunk-ARRTP33I.js +101 -0
  31. package/dist/chunk-ARRTP33I.js.map +1 -0
  32. package/dist/chunk-CPOKFNBG.cjs +101 -0
  33. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  34. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  35. package/dist/chunk-D27YFC46.cjs.map +1 -0
  36. package/dist/chunk-D6FH2YAX.cjs +131 -0
  37. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  38. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  39. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  40. package/dist/chunk-FODNLX5N.js +749 -0
  41. package/dist/chunk-FODNLX5N.js.map +1 -0
  42. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  43. package/dist/chunk-FPENXAEJ.js.map +1 -0
  44. package/dist/chunk-G2I4QJOT.cjs +762 -0
  45. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  46. package/dist/chunk-HLIMTC6N.js +1 -0
  47. package/dist/chunk-HLIMTC6N.js.map +1 -0
  48. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  49. package/dist/chunk-ITBSKI26.js.map +1 -0
  50. package/dist/{chunk-6M3BCTBD.cjs → chunk-MA2F5KHF.cjs} +470 -242
  51. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  52. package/dist/{chunk-SAZRENEZ.cjs → chunk-MCSJFWAO.cjs} +1733 -192
  53. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  54. package/dist/chunk-MKA3AHLV.cjs +256 -0
  55. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  56. package/dist/chunk-OLZJXL4R.cjs +749 -0
  57. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  58. package/dist/chunk-OXSV64JX.js +689 -0
  59. package/dist/chunk-OXSV64JX.js.map +1 -0
  60. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  61. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  62. package/dist/chunk-P6ODPZ4W.js +256 -0
  63. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  64. package/dist/chunk-PGNZKFQS.js +685 -0
  65. package/dist/chunk-PGNZKFQS.js.map +1 -0
  66. package/dist/chunk-PL4JB3BF.cjs +1 -0
  67. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  68. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  69. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  70. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  71. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  72. package/dist/chunk-TNNJXF46.cjs +115 -0
  73. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  74. package/dist/chunk-U5HZSFCS.js +131 -0
  75. package/dist/chunk-U5HZSFCS.js.map +1 -0
  76. package/dist/{chunk-RU52I7QO.js → chunk-U5KWZU4X.js} +388 -160
  77. package/dist/chunk-U5KWZU4X.js.map +1 -0
  78. package/dist/chunk-XNORY7M6.cjs +685 -0
  79. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  80. package/dist/commands/index.cjs +860 -0
  81. package/dist/commands/index.cjs.map +1 -0
  82. package/dist/commands/index.d.cts +244 -0
  83. package/dist/commands/index.d.ts +244 -0
  84. package/dist/commands/index.js +860 -0
  85. package/dist/commands/index.js.map +1 -0
  86. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  87. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  88. package/dist/compare/index.cjs +15 -0
  89. package/dist/compare/index.cjs.map +1 -0
  90. package/dist/compare/index.d.cts +58 -0
  91. package/dist/compare/index.d.ts +58 -0
  92. package/dist/compare/index.js +15 -0
  93. package/dist/compare/index.js.map +1 -0
  94. package/dist/{controller-B7GIybc4.d.cts → controller-BhLLAoi8.d.cts} +119 -5
  95. package/dist/{controller-B7GIybc4.d.ts → controller-BhLLAoi8.d.ts} +119 -5
  96. package/dist/documents-BQjzJNe2.d.ts +76 -0
  97. package/dist/documents-KRTPhvst.d.cts +76 -0
  98. package/dist/extensions/index.cjs +53 -5
  99. package/dist/extensions/index.cjs.map +1 -1
  100. package/dist/extensions/index.d.cts +7 -3
  101. package/dist/extensions/index.d.ts +7 -3
  102. package/dist/extensions/index.js +52 -4
  103. package/dist/generation/index.cjs +1373 -0
  104. package/dist/generation/index.cjs.map +1 -0
  105. package/dist/generation/index.d.cts +554 -0
  106. package/dist/generation/index.d.ts +554 -0
  107. package/dist/generation/index.js +1373 -0
  108. package/dist/generation/index.js.map +1 -0
  109. package/dist/grammar/index.cjs +48 -3
  110. package/dist/grammar/index.cjs.map +1 -1
  111. package/dist/grammar/index.d.cts +322 -100
  112. package/dist/grammar/index.d.ts +322 -100
  113. package/dist/grammar/index.js +54 -9
  114. package/dist/history/index.cjs +12 -2
  115. package/dist/history/index.cjs.map +1 -1
  116. package/dist/history/index.d.cts +211 -7
  117. package/dist/history/index.d.ts +211 -7
  118. package/dist/history/index.js +13 -3
  119. package/dist/image-editor/index.cjs +2244 -38
  120. package/dist/image-editor/index.cjs.map +1 -1
  121. package/dist/image-editor/index.d.cts +742 -4
  122. package/dist/image-editor/index.d.ts +742 -4
  123. package/dist/image-editor/index.js +2222 -16
  124. package/dist/image-editor/index.js.map +1 -1
  125. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  126. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  127. package/dist/index.cjs +193 -98
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +17 -48
  130. package/dist/index.d.ts +17 -48
  131. package/dist/index.js +198 -103
  132. package/dist/index.js.map +1 -1
  133. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  134. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  135. package/dist/persistence/index.cjs +676 -0
  136. package/dist/persistence/index.cjs.map +1 -0
  137. package/dist/persistence/index.d.cts +347 -0
  138. package/dist/persistence/index.d.ts +347 -0
  139. package/dist/persistence/index.js +676 -0
  140. package/dist/persistence/index.js.map +1 -0
  141. package/dist/registry-BDe-vlv3.d.ts +171 -0
  142. package/dist/registry-D32LpIc4.d.cts +354 -0
  143. package/dist/registry-DnzpgY27.d.cts +171 -0
  144. package/dist/registry-evKTP4ls.d.ts +354 -0
  145. package/dist/schema-DYDGdYL9.d.cts +41 -0
  146. package/dist/schema-DYDGdYL9.d.ts +41 -0
  147. package/dist/serializers/index.cjs +4 -3
  148. package/dist/serializers/index.cjs.map +1 -1
  149. package/dist/serializers/index.d.cts +2 -1
  150. package/dist/serializers/index.d.ts +2 -1
  151. package/dist/serializers/index.js +3 -2
  152. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  153. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  154. package/dist/spreadsheet/index.cjs +53 -3
  155. package/dist/spreadsheet/index.cjs.map +1 -1
  156. package/dist/spreadsheet/index.d.cts +247 -18
  157. package/dist/spreadsheet/index.d.ts +247 -18
  158. package/dist/spreadsheet/index.js +58 -8
  159. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  160. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  161. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-BK5sVf4_.d.cts} +18 -136
  162. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-CDjCrwKe.d.ts} +18 -136
  163. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.cts} +1 -1
  164. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.ts} +1 -1
  165. package/dist/types-GT5a5YAX.d.cts +86 -0
  166. package/dist/types-GT5a5YAX.d.ts +86 -0
  167. package/package.json +23 -2
  168. package/dist/chunk-2TWGLC5K.cjs +0 -262
  169. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  170. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  171. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  172. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  173. package/dist/chunk-AXV2ZW34.cjs +0 -118
  174. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  175. package/dist/chunk-B2ZRLN4S.js +0 -118
  176. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  177. package/dist/chunk-DENSCKFC.js.map +0 -1
  178. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  179. package/dist/chunk-KAADNAPF.js +0 -262
  180. package/dist/chunk-KAADNAPF.js.map +0 -1
  181. package/dist/chunk-MJZBNWG7.js.map +0 -1
  182. package/dist/chunk-OYXSKQFR.js.map +0 -1
  183. package/dist/chunk-QGHGJ56O.js.map +0 -1
  184. package/dist/chunk-RU52I7QO.js.map +0 -1
  185. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  186. package/dist/types-BZgcDsC5.d.cts +0 -42
  187. package/dist/types-BZgcDsC5.d.ts +0 -42
  188. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -630,9 +630,11 @@ function getTrackedChanges(source) {
630
630
  change.text += text;
631
631
  return change;
632
632
  };
633
+ const blockCounts = /* @__PURE__ */ new Map();
633
634
  doc.descendants((node, pos) => {
634
635
  const block = node.attrs?.[BLOCK_CHANGE_ATTRIBUTE];
635
636
  if (block?.changeId && node.isTextblock) {
637
+ blockCounts.set(block.changeId, (blockCounts.get(block.changeId) ?? 0) + 1);
636
638
  const change = add(
637
639
  `block:${block.changeId}`,
638
640
  "block",
@@ -642,7 +644,11 @@ function getTrackedChanges(source) {
642
644
  node.textContent
643
645
  );
644
646
  if (!change.block) {
645
- change.block = { previous: block.previous, current: blockSnapshot(doc, pos) };
647
+ change.block = {
648
+ previous: block.previous,
649
+ current: blockSnapshot(doc, pos),
650
+ ...block.operation ? { operation: block.operation } : {}
651
+ };
646
652
  }
647
653
  }
648
654
  if (!node.isInline) return;
@@ -679,9 +685,17 @@ function getTrackedChanges(source) {
679
685
  case "format":
680
686
  change.description = describeFormatChange(change.format);
681
687
  break;
682
- case "block":
683
- change.description = describeBlockChange(change.block.previous, change.block.current);
688
+ case "block": {
689
+ const { previous, current, operation } = change.block;
690
+ if (operation) {
691
+ const count = blockCounts.get(change.id) ?? 1;
692
+ const verb = operation === "insert" ? "Inserted" : "Deleted";
693
+ change.description = count > 1 ? `${verb} ${count} blocks` : `${verb} ${blockLabel(current.type, current.attrs)}`;
694
+ } else {
695
+ change.description = describeBlockChange(previous, current);
696
+ }
684
697
  break;
698
+ }
685
699
  }
686
700
  });
687
701
  return changes.sort((a, b) => a.from - b.from || a.to - b.to);
@@ -877,8 +891,56 @@ function restoreWrappers(tr, contentPos, wrappers) {
877
891
  return;
878
892
  }
879
893
  }
894
+ function removeBlocks(tr, ids, decision) {
895
+ const removed = decision === "accept" ? "delete" : "insert";
896
+ const memo = /* @__PURE__ */ new Map();
897
+ const removable = (node) => {
898
+ const cached = memo.get(node);
899
+ if (cached !== void 0) return cached;
900
+ let result;
901
+ if (node.isTextblock) {
902
+ const record = node.attrs?.[BLOCK_CHANGE_ATTRIBUTE];
903
+ result = !!record?.changeId && record.operation === removed && ids.has(record.changeId);
904
+ } else if (node.isLeaf || node.childCount === 0) {
905
+ result = false;
906
+ } else {
907
+ result = true;
908
+ for (let i = 0; i < node.childCount && result; i++) result = removable(node.child(i));
909
+ }
910
+ memo.set(node, result);
911
+ return result;
912
+ };
913
+ const doc = tr.doc;
914
+ if (removable(doc)) {
915
+ const filler = doc.type.contentMatch.defaultType?.createAndFill();
916
+ if (filler) tr.replaceWith(0, doc.content.size, filler);
917
+ return;
918
+ }
919
+ const ranges = [];
920
+ const visit = (node, contentStart) => {
921
+ node.forEach((child, offset) => {
922
+ const from = contentStart + offset;
923
+ if (removable(child)) {
924
+ ranges.push({ from, to: from + child.nodeSize });
925
+ } else if (!child.isTextblock && !child.isLeaf) {
926
+ visit(child, from + 1);
927
+ }
928
+ });
929
+ };
930
+ visit(doc, 0);
931
+ if (ranges.length === 0) return;
932
+ const startIndex = tr.steps.length;
933
+ ranges.reverse().forEach(({ from, to }) => {
934
+ const mapping = tr.mapping.slice(startIndex);
935
+ try {
936
+ tr.delete(mapping.map(from, 1), mapping.map(to, -1));
937
+ } catch {
938
+ }
939
+ });
940
+ }
880
941
  function decideBlocks(tr, changes, decision) {
881
942
  const ids = new Set(changes.map((c) => c.id));
943
+ removeBlocks(tr, ids, decision);
882
944
  const items = [];
883
945
  tr.doc.descendants((node, pos) => {
884
946
  const record = node.attrs?.[BLOCK_CHANGE_ATTRIBUTE];
@@ -894,7 +956,7 @@ function decideBlocks(tr, changes, decision) {
894
956
  const $pos = tr.doc.resolve(contentPos);
895
957
  if (!$pos.parent.isTextblock || $pos.parentOffset !== 0) return;
896
958
  const pos = $pos.before();
897
- if (decision === "accept") {
959
+ if (decision === "accept" || record.operation) {
898
960
  tr.setNodeAttribute(pos, BLOCK_CHANGE_ATTRIBUTE, null);
899
961
  return;
900
962
  }
@@ -1148,6 +1210,7 @@ function trackBlocks(tr, pending, ctx) {
1148
1210
  if (!node.isTextblock || $pos.parentOffset !== 0 || $pos.depth === 0) return;
1149
1211
  if (!node.type.spec.attrs || !(BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs)) return;
1150
1212
  const pos = $pos.before();
1213
+ if (existing?.operation || node.attrs[BLOCK_CHANGE_ATTRIBUTE]?.operation) return;
1151
1214
  const original = existing?.previous ?? previous;
1152
1215
  const current = blockSnapshot(tr.doc, pos);
1153
1216
  if (sameBlock(original, current, ctx.ignoredAttributes)) {
@@ -1345,6 +1408,8 @@ var TrackChanges = Extension.create({
1345
1408
  deletionHTMLAttributes: {},
1346
1409
  formatChangeHTMLAttributes: {},
1347
1410
  blockChangeClass: "pixerate-block-change border-l-2 border-amber-400 pl-2 dark:border-amber-500",
1411
+ blockInsertedClass: "pixerate-block-inserted underline decoration-emerald-500 text-emerald-700 dark:text-emerald-400",
1412
+ blockDeletedClass: "pixerate-block-deleted line-through decoration-red-500 text-red-600 dark:text-red-400",
1348
1413
  trackFormatting: true,
1349
1414
  trackBlocks: true,
1350
1415
  trackCodeBlocks: true,
@@ -1366,6 +1431,8 @@ var TrackChanges = Extension.create({
1366
1431
  addGlobalAttributes() {
1367
1432
  if (this.options?.trackBlocks === false) return [];
1368
1433
  const blockClass = this.options?.blockChangeClass ?? "";
1434
+ const insertedClass = this.options?.blockInsertedClass ?? "";
1435
+ const deletedClass = this.options?.blockDeletedClass ?? "";
1369
1436
  return [
1370
1437
  {
1371
1438
  types: this.options?.blockTypes ?? ["paragraph", "heading", "codeBlock"],
@@ -1377,9 +1444,13 @@ var TrackChanges = Extension.create({
1377
1444
  renderHTML: (attrs) => {
1378
1445
  const value = attrs[BLOCK_CHANGE_ATTRIBUTE];
1379
1446
  if (!value) return {};
1447
+ const operation = value.operation;
1448
+ const extra = operation === "insert" ? insertedClass : operation === "delete" ? deletedClass : "";
1449
+ const className = [blockClass, extra].filter(Boolean).join(" ");
1380
1450
  return {
1381
1451
  "data-block-change": JSON.stringify(value),
1382
- ...blockClass ? { class: blockClass } : {}
1452
+ ...operation ? { "data-block-operation": operation } : {},
1453
+ ...className ? { class: className } : {}
1383
1454
  };
1384
1455
  }
1385
1456
  }
@@ -1545,540 +1616,6 @@ var TrackChanges = Extension.create({
1545
1616
  }
1546
1617
  });
1547
1618
 
1548
- // src/serializers/plain-text.ts
1549
- import { Slice as Slice2, Fragment as Fragment2, Node as ProsemirrorNode } from "@tiptap/pm/model";
1550
- var TRACKED_DELETION_REGEX = /<del\b(?=[^>]*\bdata-change-type=["']deletion["'])[^>]*>[\s\S]*?<\/del>/gi;
1551
- var TRACKED_INSERTION_REGEX = /<ins\b(?=[^>]*\bdata-change-type=["']insertion["'])[^>]*>[\s\S]*?<\/ins>/gi;
1552
- function stripTrackedChanges(html, view) {
1553
- if (view === "all" || !html.includes("data-change-type")) return html;
1554
- return html.replace(
1555
- view === "accepted" ? TRACKED_DELETION_REGEX : TRACKED_INSERTION_REGEX,
1556
- ""
1557
- );
1558
- }
1559
- function escapeHtml(text) {
1560
- if (!text) return "";
1561
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1562
- }
1563
- var PARAGRAPH_HTML_REGEX = /^\s*<p[\s>][\s\S]*<\/p>\s*$/i;
1564
- function plainTextToTipTapHtml(text) {
1565
- if (!text) return "<p></p>";
1566
- if (PARAGRAPH_HTML_REGEX.test(text)) {
1567
- return text;
1568
- }
1569
- return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => `<p>${escapeHtml(line)}</p>`).join("");
1570
- }
1571
- function plainTextToSlice(text, schema) {
1572
- const nodes = [];
1573
- text.replace(/\r\n?/g, "\n").split("\n").forEach((line) => {
1574
- const nodeJson = { type: "paragraph" };
1575
- if (line.length > 0) {
1576
- nodeJson.content = [{ type: "text", text: line }];
1577
- }
1578
- try {
1579
- nodes.push(ProsemirrorNode.fromJSON(schema, nodeJson));
1580
- } catch {
1581
- }
1582
- });
1583
- return Slice2.maxOpen(Fragment2.fromArray(nodes));
1584
- }
1585
- var BLOCK_TAGS = /* @__PURE__ */ new Set([
1586
- "P",
1587
- "DIV",
1588
- "LI",
1589
- "UL",
1590
- "OL",
1591
- "PRE",
1592
- "BLOCKQUOTE",
1593
- "TABLE",
1594
- "TR",
1595
- "H1",
1596
- "H2",
1597
- "H3",
1598
- "H4",
1599
- "H5",
1600
- "H6",
1601
- "HR"
1602
- ]);
1603
- var MENTION_SPAN_REGEX = /<span\b(?=[^>]*\bdata-type=["']mention["'])([^>]*)>[\s\S]*?<\/span>/gi;
1604
- function getHtmlAttribute(attrs, name) {
1605
- const match = new RegExp(`\\b${name}=(?:"([^"]*)"|'([^']*)')`, "i").exec(
1606
- attrs
1607
- );
1608
- return match ? match[1] ?? match[2] : void 0;
1609
- }
1610
- function parseHtmlFragment(html) {
1611
- const template = document.createElement("template");
1612
- template.innerHTML = html;
1613
- return template.content;
1614
- }
1615
- function decodeHtmlEntities(text) {
1616
- return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#0*39;/g, "'").replace(/&nbsp;/g, "\xA0").replace(/&amp;/g, "&");
1617
- }
1618
- function htmlToPlainText(html, options = {}) {
1619
- if (!html) return "";
1620
- const mentionNormalized = stripTrackedChanges(
1621
- html,
1622
- options.trackedChanges ?? "accepted"
1623
- ).replace(MENTION_SPAN_REGEX, (match, attrs) => {
1624
- const label = getHtmlAttribute(attrs, "data-label") || getHtmlAttribute(attrs, "data-id");
1625
- return label ? `@${label}` : match;
1626
- });
1627
- if (typeof document !== "undefined") {
1628
- const fragment = parseHtmlFragment(mentionNormalized);
1629
- fragment.querySelectorAll("br.ProseMirror-trailingBreak").forEach((br) => br.remove());
1630
- const lines = [];
1631
- let current = null;
1632
- const flush = () => {
1633
- if (current !== null) {
1634
- lines.push(current);
1635
- current = null;
1636
- }
1637
- };
1638
- const visit = (node) => {
1639
- if (node.nodeType === 3) {
1640
- const value = node.nodeValue ?? "";
1641
- if (current === null && value.trim() === "") return;
1642
- current = (current ?? "") + value;
1643
- return;
1644
- }
1645
- if (node.nodeType !== 1) return;
1646
- const tag = node.tagName.toUpperCase();
1647
- if (tag === "BR") {
1648
- current = (current ?? "") + "\n";
1649
- return;
1650
- }
1651
- if (!BLOCK_TAGS.has(tag)) {
1652
- node.childNodes.forEach(visit);
1653
- return;
1654
- }
1655
- flush();
1656
- const linesBefore = lines.length;
1657
- node.childNodes.forEach(visit);
1658
- flush();
1659
- if (lines.length === linesBefore && tag !== "HR") {
1660
- lines.push("");
1661
- }
1662
- };
1663
- fragment.childNodes.forEach(visit);
1664
- flush();
1665
- return lines.join("\n");
1666
- }
1667
- const text = mentionNormalized.replace(/<br\s*\/?>/gi, "\n").replace(
1668
- /<\/(?:p|div|li|pre|blockquote|h[1-6])>(?:\s*<\/(?:li|ul|ol|blockquote|div)>)*/gi,
1669
- "\n"
1670
- ).replace(/<[^>]+>/g, "");
1671
- return decodeHtmlEntities(text).replace(/\n$/, "");
1672
- }
1673
- function getEditorText(editor, options = {}) {
1674
- if (!editor) return "";
1675
- const html = typeof editor.getHTML === "function" ? editor.getHTML() : "";
1676
- if (html) {
1677
- return htmlToPlainText(html, options);
1678
- }
1679
- if (typeof editor.getText === "function") {
1680
- try {
1681
- return editor.getText({ blockSeparator: "\n" });
1682
- } catch {
1683
- return editor.getText();
1684
- }
1685
- }
1686
- return "";
1687
- }
1688
- function extractMentionsFromDoc(docOrEditor) {
1689
- if (!docOrEditor) return [];
1690
- const mentions = [];
1691
- const doc = docOrEditor?.state?.doc || (typeof docOrEditor?.descendants === "function" ? docOrEditor : null);
1692
- if (doc && typeof doc.descendants === "function") {
1693
- doc.descendants((node) => {
1694
- if (node.type?.name === "mention" && node.attrs) {
1695
- mentions.push({
1696
- id: node.attrs.id || "",
1697
- label: node.attrs.label || "",
1698
- type: node.attrs.type,
1699
- avatarUrl: node.attrs.avatarUrl,
1700
- color: node.attrs.color,
1701
- ...node.attrs
1702
- });
1703
- }
1704
- });
1705
- return mentions;
1706
- }
1707
- if (typeof docOrEditor === "object" && docOrEditor.content) {
1708
- const walk = (nodes) => {
1709
- for (const node of nodes) {
1710
- if (node.type === "mention" && node.attrs) {
1711
- mentions.push({
1712
- id: node.attrs.id || "",
1713
- label: node.attrs.label || "",
1714
- type: node.attrs.type,
1715
- avatarUrl: node.attrs.avatarUrl,
1716
- color: node.attrs.color,
1717
- ...node.attrs
1718
- });
1719
- }
1720
- if (Array.isArray(node.content)) {
1721
- walk(node.content);
1722
- }
1723
- }
1724
- };
1725
- walk(docOrEditor.content);
1726
- return mentions;
1727
- }
1728
- if (typeof docOrEditor === "string") {
1729
- if (typeof document !== "undefined") {
1730
- parseHtmlFragment(docOrEditor).querySelectorAll('span[data-type="mention"]').forEach((el) => {
1731
- mentions.push({
1732
- id: el.getAttribute("data-id") || "",
1733
- label: el.getAttribute("data-label") || "",
1734
- type: el.getAttribute("data-type-name") || void 0,
1735
- avatarUrl: el.getAttribute("data-avatar-url") || void 0,
1736
- color: el.getAttribute("data-color") || void 0
1737
- });
1738
- });
1739
- } else {
1740
- const spanRegex = /<span([^>]*data-type=["']mention["'][^>]*)>/gi;
1741
- let match;
1742
- while ((match = spanRegex.exec(docOrEditor)) !== null) {
1743
- const attrStr = match[1];
1744
- const getAttr = (name) => {
1745
- const m = new RegExp(`${name}=["']([^"']*)["']`, "i").exec(attrStr);
1746
- return m ? m[1] : void 0;
1747
- };
1748
- mentions.push({
1749
- id: getAttr("data-id") || "",
1750
- label: getAttr("data-label") || "",
1751
- type: getAttr("data-type-name") || getAttr("data-entity-type"),
1752
- avatarUrl: getAttr("data-avatar-url"),
1753
- color: getAttr("data-color")
1754
- });
1755
- }
1756
- }
1757
- if (mentions.length === 0) {
1758
- const rawHandles = extractMentions(docOrEditor);
1759
- for (const handle of rawHandles) {
1760
- mentions.push({
1761
- id: handle,
1762
- label: handle,
1763
- type: "user"
1764
- });
1765
- }
1766
- }
1767
- }
1768
- return mentions;
1769
- }
1770
-
1771
- // src/serializers/mentions.ts
1772
- var MENTION_REGEX = /(?:^|[\s>(*_"';\\/[\]{}~`:]|&quot;|&gt;|&lt;|&amp;)@(?:"([^"]+)"|&quot;([^&]+)&quot;|([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*))/g;
1773
- var MARKDOWN_MENTION_SPLIT_REGEX = /(```[\s\S]*?```|~~~[\s\S]*?~~~|<pre[\s\S]*?<\/pre>|<code[\s\S]*?<\/code>|`[^`\n]+`|<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["']|data-mention=["'][^"']*["'])[^>]*>[\s\S]*?<\/span>|<[^>]+>|\]\([^)]+\)|(?:https?|file|vscode|cursor|mailto):\/\/[^\s<)]+)/gi;
1774
- function stripMarkdownCode(content) {
1775
- if (!content || typeof content !== "string") return "";
1776
- return content.replace(/```[\s\S]*?```/g, "").replace(/~~~[\s\S]*?~~~/g, "").replace(/<pre[\s\S]*?<\/pre>/gi, "").replace(/<code[\s\S]*?<\/code>/gi, "").replace(/`[^`\n]*`/g, "");
1777
- }
1778
- function extractMentions(content) {
1779
- if (!content || typeof content !== "string") return [];
1780
- const normalizedMentionNodes = content.replace(
1781
- /<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["'])[^>]*>([\s\S]*?)<\/span>/gi,
1782
- (match2, inner) => {
1783
- const labelMatch = match2.match(/\bdata-label=["']([^"']+)["']/i);
1784
- if (labelMatch) return ` @${labelMatch[1]} `;
1785
- const idMatch = match2.match(/\bdata-id=["']([^"']+)["']/i);
1786
- if (idMatch) return ` @${idMatch[1]} `;
1787
- return ` ${inner} `;
1788
- }
1789
- );
1790
- const cleanContent = stripMarkdownCode(normalizedMentionNodes);
1791
- const withoutUrls = cleanContent.replace(/(?:https?|ftp|file|vscode|cursor|mailto):\/\/[^\s<>()]+/gi, "").replace(/\]\([^)]*\)/g, "]");
1792
- const textOnly = withoutUrls.replace(/<[^>]+>/g, " ");
1793
- const mentions = [];
1794
- const seen = /* @__PURE__ */ new Set();
1795
- const regex = new RegExp(MENTION_REGEX.source, "g");
1796
- let match;
1797
- while ((match = regex.exec(textOnly)) !== null) {
1798
- const handle = (match[1] ?? match[2] ?? match[3] ?? "").trim();
1799
- if (handle && !seen.has(handle)) {
1800
- seen.add(handle);
1801
- mentions.push(handle);
1802
- }
1803
- }
1804
- return mentions;
1805
- }
1806
- function parseMentionSegments(content) {
1807
- if (!content) return [];
1808
- const segments = [];
1809
- const regex = new RegExp(MENTION_REGEX.source, "g");
1810
- let lastIndex = 0;
1811
- let match;
1812
- while ((match = regex.exec(content)) !== null) {
1813
- const fullMatch = match[0];
1814
- const atIndex = fullMatch.indexOf("@");
1815
- const prefix = atIndex > 0 ? fullMatch.slice(0, atIndex) : "";
1816
- const mentionToken = fullMatch.slice(atIndex);
1817
- const handle = match[1] ?? match[2] ?? match[3];
1818
- const matchStart = match.index + prefix.length;
1819
- if (matchStart > lastIndex) {
1820
- segments.push({
1821
- type: "text",
1822
- value: content.slice(lastIndex, matchStart)
1823
- });
1824
- }
1825
- segments.push({
1826
- type: "mention",
1827
- value: mentionToken,
1828
- handle
1829
- });
1830
- lastIndex = matchStart + mentionToken.length;
1831
- }
1832
- if (lastIndex < content.length) {
1833
- segments.push({
1834
- type: "text",
1835
- value: content.slice(lastIndex)
1836
- });
1837
- }
1838
- return segments;
1839
- }
1840
- function preprocessMarkdownMentions(content, optionsOrMentionables = []) {
1841
- if (!content || typeof content !== "string") return "";
1842
- const options = Array.isArray(optionsOrMentionables) ? { mentionables: optionsOrMentionables } : optionsOrMentionables;
1843
- const allMentionables = options.mentionables || [];
1844
- const defaultType = options.defaultType || "user";
1845
- const resolveMention = options.resolveMention;
1846
- const parts = content.split(MARKDOWN_MENTION_SPLIT_REGEX);
1847
- return parts.map((part) => {
1848
- if (!part) return "";
1849
- if (part.startsWith("```") || part.startsWith("~~~") || part.startsWith("`") || part.startsWith("](") || /^(?:https?|file|vscode|cursor|mailto):\/\//i.test(part) || /^<pre[\s>]/i.test(part) || /^<code[\s>]/i.test(part) || /^<[^>]+>$/i.test(part) || /^<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["']|data-mention=["'][^"']*["'])/i.test(
1850
- part
1851
- )) {
1852
- return part;
1853
- }
1854
- const regex = new RegExp(MENTION_REGEX.source, "g");
1855
- return part.replace(regex, (match, quotedHandle, escapedQuotedHandle, standardHandle) => {
1856
- const atIndex = match.indexOf("@");
1857
- const prefix = atIndex > 0 ? match.slice(0, atIndex) : "";
1858
- const rawHandle = (quotedHandle || escapedQuotedHandle || standardHandle || "").trim();
1859
- if (!rawHandle) return match;
1860
- const lowerHandle = rawHandle.toLowerCase();
1861
- const entity = allMentionables.find((e) => {
1862
- if (e.label?.toLowerCase() === lowerHandle) return true;
1863
- if (e.handle?.toLowerCase() === lowerHandle) return true;
1864
- if (e.name?.toLowerCase() === lowerHandle) return true;
1865
- if (e.id?.toLowerCase() === lowerHandle) return true;
1866
- if (e.type === "agent" && `agent${(e.handle || e.label || "").toLowerCase()}` === lowerHandle) return true;
1867
- if (e.aliases?.some(
1868
- (a) => a.toLowerCase() === lowerHandle || e.type === "agent" && `agent${a.toLowerCase()}` === lowerHandle
1869
- )) {
1870
- return true;
1871
- }
1872
- return false;
1873
- });
1874
- let id = entity?.id;
1875
- let label = entity?.label || entity?.handle || rawHandle;
1876
- let type = entity?.type;
1877
- let avatarUrl = entity?.avatarUrl;
1878
- let color = entity?.color || entity?.hexColor;
1879
- if (!entity) {
1880
- const customResolved = resolveMention?.(rawHandle);
1881
- if (customResolved) {
1882
- id = customResolved.id ?? id;
1883
- label = customResolved.label ?? customResolved.handle ?? label;
1884
- type = customResolved.type ?? type;
1885
- avatarUrl = customResolved.avatarUrl ?? avatarUrl;
1886
- color = customResolved.color ?? customResolved.hexColor ?? color;
1887
- } else {
1888
- const stripped = lowerHandle.replace(/^agent[\s\-_]*/i, "");
1889
- if (["supervisor", "coordinator", "planner", "validator", "executor"].includes(stripped)) {
1890
- type = "agent";
1891
- id = stripped;
1892
- label = stripped;
1893
- } else if (lowerHandle === "agents") {
1894
- type = "team";
1895
- id = "agents";
1896
- label = "agents";
1897
- } else {
1898
- type = defaultType;
1899
- id = rawHandle;
1900
- label = rawHandle;
1901
- }
1902
- }
1903
- }
1904
- const avatarAttr = avatarUrl ? ` data-avatar-url="${escapeHtml(avatarUrl)}"` : "";
1905
- const colorAttr = color ? ` data-color="${escapeHtml(color)}"` : "";
1906
- return `${prefix}<span class="pixerate-mention-node" data-type="mention" data-id="${escapeHtml(
1907
- id || label
1908
- )}" data-label="${escapeHtml(label)}" data-mention-suggestion-char="@" data-type-name="${escapeHtml(
1909
- type || defaultType
1910
- )}"${avatarAttr}${colorAttr}>@${escapeHtml(label)}</span>`;
1911
- });
1912
- }).join("");
1913
- }
1914
-
1915
- // src/serializers/markdown.ts
1916
- import MarkdownIt from "markdown-it";
1917
- import taskLists from "markdown-it-task-lists";
1918
- var md = new MarkdownIt({
1919
- html: true,
1920
- linkify: true,
1921
- breaks: true
1922
- }).use(taskLists);
1923
- var defaultValidateLink = md.validateLink;
1924
- md.validateLink = (url) => {
1925
- if (url.startsWith("file://") || url.startsWith("vscode://") || url.startsWith("cursor://")) {
1926
- return true;
1927
- }
1928
- return defaultValidateLink.call(md, url);
1929
- };
1930
- var ALLOWED_HTML_TAGS = /* @__PURE__ */ new Set([
1931
- "a",
1932
- "abbr",
1933
- "b",
1934
- "blockquote",
1935
- "br",
1936
- "code",
1937
- "del",
1938
- "details",
1939
- "div",
1940
- "em",
1941
- "h1",
1942
- "h2",
1943
- "h3",
1944
- "h4",
1945
- "h5",
1946
- "h6",
1947
- "hr",
1948
- "i",
1949
- "img",
1950
- "input",
1951
- "kbd",
1952
- "li",
1953
- "mark",
1954
- "ol",
1955
- "p",
1956
- "pre",
1957
- "s",
1958
- "span",
1959
- "strong",
1960
- "sub",
1961
- "summary",
1962
- "sup",
1963
- "table",
1964
- "tbody",
1965
- "td",
1966
- "tfoot",
1967
- "th",
1968
- "thead",
1969
- "tr",
1970
- "u",
1971
- "ul"
1972
- ]);
1973
- var ALLOWED_HTML_ATTRS = /* @__PURE__ */ new Set([
1974
- "alt",
1975
- "align",
1976
- "checked",
1977
- "class",
1978
- "colspan",
1979
- "disabled",
1980
- "height",
1981
- "href",
1982
- "rel",
1983
- "rowspan",
1984
- "src",
1985
- "start",
1986
- "target",
1987
- "title",
1988
- "type",
1989
- "width"
1990
- ]);
1991
- var HTML_TAG_REGEX = /<(\/?)([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^\s"'>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?)*)\s*\/?>/g;
1992
- var HTML_ATTR_REGEX = /([^\s"'>\/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
1993
- function sanitizeTag(tagText, isClosing, rawTagName, rawAttrs, stripDisallowed) {
1994
- const tagName = rawTagName.toLowerCase();
1995
- const reject = () => stripDisallowed ? "" : escapeHtml(tagText);
1996
- if (!ALLOWED_HTML_TAGS.has(tagName)) return reject();
1997
- if (isClosing) return `</${tagName}>`;
1998
- if (tagName === "input" && !/\stype\s*=\s*["']?checkbox["']?[\s>/]/i.test(tagText)) {
1999
- return reject();
2000
- }
2001
- let attrs = "";
2002
- let attrMatch;
2003
- HTML_ATTR_REGEX.lastIndex = 0;
2004
- while ((attrMatch = HTML_ATTR_REGEX.exec(rawAttrs)) !== null) {
2005
- const name = attrMatch[1].toLowerCase();
2006
- if (!ALLOWED_HTML_ATTRS.has(name) && !/^data-[a-z0-9_.-]+$/.test(name)) {
2007
- continue;
2008
- }
2009
- const rawValue = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4];
2010
- if (rawValue === void 0) {
2011
- attrs += ` ${name}`;
2012
- continue;
2013
- }
2014
- const value = md.utils.unescapeAll(rawValue);
2015
- if ((name === "href" || name === "src") && // Browsers ignore control characters and whitespace inside schemes.
2016
- !md.validateLink(value.replace(/[\u0000-\u0020\u007f]/g, ""))) {
2017
- continue;
2018
- }
2019
- attrs += ` ${name}="${escapeHtml(value)}"`;
2020
- }
2021
- return `<${tagName}${attrs}>`;
2022
- }
2023
- function sanitizeHtml(html, options = {}) {
2024
- return sanitizeEmbeddedHtml(html, options.disallowedTags === "strip");
2025
- }
2026
- function sanitizeEmbeddedHtml(html, stripDisallowed = false) {
2027
- let result = "";
2028
- let lastIndex = 0;
2029
- let match;
2030
- HTML_TAG_REGEX.lastIndex = 0;
2031
- while ((match = HTML_TAG_REGEX.exec(html)) !== null) {
2032
- result += html.slice(lastIndex, match.index).replace(/</g, "&lt;");
2033
- result += sanitizeTag(match[0], match[1], match[2], match[3], stripDisallowed);
2034
- lastIndex = match.index + match[0].length;
2035
- }
2036
- return result + html.slice(lastIndex).replace(/</g, "&lt;");
2037
- }
2038
- var defaultHtmlInline = md.renderer.rules.html_inline;
2039
- var defaultHtmlBlock = md.renderer.rules.html_block;
2040
- md.renderer.rules.html_inline = (tokens, idx, options, env, self) => env?.allowUnsafeHtml ? defaultHtmlInline(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
2041
- md.renderer.rules.html_block = (tokens, idx, options, env, self) => env?.allowUnsafeHtml ? defaultHtmlBlock(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
2042
- function preprocessMarkdownFileLinks(content) {
2043
- if (!content) return "";
2044
- return content.replace(
2045
- /\[([^\]]+)\]\(((?:file|vscode|cursor):\/\/[^)]+)\)/g,
2046
- (_match, rawLabel, href) => {
2047
- const trimmed = rawLabel.trim();
2048
- const codeMatch = trimmed.match(/^`([^`]+)`$/);
2049
- const labelContent = codeMatch ? `<code>${escapeHtml(codeMatch[1])}</code>` : escapeHtml(trimmed);
2050
- return `<a href="${escapeHtml(href)}" data-file-link="true" title="Click to copy file path">${labelContent}</a>`;
2051
- }
2052
- );
2053
- }
2054
- function markdownToTipTapHtml(markdown, options) {
2055
- if (!markdown) return "<p></p>";
2056
- let content = markdown;
2057
- if (options?.preprocessFileLinks) {
2058
- content = preprocessMarkdownFileLinks(content);
2059
- }
2060
- if (options?.preprocessMentions || options?.mentionables || options?.preprocessOptions) {
2061
- const mentionOpts = options.preprocessOptions || {
2062
- mentionables: options.mentionables
2063
- };
2064
- content = preprocessMarkdownMentions(content, mentionOpts);
2065
- }
2066
- return md.render(content, { allowUnsafeHtml: options?.allowUnsafeHtml });
2067
- }
2068
- function getEditorMarkdown(editor, options = {}) {
2069
- if (!editor) return "";
2070
- const markdown = editor.storage?.markdown;
2071
- if (typeof markdown?.getMarkdown === "function") {
2072
- const doc = editor.state?.doc;
2073
- if (doc && typeof markdown.serializer?.serialize === "function") {
2074
- const resolved = resolveTrackedChanges(doc, options.trackedChanges ?? "accepted");
2075
- if (resolved !== doc) return markdown.serializer.serialize(resolved);
2076
- }
2077
- return markdown.getMarkdown();
2078
- }
2079
- return getEditorText(editor, options);
2080
- }
2081
-
2082
1619
  export {
2083
1620
  createReviewId,
2084
1621
  CommentStore,
@@ -2101,22 +1638,6 @@ export {
2101
1638
  isTrackChangesEnabled,
2102
1639
  getTrackChangesStore,
2103
1640
  resolveTrackedChanges,
2104
- TrackChanges,
2105
- MENTION_REGEX,
2106
- MARKDOWN_MENTION_SPLIT_REGEX,
2107
- stripMarkdownCode,
2108
- extractMentions,
2109
- parseMentionSegments,
2110
- preprocessMarkdownMentions,
2111
- escapeHtml,
2112
- plainTextToTipTapHtml,
2113
- plainTextToSlice,
2114
- htmlToPlainText,
2115
- getEditorText,
2116
- extractMentionsFromDoc,
2117
- sanitizeHtml,
2118
- preprocessMarkdownFileLinks,
2119
- markdownToTipTapHtml,
2120
- getEditorMarkdown
1641
+ TrackChanges
2121
1642
  };
2122
- //# sourceMappingURL=chunk-MJZBNWG7.js.map
1643
+ //# sourceMappingURL=chunk-5S3Z4PPF.js.map