@pixerate/editor 0.23.0 → 0.25.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 (187) hide show
  1. package/README.md +167 -2
  2. package/THIRD_PARTY_NOTICES.md +80 -0
  3. package/dist/agent/index.cjs +10 -8
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +4 -3
  6. package/dist/agent/index.d.ts +4 -3
  7. package/dist/agent/index.js +4 -2
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +4437 -411
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +934 -4
  12. package/dist/canvas/index.d.ts +934 -4
  13. package/dist/canvas/index.js +4309 -283
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/chunk-4BVP64JJ.cjs +1406 -0
  16. package/dist/chunk-4BVP64JJ.cjs.map +1 -0
  17. package/dist/chunk-664LQYFJ.js +115 -0
  18. package/dist/chunk-664LQYFJ.js.map +1 -0
  19. package/dist/chunk-7WISYZFO.cjs +740 -0
  20. package/dist/chunk-7WISYZFO.cjs.map +1 -0
  21. package/dist/chunk-AL6JMGWW.cjs +783 -0
  22. package/dist/chunk-AL6JMGWW.cjs.map +1 -0
  23. package/dist/chunk-BVP3TSLH.cjs +69 -0
  24. package/dist/chunk-BVP3TSLH.cjs.map +1 -0
  25. package/dist/{chunk-RIKBJLS2.cjs → chunk-C7P22VIP.cjs} +2001 -279
  26. package/dist/chunk-C7P22VIP.cjs.map +1 -0
  27. package/dist/chunk-D6FH2YAX.cjs +131 -0
  28. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  29. package/dist/chunk-ECCCYKGL.js +740 -0
  30. package/dist/chunk-ECCCYKGL.js.map +1 -0
  31. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  32. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  33. package/dist/{chunk-QBJ22YZR.js → chunk-FH6F67DN.js} +1999 -277
  34. package/dist/chunk-FH6F67DN.js.map +1 -0
  35. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  36. package/dist/chunk-FPENXAEJ.js.map +1 -0
  37. package/dist/chunk-HLIMTC6N.js +1 -0
  38. package/dist/chunk-HLIMTC6N.js.map +1 -0
  39. package/dist/chunk-HRMEDT2L.js +1406 -0
  40. package/dist/chunk-HRMEDT2L.js.map +1 -0
  41. package/dist/{chunk-QGHGJ56O.js → chunk-IXHSYOVY.js} +2518 -122
  42. package/dist/chunk-IXHSYOVY.js.map +1 -0
  43. package/dist/chunk-MKA3AHLV.cjs +256 -0
  44. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  45. package/dist/chunk-NAXVVS5I.js +783 -0
  46. package/dist/chunk-NAXVVS5I.js.map +1 -0
  47. package/dist/chunk-O5RYH2PG.js +69 -0
  48. package/dist/chunk-O5RYH2PG.js.map +1 -0
  49. package/dist/chunk-OXSV64JX.js +689 -0
  50. package/dist/chunk-OXSV64JX.js.map +1 -0
  51. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  52. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  53. package/dist/chunk-P6ODPZ4W.js +256 -0
  54. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  55. package/dist/chunk-PL4JB3BF.cjs +1 -0
  56. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  57. package/dist/{chunk-GVSMRPHB.cjs → chunk-PO6A6QQH.cjs} +2607 -211
  58. package/dist/chunk-PO6A6QQH.cjs.map +1 -0
  59. package/dist/{chunk-JJDLPEWL.js → chunk-QGYDWPRM.js} +2 -2
  60. package/dist/chunk-RR7F5GUM.js +5726 -0
  61. package/dist/chunk-RR7F5GUM.js.map +1 -0
  62. package/dist/chunk-TNNJXF46.cjs +115 -0
  63. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  64. package/dist/chunk-U5HZSFCS.js +131 -0
  65. package/dist/chunk-U5HZSFCS.js.map +1 -0
  66. package/dist/{chunk-MJZBNWG7.js → chunk-UAKDG62Z.js} +309 -581
  67. package/dist/chunk-UAKDG62Z.js.map +1 -0
  68. package/dist/{chunk-CL37JGFW.cjs → chunk-V3CHHWOE.cjs} +4 -4
  69. package/dist/{chunk-CL37JGFW.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
  70. package/dist/chunk-WSQKHXW7.cjs +5726 -0
  71. package/dist/chunk-WSQKHXW7.cjs.map +1 -0
  72. package/dist/{chunk-AA4ZEVCC.cjs → chunk-X4N4WUKB.cjs} +336 -608
  73. package/dist/chunk-X4N4WUKB.cjs.map +1 -0
  74. package/dist/commands/index.cjs +74 -1
  75. package/dist/commands/index.cjs.map +1 -1
  76. package/dist/commands/index.d.cts +38 -353
  77. package/dist/commands/index.d.ts +38 -353
  78. package/dist/commands/index.js +73 -0
  79. package/dist/commands/index.js.map +1 -1
  80. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  81. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  82. package/dist/compare/index.cjs +15 -0
  83. package/dist/compare/index.cjs.map +1 -0
  84. package/dist/compare/index.d.cts +58 -0
  85. package/dist/compare/index.d.ts +58 -0
  86. package/dist/compare/index.js +15 -0
  87. package/dist/compare/index.js.map +1 -0
  88. package/dist/controller-BIJiNoVs.d.cts +1842 -0
  89. package/dist/controller-BIJiNoVs.d.ts +1842 -0
  90. package/dist/documents-CHT1U5Vs.d.ts +86 -0
  91. package/dist/documents-Gp7wb0Me.d.cts +86 -0
  92. package/dist/extensions/index.cjs +100 -5
  93. package/dist/extensions/index.cjs.map +1 -1
  94. package/dist/extensions/index.d.cts +16 -4
  95. package/dist/extensions/index.d.ts +16 -4
  96. package/dist/extensions/index.js +100 -5
  97. package/dist/generation/index.cjs +2317 -0
  98. package/dist/generation/index.cjs.map +1 -0
  99. package/dist/generation/index.d.cts +1015 -0
  100. package/dist/generation/index.d.ts +1015 -0
  101. package/dist/generation/index.js +2317 -0
  102. package/dist/generation/index.js.map +1 -0
  103. package/dist/grammar/index.cjs +48 -3
  104. package/dist/grammar/index.cjs.map +1 -1
  105. package/dist/grammar/index.d.cts +322 -100
  106. package/dist/grammar/index.d.ts +322 -100
  107. package/dist/grammar/index.js +54 -9
  108. package/dist/image-editor/index.cjs +4392 -481
  109. package/dist/image-editor/index.cjs.map +1 -1
  110. package/dist/image-editor/index.d.cts +1249 -97
  111. package/dist/image-editor/index.d.ts +1249 -97
  112. package/dist/image-editor/index.js +4281 -370
  113. package/dist/image-editor/index.js.map +1 -1
  114. package/dist/index-7a6bHTLy.d.ts +1754 -0
  115. package/dist/index-Csd5qI8u.d.cts +1754 -0
  116. package/dist/index.cjs +1682 -99
  117. package/dist/index.cjs.map +1 -1
  118. package/dist/index.d.cts +118 -21
  119. package/dist/index.d.ts +118 -21
  120. package/dist/index.js +1630 -47
  121. package/dist/index.js.map +1 -1
  122. package/dist/mention-text-CDnCFd3c.d.cts +53 -0
  123. package/dist/mention-text-CDnCFd3c.d.ts +53 -0
  124. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  125. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  126. package/dist/model-C1zApQM8.d.cts +219 -0
  127. package/dist/model-C1zApQM8.d.ts +219 -0
  128. package/dist/persistence/index.cjs +676 -0
  129. package/dist/persistence/index.cjs.map +1 -0
  130. package/dist/persistence/index.d.cts +230 -0
  131. package/dist/persistence/index.d.ts +230 -0
  132. package/dist/persistence/index.js +676 -0
  133. package/dist/persistence/index.js.map +1 -0
  134. package/dist/{registry-D5-R90p0.d.cts → registry-BDe-vlv3.d.ts} +2 -40
  135. package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.cts} +12 -1
  136. package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.ts} +12 -1
  137. package/dist/registry-D32LpIc4.d.cts +354 -0
  138. package/dist/{registry-D5-R90p0.d.ts → registry-DnzpgY27.d.cts} +2 -40
  139. package/dist/registry-evKTP4ls.d.ts +354 -0
  140. package/dist/schema-DYDGdYL9.d.cts +41 -0
  141. package/dist/schema-DYDGdYL9.d.ts +41 -0
  142. package/dist/serializers/index.cjs +12 -3
  143. package/dist/serializers/index.cjs.map +1 -1
  144. package/dist/serializers/index.d.cts +40 -12
  145. package/dist/serializers/index.d.ts +40 -12
  146. package/dist/serializers/index.js +12 -3
  147. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  148. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  149. package/dist/spreadsheet/index.cjs +161 -3
  150. package/dist/spreadsheet/index.cjs.map +1 -1
  151. package/dist/spreadsheet/index.d.cts +611 -20
  152. package/dist/spreadsheet/index.d.ts +611 -20
  153. package/dist/spreadsheet/index.js +168 -10
  154. package/dist/storage-BpFfspHm.d.cts +120 -0
  155. package/dist/storage-BpFfspHm.d.ts +120 -0
  156. package/dist/tokens/index.cjs +115 -0
  157. package/dist/tokens/index.cjs.map +1 -0
  158. package/dist/tokens/index.d.cts +212 -0
  159. package/dist/tokens/index.d.ts +212 -0
  160. package/dist/tokens/index.js +115 -0
  161. package/dist/tokens/index.js.map +1 -0
  162. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  163. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  164. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-D_VAPELi.d.cts} +110 -144
  165. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-Db_fGEvx.d.ts} +110 -144
  166. package/package.json +21 -1
  167. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  168. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  169. package/dist/chunk-AXV2ZW34.cjs +0 -118
  170. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  171. package/dist/chunk-B2ZRLN4S.js +0 -118
  172. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  173. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  174. package/dist/chunk-K3R5NG2D.js +0 -3100
  175. package/dist/chunk-K3R5NG2D.js.map +0 -1
  176. package/dist/chunk-MJZBNWG7.js.map +0 -1
  177. package/dist/chunk-OYXSKQFR.js.map +0 -1
  178. package/dist/chunk-QBJ22YZR.js.map +0 -1
  179. package/dist/chunk-QGHGJ56O.js.map +0 -1
  180. package/dist/chunk-RIKBJLS2.cjs.map +0 -1
  181. package/dist/chunk-XDMXXC4Z.cjs +0 -3100
  182. package/dist/chunk-XDMXXC4Z.cjs.map +0 -1
  183. package/dist/controller-pePCJLT1.d.cts +0 -959
  184. package/dist/controller-pePCJLT1.d.ts +0 -959
  185. package/dist/index-CCr_z9kF.d.cts +0 -899
  186. package/dist/index-Ck6ajwXh.d.ts +0 -899
  187. /package/dist/{chunk-JJDLPEWL.js.map → chunk-QGYDWPRM.js.map} +0 -0
@@ -0,0 +1,740 @@
1
+ import {
2
+ MENTION_REGEX,
3
+ NODE_ROLE_MARK,
4
+ formatMentionHandle,
5
+ readRoleSuffix
6
+ } from "./chunk-O5RYH2PG.js";
7
+ import {
8
+ BLOCK_CHANGE_ATTRIBUTE,
9
+ MOVE_ID_ATTRIBUTE,
10
+ resolveTrackedChanges
11
+ } from "./chunk-UAKDG62Z.js";
12
+
13
+ // src/serializers/plain-text.ts
14
+ import { DOMSerializer, Slice, Fragment, Node as ProsemirrorNode } from "@tiptap/pm/model";
15
+
16
+ // src/serializers/html-scan.ts
17
+ function findTagSpans(html, tag, attrTest, requireClose) {
18
+ const matches = typeof attrTest === "function" ? attrTest : (attrs) => attrTest.test(attrs);
19
+ const spans = [];
20
+ const openTag = new RegExp(`<${tag}\\b`, "gi");
21
+ const closeTag = new RegExp(`</${tag}>`, "gi");
22
+ const closeLength = tag.length + 3;
23
+ let nextGt = -1;
24
+ let nextClose = -1;
25
+ let from = 0;
26
+ for (; ; ) {
27
+ openTag.lastIndex = from;
28
+ const open = openTag.exec(html);
29
+ if (!open) break;
30
+ const start = open.index;
31
+ const attrsStart = start + open[0].length;
32
+ if (nextGt < attrsStart) {
33
+ nextGt = html.indexOf(">", attrsStart);
34
+ if (nextGt === -1) break;
35
+ }
36
+ const attrs = html.slice(attrsStart, nextGt);
37
+ const openEnd = nextGt + 1;
38
+ if (!matches(attrs)) {
39
+ from = attrsStart;
40
+ continue;
41
+ }
42
+ if (!requireClose) {
43
+ spans.push({ start, openEnd, end: openEnd, attrs });
44
+ from = openEnd;
45
+ continue;
46
+ }
47
+ if (nextClose < openEnd) {
48
+ closeTag.lastIndex = openEnd;
49
+ const close = closeTag.exec(html);
50
+ if (!close) break;
51
+ nextClose = close.index;
52
+ }
53
+ const end = nextClose + closeLength;
54
+ spans.push({ start, openEnd, end, attrs });
55
+ from = end;
56
+ }
57
+ return spans;
58
+ }
59
+ function replaceTagSpans(html, tag, attrTest, replace) {
60
+ const spans = findTagSpans(html, tag, attrTest, true);
61
+ if (spans.length === 0) return html;
62
+ let out = "";
63
+ let last = 0;
64
+ for (const span of spans) {
65
+ out += html.slice(last, span.start) + replace(html.slice(span.start, span.end), span.attrs);
66
+ last = span.end;
67
+ }
68
+ return out + html.slice(last);
69
+ }
70
+ function stripTags(html, replacement = "") {
71
+ let out = "";
72
+ let from = 0;
73
+ for (; ; ) {
74
+ const lt = html.indexOf("<", from);
75
+ if (lt === -1) break;
76
+ const gt = html.indexOf(">", lt + 1);
77
+ if (gt === -1) break;
78
+ if (gt === lt + 1) {
79
+ out += html.slice(from, gt + 1);
80
+ } else {
81
+ out += html.slice(from, lt) + replacement;
82
+ }
83
+ from = gt + 1;
84
+ }
85
+ return out + html.slice(from);
86
+ }
87
+ function replaceDelimited(text, open, close, replace = () => "", caseInsensitiveClose = false) {
88
+ const haystack = caseInsensitiveClose ? asciiLower(text) : text;
89
+ const needle = caseInsensitiveClose ? close.toLowerCase() : close;
90
+ let out = "";
91
+ let last = 0;
92
+ let from = 0;
93
+ let nextClose = -1;
94
+ for (; ; ) {
95
+ open.lastIndex = from;
96
+ const opened = open.exec(text);
97
+ if (!opened) break;
98
+ const afterOpen = opened.index + Math.max(opened[0].length, 1);
99
+ if (nextClose < afterOpen) {
100
+ nextClose = haystack.indexOf(needle, afterOpen);
101
+ if (nextClose === -1) break;
102
+ }
103
+ const end = nextClose + close.length;
104
+ out += text.slice(last, opened.index) + replace(text.slice(opened.index, end));
105
+ last = from = end;
106
+ }
107
+ return out + text.slice(last);
108
+ }
109
+ function asciiLower(text) {
110
+ return text.replace(/[A-Z]+/g, (m) => m.toLowerCase());
111
+ }
112
+
113
+ // src/serializers/plain-text.ts
114
+ var TRACKED_DELETION_ATTRIBUTE = /\bdata-change-type=["']deletion["']/i;
115
+ var TRACKED_INSERTION_ATTRIBUTE = /\bdata-change-type=["']insertion["']/i;
116
+ function stripTrackedChanges(html, view) {
117
+ if (view === "all" || !html.includes("data-change-type")) return html;
118
+ return view === "accepted" ? replaceTagSpans(html, "del", TRACKED_DELETION_ATTRIBUTE, () => "") : replaceTagSpans(html, "ins", TRACKED_INSERTION_ATTRIBUTE, () => "");
119
+ }
120
+ function escapeHtml(text) {
121
+ if (!text) return "";
122
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
123
+ }
124
+ var PARAGRAPH_HTML_REGEX = /^\s*<p[\s>][\s\S]*<\/p>\s*$/i;
125
+ function plainTextToTipTapHtml(text) {
126
+ if (!text) return "<p></p>";
127
+ if (PARAGRAPH_HTML_REGEX.test(text)) {
128
+ return text;
129
+ }
130
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => `<p>${escapeHtml(line)}</p>`).join("");
131
+ }
132
+ function plainTextToSlice(text, schema) {
133
+ const nodes = [];
134
+ text.replace(/\r\n?/g, "\n").split("\n").forEach((line) => {
135
+ const nodeJson = { type: "paragraph" };
136
+ if (line.length > 0) {
137
+ nodeJson.content = [{ type: "text", text: line }];
138
+ }
139
+ try {
140
+ nodes.push(ProsemirrorNode.fromJSON(schema, nodeJson));
141
+ } catch {
142
+ }
143
+ });
144
+ return Slice.maxOpen(Fragment.fromArray(nodes));
145
+ }
146
+ var BLOCK_TAGS = /* @__PURE__ */ new Set([
147
+ "P",
148
+ "DIV",
149
+ "LI",
150
+ "UL",
151
+ "OL",
152
+ "PRE",
153
+ "BLOCKQUOTE",
154
+ "TABLE",
155
+ "TR",
156
+ "H1",
157
+ "H2",
158
+ "H3",
159
+ "H4",
160
+ "H5",
161
+ "H6",
162
+ "HR"
163
+ ]);
164
+ var MENTION_TYPE_ATTRIBUTE = /\bdata-type=["']mention["']/i;
165
+ function getHtmlAttribute(attrs, name) {
166
+ const match = new RegExp(`\\b${name}=(?:"([^"]*)"|'([^']*)')`, "i").exec(
167
+ attrs
168
+ );
169
+ return match ? match[1] ?? match[2] : void 0;
170
+ }
171
+ function parseHtmlFragment(html) {
172
+ const template = document.createElement("template");
173
+ template.innerHTML = html;
174
+ return template.content;
175
+ }
176
+ function decodeHtmlEntities(text) {
177
+ return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#0*39;/g, "'").replace(/&nbsp;/g, "\xA0").replace(/&amp;/g, "&");
178
+ }
179
+ function htmlToPlainText(html, options = {}) {
180
+ if (!html) return "";
181
+ const trackedResolved = stripTrackedChanges(
182
+ html,
183
+ options.trackedChanges ?? "accepted"
184
+ );
185
+ const mentionNormalized = replaceTagSpans(trackedResolved, "span", MENTION_TYPE_ATTRIBUTE, (match, attrs) => {
186
+ const label = getHtmlAttribute(attrs, "data-label") || getHtmlAttribute(attrs, "data-id");
187
+ const role = getHtmlAttribute(attrs, "data-role");
188
+ const validRole = role && /^[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9])?$/.test(role) ? role : "";
189
+ return label ? `@${label}${validRole ? `:${validRole}` : ""}` : match;
190
+ });
191
+ if (typeof document !== "undefined") {
192
+ const fragment = parseHtmlFragment(mentionNormalized);
193
+ fragment.querySelectorAll("br.ProseMirror-trailingBreak").forEach((br) => br.remove());
194
+ const lines = [];
195
+ let current = null;
196
+ const flush = () => {
197
+ if (current !== null) {
198
+ lines.push(current);
199
+ current = null;
200
+ }
201
+ };
202
+ const visit = (node) => {
203
+ if (node.nodeType === 3) {
204
+ const value = node.nodeValue ?? "";
205
+ if (current === null && value.trim() === "") return;
206
+ current = (current ?? "") + value;
207
+ return;
208
+ }
209
+ if (node.nodeType !== 1) return;
210
+ const tag = node.tagName.toUpperCase();
211
+ if (tag === "BR") {
212
+ current = (current ?? "") + "\n";
213
+ return;
214
+ }
215
+ if (!BLOCK_TAGS.has(tag)) {
216
+ node.childNodes.forEach(visit);
217
+ return;
218
+ }
219
+ flush();
220
+ const linesBefore = lines.length;
221
+ node.childNodes.forEach(visit);
222
+ flush();
223
+ if (lines.length === linesBefore && tag !== "HR") {
224
+ lines.push("");
225
+ }
226
+ };
227
+ fragment.childNodes.forEach(visit);
228
+ flush();
229
+ return lines.join("\n");
230
+ }
231
+ const text = mentionNormalized.replace(/<br\s*\/?>/gi, "\n").replace(
232
+ /<\/(?:p|div|li|pre|blockquote|h[1-6])>(?:\s*<\/(?:li|ul|ol|blockquote|div)>)*/gi,
233
+ "\n"
234
+ );
235
+ return decodeHtmlEntities(stripTags(text)).replace(/\n$/, "");
236
+ }
237
+ function resolvedBlockOperationsHtml(editor, view) {
238
+ const doc = editor?.state?.doc;
239
+ if (!doc || view === "all" || typeof document === "undefined") return null;
240
+ let found = false;
241
+ doc.descendants((node) => {
242
+ if (found) return false;
243
+ if (node.isTextblock) {
244
+ if (node.attrs?.[BLOCK_CHANGE_ATTRIBUTE]?.operation) found = true;
245
+ else node.forEach((child) => {
246
+ if (child.marks.some((mark) => mark.attrs?.[MOVE_ID_ATTRIBUTE])) found = true;
247
+ });
248
+ return false;
249
+ }
250
+ return true;
251
+ });
252
+ if (!found) return null;
253
+ const resolved = resolveTrackedChanges(doc, view);
254
+ const container = document.createElement("div");
255
+ container.appendChild(DOMSerializer.fromSchema(doc.type.schema).serializeFragment(resolved.content));
256
+ return container.innerHTML;
257
+ }
258
+ function getEditorText(editor, options = {}) {
259
+ if (!editor) return "";
260
+ const html = resolvedBlockOperationsHtml(editor, options.trackedChanges ?? "accepted") ?? (typeof editor.getHTML === "function" ? editor.getHTML() : "");
261
+ if (html) {
262
+ return htmlToPlainText(html, options);
263
+ }
264
+ if (typeof editor.getText === "function") {
265
+ try {
266
+ return editor.getText({ blockSeparator: "\n" });
267
+ } catch {
268
+ return editor.getText();
269
+ }
270
+ }
271
+ return "";
272
+ }
273
+ function extractMentionsFromDoc(docOrEditor) {
274
+ if (!docOrEditor) return [];
275
+ const mentions = [];
276
+ const doc = docOrEditor?.state?.doc || (typeof docOrEditor?.descendants === "function" ? docOrEditor : null);
277
+ if (doc && typeof doc.descendants === "function") {
278
+ doc.descendants((node) => {
279
+ if (node.type?.name === "mention" && node.attrs) {
280
+ mentions.push({
281
+ id: node.attrs.id || "",
282
+ label: node.attrs.label || "",
283
+ type: node.attrs.type,
284
+ avatarUrl: node.attrs.avatarUrl,
285
+ color: node.attrs.color,
286
+ ...node.attrs,
287
+ ...node.attrs.assetRole ? { role: node.attrs.assetRole } : {}
288
+ });
289
+ }
290
+ });
291
+ return mentions;
292
+ }
293
+ if (typeof docOrEditor === "object" && docOrEditor.content) {
294
+ const walk = (nodes) => {
295
+ for (const node of nodes) {
296
+ if (node.type === "mention" && node.attrs) {
297
+ mentions.push({
298
+ id: node.attrs.id || "",
299
+ label: node.attrs.label || "",
300
+ type: node.attrs.type,
301
+ avatarUrl: node.attrs.avatarUrl,
302
+ color: node.attrs.color,
303
+ ...node.attrs,
304
+ ...node.attrs.assetRole ? { role: node.attrs.assetRole } : {}
305
+ });
306
+ }
307
+ if (Array.isArray(node.content)) {
308
+ walk(node.content);
309
+ }
310
+ }
311
+ };
312
+ walk(docOrEditor.content);
313
+ return mentions;
314
+ }
315
+ if (typeof docOrEditor === "string") {
316
+ if (typeof document !== "undefined") {
317
+ parseHtmlFragment(docOrEditor).querySelectorAll('span[data-type="mention"]').forEach((el) => {
318
+ mentions.push({
319
+ id: el.getAttribute("data-id") || "",
320
+ label: el.getAttribute("data-label") || "",
321
+ type: el.getAttribute("data-type-name") || void 0,
322
+ avatarUrl: el.getAttribute("data-avatar-url") || void 0,
323
+ color: el.getAttribute("data-color") || void 0,
324
+ ...el.getAttribute("data-role") ? { role: el.getAttribute("data-role") } : {}
325
+ });
326
+ });
327
+ } else {
328
+ for (const span of findTagSpans(docOrEditor, "span", MENTION_TYPE_ATTRIBUTE, false)) {
329
+ const attrStr = span.attrs;
330
+ const getAttr = (name) => {
331
+ const m = new RegExp(`${name}=["']([^"']*)["']`, "i").exec(attrStr);
332
+ return m ? m[1] : void 0;
333
+ };
334
+ mentions.push({
335
+ id: getAttr("data-id") || "",
336
+ label: getAttr("data-label") || "",
337
+ type: getAttr("data-type-name") || getAttr("data-entity-type"),
338
+ avatarUrl: getAttr("data-avatar-url"),
339
+ color: getAttr("data-color"),
340
+ ...getAttr("data-role") ? { role: getAttr("data-role") } : {}
341
+ });
342
+ }
343
+ }
344
+ if (mentions.length === 0) {
345
+ const rawHandles = extractMentions(docOrEditor);
346
+ for (const handle of rawHandles) {
347
+ mentions.push({
348
+ id: handle,
349
+ label: handle,
350
+ type: "user"
351
+ });
352
+ }
353
+ }
354
+ }
355
+ return mentions;
356
+ }
357
+
358
+ // src/serializers/mentions.ts
359
+ 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;
360
+ function stripMarkdownCode(content) {
361
+ if (!content || typeof content !== "string") return "";
362
+ let text = replaceDelimited(content, /```/g, "```");
363
+ text = replaceDelimited(text, /~~~/g, "~~~");
364
+ text = replaceDelimited(text, /<pre/gi, "</pre>", void 0, true);
365
+ text = replaceDelimited(text, /<code/gi, "</code>", void 0, true);
366
+ return text.replace(/`[^`\n]*`/g, "");
367
+ }
368
+ function isMentionNodeAttributes(attrs) {
369
+ if (/\bdata-type=["']mention["']/i.test(attrs)) return true;
370
+ const classAttr = /\bclass=(["'])/i.exec(attrs);
371
+ if (!classAttr) return false;
372
+ const valueStart = classAttr.index + classAttr[0].length;
373
+ const valueEnd = attrs.indexOf(classAttr[1], valueStart);
374
+ return valueEnd !== -1 && attrs.slice(valueStart, valueEnd).includes("pixerate-mention-node");
375
+ }
376
+ function extractMentions(content, options = {}) {
377
+ if (!content || typeof content !== "string") return [];
378
+ const details = options.details === true;
379
+ let normalizedMentionNodes = "";
380
+ let last = 0;
381
+ for (const span of findTagSpans(content, "span", isMentionNodeAttributes, true)) {
382
+ const labelMatch = /\bdata-label=["']([^"']+)["']/i.exec(span.attrs);
383
+ const idMatch = labelMatch ? null : /\bdata-id=["']([^"']+)["']/i.exec(span.attrs);
384
+ const inner = content.slice(span.openEnd, span.end - "</span>".length);
385
+ let replacement = labelMatch ? ` @${labelMatch[1]} ` : idMatch ? ` @${idMatch[1]} ` : ` ${inner} `;
386
+ if (details && (labelMatch || idMatch)) {
387
+ const roleMatch = /\bdata-role=["']([^"']+)["']/i.exec(span.attrs);
388
+ const role = roleMatch && /^[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9])?$/.test(roleMatch[1]) ? roleMatch[1] : null;
389
+ const label = (labelMatch ?? idMatch)[1];
390
+ replacement = ` ${formatMentionHandle(label)}${role ? NODE_ROLE_MARK + role : ""} `;
391
+ }
392
+ normalizedMentionNodes += content.slice(last, span.start) + replacement;
393
+ last = span.end;
394
+ }
395
+ normalizedMentionNodes += content.slice(last);
396
+ const cleanContent = stripMarkdownCode(normalizedMentionNodes);
397
+ const withoutUrls = cleanContent.replace(/(?:https?|ftp|file|vscode|cursor|mailto):\/\/[^\s<>()]+/gi, "");
398
+ const withoutLinks = replaceDelimited(withoutUrls, /\]\(/g, ")", () => "]");
399
+ const textOnly = stripTags(withoutLinks, " ");
400
+ const mentions = [];
401
+ const detailed = [];
402
+ const seen = /* @__PURE__ */ new Set();
403
+ const regex = new RegExp(MENTION_REGEX.source, "g");
404
+ let match;
405
+ while ((match = regex.exec(textOnly)) !== null) {
406
+ const handle = (match[1] ?? match[2] ?? match[3] ?? "").trim();
407
+ if (details) {
408
+ const suffix = readRoleSuffix(textOnly, regex.lastIndex, options.roles);
409
+ if (suffix) regex.lastIndex = suffix.end;
410
+ const key = `${handle}\0${suffix?.role ?? ""}`;
411
+ if (handle && !seen.has(key)) {
412
+ seen.add(key);
413
+ detailed.push(suffix ? { handle, role: suffix.role } : { handle });
414
+ }
415
+ continue;
416
+ }
417
+ if (handle && !seen.has(handle)) {
418
+ seen.add(handle);
419
+ mentions.push(handle);
420
+ }
421
+ }
422
+ return details ? detailed : mentions;
423
+ }
424
+ function parseMentionSegments(content, options = {}) {
425
+ if (!content) return [];
426
+ const segments = [];
427
+ const regex = new RegExp(MENTION_REGEX.source, "g");
428
+ let lastIndex = 0;
429
+ let match;
430
+ while ((match = regex.exec(content)) !== null) {
431
+ const fullMatch = match[0];
432
+ const atIndex = fullMatch.indexOf("@");
433
+ const prefix = atIndex > 0 ? fullMatch.slice(0, atIndex) : "";
434
+ let mentionToken = fullMatch.slice(atIndex);
435
+ const handle = match[1] ?? match[2] ?? match[3];
436
+ const matchStart = match.index + prefix.length;
437
+ const suffix = options.roles && content.charAt(regex.lastIndex) === ":" ? readRoleSuffix(content, regex.lastIndex, options.roles) : null;
438
+ if (suffix) {
439
+ mentionToken = content.slice(matchStart, suffix.end);
440
+ regex.lastIndex = suffix.end;
441
+ }
442
+ if (matchStart > lastIndex) {
443
+ segments.push({
444
+ type: "text",
445
+ value: content.slice(lastIndex, matchStart)
446
+ });
447
+ }
448
+ segments.push({
449
+ type: "mention",
450
+ value: mentionToken,
451
+ handle,
452
+ ...suffix ? { role: suffix.role } : {}
453
+ });
454
+ lastIndex = matchStart + mentionToken.length;
455
+ }
456
+ if (lastIndex < content.length) {
457
+ segments.push({
458
+ type: "text",
459
+ value: content.slice(lastIndex)
460
+ });
461
+ }
462
+ return segments;
463
+ }
464
+ function preprocessMarkdownMentions(content, optionsOrMentionables = []) {
465
+ if (!content || typeof content !== "string") return "";
466
+ const options = Array.isArray(optionsOrMentionables) ? { mentionables: optionsOrMentionables } : optionsOrMentionables;
467
+ const allMentionables = options.mentionables || [];
468
+ const defaultType = options.defaultType || "user";
469
+ const resolveMention = options.resolveMention;
470
+ const parts = content.split(MARKDOWN_MENTION_SPLIT_REGEX);
471
+ return parts.map((part) => {
472
+ if (!part) return "";
473
+ 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(
474
+ part
475
+ )) {
476
+ return part;
477
+ }
478
+ const regex = new RegExp(MENTION_REGEX.source, "g");
479
+ const render = (match2, quotedHandle, escapedQuotedHandle, standardHandle, role) => {
480
+ const atIndex = match2.indexOf("@");
481
+ const prefix = atIndex > 0 ? match2.slice(0, atIndex) : "";
482
+ const rawHandle = (quotedHandle || escapedQuotedHandle || standardHandle || "").trim();
483
+ if (!rawHandle) return match2;
484
+ const lowerHandle = rawHandle.toLowerCase();
485
+ const entity = allMentionables.find((e) => {
486
+ if (e.label?.toLowerCase() === lowerHandle) return true;
487
+ if (e.handle?.toLowerCase() === lowerHandle) return true;
488
+ if (e.name?.toLowerCase() === lowerHandle) return true;
489
+ if (e.id?.toLowerCase() === lowerHandle) return true;
490
+ if (e.type === "agent" && `agent${(e.handle || e.label || "").toLowerCase()}` === lowerHandle) return true;
491
+ if (e.aliases?.some(
492
+ (a) => a.toLowerCase() === lowerHandle || e.type === "agent" && `agent${a.toLowerCase()}` === lowerHandle
493
+ )) {
494
+ return true;
495
+ }
496
+ return false;
497
+ });
498
+ let id = entity?.id;
499
+ let label = entity?.label || entity?.handle || rawHandle;
500
+ let type = entity?.type;
501
+ let avatarUrl = entity?.avatarUrl;
502
+ let color = entity?.color || entity?.hexColor;
503
+ if (!entity) {
504
+ const customResolved = resolveMention?.(rawHandle);
505
+ if (customResolved) {
506
+ id = customResolved.id ?? id;
507
+ label = customResolved.label ?? customResolved.handle ?? label;
508
+ type = customResolved.type ?? type;
509
+ avatarUrl = customResolved.avatarUrl ?? avatarUrl;
510
+ color = customResolved.color ?? customResolved.hexColor ?? color;
511
+ } else {
512
+ const stripped = lowerHandle.replace(/^agent[\s\-_]*/i, "");
513
+ if (["supervisor", "coordinator", "planner", "validator", "executor"].includes(stripped)) {
514
+ type = "agent";
515
+ id = stripped;
516
+ label = stripped;
517
+ } else if (lowerHandle === "agents") {
518
+ type = "team";
519
+ id = "agents";
520
+ label = "agents";
521
+ } else {
522
+ type = defaultType;
523
+ id = rawHandle;
524
+ label = rawHandle;
525
+ }
526
+ }
527
+ }
528
+ const avatarAttr = avatarUrl ? ` data-avatar-url="${escapeHtml(avatarUrl)}"` : "";
529
+ const colorAttr = color ? ` data-color="${escapeHtml(color)}"` : "";
530
+ return `${prefix}<span class="pixerate-mention-node" data-type="mention" data-id="${escapeHtml(
531
+ id || label
532
+ )}" data-label="${escapeHtml(label)}" data-mention-suggestion-char="@" data-type-name="${escapeHtml(
533
+ type || defaultType
534
+ )}"${avatarAttr}${colorAttr}${role ? ` data-role="${escapeHtml(role)}"` : ""}>@${escapeHtml(label)}</span>`;
535
+ };
536
+ if (!options.roles) {
537
+ return part.replace(
538
+ regex,
539
+ (match2, quotedHandle, escapedQuotedHandle, standardHandle) => render(match2, quotedHandle, escapedQuotedHandle, standardHandle)
540
+ );
541
+ }
542
+ let out = "";
543
+ let last = 0;
544
+ let match;
545
+ while ((match = regex.exec(part)) !== null) {
546
+ const suffix = readRoleSuffix(part, regex.lastIndex, options.roles);
547
+ const rendered = render(match[0], match[1], match[2], match[3], suffix?.role);
548
+ if (suffix && rendered !== match[0]) regex.lastIndex = suffix.end;
549
+ out += part.slice(last, match.index) + rendered;
550
+ last = regex.lastIndex;
551
+ }
552
+ return out + part.slice(last);
553
+ }).join("");
554
+ }
555
+
556
+ // src/serializers/markdown.ts
557
+ import MarkdownIt from "markdown-it";
558
+ import taskLists from "markdown-it-task-lists";
559
+ var md = new MarkdownIt({
560
+ html: true,
561
+ linkify: true,
562
+ breaks: true
563
+ }).use(taskLists);
564
+ var defaultValidateLink = md.validateLink;
565
+ md.validateLink = (url) => {
566
+ if (url.startsWith("file://") || url.startsWith("vscode://") || url.startsWith("cursor://")) {
567
+ return true;
568
+ }
569
+ return defaultValidateLink.call(md, url);
570
+ };
571
+ var ALLOWED_HTML_TAGS = /* @__PURE__ */ new Set([
572
+ "a",
573
+ "abbr",
574
+ "b",
575
+ "blockquote",
576
+ "br",
577
+ "code",
578
+ "del",
579
+ "details",
580
+ "div",
581
+ "em",
582
+ "h1",
583
+ "h2",
584
+ "h3",
585
+ "h4",
586
+ "h5",
587
+ "h6",
588
+ "hr",
589
+ "i",
590
+ "img",
591
+ "input",
592
+ "kbd",
593
+ "li",
594
+ "mark",
595
+ "ol",
596
+ "p",
597
+ "pre",
598
+ "s",
599
+ "span",
600
+ "strong",
601
+ "sub",
602
+ "summary",
603
+ "sup",
604
+ "table",
605
+ "tbody",
606
+ "td",
607
+ "tfoot",
608
+ "th",
609
+ "thead",
610
+ "tr",
611
+ "u",
612
+ "ul"
613
+ ]);
614
+ var ALLOWED_HTML_ATTRS = /* @__PURE__ */ new Set([
615
+ "alt",
616
+ "align",
617
+ "checked",
618
+ "class",
619
+ "colspan",
620
+ "disabled",
621
+ "height",
622
+ "href",
623
+ "rel",
624
+ "rowspan",
625
+ "src",
626
+ "start",
627
+ "target",
628
+ "title",
629
+ "type",
630
+ "width"
631
+ ]);
632
+ var HTML_TAG_REGEX = /<(\/?)([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^\s"'>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?)*)\s*\/?>/g;
633
+ var HTML_ATTR_REGEX = /([^\s"'>\/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
634
+ function sanitizeTag(tagText, isClosing, rawTagName, rawAttrs, stripDisallowed) {
635
+ const tagName = rawTagName.toLowerCase();
636
+ const reject = () => stripDisallowed ? "" : escapeHtml(tagText);
637
+ if (!ALLOWED_HTML_TAGS.has(tagName)) return reject();
638
+ if (isClosing) return `</${tagName}>`;
639
+ if (tagName === "input" && !/\stype\s*=\s*["']?checkbox["']?[\s>/]/i.test(tagText)) {
640
+ return reject();
641
+ }
642
+ let attrs = "";
643
+ let attrMatch;
644
+ HTML_ATTR_REGEX.lastIndex = 0;
645
+ while ((attrMatch = HTML_ATTR_REGEX.exec(rawAttrs)) !== null) {
646
+ const name = attrMatch[1].toLowerCase();
647
+ if (!ALLOWED_HTML_ATTRS.has(name) && !/^data-[a-z0-9_.-]+$/.test(name)) {
648
+ continue;
649
+ }
650
+ const rawValue = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4];
651
+ if (rawValue === void 0) {
652
+ attrs += ` ${name}`;
653
+ continue;
654
+ }
655
+ const value = md.utils.unescapeAll(rawValue);
656
+ if ((name === "href" || name === "src") && // Browsers ignore control characters and whitespace inside schemes.
657
+ !md.validateLink(value.replace(/[\u0000-\u0020\u007f]/g, ""))) {
658
+ continue;
659
+ }
660
+ attrs += ` ${name}="${escapeHtml(value)}"`;
661
+ }
662
+ return `<${tagName}${attrs}>`;
663
+ }
664
+ function sanitizeHtml(html, options = {}) {
665
+ return sanitizeEmbeddedHtml(html, options.disallowedTags === "strip");
666
+ }
667
+ function sanitizeEmbeddedHtml(html, stripDisallowed = false) {
668
+ let result = "";
669
+ let lastIndex = 0;
670
+ let match;
671
+ HTML_TAG_REGEX.lastIndex = 0;
672
+ while ((match = HTML_TAG_REGEX.exec(html)) !== null) {
673
+ result += html.slice(lastIndex, match.index).replace(/</g, "&lt;");
674
+ result += sanitizeTag(match[0], match[1], match[2], match[3], stripDisallowed);
675
+ lastIndex = match.index + match[0].length;
676
+ }
677
+ return result + html.slice(lastIndex).replace(/</g, "&lt;");
678
+ }
679
+ var defaultHtmlInline = md.renderer.rules.html_inline;
680
+ var defaultHtmlBlock = md.renderer.rules.html_block;
681
+ md.renderer.rules.html_inline = (tokens, idx, options, env, self) => env?.allowUnsafeHtml ? defaultHtmlInline(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
682
+ md.renderer.rules.html_block = (tokens, idx, options, env, self) => env?.allowUnsafeHtml ? defaultHtmlBlock(tokens, idx, options, env, self) : sanitizeEmbeddedHtml(tokens[idx].content);
683
+ function preprocessMarkdownFileLinks(content) {
684
+ if (!content) return "";
685
+ return content.replace(
686
+ /\[([^\]]+)\]\(((?:file|vscode|cursor):\/\/[^)]+)\)/g,
687
+ (_match, rawLabel, href) => {
688
+ const trimmed = rawLabel.trim();
689
+ const codeMatch = trimmed.match(/^`([^`]+)`$/);
690
+ const labelContent = codeMatch ? `<code>${escapeHtml(codeMatch[1])}</code>` : escapeHtml(trimmed);
691
+ return `<a href="${escapeHtml(href)}" data-file-link="true" title="Click to copy file path">${labelContent}</a>`;
692
+ }
693
+ );
694
+ }
695
+ function markdownToTipTapHtml(markdown, options) {
696
+ if (!markdown) return "<p></p>";
697
+ let content = markdown;
698
+ if (options?.preprocessFileLinks) {
699
+ content = preprocessMarkdownFileLinks(content);
700
+ }
701
+ if (options?.preprocessMentions || options?.mentionables || options?.preprocessOptions) {
702
+ const mentionOpts = options.preprocessOptions || {
703
+ mentionables: options.mentionables
704
+ };
705
+ content = preprocessMarkdownMentions(content, mentionOpts);
706
+ }
707
+ return md.render(content, { allowUnsafeHtml: options?.allowUnsafeHtml });
708
+ }
709
+ function getEditorMarkdown(editor, options = {}) {
710
+ if (!editor) return "";
711
+ const markdown = editor.storage?.markdown;
712
+ if (typeof markdown?.getMarkdown === "function") {
713
+ const doc = editor.state?.doc;
714
+ if (doc && typeof markdown.serializer?.serialize === "function") {
715
+ const resolved = resolveTrackedChanges(doc, options.trackedChanges ?? "accepted");
716
+ if (resolved !== doc) return markdown.serializer.serialize(resolved);
717
+ }
718
+ return markdown.getMarkdown();
719
+ }
720
+ return getEditorText(editor, options);
721
+ }
722
+
723
+ export {
724
+ MARKDOWN_MENTION_SPLIT_REGEX,
725
+ stripMarkdownCode,
726
+ extractMentions,
727
+ parseMentionSegments,
728
+ preprocessMarkdownMentions,
729
+ escapeHtml,
730
+ plainTextToTipTapHtml,
731
+ plainTextToSlice,
732
+ htmlToPlainText,
733
+ getEditorText,
734
+ extractMentionsFromDoc,
735
+ sanitizeHtml,
736
+ preprocessMarkdownFileLinks,
737
+ markdownToTipTapHtml,
738
+ getEditorMarkdown
739
+ };
740
+ //# sourceMappingURL=chunk-ECCCYKGL.js.map