@ai-markdown/core 3.2.2 → 3.3.1

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/LICENSE CHANGED
@@ -19,3 +19,75 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ ---
24
+ The default image icons are adapted from Lucide (https://lucide.dev).
25
+
26
+ ISC License
27
+
28
+ Copyright (c) 2026 Lucide Icons and Contributors
29
+
30
+ Permission to use, copy, modify, and/or distribute this software for any
31
+ purpose with or without fee is hereby granted, provided that the above
32
+ copyright notice and this permission notice appear in all copies.
33
+
34
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
35
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
36
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
37
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
39
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
40
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41
+
42
+ ---
43
+
44
+ The following Lucide icons are derived from the Feather project:
45
+
46
+ airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out
47
+
48
+ The MIT License (MIT) (for the icons listed above)
49
+
50
+ Copyright (c) 2013-present Cole Bemis
51
+
52
+ Permission is hereby granted, free of charge, to any person obtaining a copy
53
+ of this software and associated documentation files (the "Software"), to deal
54
+ in the Software without restriction, including without limitation the rights
55
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ copies of the Software, and to permit persons to whom the Software is
57
+ furnished to do so, subject to the following conditions:
58
+
59
+ The above copyright notice and this permission notice shall be included in all
60
+ copies or substantial portions of the Software.
61
+
62
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
68
+ SOFTWARE.
69
+
70
+ ---
71
+ Image gesture calculations are adapted from @rc-component/image 1.10.0.
72
+
73
+ MIT License
74
+
75
+ Copyright (c) 2019-present react-component
76
+
77
+ Permission is hereby granted, free of charge, to any person obtaining a copy
78
+ of this software and associated documentation files (the "Software"), to deal
79
+ in the Software without restriction, including without limitation the rights
80
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
81
+ copies of the Software, and to permit persons to whom the Software is
82
+ furnished to do so, subject to the following conditions:
83
+
84
+ The above copyright notice and this permission notice shall be included in all
85
+ copies or substantial portions of the Software.
86
+
87
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
88
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
89
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
90
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
91
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
92
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
93
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@ai-markdown/core/components",
3
+ "private": true,
4
+ "main": "../dist/components/index.cjs",
5
+ "module": "../dist/components/index.js",
6
+ "types": "../dist/components/index.d.ts",
7
+ "sideEffects": false
8
+ }
@@ -0,0 +1,555 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function extractCode(node) {
4
+ if (node?.tagName !== "pre" || node.children.length !== 1 || Object.keys(node.properties).length) return null;
5
+ const child = node.children[0];
6
+ if (child.type !== "element" || child.tagName !== "code" || child.children.some((n) => n.type !== "text") || Object.keys(child.properties).some((k) => k !== "className")) return null;
7
+ const classes = child.properties.className ?? [];
8
+ const names = (Array.isArray(classes) ? classes : String(classes).split(/\s+/)).map(String).filter(Boolean);
9
+ if (names.some((n) => !n.startsWith("language-"))) return null;
10
+ const languages = [...new Set(names.map((n) => n.slice(9).trim().toLowerCase()))];
11
+ if (languages.length > 1) return null;
12
+ return {
13
+ code: child.children.map((n) => n.type === "text" ? n.value : "").join(""),
14
+ language: languages[0] ?? ""
15
+ };
16
+ }
17
+ function normalizeRenderers(renderers) {
18
+ const result = Object.create(null);
19
+ for (const [language, renderer] of Object.entries(renderers)) {
20
+ const key = language.trim().toLowerCase();
21
+ if (!key) throw new Error("Code renderer language must not be empty");
22
+ if (Object.hasOwn(result, key)) throw new Error(`Duplicate code renderer: ${key}`);
23
+ result[key] = renderer;
24
+ }
25
+ return Object.freeze(result);
26
+ }
27
+ function annotation(node) {
28
+ if (node.type !== "element") return;
29
+ if (node.tagName === "annotation" && node.properties.encoding === "application/x-tex") return node;
30
+ for (const child of node.children) {
31
+ const found = annotation(child);
32
+ if (found) return found;
33
+ }
34
+ }
35
+ function text(node) {
36
+ if (node.type === "text") return node.value;
37
+ if (node.type !== "element") return "";
38
+ if (node.tagName === "table") throw new Error("Nested tables cannot be exported");
39
+ if (Array.isArray(node.properties.className) && node.properties.className.includes("katex")) {
40
+ const tex = annotation(node);
41
+ if (!tex) throw new Error("Math is missing its text annotation");
42
+ return tex.children.map(text).join("");
43
+ }
44
+ if (node.tagName === "br") return "\n";
45
+ if (node.tagName === "img" || node.tagName === "cross-chunk-image") return String(node.properties.alt ?? "");
46
+ return node.children.map(text).join("");
47
+ }
48
+ function projectTable(node) {
49
+ try {
50
+ if (node?.tagName !== "table") throw new Error("Table source is unavailable");
51
+ const rows = [];
52
+ const walk = (parent) => {
53
+ for (const child of parent.children) {
54
+ if (child.type === "text" && !child.value.trim()) continue;
55
+ if (child.type !== "element") throw new Error("Unsupported table content");
56
+ if (child.tagName === "tr") {
57
+ const cells = [];
58
+ for (const cell of child.children) {
59
+ if (cell.type === "text" && !cell.value.trim()) continue;
60
+ if (cell.type !== "element" || !["th", "td"].includes(cell.tagName) || Number(cell.properties.colSpan ?? 1) !== 1 || Number(cell.properties.rowSpan ?? 1) !== 1) throw new Error("Only tables without merged cells can be exported");
61
+ cells.push(text(cell));
62
+ }
63
+ rows.push(cells);
64
+ } else if ([
65
+ "thead",
66
+ "tbody",
67
+ "tfoot"
68
+ ].includes(child.tagName) && parent === node) walk(child);
69
+ else throw new Error("Unsupported table structure");
70
+ }
71
+ };
72
+ walk(node);
73
+ if (!rows.length || !rows[0].length || rows.some((r) => r.length !== rows[0].length)) throw new Error("Only rectangular tables can be exported");
74
+ return { rows };
75
+ } catch (error) {
76
+ return { reason: error instanceof Error ? error.message : "Table cannot be exported" };
77
+ }
78
+ }
79
+ const formulaPrefix = /^[\s\u0000-\u001f]*[=+@-]/;
80
+ function serializeTable(rows, delimiter = ",") {
81
+ return rows.map((row) => row.map((value) => {
82
+ if (formulaPrefix.test(value) && !/^\s*-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?\s*$/i.test(value) || /^[\t\r\n]/.test(value)) value = `'${value}`;
83
+ return /["\r\n\t,]/.test(value) ? `"${value.replaceAll("\"", "\"\"")}"` : value;
84
+ }).join(delimiter)).join("\r\n");
85
+ }
86
+ function createCodeFrame(initial, publish) {
87
+ let shown = initial;
88
+ let latest = initial;
89
+ let delay = 0;
90
+ let timer;
91
+ const cancel = () => {
92
+ if (timer !== void 0) clearTimeout(timer);
93
+ timer = void 0;
94
+ };
95
+ const flush = () => {
96
+ cancel();
97
+ if (shown.code === latest.code && shown.language === latest.language) return;
98
+ shown = latest;
99
+ publish(shown);
100
+ };
101
+ return {
102
+ update(next, streaming, interval) {
103
+ const replaced = next.language !== latest.language || !next.code.startsWith(latest.code);
104
+ latest = next;
105
+ if (delay !== interval) cancel();
106
+ delay = interval;
107
+ if (!streaming || interval === 0 || replaced) return flush();
108
+ if (shown.code === next.code && shown.language === next.language) return cancel();
109
+ timer ??= setTimeout(flush, interval);
110
+ },
111
+ dispose: cancel
112
+ };
113
+ }
114
+ function prettyPrintJson(text, expandNested = true) {
115
+ try {
116
+ return format(text, expandNested, 0);
117
+ } catch {
118
+ return text;
119
+ }
120
+ }
121
+ function format(text, expandNested, baseIndent) {
122
+ JSON.parse(text);
123
+ const tokens = text.match(/"(?:\\[\s\S]|[^"\\])*"|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null|[{}[\],:]/g) ?? [];
124
+ const out = [];
125
+ let indent = baseIndent;
126
+ const newline = () => out.push("\n", " ".repeat(indent));
127
+ for (let i = 0; i < tokens.length; i++) {
128
+ const token = tokens[i];
129
+ if (token === "{" || token === "[") {
130
+ out.push(token);
131
+ if (tokens[i + 1] !== (token === "{" ? "}" : "]")) {
132
+ indent++;
133
+ newline();
134
+ }
135
+ } else if (token === "}" || token === "]") {
136
+ if (tokens[i - 1] !== (token === "}" ? "{" : "[")) {
137
+ indent--;
138
+ newline();
139
+ }
140
+ out.push(token);
141
+ } else if (token === ",") {
142
+ out.push(",");
143
+ newline();
144
+ } else if (token === ":") out.push(": ");
145
+ else if (token.startsWith("\"")) {
146
+ const value = JSON.parse(token);
147
+ const trimmed = value.trim();
148
+ if (expandNested && tokens[i + 1] !== ":" && /^[{[]/.test(trimmed) && indent < 100) try {
149
+ out.push(format(trimmed, true, indent));
150
+ continue;
151
+ } catch {}
152
+ out.push(JSON.stringify(value));
153
+ } else out.push(token);
154
+ }
155
+ return out.join("");
156
+ }
157
+ function createJsonCompletenessScanner() {
158
+ let previous = "";
159
+ let depth = 0;
160
+ let quoted = false;
161
+ let escaped = false;
162
+ let invalid = false;
163
+ let last = "";
164
+ return (text) => {
165
+ let from = previous.length;
166
+ if (!text.startsWith(previous)) {
167
+ from = 0;
168
+ depth = 0;
169
+ quoted = escaped = invalid = false;
170
+ last = "";
171
+ }
172
+ previous = text;
173
+ for (let i = from; i < text.length; i++) {
174
+ const c = text[i];
175
+ if (!/\s/.test(c)) last = c;
176
+ if (quoted) {
177
+ if (escaped) escaped = false;
178
+ else if (c === "\\") escaped = true;
179
+ else if (c === "\"") quoted = false;
180
+ } else if (c === "\"") quoted = true;
181
+ else if (c === "{" || c === "[") depth++;
182
+ else if (c === "}" || c === "]") {
183
+ depth--;
184
+ if (depth < 0) invalid = true;
185
+ }
186
+ }
187
+ return !invalid && !quoted && depth === 0 && (last === "}" || last === "]");
188
+ };
189
+ }
190
+ function jsonLooksComplete(text) {
191
+ return createJsonCompletenessScanner()(text);
192
+ }
193
+ function createRenderQueue() {
194
+ const pending = /* @__PURE__ */ new Map();
195
+ let running = false;
196
+ async function drain() {
197
+ if (running) return;
198
+ running = true;
199
+ try {
200
+ while (pending.size) {
201
+ const [owner, job] = pending.entries().next().value;
202
+ pending.delete(owner);
203
+ try {
204
+ await job.run();
205
+ job.resolve();
206
+ } catch (error) {
207
+ job.reject(error);
208
+ }
209
+ }
210
+ } finally {
211
+ running = false;
212
+ }
213
+ }
214
+ return {
215
+ enqueue(owner, run) {
216
+ pending.get(owner)?.resolve();
217
+ const promise = new Promise((resolve, reject) => pending.set(owner, {
218
+ run,
219
+ resolve,
220
+ reject
221
+ }));
222
+ drain();
223
+ return promise;
224
+ },
225
+ cancel(owner) {
226
+ pending.get(owner)?.resolve();
227
+ pending.delete(owner);
228
+ }
229
+ };
230
+ }
231
+ const mermaidRenderQueue = createRenderQueue();
232
+ const SAFE_SECURITY_LEVELS = /* @__PURE__ */ new Set(["strict", "sandbox"]);
233
+ let ownedThemes = /* @__PURE__ */ new WeakMap();
234
+ const resetMermaidInitializationForTests = () => {
235
+ ownedThemes = /* @__PURE__ */ new WeakMap();
236
+ };
237
+ const readSiteConfig = (mermaid) => {
238
+ const api = mermaid.mermaidAPI;
239
+ return api?.getSiteConfig?.() ?? api?.getConfig?.() ?? {};
240
+ };
241
+ const MERMAID_DEFAULT_MAX_TEXT_SIZE = 5e4;
242
+ const getMermaidMaxTextSize = (mermaid) => {
243
+ const configured = readSiteConfig(mermaid).maxTextSize;
244
+ return typeof configured === "number" && Number.isFinite(configured) && configured >= 0 ? configured : MERMAID_DEFAULT_MAX_TEXT_SIZE;
245
+ };
246
+ const ensureMermaidInitialized = (mermaid, isDark) => {
247
+ const site = readSiteConfig(mermaid);
248
+ const ownedTheme = ownedThemes.get(mermaid);
249
+ const wantedTheme = isDark ? "dark" : "base";
250
+ const hostOwnsTheme = site.theme !== void 0 && site.theme !== "default" && site.theme !== ownedTheme;
251
+ const levelOk = SAFE_SECURITY_LEVELS.has(site.securityLevel);
252
+ const themeOk = hostOwnsTheme || site.theme === wantedTheme && Boolean(site.darkMode) === isDark;
253
+ const suppressOk = site.suppressErrorRendering === true;
254
+ if (levelOk && themeOk && suppressOk) return;
255
+ const next = {
256
+ ...site,
257
+ suppressErrorRendering: true
258
+ };
259
+ if (!levelOk) next.securityLevel = "strict";
260
+ if (!hostOwnsTheme) {
261
+ next.theme = wantedTheme;
262
+ next.darkMode = isDark;
263
+ const fontFamily = site.themeVariables?.fontFamily;
264
+ if (typeof fontFamily === "string") next.themeVariables = {
265
+ fontFamily,
266
+ ...isDark ? { edgeLabelBackground: "#444444" } : {}
267
+ };
268
+ else if (isDark) next.themeVariables = { edgeLabelBackground: "#444444" };
269
+ else delete next.themeVariables;
270
+ ownedThemes.set(mermaid, wantedTheme);
271
+ }
272
+ mermaid.initialize(next);
273
+ };
274
+ let nextId = 0;
275
+ function createDiagramController(load, publish) {
276
+ const owner = {};
277
+ let epoch = 0;
278
+ let previous;
279
+ let svg = "";
280
+ let bind;
281
+ let timer;
282
+ const cancel = () => {
283
+ epoch++;
284
+ if (timer !== void 0) clearTimeout(timer);
285
+ timer = void 0;
286
+ mermaidRenderQueue.cancel(owner);
287
+ };
288
+ return {
289
+ update(request) {
290
+ const replaced = !previous || previous.resetKey !== request.resetKey || previous.dark !== request.dark || !request.code.startsWith(previous.code);
291
+ const pending = timer !== void 0;
292
+ epoch++;
293
+ mermaidRenderQueue.cancel(owner);
294
+ if (replaced) {
295
+ svg = "";
296
+ bind = void 0;
297
+ if (timer !== void 0) clearTimeout(timer);
298
+ timer = void 0;
299
+ }
300
+ previous = request;
301
+ if (!request.active) {
302
+ cancel();
303
+ return;
304
+ }
305
+ publish({
306
+ status: "loading",
307
+ svg,
308
+ bind
309
+ });
310
+ const attempt = () => {
311
+ timer = void 0;
312
+ const current = previous;
313
+ const generation = epoch;
314
+ const valid = () => generation === epoch;
315
+ let phase = "load";
316
+ load().then((engine) => {
317
+ phase = "render";
318
+ if (!valid()) return;
319
+ return mermaidRenderQueue.enqueue(owner, async () => {
320
+ if (!valid()) return;
321
+ ensureMermaidInitialized(engine, current.dark);
322
+ if (current.code.length > getMermaidMaxTextSize(engine)) throw new Error("Diagram exceeds Mermaid’s maximum text size");
323
+ const parsed = await engine.parse(current.code, { suppressErrors: true });
324
+ if (!valid()) return;
325
+ if (parsed === false) throw new Error("Diagram syntax is incomplete or invalid");
326
+ const result = await engine.render(`aimd-diagram-${++nextId}`, current.code);
327
+ if (!valid()) return;
328
+ svg = result.svg;
329
+ bind = result.bindFunctions;
330
+ publish({
331
+ status: "ready",
332
+ svg,
333
+ bind
334
+ });
335
+ });
336
+ }).catch((error) => {
337
+ if (valid()) publish({
338
+ status: current.streaming && phase === "render" ? "loading" : "error",
339
+ svg,
340
+ bind,
341
+ error: (phase === "load" ? "Diagram engine could not load: " : "") + (error instanceof Error ? error.message : String(error)).slice(0, 500)
342
+ });
343
+ });
344
+ };
345
+ if (!request.streaming || request.interval <= 0) {
346
+ if (timer !== void 0) clearTimeout(timer);
347
+ attempt();
348
+ } else if (!pending || replaced) timer = setTimeout(attempt, request.interval);
349
+ },
350
+ dispose: cancel
351
+ };
352
+ }
353
+ const locks = /* @__PURE__ */ new WeakMap();
354
+ function lockImagePreviewScroll(target) {
355
+ let lock = locks.get(target);
356
+ if (!lock) {
357
+ lock = {
358
+ count: 0,
359
+ overflow: target.style.overflow
360
+ };
361
+ locks.set(target, lock);
362
+ }
363
+ lock.count++;
364
+ target.style.overflow = "hidden";
365
+ let released = false;
366
+ return () => {
367
+ if (released) return;
368
+ released = true;
369
+ if (--lock.count === 0) {
370
+ if (target.style.overflow === "hidden") target.style.overflow = lock.overflow;
371
+ locks.delete(target);
372
+ }
373
+ };
374
+ }
375
+ const imageIconPaths = {
376
+ rotateLeft: ["M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", "M3 3v5h5"],
377
+ rotateRight: ["M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8", "M21 3v5h-5"],
378
+ zoomIn: [
379
+ "M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0",
380
+ "M21 21L16.65 16.65",
381
+ "M11 8L11 14",
382
+ "M8 11L14 11"
383
+ ],
384
+ zoomOut: [
385
+ "M19 11a8 8 0 1 1 -16 0a8 8 0 1 1 16 0",
386
+ "M21 21L16.65 16.65",
387
+ "M8 11L14 11"
388
+ ],
389
+ close: ["M18 6 6 18", "m6 6 12 12"],
390
+ prev: ["m15 18-6-6 6-6"],
391
+ next: ["m9 18 6-6-6-6"],
392
+ flipX: [
393
+ "M8 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h3",
394
+ "M16 3h3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-3",
395
+ "M12 20v2",
396
+ "M12 14v2",
397
+ "M12 8v2",
398
+ "M12 2v2"
399
+ ],
400
+ flipY: [
401
+ "M21 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v3",
402
+ "M21 16v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3",
403
+ "M4 12H2",
404
+ "M10 12H8",
405
+ "M16 12h-2",
406
+ "M22 12h-2"
407
+ ],
408
+ placeholder: [
409
+ "M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z",
410
+ "M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0",
411
+ "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"
412
+ ],
413
+ error: ["m2 2 20 20M10.41 10.41a2 2 0 1 1-2.83-2.83m5.92 5.92L6 21m12-9 3 3", "M3.59 3.59A2 2 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59M21 15V5a2 2 0 0 0-2-2H9"],
414
+ gallery: ["M5 3h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z", "M4 21h1m4 0h1m4 0h1m4 0h1"],
415
+ preview: [
416
+ "M15 15.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997a1 1 0 0 1-1.517-.86z",
417
+ "M21 12.17V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6m-5 0 5-5",
418
+ "M11 9a2 2 0 1 1-4 0 2 2 0 0 1 4 0"
419
+ ]
420
+ };
421
+ const imageGroupSelector = "[data-aimd-image-scope], .aim-typography-root, .aimd-vue, .mantine-Typography-root";
422
+ const galleries = /* @__PURE__ */ new WeakMap();
423
+ function getImageGallery(scope) {
424
+ const existing = galleries.get(scope);
425
+ if (existing) return existing;
426
+ const entries = /* @__PURE__ */ new Map();
427
+ const listeners = /* @__PURE__ */ new Set();
428
+ const notify = () => listeners.forEach((listener) => listener());
429
+ const gallery = {
430
+ items: () => [...entries.values()].sort((a, b) => a.precedes(b.id) ? -1 : b.precedes(a.id) ? 1 : 0),
431
+ subscribe(listener) {
432
+ listeners.add(listener);
433
+ return () => {
434
+ listeners.delete(listener);
435
+ };
436
+ },
437
+ set(item) {
438
+ const old = entries.get(item.id);
439
+ if (old?.src === item.src && old?.alt === item.alt) return;
440
+ entries.set(item.id, item);
441
+ notify();
442
+ },
443
+ remove(id) {
444
+ if (entries.delete(id)) notify();
445
+ }
446
+ };
447
+ galleries.set(scope, gallery);
448
+ return gallery;
449
+ }
450
+ const imageActionLabels = {
451
+ close: "Close preview",
452
+ prev: "Previous image",
453
+ next: "Next image",
454
+ rotateLeft: "Rotate left",
455
+ rotateRight: "Rotate right",
456
+ zoomIn: "Zoom in",
457
+ zoomOut: "Zoom out",
458
+ flipX: "Flip horizontally",
459
+ flipY: "Flip vertically"
460
+ };
461
+ const initialImageTransform = () => ({
462
+ x: 0,
463
+ y: 0,
464
+ rotate: 0,
465
+ scale: 1,
466
+ flipX: false,
467
+ flipY: false
468
+ });
469
+ function imageTransformStyle(transform) {
470
+ const { x, y, scale, rotate, flipX, flipY } = transform;
471
+ return `translate3d(${x}px, ${y}px, 0) scale3d(${flipX ? "-" : ""}${scale}, ${flipY ? "-" : ""}${scale}, 1) rotate(${rotate}deg)`;
472
+ }
473
+ function zoomImage(transform, ratio, geometry, centerX = geometry.viewportWidth / 2, centerY = geometry.viewportHeight / 2, touch = false) {
474
+ if (!Number.isFinite(ratio) || ratio <= 0) return transform;
475
+ const scale = Math.min(50, touch ? Math.max(.01, transform.scale * ratio) : Math.max(1, transform.scale * ratio));
476
+ const difference = scale / transform.scale - 1;
477
+ let x = transform.x - difference * (centerX - transform.x - geometry.left - geometry.width / 2);
478
+ let y = transform.y - difference * (centerY - transform.y - geometry.top - geometry.height / 2);
479
+ if (ratio < 1 && scale === 1 && geometry.width <= geometry.viewportWidth && geometry.height <= geometry.viewportHeight) x = y = 0;
480
+ return {
481
+ ...transform,
482
+ x,
483
+ y,
484
+ scale
485
+ };
486
+ }
487
+ function imageWheelRatio(delta) {
488
+ const ratio = 1 + Math.min(Math.abs(delta / 100), 1) * .5;
489
+ return delta > 0 ? 1 / ratio : ratio;
490
+ }
491
+ function reboundImage(transform, geometry, bounds) {
492
+ if (transform.scale < 1) return {
493
+ ...transform,
494
+ x: 0,
495
+ y: 0,
496
+ scale: 1
497
+ };
498
+ const rotated = transform.rotate % 180 !== 0;
499
+ const width = (rotated ? geometry.height : geometry.width) * transform.scale;
500
+ const height = (rotated ? geometry.width : geometry.height) * transform.scale;
501
+ if (width <= geometry.viewportWidth && height <= geometry.viewportHeight) return {
502
+ ...transform,
503
+ x: 0,
504
+ y: 0
505
+ };
506
+ const fix = (position, start, size, viewport) => {
507
+ const offset = (size - viewport) / 2;
508
+ if (size > viewport) {
509
+ if (start > 0) return offset;
510
+ if (start < 0 && start + size < viewport) return -offset;
511
+ } else if (start < 0 || start + size > viewport) return start < 0 ? offset : -offset;
512
+ return position;
513
+ };
514
+ return {
515
+ ...transform,
516
+ x: fix(transform.x, bounds.left, width, geometry.viewportWidth),
517
+ y: fix(transform.y, bounds.top, height, geometry.viewportHeight)
518
+ };
519
+ }
520
+ function imagePinchCenter(oldA, oldB, a, b) {
521
+ const distanceA = Math.hypot(a.x - oldA.x, a.y - oldA.y), distanceB = Math.hypot(b.x - oldB.x, b.y - oldB.y);
522
+ const ratio = distanceA + distanceB ? distanceA / (distanceA + distanceB) : 0;
523
+ return {
524
+ x: oldA.x + ratio * (oldB.x - oldA.x),
525
+ y: oldA.y + ratio * (oldB.y - oldA.y)
526
+ };
527
+ }
528
+ exports.MERMAID_DEFAULT_MAX_TEXT_SIZE = MERMAID_DEFAULT_MAX_TEXT_SIZE;
529
+ exports.createCodeFrame = createCodeFrame;
530
+ exports.createDiagramController = createDiagramController;
531
+ exports.createJsonCompletenessScanner = createJsonCompletenessScanner;
532
+ exports.createRenderQueue = createRenderQueue;
533
+ exports.ensureMermaidInitialized = ensureMermaidInitialized;
534
+ exports.extractCode = extractCode;
535
+ exports.getImageGallery = getImageGallery;
536
+ exports.getMermaidMaxTextSize = getMermaidMaxTextSize;
537
+ exports.imageActionLabels = imageActionLabels;
538
+ exports.imageGroupSelector = imageGroupSelector;
539
+ exports.imageIconPaths = imageIconPaths;
540
+ exports.imagePinchCenter = imagePinchCenter;
541
+ exports.imageTransformStyle = imageTransformStyle;
542
+ exports.imageWheelRatio = imageWheelRatio;
543
+ exports.initialImageTransform = initialImageTransform;
544
+ exports.jsonLooksComplete = jsonLooksComplete;
545
+ exports.lockImagePreviewScroll = lockImagePreviewScroll;
546
+ exports.mermaidRenderQueue = mermaidRenderQueue;
547
+ exports.normalizeRenderers = normalizeRenderers;
548
+ exports.prettyPrintJson = prettyPrintJson;
549
+ exports.projectTable = projectTable;
550
+ exports.reboundImage = reboundImage;
551
+ exports.resetMermaidInitializationForTests = resetMermaidInitializationForTests;
552
+ exports.serializeTable = serializeTable;
553
+ exports.zoomImage = zoomImage;
554
+
555
+ //# sourceMappingURL=index.cjs.map