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