@particle-academy/react-fancy 5.60.0 → 5.60.2
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/CHANGELOG.md +56 -0
- package/dist/chunk-L24LUSEE.js +882 -0
- package/dist/chunk-L24LUSEE.js.map +1 -0
- package/dist/chunk-MCQJFMDP.cjs +893 -0
- package/dist/chunk-MCQJFMDP.cjs.map +1 -0
- package/dist/{chunk-ZASX5GO4.js → chunk-VD3C7IA4.js} +14 -13
- package/dist/chunk-VD3C7IA4.js.map +1 -0
- package/dist/{chunk-ICI33QMY.cjs → chunk-XAQQX7J2.cjs} +18 -17
- package/dist/chunk-XAQQX7J2.cjs.map +1 -0
- package/dist/content-renderer.cjs +4 -4
- package/dist/content-renderer.js +1 -1
- package/dist/editor.cjs +4 -4
- package/dist/editor.js +2 -2
- package/dist/index.cjs +8 -8
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-5IWKZ2WK.cjs +0 -360
- package/dist/chunk-5IWKZ2WK.cjs.map +0 -1
- package/dist/chunk-ICI33QMY.cjs.map +0 -1
- package/dist/chunk-JXXUTPDH.js +0 -350
- package/dist/chunk-JXXUTPDH.js.map +0 -1
- package/dist/chunk-ZASX5GO4.js.map +0 -1
|
@@ -0,0 +1,893 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkX2FC7ODX_cjs = require('./chunk-X2FC7ODX.cjs');
|
|
4
|
+
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
5
|
+
var marked = require('marked');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
// src/components/ContentRenderer/extensions.ts
|
|
10
|
+
var globalRegistry = [];
|
|
11
|
+
function registerExtension(extension) {
|
|
12
|
+
const idx = globalRegistry.findIndex(
|
|
13
|
+
(e) => e.tag.toLowerCase() === extension.tag.toLowerCase()
|
|
14
|
+
);
|
|
15
|
+
if (idx >= 0) {
|
|
16
|
+
globalRegistry[idx] = extension;
|
|
17
|
+
} else {
|
|
18
|
+
globalRegistry.push(extension);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function registerExtensions(extensions) {
|
|
22
|
+
for (const ext of extensions) {
|
|
23
|
+
registerExtension(ext);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function getGlobalExtensions() {
|
|
27
|
+
return [...globalRegistry];
|
|
28
|
+
}
|
|
29
|
+
function parseAttributes(attrString) {
|
|
30
|
+
const attrs = {};
|
|
31
|
+
const re = /(\w[\w-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/g;
|
|
32
|
+
let m;
|
|
33
|
+
while ((m = re.exec(attrString)) !== null) {
|
|
34
|
+
attrs[m[1]] = m[2] ?? m[3] ?? m[4] ?? "";
|
|
35
|
+
}
|
|
36
|
+
return attrs;
|
|
37
|
+
}
|
|
38
|
+
function parseSegments(html, extensions) {
|
|
39
|
+
if (extensions.length === 0) {
|
|
40
|
+
return html ? [{ type: "html", content: html }] : [];
|
|
41
|
+
}
|
|
42
|
+
const tagNames = extensions.map((e) => e.tag).join("|");
|
|
43
|
+
const pattern = new RegExp(
|
|
44
|
+
`<(${tagNames})((?:\\s+[^>]*)?)>([\\s\\S]*?)<\\/\\1>`,
|
|
45
|
+
"gi"
|
|
46
|
+
);
|
|
47
|
+
const segments = [];
|
|
48
|
+
let lastIndex = 0;
|
|
49
|
+
let match;
|
|
50
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
51
|
+
if (match.index > lastIndex) {
|
|
52
|
+
segments.push({ type: "html", content: html.slice(lastIndex, match.index) });
|
|
53
|
+
}
|
|
54
|
+
const tag = match[1].toLowerCase();
|
|
55
|
+
const rawAttrs = match[2] ? match[2].trim() : "";
|
|
56
|
+
const innerContent = match[3];
|
|
57
|
+
segments.push({
|
|
58
|
+
type: "extension",
|
|
59
|
+
tag,
|
|
60
|
+
content: innerContent,
|
|
61
|
+
attributes: rawAttrs ? parseAttributes(rawAttrs) : {}
|
|
62
|
+
});
|
|
63
|
+
lastIndex = match.index + match[0].length;
|
|
64
|
+
}
|
|
65
|
+
if (lastIndex < html.length) {
|
|
66
|
+
segments.push({ type: "html", content: html.slice(lastIndex) });
|
|
67
|
+
}
|
|
68
|
+
return segments;
|
|
69
|
+
}
|
|
70
|
+
function mergeExtensions(instanceExtensions) {
|
|
71
|
+
const globals = getGlobalExtensions();
|
|
72
|
+
if (!instanceExtensions || instanceExtensions.length === 0) return globals;
|
|
73
|
+
if (globals.length === 0) return instanceExtensions;
|
|
74
|
+
const merged = [...globals];
|
|
75
|
+
for (const ext of instanceExtensions) {
|
|
76
|
+
const idx = merged.findIndex(
|
|
77
|
+
(e) => e.tag.toLowerCase() === ext.tag.toLowerCase()
|
|
78
|
+
);
|
|
79
|
+
if (idx >= 0) {
|
|
80
|
+
merged[idx] = ext;
|
|
81
|
+
} else {
|
|
82
|
+
merged.push(ext);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return merged;
|
|
86
|
+
}
|
|
87
|
+
function markdownToRawHtml(markdown) {
|
|
88
|
+
return marked.marked.parse(markdown ?? "", { async: false });
|
|
89
|
+
}
|
|
90
|
+
function renderMarkdown(markdown, sanitize) {
|
|
91
|
+
return chunkX2FC7ODX_cjs.sanitizeHtml(markdownToRawHtml(markdown), sanitize);
|
|
92
|
+
}
|
|
93
|
+
var proseClasses = [
|
|
94
|
+
"[&_h1]:text-2xl [&_h1]:font-bold [&_h1]:mt-4 [&_h1]:mb-2",
|
|
95
|
+
"[&_h2]:text-xl [&_h2]:font-semibold [&_h2]:mt-3 [&_h2]:mb-2",
|
|
96
|
+
"[&_h3]:text-lg [&_h3]:font-semibold [&_h3]:mt-2 [&_h3]:mb-1",
|
|
97
|
+
"[&_p]:mb-2",
|
|
98
|
+
"[&_a]:text-blue-500 [&_a]:underline",
|
|
99
|
+
"[&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5",
|
|
100
|
+
"[&_li]:mb-1",
|
|
101
|
+
"[&_blockquote]:border-l-4 [&_blockquote]:border-zinc-300 [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] dark:[&_blockquote]:border-zinc-600 dark:[&_blockquote]:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))]",
|
|
102
|
+
"[&_code]:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] [&_code]:px-1 [&_code]:rounded [&_code]:text-sm dark:[&_code]:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]",
|
|
103
|
+
"[&_pre]:bg-zinc-950 [&_pre]:text-zinc-100 [&_pre]:p-4 [&_pre]:rounded-lg [&_pre]:overflow-x-auto",
|
|
104
|
+
"[&_pre_code]:bg-transparent [&_pre_code]:px-0",
|
|
105
|
+
"[&_strong]:font-bold [&_em]:italic"
|
|
106
|
+
].join(" ");
|
|
107
|
+
var HTML_TAG_PATTERN = /<(p|div|br|h[1-6]|ul|ol|strong|em|a |img |table|pre|code|blockquote)[>\s/]/i;
|
|
108
|
+
function detectFormat(value) {
|
|
109
|
+
return HTML_TAG_PATTERN.test(value) ? "html" : "markdown";
|
|
110
|
+
}
|
|
111
|
+
var STANDARD_HTML_TAGS = /* @__PURE__ */ new Set([
|
|
112
|
+
"a",
|
|
113
|
+
"abbr",
|
|
114
|
+
"address",
|
|
115
|
+
"area",
|
|
116
|
+
"article",
|
|
117
|
+
"aside",
|
|
118
|
+
"audio",
|
|
119
|
+
"b",
|
|
120
|
+
"base",
|
|
121
|
+
"bdi",
|
|
122
|
+
"bdo",
|
|
123
|
+
"blockquote",
|
|
124
|
+
"body",
|
|
125
|
+
"br",
|
|
126
|
+
"button",
|
|
127
|
+
"canvas",
|
|
128
|
+
"caption",
|
|
129
|
+
"cite",
|
|
130
|
+
"code",
|
|
131
|
+
"col",
|
|
132
|
+
"colgroup",
|
|
133
|
+
"data",
|
|
134
|
+
"datalist",
|
|
135
|
+
"dd",
|
|
136
|
+
"del",
|
|
137
|
+
"details",
|
|
138
|
+
"dfn",
|
|
139
|
+
"dialog",
|
|
140
|
+
"div",
|
|
141
|
+
"dl",
|
|
142
|
+
"dt",
|
|
143
|
+
"em",
|
|
144
|
+
"embed",
|
|
145
|
+
"fieldset",
|
|
146
|
+
"figcaption",
|
|
147
|
+
"figure",
|
|
148
|
+
"footer",
|
|
149
|
+
"form",
|
|
150
|
+
"h1",
|
|
151
|
+
"h2",
|
|
152
|
+
"h3",
|
|
153
|
+
"h4",
|
|
154
|
+
"h5",
|
|
155
|
+
"h6",
|
|
156
|
+
"head",
|
|
157
|
+
"header",
|
|
158
|
+
"hgroup",
|
|
159
|
+
"hr",
|
|
160
|
+
"html",
|
|
161
|
+
"i",
|
|
162
|
+
"iframe",
|
|
163
|
+
"img",
|
|
164
|
+
"input",
|
|
165
|
+
"ins",
|
|
166
|
+
"kbd",
|
|
167
|
+
"label",
|
|
168
|
+
"legend",
|
|
169
|
+
"li",
|
|
170
|
+
"link",
|
|
171
|
+
"main",
|
|
172
|
+
"map",
|
|
173
|
+
"mark",
|
|
174
|
+
"menu",
|
|
175
|
+
"meta",
|
|
176
|
+
"meter",
|
|
177
|
+
"nav",
|
|
178
|
+
"noscript",
|
|
179
|
+
"object",
|
|
180
|
+
"ol",
|
|
181
|
+
"optgroup",
|
|
182
|
+
"option",
|
|
183
|
+
"output",
|
|
184
|
+
"p",
|
|
185
|
+
"param",
|
|
186
|
+
"picture",
|
|
187
|
+
"pre",
|
|
188
|
+
"progress",
|
|
189
|
+
"q",
|
|
190
|
+
"rp",
|
|
191
|
+
"rt",
|
|
192
|
+
"ruby",
|
|
193
|
+
"s",
|
|
194
|
+
"samp",
|
|
195
|
+
"script",
|
|
196
|
+
"section",
|
|
197
|
+
"select",
|
|
198
|
+
"slot",
|
|
199
|
+
"small",
|
|
200
|
+
"source",
|
|
201
|
+
"span",
|
|
202
|
+
"strike",
|
|
203
|
+
"strong",
|
|
204
|
+
"style",
|
|
205
|
+
"sub",
|
|
206
|
+
"summary",
|
|
207
|
+
"sup",
|
|
208
|
+
"table",
|
|
209
|
+
"tbody",
|
|
210
|
+
"td",
|
|
211
|
+
"template",
|
|
212
|
+
"textarea",
|
|
213
|
+
"tfoot",
|
|
214
|
+
"th",
|
|
215
|
+
"thead",
|
|
216
|
+
"time",
|
|
217
|
+
"title",
|
|
218
|
+
"tr",
|
|
219
|
+
"track",
|
|
220
|
+
"u",
|
|
221
|
+
"ul",
|
|
222
|
+
"var",
|
|
223
|
+
"video",
|
|
224
|
+
"wbr"
|
|
225
|
+
]);
|
|
226
|
+
function htmlToMarkdown(html, source) {
|
|
227
|
+
if (typeof document === "undefined") return legacyHtmlToMarkdown(html);
|
|
228
|
+
const template = document.createElement("template");
|
|
229
|
+
template.innerHTML = html;
|
|
230
|
+
if (source) return serializeWithSource(template.content, source);
|
|
231
|
+
return serializeBlocks(template.content).replace(/^\n+/, "").replace(/\s+$/, "");
|
|
232
|
+
}
|
|
233
|
+
var BLOCK_ATTR = "data-md-block";
|
|
234
|
+
var ITEM_ATTR = "data-md-item";
|
|
235
|
+
var ROW_ATTR = "data-md-row";
|
|
236
|
+
function stripTrailingNewlines(text) {
|
|
237
|
+
return text.replace(/\n+$/, "");
|
|
238
|
+
}
|
|
239
|
+
function indexAttr(el, attr, size) {
|
|
240
|
+
const value = el.getAttribute(attr);
|
|
241
|
+
if (value == null || !/^\d+$/.test(value)) return void 0;
|
|
242
|
+
const n = Number(value);
|
|
243
|
+
return n < size ? n : void 0;
|
|
244
|
+
}
|
|
245
|
+
function markdownToEditorHtml(md, sanitize = (html) => html) {
|
|
246
|
+
const plain = () => ({
|
|
247
|
+
html: sanitize(marked.marked.parse(md, { async: false }).trim()),
|
|
248
|
+
source: null
|
|
249
|
+
});
|
|
250
|
+
if (typeof document === "undefined" || md.includes("\r")) return plain();
|
|
251
|
+
const tokens = marked.marked.lexer(md);
|
|
252
|
+
const parts = [];
|
|
253
|
+
const spans = [];
|
|
254
|
+
let cursor = 0;
|
|
255
|
+
for (const token of tokens) {
|
|
256
|
+
if (token.type === "space") continue;
|
|
257
|
+
const at = md.indexOf(token.raw, cursor);
|
|
258
|
+
if (at < 0) return plain();
|
|
259
|
+
cursor = at + token.raw.length;
|
|
260
|
+
const template = document.createElement("template");
|
|
261
|
+
template.innerHTML = marked.marked.parser([token]);
|
|
262
|
+
let nodes = Array.from(template.content.childNodes);
|
|
263
|
+
const strayText = nodes.some((n) => n.nodeType === 3 && (n.textContent ?? "").trim() !== "");
|
|
264
|
+
if (!nodes.some(isElement) && !strayText) {
|
|
265
|
+
parts.push(template.innerHTML.trim());
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (strayText) {
|
|
269
|
+
const wrapper = document.createElement("div");
|
|
270
|
+
wrapper.append(...nodes);
|
|
271
|
+
template.content.append(wrapper);
|
|
272
|
+
nodes = [wrapper];
|
|
273
|
+
}
|
|
274
|
+
const id = spans.length;
|
|
275
|
+
const elements = nodes.filter(isElement);
|
|
276
|
+
for (const el of elements) el.setAttribute(BLOCK_ATTR, String(id));
|
|
277
|
+
if (token.type === "list" && elements.length === 1) {
|
|
278
|
+
const items = Array.from(elements[0].children).filter((c) => tagOf(c) === "li");
|
|
279
|
+
if (items.length === token.items.length) {
|
|
280
|
+
items.forEach((li, k) => li.setAttribute(ITEM_ATTR, String(k)));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (token.type === "table" && elements.length === 1) {
|
|
284
|
+
const rows = tableRows(elements[0]);
|
|
285
|
+
if (rows.length === token.rows.length + 1) {
|
|
286
|
+
rows.forEach((tr, i) => tr.setAttribute(ROW_ATTR, String(i === 0 ? 0 : i + 1)));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
parts.push(template.innerHTML.trim());
|
|
290
|
+
spans.push({ start: at, end: at + stripTrailingNewlines(token.raw).length, token });
|
|
291
|
+
}
|
|
292
|
+
const html = sanitize(parts.join("\n"));
|
|
293
|
+
if (spans.length === 0) return { html, source: null };
|
|
294
|
+
const seeded = document.createElement("template");
|
|
295
|
+
seeded.innerHTML = html;
|
|
296
|
+
const byId = /* @__PURE__ */ new Map();
|
|
297
|
+
for (const node of Array.from(seeded.content.childNodes)) {
|
|
298
|
+
if (!isElement(node)) continue;
|
|
299
|
+
const id = indexAttr(node, BLOCK_ATTR, spans.length);
|
|
300
|
+
if (id === void 0) continue;
|
|
301
|
+
byId.set(id, [...byId.get(id) ?? [], node]);
|
|
302
|
+
}
|
|
303
|
+
const blocks = spans.map((span, id) => {
|
|
304
|
+
const elements = byId.get(id) ?? [];
|
|
305
|
+
const block = {
|
|
306
|
+
raw: md.slice(span.start, span.end),
|
|
307
|
+
snapshot: elements.map((el) => el.outerHTML).join(""),
|
|
308
|
+
elementCount: elements.length
|
|
309
|
+
};
|
|
310
|
+
if (span.token.type === "list" && elements.length === 1) {
|
|
311
|
+
block.list = sourceList(md, span.start, span.token, elements[0]);
|
|
312
|
+
}
|
|
313
|
+
if (span.token.type === "table" && elements.length === 1) {
|
|
314
|
+
block.table = sourceTable(block.raw, span.token, elements[0]);
|
|
315
|
+
}
|
|
316
|
+
return block;
|
|
317
|
+
});
|
|
318
|
+
const gaps = spans.map((span, i) => md.slice(span.end, spans[i + 1]?.start ?? md.length));
|
|
319
|
+
return { html, source: { leading: md.slice(0, spans[0].start), blocks, gaps } };
|
|
320
|
+
}
|
|
321
|
+
function sourceList(md, start, token, list) {
|
|
322
|
+
const lis = Array.from(list.children).filter((c) => tagOf(c) === "li");
|
|
323
|
+
if (lis.length !== token.items.length || lis.length === 0) return void 0;
|
|
324
|
+
const items = [];
|
|
325
|
+
const bounds = [];
|
|
326
|
+
let cursor = start;
|
|
327
|
+
for (const item of token.items) {
|
|
328
|
+
const at = md.indexOf(item.raw, cursor);
|
|
329
|
+
if (at < 0) return void 0;
|
|
330
|
+
const body = stripTrailingNewlines(item.raw);
|
|
331
|
+
items.push(body);
|
|
332
|
+
bounds.push([at, at + body.length]);
|
|
333
|
+
cursor = at + item.raw.length;
|
|
334
|
+
}
|
|
335
|
+
const itemGaps = bounds.slice(0, -1).map(([, end], k) => md.slice(end, bounds[k + 1][0]));
|
|
336
|
+
const first = items[0];
|
|
337
|
+
return {
|
|
338
|
+
bullet: /^\s*([*+-])/.exec(first)?.[1] ?? "-",
|
|
339
|
+
delimiter: /^\s*\d+([.)])/.exec(first)?.[1] ?? ".",
|
|
340
|
+
loose: token.loose,
|
|
341
|
+
items,
|
|
342
|
+
itemGaps,
|
|
343
|
+
itemSnapshots: lis.map((li) => li.outerHTML)
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function sourceTable(raw, token, table) {
|
|
347
|
+
const lines = raw.split("\n");
|
|
348
|
+
const rows = tableRows(table);
|
|
349
|
+
if (lines.length !== rows.length + 1) return void 0;
|
|
350
|
+
const rowSnapshots = /* @__PURE__ */ new Map();
|
|
351
|
+
for (const tr of rows) {
|
|
352
|
+
const r = indexAttr(tr, ROW_ATTR, lines.length);
|
|
353
|
+
if (r !== void 0) rowSnapshots.set(r, tr.outerHTML);
|
|
354
|
+
}
|
|
355
|
+
return { lines, columns: token.header.length, rowSnapshots };
|
|
356
|
+
}
|
|
357
|
+
function outerHtmlOf(nodes) {
|
|
358
|
+
return nodes.filter(isElement).map((el) => el.outerHTML).join("");
|
|
359
|
+
}
|
|
360
|
+
function serializeWithSource(root, src) {
|
|
361
|
+
const segments = [];
|
|
362
|
+
for (const node of Array.from(root.childNodes)) {
|
|
363
|
+
const last = segments[segments.length - 1];
|
|
364
|
+
if (node.nodeType === 3 && (node.textContent ?? "").trim() === "") {
|
|
365
|
+
if (last && last.id === void 0) last.nodes.push(node);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
const id = isElement(node) ? indexAttr(node, BLOCK_ATTR, src.blocks.length) : void 0;
|
|
369
|
+
if (last && last.id === id) last.nodes.push(node);
|
|
370
|
+
else segments.push({ id, nodes: [node] });
|
|
371
|
+
}
|
|
372
|
+
const verbatim = /* @__PURE__ */ new Map();
|
|
373
|
+
segments.forEach((seg, i) => {
|
|
374
|
+
if (seg.id === void 0 || verbatim.has(seg.id)) return;
|
|
375
|
+
if (outerHtmlOf(seg.nodes) === src.blocks[seg.id].snapshot) verbatim.set(seg.id, i);
|
|
376
|
+
});
|
|
377
|
+
const pieces = [];
|
|
378
|
+
const owned = new Set(verbatim.keys());
|
|
379
|
+
const fresh = (nodes) => {
|
|
380
|
+
for (const b of collectBlocks(nodes)) pieces.push({ text: b.text, kind: b.kind });
|
|
381
|
+
};
|
|
382
|
+
segments.forEach((seg, i) => {
|
|
383
|
+
if (seg.id === void 0) return fresh(seg.nodes);
|
|
384
|
+
const id = seg.id;
|
|
385
|
+
const block = src.blocks[id];
|
|
386
|
+
if (verbatim.get(id) === i) return void pieces.push({ text: block.raw, id, kind: "block" });
|
|
387
|
+
if (owned.has(id)) return fresh(seg.nodes);
|
|
388
|
+
owned.add(id);
|
|
389
|
+
if (block.elementCount === 1) {
|
|
390
|
+
const j = seg.nodes.findIndex((n) => isElement(n) && n.outerHTML === block.snapshot);
|
|
391
|
+
if (j >= 0) {
|
|
392
|
+
fresh(seg.nodes.slice(0, j));
|
|
393
|
+
pieces.push({ text: block.raw, id, kind: "block" });
|
|
394
|
+
fresh(seg.nodes.slice(j + 1));
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
pieces.push({ text: serializeChangedBlock(seg.nodes, block), id, kind: "block" });
|
|
399
|
+
});
|
|
400
|
+
if (pieces.length === 0) return "";
|
|
401
|
+
const used = /* @__PURE__ */ new Set();
|
|
402
|
+
const hasContent = (gap) => gap.trim() !== "";
|
|
403
|
+
const separator = (a, b) => {
|
|
404
|
+
if (a.id !== void 0 && b.id === a.id + 1) {
|
|
405
|
+
used.add(a.id);
|
|
406
|
+
return src.gaps[a.id];
|
|
407
|
+
}
|
|
408
|
+
const fallback = a.kind === "div" || b.kind === "div" ? "\n" : "\n\n";
|
|
409
|
+
if (a.id === void 0 || used.has(a.id)) return fallback;
|
|
410
|
+
const upto = b.id !== void 0 && b.id > a.id ? b.id : a.id + 1;
|
|
411
|
+
const range = [];
|
|
412
|
+
for (let g = a.id; g < upto; g++) if (!used.has(g)) range.push(g);
|
|
413
|
+
for (const g of range) used.add(g);
|
|
414
|
+
const kept = range.map((g) => src.gaps[g]).filter(hasContent).map((g) => g.trim());
|
|
415
|
+
if (kept.length > 0) return `
|
|
416
|
+
|
|
417
|
+
${kept.join("\n\n")}
|
|
418
|
+
|
|
419
|
+
`;
|
|
420
|
+
const own = src.gaps[a.id];
|
|
421
|
+
return (own.match(/\n/g)?.length ?? 0) >= 2 ? own : fallback;
|
|
422
|
+
};
|
|
423
|
+
let out = src.leading;
|
|
424
|
+
pieces.forEach((piece, i) => {
|
|
425
|
+
if (i > 0) out += separator(pieces[i - 1], piece);
|
|
426
|
+
out += piece.text;
|
|
427
|
+
});
|
|
428
|
+
const lastId = src.blocks.length - 1;
|
|
429
|
+
const trailing = src.gaps[lastId];
|
|
430
|
+
if (pieces[pieces.length - 1].id === lastId && !used.has(lastId)) {
|
|
431
|
+
used.add(lastId);
|
|
432
|
+
out += trailing;
|
|
433
|
+
} else {
|
|
434
|
+
const orphans = src.gaps.filter((gap, g) => !used.has(g) && hasContent(gap)).map((gap) => gap.trim());
|
|
435
|
+
if (orphans.length > 0) out += `
|
|
436
|
+
|
|
437
|
+
${orphans.join("\n\n")}`;
|
|
438
|
+
out += /\s*$/.exec(trailing)[0];
|
|
439
|
+
}
|
|
440
|
+
return out;
|
|
441
|
+
}
|
|
442
|
+
function serializeChangedBlock(nodes, block) {
|
|
443
|
+
const elements = nodes.filter(isElement);
|
|
444
|
+
if (elements.length === 1) {
|
|
445
|
+
const el = elements[0];
|
|
446
|
+
const tag = tagOf(el);
|
|
447
|
+
if (block.list && (tag === "ul" || tag === "ol")) return serializeListWithSource(el, block.list);
|
|
448
|
+
if (block.table && tag === "table") return serializeTableWithSource(el, block.table);
|
|
449
|
+
}
|
|
450
|
+
return joinBlocks(collectBlocks(nodes));
|
|
451
|
+
}
|
|
452
|
+
function serializeListWithSource(list, info) {
|
|
453
|
+
const ordered = tagOf(list) === "ol";
|
|
454
|
+
const children = Array.from(list.children);
|
|
455
|
+
const verbatim = /* @__PURE__ */ new Map();
|
|
456
|
+
for (const li of children) {
|
|
457
|
+
if (tagOf(li) !== "li") continue;
|
|
458
|
+
const k = indexAttr(li, ITEM_ATTR, info.items.length);
|
|
459
|
+
if (k !== void 0 && !verbatim.has(k) && li.outerHTML === info.itemSnapshots[k]) verbatim.set(k, li);
|
|
460
|
+
}
|
|
461
|
+
const owned = new Set(verbatim.keys());
|
|
462
|
+
const out = [];
|
|
463
|
+
let num = ordered ? (Number.parseInt(list.getAttribute("start") ?? "1", 10) || 1) - 1 : 0;
|
|
464
|
+
const numberOf = (k) => Number(/^\s*(\d+)/.exec(info.items[k])?.[1] ?? Number.NaN);
|
|
465
|
+
for (const child of children) {
|
|
466
|
+
const tag = tagOf(child);
|
|
467
|
+
if (tag === "ul" || tag === "ol") {
|
|
468
|
+
const nested = indent(serializeList(child), ordered ? 3 : 2);
|
|
469
|
+
if (out.length > 0) out[out.length - 1].text += `
|
|
470
|
+
${nested}`;
|
|
471
|
+
else out.push({ text: nested });
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
if (tag !== "li") continue;
|
|
475
|
+
const k = indexAttr(child, ITEM_ATTR, info.items.length);
|
|
476
|
+
if (k !== void 0 && verbatim.get(k) === child) {
|
|
477
|
+
if (ordered && !Number.isNaN(numberOf(k))) num = numberOf(k);
|
|
478
|
+
out.push({ text: info.items[k], k });
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
const mine = k !== void 0 && !owned.has(k) ? k : void 0;
|
|
482
|
+
if (mine !== void 0) owned.add(mine);
|
|
483
|
+
num = ordered && mine !== void 0 && !Number.isNaN(numberOf(mine)) ? numberOf(mine) : num + 1;
|
|
484
|
+
const marker = ordered ? `${num}${info.delimiter} ` : `${info.bullet} `;
|
|
485
|
+
out.push({
|
|
486
|
+
text: `${marker}${indent(serializeListItem(child), marker.length, true)}`.replace(/[ \t]+$/, ""),
|
|
487
|
+
k: mine
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
let last;
|
|
491
|
+
let text = "";
|
|
492
|
+
out.forEach((item, i) => {
|
|
493
|
+
if (i > 0) {
|
|
494
|
+
const prev = out[i - 1];
|
|
495
|
+
const sep = prev.k !== void 0 && item.k === prev.k + 1 ? info.itemGaps[prev.k] : last ?? info.itemGaps[0] ?? (info.loose ? "\n\n" : "\n");
|
|
496
|
+
last = sep;
|
|
497
|
+
text += sep;
|
|
498
|
+
}
|
|
499
|
+
text += item.text;
|
|
500
|
+
});
|
|
501
|
+
return text;
|
|
502
|
+
}
|
|
503
|
+
function serializeTableWithSource(table, info) {
|
|
504
|
+
const rows = tableRows(table);
|
|
505
|
+
if (rows.length === 0) return "";
|
|
506
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
507
|
+
const lines = [];
|
|
508
|
+
rows.forEach((tr, i) => {
|
|
509
|
+
const r = indexAttr(tr, ROW_ATTR, info.lines.length);
|
|
510
|
+
if (r !== void 0 && r !== 1 && !claimed.has(r) && tr.outerHTML === info.rowSnapshots.get(r)) {
|
|
511
|
+
claimed.add(r);
|
|
512
|
+
lines.push(info.lines[r]);
|
|
513
|
+
} else {
|
|
514
|
+
lines.push(serializeTableRow(tr));
|
|
515
|
+
}
|
|
516
|
+
if (i === 0) {
|
|
517
|
+
lines.push(tableCells(tr).length === info.columns ? info.lines[1] : tableDelimiterRow(tr));
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
return lines.join("\n");
|
|
521
|
+
}
|
|
522
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
523
|
+
"address",
|
|
524
|
+
"article",
|
|
525
|
+
"aside",
|
|
526
|
+
"blockquote",
|
|
527
|
+
"details",
|
|
528
|
+
"dialog",
|
|
529
|
+
"div",
|
|
530
|
+
"dl",
|
|
531
|
+
"fieldset",
|
|
532
|
+
"figcaption",
|
|
533
|
+
"figure",
|
|
534
|
+
"footer",
|
|
535
|
+
"form",
|
|
536
|
+
"h1",
|
|
537
|
+
"h2",
|
|
538
|
+
"h3",
|
|
539
|
+
"h4",
|
|
540
|
+
"h5",
|
|
541
|
+
"h6",
|
|
542
|
+
"header",
|
|
543
|
+
"hgroup",
|
|
544
|
+
"hr",
|
|
545
|
+
"li",
|
|
546
|
+
"main",
|
|
547
|
+
"nav",
|
|
548
|
+
"ol",
|
|
549
|
+
"p",
|
|
550
|
+
"pre",
|
|
551
|
+
"section",
|
|
552
|
+
"table",
|
|
553
|
+
"ul"
|
|
554
|
+
]);
|
|
555
|
+
function isElement(node) {
|
|
556
|
+
return node.nodeType === 1;
|
|
557
|
+
}
|
|
558
|
+
function tagOf(node) {
|
|
559
|
+
return isElement(node) ? node.tagName.toLowerCase() : "";
|
|
560
|
+
}
|
|
561
|
+
function isCustomTag(tag) {
|
|
562
|
+
return tag !== "" && !STANDARD_HTML_TAGS.has(tag);
|
|
563
|
+
}
|
|
564
|
+
function isBlockNode(node) {
|
|
565
|
+
return isElement(node) && BLOCK_TAGS.has(tagOf(node));
|
|
566
|
+
}
|
|
567
|
+
function collectBlocks(parent) {
|
|
568
|
+
const blocks = [];
|
|
569
|
+
let run = [];
|
|
570
|
+
const flush = () => {
|
|
571
|
+
if (run.length === 0) return;
|
|
572
|
+
const text = serializeInlineRun(run);
|
|
573
|
+
run = [];
|
|
574
|
+
if (text.trim() !== "") blocks.push({ kind: "inline", text });
|
|
575
|
+
};
|
|
576
|
+
const nodes = Array.isArray(parent) ? parent : Array.from(parent.childNodes);
|
|
577
|
+
for (const child of nodes) {
|
|
578
|
+
if (isBlockNode(child)) {
|
|
579
|
+
flush();
|
|
580
|
+
const el = child;
|
|
581
|
+
const tag = tagOf(el);
|
|
582
|
+
blocks.push({ kind: tag === "div" ? "div" : "block", text: serializeBlock(el), tag });
|
|
583
|
+
} else {
|
|
584
|
+
run.push(child);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
flush();
|
|
588
|
+
return blocks;
|
|
589
|
+
}
|
|
590
|
+
function joinBlocks(blocks) {
|
|
591
|
+
let out = "";
|
|
592
|
+
blocks.forEach((b, i) => {
|
|
593
|
+
if (i > 0) {
|
|
594
|
+
const prev = blocks[i - 1];
|
|
595
|
+
out += prev.kind === "div" || b.kind === "div" ? "\n" : "\n\n";
|
|
596
|
+
}
|
|
597
|
+
out += b.text;
|
|
598
|
+
});
|
|
599
|
+
return out;
|
|
600
|
+
}
|
|
601
|
+
function serializeBlocks(parent) {
|
|
602
|
+
return joinBlocks(collectBlocks(parent));
|
|
603
|
+
}
|
|
604
|
+
function serializeBlock(el) {
|
|
605
|
+
const tag = tagOf(el);
|
|
606
|
+
switch (tag) {
|
|
607
|
+
case "h1":
|
|
608
|
+
case "h2":
|
|
609
|
+
case "h3":
|
|
610
|
+
case "h4":
|
|
611
|
+
case "h5":
|
|
612
|
+
case "h6":
|
|
613
|
+
return `${"#".repeat(Number(tag[1]))} ${serializeInline(el).trim()}`;
|
|
614
|
+
case "p":
|
|
615
|
+
case "div":
|
|
616
|
+
return trimEdgeNewlines(serializeInline(el, true));
|
|
617
|
+
case "ul":
|
|
618
|
+
case "ol":
|
|
619
|
+
return serializeList(el);
|
|
620
|
+
case "pre":
|
|
621
|
+
return serializePre(el);
|
|
622
|
+
case "blockquote":
|
|
623
|
+
return serializeBlocks(el).split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n");
|
|
624
|
+
case "hr":
|
|
625
|
+
return "---";
|
|
626
|
+
case "table":
|
|
627
|
+
return serializeTable(el);
|
|
628
|
+
default:
|
|
629
|
+
return serializeBlocks(el);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
function tableRows(table) {
|
|
633
|
+
return Array.from(table.querySelectorAll("tr")).filter((tr) => tr.closest("table") === table);
|
|
634
|
+
}
|
|
635
|
+
function tableCells(tr) {
|
|
636
|
+
return Array.from(tr.children).filter((c) => tagOf(c) === "td" || tagOf(c) === "th");
|
|
637
|
+
}
|
|
638
|
+
function serializeTableCell(cell) {
|
|
639
|
+
const children = Array.from(cell.childNodes);
|
|
640
|
+
while (children.length > 0 && tagOf(children[children.length - 1]) === "br") children.pop();
|
|
641
|
+
return children.map((n) => tagOf(n) === "br" ? "<br>" : serializeInlineNode(n)).join("").replace(/\n/g, " ").replace(/\|/g, "\\|").trim();
|
|
642
|
+
}
|
|
643
|
+
function serializeTableRow(tr) {
|
|
644
|
+
return `| ${tableCells(tr).map(serializeTableCell).join(" | ")} |`;
|
|
645
|
+
}
|
|
646
|
+
function tableDelimiterRow(header) {
|
|
647
|
+
const marks = tableCells(header).map((cell) => {
|
|
648
|
+
const align = cell.getAttribute("align") || cell.style?.textAlign || "";
|
|
649
|
+
if (align === "left") return ":---";
|
|
650
|
+
if (align === "center") return ":---:";
|
|
651
|
+
if (align === "right") return "---:";
|
|
652
|
+
return "---";
|
|
653
|
+
});
|
|
654
|
+
return `| ${marks.join(" | ")} |`;
|
|
655
|
+
}
|
|
656
|
+
function serializeTable(table) {
|
|
657
|
+
const rows = tableRows(table);
|
|
658
|
+
if (rows.length === 0) return "";
|
|
659
|
+
const lines = rows.map(serializeTableRow);
|
|
660
|
+
lines.splice(1, 0, tableDelimiterRow(rows[0]));
|
|
661
|
+
return lines.join("\n");
|
|
662
|
+
}
|
|
663
|
+
function serializePre(el) {
|
|
664
|
+
const code = el.querySelector("code");
|
|
665
|
+
const lang = /(?:^|\s)language-(\S+)/.exec(code?.getAttribute("class") ?? "")?.[1] ?? "";
|
|
666
|
+
const text = (code ?? el).textContent ?? "";
|
|
667
|
+
return `\`\`\`${lang}
|
|
668
|
+
${text.replace(/\n$/, "")}
|
|
669
|
+
\`\`\``;
|
|
670
|
+
}
|
|
671
|
+
function serializeList(list) {
|
|
672
|
+
const ordered = tagOf(list) === "ol";
|
|
673
|
+
let n = ordered ? Number.parseInt(list.getAttribute("start") ?? "1", 10) || 1 : 0;
|
|
674
|
+
const items = Array.from(list.children);
|
|
675
|
+
const loose = items.some(
|
|
676
|
+
(li) => tagOf(li) === "li" && Array.from(li.children).some((c) => tagOf(c) === "p")
|
|
677
|
+
);
|
|
678
|
+
const out = [];
|
|
679
|
+
for (const item of items) {
|
|
680
|
+
const tag = tagOf(item);
|
|
681
|
+
if (tag === "ul" || tag === "ol") {
|
|
682
|
+
const nested = indent(serializeList(item), ordered ? 3 : 2);
|
|
683
|
+
if (out.length > 0) out[out.length - 1] += `
|
|
684
|
+
${nested}`;
|
|
685
|
+
else out.push(nested);
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
if (tag !== "li") continue;
|
|
689
|
+
const marker = ordered ? `${n++}. ` : "- ";
|
|
690
|
+
out.push(`${marker}${indent(serializeListItem(item), marker.length, true)}`.replace(/[ \t]+$/, ""));
|
|
691
|
+
}
|
|
692
|
+
return out.join(loose ? "\n\n" : "\n");
|
|
693
|
+
}
|
|
694
|
+
function serializeListItem(li) {
|
|
695
|
+
const blocks = collectBlocks(li);
|
|
696
|
+
let out = "";
|
|
697
|
+
blocks.forEach((b, i) => {
|
|
698
|
+
if (i > 0) out += b.tag === "ul" || b.tag === "ol" ? "\n" : "\n\n";
|
|
699
|
+
out += b.text;
|
|
700
|
+
});
|
|
701
|
+
return out;
|
|
702
|
+
}
|
|
703
|
+
function indent(text, width, skipFirst = false) {
|
|
704
|
+
const pad = " ".repeat(width);
|
|
705
|
+
return text.split("\n").map((line, i) => line === "" || skipFirst && i === 0 ? line : pad + line).join("\n");
|
|
706
|
+
}
|
|
707
|
+
function trimEdgeNewlines(text) {
|
|
708
|
+
return text.replace(/^\n+/, "").replace(/\n+$/, "");
|
|
709
|
+
}
|
|
710
|
+
function serializeInlineRun(nodes) {
|
|
711
|
+
return trimEdgeNewlines(nodes.map((n) => serializeInlineNode(n)).join(""));
|
|
712
|
+
}
|
|
713
|
+
function serializeInline(el, dropTrailingBr = false) {
|
|
714
|
+
const children = Array.from(el.childNodes);
|
|
715
|
+
if (dropTrailingBr) {
|
|
716
|
+
while (children.length > 0) {
|
|
717
|
+
const last = children[children.length - 1];
|
|
718
|
+
if (tagOf(last) === "br") children.pop();
|
|
719
|
+
else break;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return children.map((n) => serializeInlineNode(n)).join("");
|
|
723
|
+
}
|
|
724
|
+
function serializeInlineNode(node) {
|
|
725
|
+
if (node.nodeType === 3) return (node.textContent ?? "").replace(/ /g, " ");
|
|
726
|
+
if (!isElement(node)) return "";
|
|
727
|
+
const tag = tagOf(node);
|
|
728
|
+
if (isCustomTag(tag)) return node.outerHTML;
|
|
729
|
+
if (BLOCK_TAGS.has(tag)) return serializeBlock(node);
|
|
730
|
+
const inner = () => serializeInline(node);
|
|
731
|
+
switch (tag) {
|
|
732
|
+
case "br":
|
|
733
|
+
return "\n";
|
|
734
|
+
case "strong":
|
|
735
|
+
case "b":
|
|
736
|
+
return `**${inner()}**`;
|
|
737
|
+
case "em":
|
|
738
|
+
case "i":
|
|
739
|
+
return `*${inner()}*`;
|
|
740
|
+
case "s":
|
|
741
|
+
case "strike":
|
|
742
|
+
case "del":
|
|
743
|
+
return `~~${inner()}~~`;
|
|
744
|
+
case "code":
|
|
745
|
+
return `\`${node.textContent ?? ""}\``;
|
|
746
|
+
case "a": {
|
|
747
|
+
const href = node.getAttribute("href");
|
|
748
|
+
if (href == null) return inner();
|
|
749
|
+
const title = node.getAttribute("title");
|
|
750
|
+
return `[${inner()}](${href}${title ? ` "${title}"` : ""})`;
|
|
751
|
+
}
|
|
752
|
+
case "img": {
|
|
753
|
+
const title = node.getAttribute("title");
|
|
754
|
+
return ` ?? ""}${title ? ` "${title}"` : ""})`;
|
|
755
|
+
}
|
|
756
|
+
default:
|
|
757
|
+
return inner();
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
function legacyHtmlToMarkdown(html) {
|
|
761
|
+
let md = html;
|
|
762
|
+
md = md.replace(/<h1[^>]*>(.*?)<\/h1>/gi, "# $1\n");
|
|
763
|
+
md = md.replace(/<h2[^>]*>(.*?)<\/h2>/gi, "## $1\n");
|
|
764
|
+
md = md.replace(/<h3[^>]*>(.*?)<\/h3>/gi, "### $1\n");
|
|
765
|
+
md = md.replace(/<h4[^>]*>(.*?)<\/h4>/gi, "#### $1\n");
|
|
766
|
+
md = md.replace(/<h5[^>]*>(.*?)<\/h5>/gi, "##### $1\n");
|
|
767
|
+
md = md.replace(/<h6[^>]*>(.*?)<\/h6>/gi, "###### $1\n");
|
|
768
|
+
md = md.replace(/<li[^>]*>(.*?)<\/li>/gi, "- $1\n");
|
|
769
|
+
md = md.replace(/<\/?[uo]l[^>]*>/gi, "\n");
|
|
770
|
+
md = md.replace(/<strong[^>]*>(.*?)<\/strong>/gi, "**$1**");
|
|
771
|
+
md = md.replace(/<b[^>]*>(.*?)<\/b>/gi, "**$1**");
|
|
772
|
+
md = md.replace(/<em[^>]*>(.*?)<\/em>/gi, "*$1*");
|
|
773
|
+
md = md.replace(/<i[^>]*>(.*?)<\/i>/gi, "*$1*");
|
|
774
|
+
md = md.replace(/<u[^>]*>(.*?)<\/u>/gi, "$1");
|
|
775
|
+
md = md.replace(/<s[^>]*>(.*?)<\/s>/gi, "~~$1~~");
|
|
776
|
+
md = md.replace(/<strike[^>]*>(.*?)<\/strike>/gi, "~~$1~~");
|
|
777
|
+
md = md.replace(/<del[^>]*>(.*?)<\/del>/gi, "~~$1~~");
|
|
778
|
+
md = md.replace(/<code[^>]*>(.*?)<\/code>/gi, "`$1`");
|
|
779
|
+
md = md.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, "[$2]($1)");
|
|
780
|
+
md = md.replace(/<blockquote[^>]*>(.*?)<\/blockquote>/gi, "> $1\n");
|
|
781
|
+
md = md.replace(/<br\s*\/?>/gi, "\n");
|
|
782
|
+
md = md.replace(/<p[^>]*>(.*?)<\/p>/gi, "$1\n\n");
|
|
783
|
+
md = md.replace(/<div[^>]*>(.*?)<\/div>/gi, "$1\n");
|
|
784
|
+
md = md.replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, (match, tagName) => {
|
|
785
|
+
return STANDARD_HTML_TAGS.has(tagName.toLowerCase()) ? "" : match;
|
|
786
|
+
});
|
|
787
|
+
md = md.replace(/</g, "<");
|
|
788
|
+
md = md.replace(/>/g, ">");
|
|
789
|
+
md = md.replace(/"/g, '"');
|
|
790
|
+
md = md.replace(/'/g, "'");
|
|
791
|
+
md = md.replace(/ /g, " ");
|
|
792
|
+
md = md.replace(/&/g, "&");
|
|
793
|
+
md = md.replace(/\n{3,}/g, "\n\n");
|
|
794
|
+
md = md.trim();
|
|
795
|
+
return md;
|
|
796
|
+
}
|
|
797
|
+
function extensionEditorClasses(extensions) {
|
|
798
|
+
if (extensions.length === 0) return "";
|
|
799
|
+
return extensions.map((ext) => {
|
|
800
|
+
const tag = ext.tag.toLowerCase();
|
|
801
|
+
return [
|
|
802
|
+
`[&_${tag}]:block`,
|
|
803
|
+
`[&_${tag}]:my-2`,
|
|
804
|
+
`[&_${tag}]:rounded-lg`,
|
|
805
|
+
`[&_${tag}]:border`,
|
|
806
|
+
`[&_${tag}]:border-dashed`,
|
|
807
|
+
`[&_${tag}]:border-zinc-300`,
|
|
808
|
+
`[&_${tag}]:bg-zinc-50`,
|
|
809
|
+
`[&_${tag}]:p-3`,
|
|
810
|
+
`[&_${tag}]:text-xs`,
|
|
811
|
+
`dark:[&_${tag}]:border-zinc-600`,
|
|
812
|
+
`dark:[&_${tag}]:bg-zinc-800/50`
|
|
813
|
+
].join(" ");
|
|
814
|
+
}).join(" ");
|
|
815
|
+
}
|
|
816
|
+
function RenderedContent({
|
|
817
|
+
html,
|
|
818
|
+
extensions: instanceExtensions,
|
|
819
|
+
unsafe = false
|
|
820
|
+
}) {
|
|
821
|
+
const extensions = react.useMemo(
|
|
822
|
+
() => mergeExtensions(instanceExtensions),
|
|
823
|
+
[instanceExtensions]
|
|
824
|
+
);
|
|
825
|
+
const segments = react.useMemo(
|
|
826
|
+
() => parseSegments(html, extensions),
|
|
827
|
+
[html, extensions]
|
|
828
|
+
);
|
|
829
|
+
const renderHtml = (content) => unsafe ? content : chunkX2FC7ODX_cjs.sanitizeHtml(content);
|
|
830
|
+
if (segments.length === 1 && segments[0].type === "html") {
|
|
831
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: renderHtml(segments[0].content) } });
|
|
832
|
+
}
|
|
833
|
+
if (segments.length === 0) {
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
836
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: segments.map((segment, i) => {
|
|
837
|
+
if (segment.type === "html") {
|
|
838
|
+
return segment.content ? /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: renderHtml(segment.content) } }, i) : null;
|
|
839
|
+
}
|
|
840
|
+
const ext = extensions.find(
|
|
841
|
+
(e) => e.tag.toLowerCase() === segment.tag
|
|
842
|
+
);
|
|
843
|
+
if (!ext) return null;
|
|
844
|
+
const Component = ext.component;
|
|
845
|
+
const isBlock = ext.block !== false;
|
|
846
|
+
const Wrapper = isBlock ? "div" : "span";
|
|
847
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Wrapper, { "data-render-extension": segment.tag, children: /* @__PURE__ */ jsxRuntime.jsx(Component, { content: segment.content, attributes: segment.attributes }) }, i);
|
|
848
|
+
}) });
|
|
849
|
+
}
|
|
850
|
+
RenderedContent.displayName = "RenderedContent";
|
|
851
|
+
function ContentRenderer({
|
|
852
|
+
value,
|
|
853
|
+
format = "auto",
|
|
854
|
+
lineSpacing = 1.6,
|
|
855
|
+
className,
|
|
856
|
+
extensions: instanceExtensions,
|
|
857
|
+
unsafe = false
|
|
858
|
+
}) {
|
|
859
|
+
const extensions = react.useMemo(
|
|
860
|
+
() => mergeExtensions(instanceExtensions),
|
|
861
|
+
[instanceExtensions]
|
|
862
|
+
);
|
|
863
|
+
const html = react.useMemo(() => {
|
|
864
|
+
const safe = value ?? "";
|
|
865
|
+
const resolvedFormat = format === "auto" ? detectFormat(safe) : format;
|
|
866
|
+
const raw = resolvedFormat === "markdown" ? markdownToRawHtml(safe) : safe;
|
|
867
|
+
return unsafe ? raw : chunkX2FC7ODX_cjs.sanitizeHtml(raw);
|
|
868
|
+
}, [value, format, unsafe]);
|
|
869
|
+
const hasExtensions = extensions.length > 0;
|
|
870
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
871
|
+
"div",
|
|
872
|
+
{
|
|
873
|
+
"data-react-fancy-content-renderer": "",
|
|
874
|
+
style: { lineHeight: lineSpacing },
|
|
875
|
+
className: chunkZU5Q77OT_cjs.cn("text-sm", proseClasses, className),
|
|
876
|
+
children: hasExtensions ? /* @__PURE__ */ jsxRuntime.jsx(RenderedContent, { html, extensions, unsafe }) : /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: html } })
|
|
877
|
+
}
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
ContentRenderer.displayName = "ContentRenderer";
|
|
881
|
+
|
|
882
|
+
exports.ContentRenderer = ContentRenderer;
|
|
883
|
+
exports.detectFormat = detectFormat;
|
|
884
|
+
exports.extensionEditorClasses = extensionEditorClasses;
|
|
885
|
+
exports.htmlToMarkdown = htmlToMarkdown;
|
|
886
|
+
exports.markdownToEditorHtml = markdownToEditorHtml;
|
|
887
|
+
exports.mergeExtensions = mergeExtensions;
|
|
888
|
+
exports.proseClasses = proseClasses;
|
|
889
|
+
exports.registerExtension = registerExtension;
|
|
890
|
+
exports.registerExtensions = registerExtensions;
|
|
891
|
+
exports.renderMarkdown = renderMarkdown;
|
|
892
|
+
//# sourceMappingURL=chunk-MCQJFMDP.cjs.map
|
|
893
|
+
//# sourceMappingURL=chunk-MCQJFMDP.cjs.map
|