@noirmd/previewer 1.0.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.
@@ -0,0 +1,2375 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // NReditor.tsx
31
+ var NReditor_exports = {};
32
+ __export(NReditor_exports, {
33
+ default: () => NReditor_default
34
+ });
35
+ module.exports = __toCommonJS(NReditor_exports);
36
+ var import_react11 = __toESM(require("react"));
37
+ var import_react_codemirror = __toESM(require("@uiw/react-codemirror"));
38
+ var import_view = require("@codemirror/view");
39
+
40
+ // custom-syntax.ts
41
+ var import_language = require("@codemirror/language");
42
+ var import_highlight = require("@lezer/highlight");
43
+ var customStreamParserV2 = import_language.StreamLanguage.define({
44
+ startState: () => ({
45
+ inCodeBlock: false,
46
+ inDirectiveHeader: false,
47
+ inPropsBlock: false,
48
+ braceDepth: 0,
49
+ blockStack: [],
50
+ imageState: "none",
51
+ linkState: "none",
52
+ lastPropKey: "",
53
+ inHtmlBlock: false,
54
+ htmlTagName: "",
55
+ isClosingHtmlTag: false,
56
+ embeddedLang: "none"
57
+ }),
58
+ token(stream, state) {
59
+ if (stream.sol()) {
60
+ state.inDirectiveHeader = false;
61
+ state.imageState = "none";
62
+ state.linkState = "none";
63
+ if (state.inCodeBlock && stream.match(/^\s*```/)) {
64
+ state.inCodeBlock = false;
65
+ return "comment";
66
+ }
67
+ }
68
+ if (state.inHtmlBlock) {
69
+ stream.eatSpace();
70
+ if (stream.match(/^\/>/)) {
71
+ state.inHtmlBlock = false;
72
+ state.htmlTagName = "";
73
+ state.isClosingHtmlTag = false;
74
+ return "typeName";
75
+ }
76
+ if (stream.match(/^>/)) {
77
+ state.inHtmlBlock = false;
78
+ if (!state.isClosingHtmlTag && (state.htmlTagName === "script" || state.htmlTagName === "style")) {
79
+ state.embeddedLang = state.htmlTagName;
80
+ }
81
+ state.htmlTagName = "";
82
+ state.isClosingHtmlTag = false;
83
+ return "typeName";
84
+ }
85
+ if (stream.match(/^[a-zA-Z_:][\w-.:]*/)) return "attributeName";
86
+ if (stream.match(/^=/)) return "keyword";
87
+ if (stream.match(/^"[^"]*"/)) return "string";
88
+ if (stream.match(/^"[^"]*$/)) return "string";
89
+ if (stream.match(/^'[^']*'/)) return "string";
90
+ if (stream.match(/^'[^']*$/)) return "string";
91
+ if (stream.match(/^[^\s>]+/)) return "string";
92
+ if (stream.eatSpace()) return null;
93
+ stream.next();
94
+ return null;
95
+ }
96
+ if (state.embeddedLang !== "none") {
97
+ if (stream.match(/^<\/(script|style)\b/i)) {
98
+ const closeTag = stream.current().replace(/^<\//, "").toLowerCase();
99
+ state.embeddedLang = "none";
100
+ state.inHtmlBlock = true;
101
+ state.htmlTagName = closeTag;
102
+ state.isClosingHtmlTag = true;
103
+ return "typeName";
104
+ }
105
+ if (state.embeddedLang === "script") {
106
+ if (stream.match(/^\/\//)) {
107
+ stream.skipToEnd();
108
+ return "comment";
109
+ }
110
+ if (stream.match(/^\/\*/)) {
111
+ while (!stream.eol()) {
112
+ if (stream.match(/\*\//)) return "comment";
113
+ stream.next();
114
+ }
115
+ return "comment";
116
+ }
117
+ if (stream.match(/^["']/)) {
118
+ const q = stream.current();
119
+ while (!stream.eol()) {
120
+ const ch = stream.next();
121
+ if (ch === q && stream.string[stream.pos - 2] !== "\\") break;
122
+ }
123
+ return "string";
124
+ }
125
+ if (stream.match(/^`/)) {
126
+ while (!stream.eol()) {
127
+ if (stream.next() === "`") break;
128
+ }
129
+ return "string";
130
+ }
131
+ if (stream.match(/\b(const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|new|this|class|extends|import|export|default|from|try|catch|finally|throw|async|await|typeof|instanceof|in|of|void|null|undefined|true|false)\b/)) return "keyword";
132
+ if (stream.match(/^\d+(\.\d+)?/)) return "number";
133
+ if (stream.match(/^[a-zA-Z_$][\w$]*(?=\s*\()/)) return "function";
134
+ if (stream.match(/^[a-zA-Z_$][\w$]*/)) return "variableName";
135
+ if (stream.match(/^[+\-*\/%=!<>&|^~?:]+/)) return "keyword";
136
+ stream.next();
137
+ return null;
138
+ }
139
+ if (state.embeddedLang === "style") {
140
+ if (stream.match(/^\/\*/)) {
141
+ while (!stream.eol()) {
142
+ if (stream.match(/\*\//)) return "comment";
143
+ stream.next();
144
+ }
145
+ return "comment";
146
+ }
147
+ if (stream.match(/^["']/)) {
148
+ const q = stream.current();
149
+ while (!stream.eol()) {
150
+ const ch = stream.next();
151
+ if (ch === q && stream.string[stream.pos - 2] !== "\\") break;
152
+ }
153
+ return "string";
154
+ }
155
+ if (stream.match(/^@[a-zA-Z-]+/)) return "keyword";
156
+ if (stream.match(/^#[0-9a-fA-F]{3,8}\b/)) return "string";
157
+ if (stream.match(/^\d+(\.\d+)?(px|em|rem|%|vh|vw|vmin|vmax|s|ms|deg|fr)?\b/)) return "number";
158
+ if (stream.match(/^[a-zA-Z-]+(?=\s*:)/)) return "propertyName";
159
+ if (stream.match(/^[.#][a-zA-Z][\w-]*/)) return "className";
160
+ if (stream.match(/\b(none|auto|inherit|initial|unset|normal|bold|italic|center|left|right|flex|grid|block|inline|relative|absolute|fixed|sticky|hidden|visible|scroll|cover|contain)\b/)) return "keyword";
161
+ if (stream.match(/^[a-zA-Z][\w-]*/)) return "typeName";
162
+ if (stream.match(/^[{}();:,]/)) return "keyword";
163
+ stream.next();
164
+ return null;
165
+ }
166
+ }
167
+ if (state.inCodeBlock) {
168
+ stream.skipToEnd();
169
+ return "comment";
170
+ }
171
+ if (state.inPropsBlock) {
172
+ stream.eatSpace();
173
+ if (stream.peek() === "}") {
174
+ stream.next();
175
+ state.inPropsBlock = false;
176
+ state.inDirectiveHeader = false;
177
+ state.lastPropKey = "";
178
+ return "keyword";
179
+ }
180
+ if (stream.match(/^\.[a-zA-Z0-9_-]+/)) return "className";
181
+ if (stream.match(/^#[a-zA-Z0-9_-]+/)) return "propertyName";
182
+ const urlKeys = /^(url|href|image|src|icon)$/i;
183
+ if (stream.match(/^[a-zA-Z][\w-]*(?==)/)) {
184
+ state.lastPropKey = stream.current();
185
+ return "propertyName";
186
+ }
187
+ if (stream.match(/^=/)) return "keyword";
188
+ if (stream.match(/^"[^"]*"|^'[^']*'/)) {
189
+ return urlKeys.test(state.lastPropKey) ? "url" : "string";
190
+ }
191
+ stream.next();
192
+ return null;
193
+ }
194
+ if (stream.sol()) {
195
+ let match;
196
+ if (match = stream.match(/^\s*(:::)\s*/)) {
197
+ const rest = stream.string.slice(stream.pos).trim();
198
+ if (rest === "") {
199
+ state.blockStack.pop();
200
+ } else {
201
+ const typeMatch = rest.match(/^([\w-]+)/);
202
+ state.blockStack.push(typeMatch ? typeMatch[1].toLowerCase() : "generic");
203
+ }
204
+ state.inDirectiveHeader = true;
205
+ return "keyword";
206
+ }
207
+ if (stream.match(/^\s*#[a-zA-Z][\w-]*\s*$/) && !stream.match(/^\s*#{1,6}\s/)) {
208
+ return "propertyName";
209
+ }
210
+ if (stream.match(/^\s*(#{1,6})\s+/)) return "heading";
211
+ if (stream.match(/^\s*```/)) {
212
+ state.inCodeBlock = true;
213
+ stream.skipToEnd();
214
+ return "comment";
215
+ }
216
+ if (stream.match(/^\s*([-*+]|\d+\.)\s+/)) return "variableName";
217
+ if (stream.match(/^\s*(---|___|(\*\s*){3,})\s*$/)) return "meta";
218
+ if (stream.match(/^\s*\[TOC\d?\]/)) return "keyword";
219
+ }
220
+ if (state.inDirectiveHeader) {
221
+ stream.eatSpace();
222
+ if (stream.match(/^[\w-]+/)) return "typeName";
223
+ if (stream.peek() === "{") {
224
+ stream.next();
225
+ state.inPropsBlock = true;
226
+ state.inDirectiveHeader = true;
227
+ return "keyword";
228
+ }
229
+ state.inDirectiveHeader = false;
230
+ }
231
+ const currentBlockType = state.blockStack[state.blockStack.length - 1];
232
+ if (currentBlockType === "raw" && !state.inDirectiveHeader) {
233
+ if (stream.eatSpace()) return null;
234
+ if (stream.match(/^<\/?[a-zA-Z0-9-]+/)) return "typeName";
235
+ if (stream.match(/^>/)) return "typeName";
236
+ if (stream.match(/^[{}]/)) return "keyword";
237
+ if (stream.match(/^--[a-zA-Z0-9_-]+/)) return "variableName";
238
+ if (stream.match(/^[a-zA-Z-]+(?=\s*:)/)) return "propertyName";
239
+ if (stream.match(/^var\([^)]+\)/)) return "variableName";
240
+ if (stream.match(/^['"`][^'"`]*['"`]/)) return "string";
241
+ if (stream.match(/^[#.][a-zA-Z0-9_-]+/)) return "className";
242
+ if (stream.match(/^:[a-zA-Z0-9_-]+/)) return "keyword";
243
+ if (stream.match(/\b(const|let|var|function|return|if|else|for|while)\b/)) return "keyword";
244
+ stream.next();
245
+ return null;
246
+ }
247
+ if (state.imageState === "expectUrl") {
248
+ state.imageState = "expectOptions";
249
+ if (stream.eat("(")) {
250
+ let parenLevel = 1;
251
+ while (!stream.eol() && parenLevel > 0) {
252
+ const next = stream.next();
253
+ if (next === "(") parenLevel++;
254
+ else if (next === ")" && stream.string[stream.pos - 2] !== "\\") parenLevel--;
255
+ }
256
+ return "url";
257
+ } else {
258
+ state.imageState = "none";
259
+ }
260
+ }
261
+ if (state.imageState === "expectOptions") {
262
+ state.imageState = "none";
263
+ if (stream.eat("{")) {
264
+ stream.eatWhile(/[^}]/);
265
+ stream.eat("}");
266
+ return "attributeName";
267
+ }
268
+ }
269
+ if (state.linkState === "expectUrl") {
270
+ state.linkState = "none";
271
+ if (stream.eat("(")) {
272
+ let parenLevel = 1;
273
+ while (!stream.eol() && parenLevel > 0) {
274
+ const next = stream.next();
275
+ if (next === "(") parenLevel++;
276
+ else if (next === ")" && stream.string[stream.pos - 2] !== "\\") parenLevel--;
277
+ }
278
+ return "url";
279
+ }
280
+ }
281
+ if (stream.match(/^<\/?[a-zA-Z][\w-]*(?=[>\s/]|$)/)) {
282
+ const raw = stream.current();
283
+ state.htmlTagName = raw.replace(/^<\/?/, "").toLowerCase();
284
+ state.isClosingHtmlTag = raw.startsWith("</");
285
+ state.inHtmlBlock = true;
286
+ return "typeName";
287
+ }
288
+ if (stream.match(/\*\*\*.+?\*\*\*/)) return "strongEmphasis";
289
+ if (stream.match(/\*\*.+?\*\*/)) return "strong";
290
+ if (stream.match(/!\[[^\]]*?\]/)) {
291
+ if (stream.peek() === "(") state.imageState = "expectUrl";
292
+ return "string";
293
+ }
294
+ if (stream.match(/\[[^\]]+?\]/)) {
295
+ if (stream.peek() === "(") state.linkState = "expectUrl";
296
+ return "string";
297
+ }
298
+ if (stream.match(/\|\[[^\]]+?\]\|/)) return "keyword";
299
+ if (stream.match(/`[^`]+`/)) return "comment";
300
+ if (stream.match(/_(.+?)_/)) return "emphasis";
301
+ if (stream.match(/~~(.+?)~~/)) return "strikethrough";
302
+ if (stream.match(/!~(.+?)~!/)) return "underline";
303
+ if (stream.match(/==(.+?)==/)) return "highlight";
304
+ if (stream.match(/!>.+?<!/)) return "comment";
305
+ if (stream.match(/%[^%\s]+?%[^%]+?%%/)) return "string";
306
+ if (stream.match(/->|<-|\|/)) return "meta";
307
+ stream.next();
308
+ return null;
309
+ },
310
+ tokenTable: {
311
+ heading: import_highlight.tags.heading,
312
+ keyword: import_highlight.tags.keyword,
313
+ typeName: import_highlight.tags.typeName,
314
+ string: import_highlight.tags.string,
315
+ attributeName: import_highlight.tags.attributeName,
316
+ propertyName: import_highlight.tags.propertyName,
317
+ className: import_highlight.tags.className,
318
+ comment: import_highlight.tags.comment,
319
+ variableName: import_highlight.tags.variableName,
320
+ meta: import_highlight.tags.meta,
321
+ strong: import_highlight.tags.strong,
322
+ emphasis: import_highlight.tags.emphasis,
323
+ strongEmphasis: [import_highlight.tags.strong, import_highlight.tags.emphasis],
324
+ strikethrough: import_highlight.tags.strikethrough,
325
+ underline: import_highlight.tags.special(import_highlight.tags.emphasis),
326
+ highlight: import_highlight.tags.special(import_highlight.tags.comment),
327
+ url: import_highlight.tags.url,
328
+ link: import_highlight.tags.string,
329
+ number: import_highlight.tags.number,
330
+ function: import_highlight.tags.function(import_highlight.tags.variableName)
331
+ }
332
+ });
333
+
334
+ // NReditor.tsx
335
+ var import_state = require("@codemirror/state");
336
+ var import_language2 = require("@codemirror/language");
337
+ var import_highlight2 = require("@lezer/highlight");
338
+
339
+ // useDebounce.ts
340
+ var import_react = require("react");
341
+ function useDebounce(value, delay) {
342
+ const [debouncedValue, setDebouncedValue] = (0, import_react.useState)(value);
343
+ (0, import_react.useEffect)(() => {
344
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
345
+ return () => clearTimeout(timer);
346
+ }, [value, delay]);
347
+ return debouncedValue;
348
+ }
349
+
350
+ // CustomMarkdownRenderer.tsx
351
+ var import_react10 = __toESM(require("react"));
352
+
353
+ // utils.ts
354
+ function parseCssString(cssText) {
355
+ if (!cssText) return {};
356
+ return cssText.split(";").filter(Boolean).reduce((styleObj, styleString) => {
357
+ const parts = styleString.split(":");
358
+ if (parts.length < 2) return styleObj;
359
+ const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());
360
+ const value = parts.slice(1).join(":").trim();
361
+ styleObj[key] = value;
362
+ return styleObj;
363
+ }, {});
364
+ }
365
+ function generateId(text) {
366
+ return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-");
367
+ }
368
+ function scrollToId(id) {
369
+ const element = document.getElementById(id);
370
+ if (element) {
371
+ element.scrollIntoView({ behavior: "smooth", block: "start" });
372
+ }
373
+ }
374
+ function extractAttributes(text) {
375
+ const match = text.match(/^(.*?)\s*##\{([^}]*)\}\s*$/);
376
+ if (!match) return { text, classes: "", id: "" };
377
+ const rawAttrs = match[2];
378
+ const cleanedText = match[1];
379
+ const classList = [];
380
+ let id = "";
381
+ for (const [, key, value] of rawAttrs.matchAll(/([\w-]+)="([^"]*)"/g)) {
382
+ if (key === "class") {
383
+ classList.push(...value.split(/\s+/).filter(Boolean));
384
+ } else if (key === "id") {
385
+ id = value;
386
+ }
387
+ }
388
+ const stripped = rawAttrs.replace(/[\w-]+="[^"]*"/g, "");
389
+ for (const token of stripped.split(/\s+/).filter(Boolean)) {
390
+ if (token.startsWith(".")) classList.push(token.slice(1));
391
+ else if (token.startsWith("#") && !id) id = token.slice(1);
392
+ }
393
+ return { text: cleanedText, classes: classList.join(" "), id };
394
+ }
395
+ var _scopeCounter = 0;
396
+ function resetScopeCounter() {
397
+ _scopeCounter = 0;
398
+ }
399
+ function generateScopeId() {
400
+ return `scope-${++_scopeCounter}`;
401
+ }
402
+ function parseProps(propsString) {
403
+ const props = {};
404
+ if (!propsString?.trim()) return props;
405
+ const pairRegex = /(\w[\w-]*)=(?:"([^"]*)"|'([^']*)')/g;
406
+ let match;
407
+ while ((match = pairRegex.exec(propsString)) !== null) {
408
+ const key = match[1];
409
+ const value = match[2] ?? match[3] ?? "";
410
+ props[key] = value;
411
+ }
412
+ const classMatches = propsString.match(/\.([a-zA-Z0-9_!/.\-]+)/g);
413
+ if (classMatches) {
414
+ const existing = props["class"] || "";
415
+ const newClasses = classMatches.map((c) => c.substring(1)).join(" ");
416
+ props["class"] = existing ? `${existing} ${newClasses}` : newClasses;
417
+ }
418
+ const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\s|}|$)/);
419
+ if (idMatch && !props["id"]) {
420
+ props["id"] = idMatch[1];
421
+ }
422
+ return props;
423
+ }
424
+ function parseHtmlAttrs(attrsString) {
425
+ const props = {};
426
+ if (!attrsString?.trim()) return props;
427
+ const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
428
+ let match;
429
+ while ((match = pairRegex.exec(attrsString)) !== null) {
430
+ let key = match[1];
431
+ const value = match[2] ?? match[3] ?? match[4] ?? true;
432
+ if (key === "class") key = "className";
433
+ else if (key === "for") key = "htmlFor";
434
+ else if (key === "tabindex") key = "tabIndex";
435
+ if (key === "style" && typeof value === "string") {
436
+ props[key] = parseCssString(value);
437
+ } else {
438
+ props[key] = value;
439
+ }
440
+ }
441
+ return props;
442
+ }
443
+
444
+ // parser.ts
445
+ function parseMarkdown(markdown2) {
446
+ if (!markdown2) return [];
447
+ const lines = markdown2.split("\n");
448
+ const result = [];
449
+ let i = 0;
450
+ while (i < lines.length) {
451
+ const line = lines[i];
452
+ const trimmed = line.trim();
453
+ let match;
454
+ if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
455
+ const level = match[1].length;
456
+ const rawText = match[2];
457
+ const { text: text2, classes: classes2, id: customId } = extractAttributes(rawText);
458
+ const id2 = customId || generateId(text2.replace(/->|<-/g, ""));
459
+ result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
460
+ i++;
461
+ continue;
462
+ }
463
+ if (match = trimmed.match(/^->\s*(.+?)\s*(<-|->)\s*$/)) {
464
+ const content = match[1];
465
+ const align = match[2] === "<-" ? "center" : "right";
466
+ result.push({ type: "paragraph", content, align });
467
+ i++;
468
+ continue;
469
+ }
470
+ if (trimmed.startsWith("```")) {
471
+ const fenceHeader = trimmed.slice(3).trim();
472
+ const titleMatch = fenceHeader.match(/title=["']([^"']*)["']/);
473
+ const lang = fenceHeader.replace(/title=["'][^"']*["']/, "").trim();
474
+ const title = titleMatch ? titleMatch[1] : void 0;
475
+ const content = [];
476
+ i++;
477
+ while (i < lines.length && !lines[i].trim().startsWith("```")) {
478
+ content.push(lines[i]);
479
+ i++;
480
+ }
481
+ result.push({ type: "codeblock", language: lang, title, content: content.join("\n") });
482
+ i++;
483
+ continue;
484
+ }
485
+ if (trimmed.startsWith(":::")) {
486
+ const rest = trimmed.slice(3).trim();
487
+ if (rest === "") {
488
+ result.push({ type: "paragraph", content: line });
489
+ i++;
490
+ continue;
491
+ }
492
+ const typeMatch = rest.match(/^([\w-]+)/);
493
+ const directiveType = typeMatch ? typeMatch[1] : "custom";
494
+ let j = i + 1;
495
+ let nestedLevel = 0;
496
+ let foundClose = false;
497
+ while (j < lines.length) {
498
+ const currentTrimmed = lines[j].trim();
499
+ if (currentTrimmed === ":::") {
500
+ if (nestedLevel === 0) {
501
+ foundClose = true;
502
+ break;
503
+ } else {
504
+ nestedLevel--;
505
+ }
506
+ } else if (currentTrimmed.startsWith(":::")) {
507
+ nestedLevel++;
508
+ }
509
+ j++;
510
+ }
511
+ if (foundClose) {
512
+ const contentLines = [];
513
+ for (let k = i + 1; k < j; k++) {
514
+ contentLines.push(lines[k]);
515
+ }
516
+ const rawContent = contentLines.join("\n");
517
+ const headerRest = typeMatch ? rest.slice(directiveType.length).trim() : rest;
518
+ let propsString = "";
519
+ let shortForm = "";
520
+ const propsBlockMatch = headerRest.match(/^\{([^]*)\}\s*$/);
521
+ if (propsBlockMatch) {
522
+ propsString = propsBlockMatch[1];
523
+ } else if (headerRest) {
524
+ shortForm = headerRest;
525
+ }
526
+ const props = parseProps(propsString);
527
+ if (shortForm && !props["title"]) {
528
+ props["title"] = shortForm;
529
+ }
530
+ const slots = splitSlots(rawContent);
531
+ result.push({
532
+ type: "directive",
533
+ directiveType,
534
+ props,
535
+ slots,
536
+ scopeId: generateScopeId()
537
+ });
538
+ i = j + 1;
539
+ continue;
540
+ } else {
541
+ result.push({ type: "paragraph", content: line });
542
+ i++;
543
+ continue;
544
+ }
545
+ }
546
+ if (match = trimmed.match(/^(.*?)!\[([^\]]*)\]\(([^)]+?)\)(?:\{([^}]+?)\})?(.*)$/)) {
547
+ const [, preText, alt, srcAndFloat, size, postText] = match;
548
+ if (preText.trim()) {
549
+ result.push({ type: "paragraph", content: preText.trim() });
550
+ }
551
+ let src = srcAndFloat;
552
+ const style = {};
553
+ if (src.includes("#left")) {
554
+ src = src.replace("#left", "");
555
+ style.float = "left";
556
+ style.margin = "0 1em 1em 0";
557
+ } else if (src.includes("#right")) {
558
+ src = src.replace("#right", "");
559
+ style.float = "right";
560
+ style.margin = "0 0 1em 1em";
561
+ } else if (src.includes("#center")) {
562
+ src = src.replace("#center", "");
563
+ style.display = "block";
564
+ style.margin = "0 auto 1em auto";
565
+ }
566
+ if (size) {
567
+ const [width, height] = size.split(":");
568
+ if (width) style.width = width.trim();
569
+ if (height) style.height = height.trim();
570
+ }
571
+ result.push({ type: "image", alt, src, style });
572
+ if (postText.trim()) {
573
+ result.push({ type: "paragraph", content: postText.trim() });
574
+ }
575
+ i++;
576
+ continue;
577
+ }
578
+ if (trimmed.includes("|") && i + 1 < lines.length && lines[i + 1].includes("---")) {
579
+ const tableLines = [line];
580
+ i++;
581
+ tableLines.push(lines[i]);
582
+ i++;
583
+ while (i < lines.length && lines[i].trim().includes("|")) {
584
+ tableLines.push(lines[i]);
585
+ i++;
586
+ }
587
+ result.push({ type: "table", content: tableLines.join("\n") });
588
+ continue;
589
+ }
590
+ if (match = trimmed.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/)) {
591
+ const listItems = [line];
592
+ i++;
593
+ while (i < lines.length) {
594
+ const nextLine = lines[i];
595
+ const nextTrimmed = nextLine.trim();
596
+ if (nextTrimmed.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/) || nextTrimmed === "" || nextLine.startsWith(" ")) {
597
+ listItems.push(nextLine);
598
+ i++;
599
+ } else {
600
+ break;
601
+ }
602
+ }
603
+ result.push({ type: "list", content: listItems.join("\n") });
604
+ continue;
605
+ }
606
+ if (trimmed.startsWith(">")) {
607
+ const quoteLines = [line];
608
+ i++;
609
+ while (i < lines.length && (lines[i].trim().startsWith(">") || lines[i].trim() === "")) {
610
+ quoteLines.push(lines[i]);
611
+ i++;
612
+ }
613
+ const rawQuote = quoteLines.join("\n").replace(/^>\s?/gm, "");
614
+ const { text: text2, classes: classes2, id: id2 } = extractAttributes(rawQuote);
615
+ result.push({ type: "blockquote", content: text2, classes: classes2 || void 0, id: id2 });
616
+ continue;
617
+ }
618
+ if (/^(---|___|(\*\s*){3,})\s*$/.test(trimmed)) {
619
+ result.push({ type: "hr" });
620
+ i++;
621
+ continue;
622
+ }
623
+ if (/^\[TOC\d?\]\s*$/.test(trimmed)) {
624
+ result.push({ type: "toc" });
625
+ i++;
626
+ continue;
627
+ }
628
+ if (trimmed === "") {
629
+ i++;
630
+ continue;
631
+ }
632
+ let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
633
+ if (tagStartMatch) {
634
+ const tagName = tagStartMatch[1].toLowerCase();
635
+ const voidElements = /* @__PURE__ */ new Set([
636
+ "area",
637
+ "base",
638
+ "br",
639
+ "col",
640
+ "embed",
641
+ "hr",
642
+ "img",
643
+ "input",
644
+ "link",
645
+ "meta",
646
+ "param",
647
+ "source",
648
+ "track",
649
+ "wbr"
650
+ ]);
651
+ const remainingText = lines.slice(i).join("\n");
652
+ const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
653
+ const openTagMatch = remainingText.match(openTagRegex);
654
+ if (openTagMatch) {
655
+ const fullOpenTag = openTagMatch[0];
656
+ const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
657
+ const isSelfClosing = fullOpenTag.endsWith("/>") || voidElements.has(tagName);
658
+ if (isSelfClosing) {
659
+ const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
660
+ const consumedLines = blockText.split("\n").length;
661
+ result.push({
662
+ type: "html-block",
663
+ tag: tagName,
664
+ attrs,
665
+ children: []
666
+ // No children
667
+ });
668
+ i += consumedLines;
669
+ continue;
670
+ } else {
671
+ let nestedLevel = 0;
672
+ let closeIndex = -1;
673
+ let closeTagLength = 0;
674
+ const tagRegex = new RegExp(`</?${tagName}\\b[^>]*>`, "gi");
675
+ tagRegex.lastIndex = openTagMatch.index + fullOpenTag.length;
676
+ let execMatch;
677
+ while ((execMatch = tagRegex.exec(remainingText)) !== null) {
678
+ if (execMatch[0].startsWith("</")) {
679
+ nestedLevel--;
680
+ if (nestedLevel < 0) {
681
+ closeIndex = execMatch.index;
682
+ closeTagLength = execMatch[0].length;
683
+ break;
684
+ }
685
+ } else {
686
+ if (!execMatch[0].endsWith("/>")) {
687
+ nestedLevel++;
688
+ }
689
+ }
690
+ }
691
+ if (closeIndex !== -1) {
692
+ const fullBlock = remainingText.substring(0, closeIndex + closeTagLength);
693
+ const consumedLines = fullBlock.split("\n").length;
694
+ if (tagName === "style" || tagName === "script") {
695
+ result.push({
696
+ type: "html",
697
+ content: fullBlock,
698
+ scopeId: generateScopeId()
699
+ });
700
+ } else {
701
+ const innerContent = remainingText.substring(openTagMatch.index + fullOpenTag.length, closeIndex);
702
+ result.push({
703
+ type: "html-block",
704
+ tag: tagName,
705
+ attrs,
706
+ children: parseMarkdown(innerContent)
707
+ });
708
+ }
709
+ i += consumedLines;
710
+ continue;
711
+ } else {
712
+ const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
713
+ const consumedLines = blockText.split("\n").length;
714
+ result.push({
715
+ type: "html-block",
716
+ tag: tagName,
717
+ attrs,
718
+ children: []
719
+ });
720
+ i += consumedLines;
721
+ continue;
722
+ }
723
+ }
724
+ }
725
+ }
726
+ const paragraphLines = [line];
727
+ i++;
728
+ while (i < lines.length) {
729
+ const nextLine = lines[i];
730
+ const nextTrimmed = nextLine.trim();
731
+ if (nextTrimmed === "" || nextTrimmed.startsWith("#") || nextTrimmed.startsWith(":::") || nextTrimmed.includes("|") || nextTrimmed.match(/^(\s*)([-*+]|\d+\.)\s+/) || nextTrimmed.startsWith(">") || nextTrimmed.startsWith("```") || nextTrimmed.startsWith("->") || nextTrimmed.match(/^<([a-zA-Z][\w-]*)\b/)) {
732
+ break;
733
+ }
734
+ paragraphLines.push(nextLine);
735
+ i++;
736
+ }
737
+ const rawParagraph = paragraphLines.join("\n").trim();
738
+ const { text, classes, id } = extractAttributes(rawParagraph);
739
+ result.push({ type: "paragraph", content: text, classes: classes || void 0, id });
740
+ }
741
+ return result;
742
+ }
743
+ function splitSlots(rawContent) {
744
+ const slots = {};
745
+ const lines = rawContent.split("\n");
746
+ let currentSlot = "default";
747
+ let buffer = [];
748
+ let nestingDepth = 0;
749
+ for (const line of lines) {
750
+ const trimmed = line.trim();
751
+ if (trimmed.startsWith(":::")) {
752
+ const rest = trimmed.slice(3).trim();
753
+ if (rest === "") {
754
+ nestingDepth = Math.max(0, nestingDepth - 1);
755
+ } else {
756
+ nestingDepth++;
757
+ }
758
+ }
759
+ const slotMatch = trimmed.match(/^#([\w-]+)$/);
760
+ if (slotMatch && nestingDepth === 0) {
761
+ slots[currentSlot] = buffer.join("\n").trim();
762
+ buffer = [];
763
+ currentSlot = slotMatch[1];
764
+ } else {
765
+ buffer.push(line);
766
+ }
767
+ }
768
+ slots[currentSlot] = buffer.join("\n").trim();
769
+ for (const key of Object.keys(slots)) {
770
+ if (!slots[key]) delete slots[key];
771
+ }
772
+ return slots;
773
+ }
774
+
775
+ // ui-components.tsx
776
+ var import_react2 = require("react");
777
+
778
+ // highlightSetup.ts
779
+ var import_core = __toESM(require("highlight.js/lib/core"));
780
+ var import_javascript = __toESM(require("highlight.js/lib/languages/javascript"));
781
+ var import_typescript = __toESM(require("highlight.js/lib/languages/typescript"));
782
+ var import_python = __toESM(require("highlight.js/lib/languages/python"));
783
+ var import_css = __toESM(require("highlight.js/lib/languages/css"));
784
+ var import_xml = __toESM(require("highlight.js/lib/languages/xml"));
785
+ var import_json = __toESM(require("highlight.js/lib/languages/json"));
786
+ var import_bash = __toESM(require("highlight.js/lib/languages/bash"));
787
+ var import_sql = __toESM(require("highlight.js/lib/languages/sql"));
788
+ var import_markdown = __toESM(require("highlight.js/lib/languages/markdown"));
789
+ var import_java = __toESM(require("highlight.js/lib/languages/java"));
790
+ var import_csharp = __toESM(require("highlight.js/lib/languages/csharp"));
791
+ var import_cpp = __toESM(require("highlight.js/lib/languages/cpp"));
792
+ var import_go = __toESM(require("highlight.js/lib/languages/go"));
793
+ var import_rust = __toESM(require("highlight.js/lib/languages/rust"));
794
+ var import_php = __toESM(require("highlight.js/lib/languages/php"));
795
+ var import_ruby = __toESM(require("highlight.js/lib/languages/ruby"));
796
+ var import_swift = __toESM(require("highlight.js/lib/languages/swift"));
797
+ var import_kotlin = __toESM(require("highlight.js/lib/languages/kotlin"));
798
+ var import_dart = __toESM(require("highlight.js/lib/languages/dart"));
799
+ var import_yaml = __toESM(require("highlight.js/lib/languages/yaml"));
800
+ var import_ini = __toESM(require("highlight.js/lib/languages/ini"));
801
+ var import_dockerfile = __toESM(require("highlight.js/lib/languages/dockerfile"));
802
+ var import_diff = __toESM(require("highlight.js/lib/languages/diff"));
803
+ var import_shell = __toESM(require("highlight.js/lib/languages/shell"));
804
+ import_core.default.registerLanguage("javascript", import_javascript.default);
805
+ import_core.default.registerLanguage("js", import_javascript.default);
806
+ import_core.default.registerLanguage("jsx", import_javascript.default);
807
+ import_core.default.registerLanguage("typescript", import_typescript.default);
808
+ import_core.default.registerLanguage("ts", import_typescript.default);
809
+ import_core.default.registerLanguage("tsx", import_typescript.default);
810
+ import_core.default.registerLanguage("python", import_python.default);
811
+ import_core.default.registerLanguage("py", import_python.default);
812
+ import_core.default.registerLanguage("css", import_css.default);
813
+ import_core.default.registerLanguage("html", import_xml.default);
814
+ import_core.default.registerLanguage("xml", import_xml.default);
815
+ import_core.default.registerLanguage("svg", import_xml.default);
816
+ import_core.default.registerLanguage("json", import_json.default);
817
+ import_core.default.registerLanguage("bash", import_bash.default);
818
+ import_core.default.registerLanguage("sh", import_bash.default);
819
+ import_core.default.registerLanguage("zsh", import_bash.default);
820
+ import_core.default.registerLanguage("sql", import_sql.default);
821
+ import_core.default.registerLanguage("markdown", import_markdown.default);
822
+ import_core.default.registerLanguage("md", import_markdown.default);
823
+ import_core.default.registerLanguage("java", import_java.default);
824
+ import_core.default.registerLanguage("csharp", import_csharp.default);
825
+ import_core.default.registerLanguage("cs", import_csharp.default);
826
+ import_core.default.registerLanguage("cpp", import_cpp.default);
827
+ import_core.default.registerLanguage("c", import_cpp.default);
828
+ import_core.default.registerLanguage("go", import_go.default);
829
+ import_core.default.registerLanguage("rust", import_rust.default);
830
+ import_core.default.registerLanguage("rs", import_rust.default);
831
+ import_core.default.registerLanguage("php", import_php.default);
832
+ import_core.default.registerLanguage("ruby", import_ruby.default);
833
+ import_core.default.registerLanguage("rb", import_ruby.default);
834
+ import_core.default.registerLanguage("swift", import_swift.default);
835
+ import_core.default.registerLanguage("kotlin", import_kotlin.default);
836
+ import_core.default.registerLanguage("kt", import_kotlin.default);
837
+ import_core.default.registerLanguage("dart", import_dart.default);
838
+ import_core.default.registerLanguage("yaml", import_yaml.default);
839
+ import_core.default.registerLanguage("yml", import_yaml.default);
840
+ import_core.default.registerLanguage("toml", import_ini.default);
841
+ import_core.default.registerLanguage("ini", import_ini.default);
842
+ import_core.default.registerLanguage("dockerfile", import_dockerfile.default);
843
+ import_core.default.registerLanguage("docker", import_dockerfile.default);
844
+ import_core.default.registerLanguage("diff", import_diff.default);
845
+ import_core.default.registerLanguage("shell", import_shell.default);
846
+ var highlightSetup_default = import_core.default;
847
+
848
+ // ui-components.tsx
849
+ var import_dialog = require("@base-ui/react/dialog");
850
+ var import_jsx_runtime = require("react/jsx-runtime");
851
+ var IconRenderer = ({ iconName, extraClasses = "" }) => {
852
+ if (!iconName) return null;
853
+ const baseClass = `material-symbols-rounded !text-[1em] leading-none align-top ${extraClasses}`;
854
+ const isCodepoint = /^[eE][0-9a-fA-F]{3,4}$/.test(iconName);
855
+ if (isCodepoint) {
856
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
857
+ "span",
858
+ {
859
+ className: baseClass,
860
+ dangerouslySetInnerHTML: { __html: `&#x${iconName};` },
861
+ "aria-hidden": "true"
862
+ }
863
+ );
864
+ }
865
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: baseClass, "aria-hidden": "true", children: iconName });
866
+ };
867
+ var CodeBlock = ({ code, language, title }) => {
868
+ const [copied, setCopied] = (0, import_react2.useState)(false);
869
+ const timerRef = (0, import_react2.useRef)(null);
870
+ const lang = language?.split(/[\s{]/)[0]?.trim() || "";
871
+ let html;
872
+ try {
873
+ if (lang && highlightSetup_default.getLanguage(lang)) {
874
+ html = highlightSetup_default.highlight(code, { language: lang }).value;
875
+ } else {
876
+ html = highlightSetup_default.highlightAuto(code).value;
877
+ }
878
+ } catch {
879
+ html = "";
880
+ }
881
+ const handleCopy = () => {
882
+ navigator.clipboard.writeText(code);
883
+ setCopied(true);
884
+ if (timerRef.current) clearTimeout(timerRef.current);
885
+ timerRef.current = setTimeout(() => setCopied(false), 1800);
886
+ };
887
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "not-prose my-4 rounded-2xl border border-border overflow-hidden bg-background-secondary-solid/5", children: [
888
+ title && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 px-4 py-2 border-b border-border bg-background-secondary-solid/10 text-xs sm:text-sm font-mono text-text-secondary", children: [
889
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "material-symbols-rounded text-base", children: "description" }),
890
+ title
891
+ ] }),
892
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-auto [&_pre]:m-0 [&_pre]:p-4 [&_pre]:text-xs sm:[&_pre]:text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: "m-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: `language-${lang || "plaintext"}`, dangerouslySetInnerHTML: { __html: html } }) }) }),
893
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "absolute top-2 right-2 p-1.5 rounded-lg bg-background-secondary-solid/20 hover:bg-background-secondary-solid/40 transition-colors cursor-pointer border-none text-text-secondary hover:text-text-primary", onClick: handleCopy, title: "Copy code", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "material-symbols-rounded", style: { fontSize: "1rem" }, children: copied ? "check" : "content_copy" }) })
894
+ ] });
895
+ };
896
+ var defaultIcons = {
897
+ note: "info",
898
+ info: "lightbulb",
899
+ warning: "warning",
900
+ danger: "report",
901
+ greentext: "subdirectory_play_arrow"
902
+ };
903
+ var typeClasses = {
904
+ note: "border-info/20 bg-info/5 text-info",
905
+ info: "border-info/30 bg-info/10 text-info",
906
+ warning: "border-amber-500/30 bg-amber-500/10 text-amber-500",
907
+ danger: "border-danger/30 bg-danger/10 text-danger",
908
+ greentext: "border-success/30 bg-success/10 text-success"
909
+ };
910
+ var Admonition = ({ type, title, icon, className = "", style, children }) => {
911
+ const iconToRender = icon || defaultIcons[type] || "info";
912
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
913
+ "div",
914
+ {
915
+ className: `not-prose rounded-2xl mb-6 border shadow-xs p-4 ${typeClasses[type] || typeClasses.note} ${className}`,
916
+ style,
917
+ children: [
918
+ title && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h5", { className: "font-bold text-base mb-2 m-0 flex items-center gap-2", children: [
919
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconRenderer, { iconName: iconToRender, extraClasses: "shrink-0" }),
920
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: title })
921
+ ] }),
922
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm leading-relaxed opacity-90", children })
923
+ ]
924
+ }
925
+ );
926
+ };
927
+ var Details = ({
928
+ title,
929
+ icon,
930
+ defaultOpen = false,
931
+ className = "",
932
+ style,
933
+ children
934
+ }) => {
935
+ const [isOpen, setIsOpen] = (0, import_react2.useState)(defaultOpen);
936
+ const iconToRender = icon || "play_arrow";
937
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
938
+ "details",
939
+ {
940
+ className: `not-prose rounded-2xl border border-border mb-4 bg-background-primary/5 ${className}`,
941
+ open: isOpen,
942
+ style,
943
+ children: [
944
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
945
+ "summary",
946
+ {
947
+ className: "cursor-pointer p-4 font-bold flex items-center gap-2 list-none [&::-webkit-details-marker]:hidden hover:text-accent-primary transition-colors",
948
+ onClick: (e) => {
949
+ e.preventDefault();
950
+ setIsOpen((prev) => !prev);
951
+ },
952
+ children: [
953
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
954
+ IconRenderer,
955
+ {
956
+ iconName: iconToRender,
957
+ extraClasses: `transition-transform ${isOpen ? "rotate-90" : ""}`
958
+ }
959
+ ),
960
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: title })
961
+ ]
962
+ }
963
+ ),
964
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-4 pb-4 border-t border-border pt-3 text-sm leading-relaxed opacity-90 overflow-hidden min-w-0", children })
965
+ ]
966
+ }
967
+ );
968
+ };
969
+ var Modal = ({ title, isOpen, onClose, children }) => {
970
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Root, { open: isOpen, onOpenChange: (open) => {
971
+ if (!open) onClose();
972
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.Dialog.Portal, { children: [
973
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Backdrop, { className: "fixed inset-0 z-[9999] bg-black/60" }),
974
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Viewport, { className: "fixed inset-0 z-[9999] flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.Dialog.Popup, { className: "bg-background-primary border border-border shadow-2xl rounded-3xl w-full max-w-3xl max-h-[85vh] flex flex-col overflow-hidden", children: [
975
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between items-center p-4 border-b border-border bg-background-secondary-solid/20", children: [
976
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Title, { className: "text-lg font-bold !m-0", children: title }),
977
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Close, { className: "w-8 h-8 rounded-full hover:bg-white/10 flex items-center justify-center transition-colors cursor-pointer border-none bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "material-symbols-rounded text-base", children: "close" }) })
978
+ ] }),
979
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-6 overflow-auto min-h-0 text-text-primary [&_h1:first-child]:mt-0 [&_h2:first-child]:mt-0 [&_h3:first-child]:mt-0 [&_h4:first-child]:mt-0 [&_h5:first-child]:mt-0 [&_h6:first-child]:mt-0", children })
980
+ ] }) })
981
+ ] }) });
982
+ };
983
+
984
+ // renderers.tsx
985
+ var import_jsx_runtime2 = require("react/jsx-runtime");
986
+ function renderInline(text) {
987
+ if (!text) return text;
988
+ const parsePart = (part, key) => {
989
+ let match2;
990
+ if (match2 = part.match(/^\|\[([^\]]+)\]\|$/)) {
991
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconRenderer, { iconName: match2[1] }, key);
992
+ }
993
+ if (match2 = part.match(/^!~(.+?)~!$/)) {
994
+ const content = match2[1];
995
+ const parts = content.split(";");
996
+ let color = "currentColor";
997
+ let decorationStyle = "solid";
998
+ let type = "underline";
999
+ let textIndex = 0;
1000
+ if (parts[textIndex]?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) || ["red", "blue", "green", "purple", "orange", "yellow", "pink"].includes(parts[textIndex])) {
1001
+ color = parts[textIndex++];
1002
+ }
1003
+ if (["solid", "double", "dotted", "dashed", "wavy"].includes(parts[textIndex])) {
1004
+ decorationStyle = parts[textIndex++];
1005
+ }
1006
+ if (["underline", "line-through", "overline", "both"].includes(parts[textIndex])) {
1007
+ type = parts[textIndex] === "both" ? "underline line-through" : parts[textIndex++];
1008
+ }
1009
+ const innerText = parts.slice(textIndex).join(";");
1010
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1011
+ "span",
1012
+ {
1013
+ style: {
1014
+ textDecoration: `${type} ${decorationStyle} ${color}`,
1015
+ textDecorationThickness: "auto"
1016
+ },
1017
+ children: renderInline(innerText)
1018
+ },
1019
+ key
1020
+ );
1021
+ }
1022
+ if (match2 = part.match(/%([^%\s]+?)%([\s\S]+?)%%/)) {
1023
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: match2[1] }, children: renderInline(match2[2]) }, key);
1024
+ }
1025
+ if (match2 = part.match(/^!>([^<]+?)<!$/)) {
1026
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "bg-text-primary text-bg-primary px-1 rounded hover:bg-transparent transition-colors cursor-pointer", children: renderInline(match2[1]) }, key);
1027
+ }
1028
+ if (match2 = part.match(/^==(.+?)==$/)) {
1029
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("mark", { className: "bg-yellow-500/20 text-inherit px-0.5 rounded", children: renderInline(match2[1]) }, key);
1030
+ }
1031
+ if (match2 = part.match(/^\*\*\*(.+?)\*\*\*$/)) {
1032
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: renderInline(match2[1]) }) }, key);
1033
+ }
1034
+ if (match2 = part.match(/^\*\*(.+?)\*\*$/)) {
1035
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: renderInline(match2[1]) }, key);
1036
+ }
1037
+ if (match2 = part.match(/^_(.+?)_$/)) {
1038
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: renderInline(match2[1]) }, key);
1039
+ }
1040
+ if (match2 = part.match(/^~~(.+?)~~$/)) {
1041
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("del", { children: renderInline(match2[1]) }, key);
1042
+ }
1043
+ if (match2 = part.match(/^`([^`]+)`$/)) {
1044
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { className: "text-[0.875em] font-mono bg-background-secondary/50 px-1.5 py-0.5 rounded text-text-primary", children: match2[1] }, key);
1045
+ }
1046
+ if (match2 = part.match(/^\[([^\]]+?)\]\(([^)]+?)\)$/)) {
1047
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1048
+ "a",
1049
+ {
1050
+ href: match2[2],
1051
+ className: "text-accent-primary underline decoration-accent-primary/40 hover:decoration-accent-primary transition-colors",
1052
+ target: "_blank",
1053
+ rel: "noopener noreferrer",
1054
+ children: renderInline(match2[1])
1055
+ },
1056
+ key
1057
+ );
1058
+ }
1059
+ if (part.startsWith("<") && part.endsWith(">")) {
1060
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { dangerouslySetInnerHTML: { __html: part } }, key);
1061
+ }
1062
+ return part;
1063
+ };
1064
+ const regex = /(\|\[[^\]]+\]\||\*\*\*.+?\*\*\*|\*\*.+?\*\*|_.+?_|~~.+?~~|`[^`]+?`|!~.+?~!|%[^%\s]+?%[\s\S]+?%%|!>.+?<!|==.+?==|\[[^\]]+?\]\([^)]+?\)|<[^>]+>)/g;
1065
+ const elements = [];
1066
+ let lastIndex = 0;
1067
+ let match;
1068
+ let keyCounter = 0;
1069
+ while ((match = regex.exec(text)) !== null) {
1070
+ if (match.index > lastIndex) {
1071
+ elements.push(text.slice(lastIndex, match.index));
1072
+ }
1073
+ elements.push(parsePart(match[0], `inline-${keyCounter++}`));
1074
+ lastIndex = regex.lastIndex;
1075
+ }
1076
+ if (lastIndex < text.length) {
1077
+ elements.push(text.slice(lastIndex));
1078
+ }
1079
+ return elements;
1080
+ }
1081
+ function renderTable(content) {
1082
+ const rows = content.split("\n").filter((r) => r.trim());
1083
+ if (rows.length < 2) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: content });
1084
+ const parseRow = (row) => row.split("|").map((c) => c.trim()).filter(Boolean);
1085
+ const headerCells = parseRow(rows[0]);
1086
+ const bodyRows = rows.slice(2).map(parseRow);
1087
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { className: "w-full text-sm sm:text-base border-collapse my-4", children: [
1088
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: headerCells.map((cell, ci) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { className: "border border-border px-3 py-2 bg-background-secondary-solid/10 text-left font-bold", children: renderInline(cell) }, ci)) }) }),
1089
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: bodyRows.map((cells, ri) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: cells.map((cell, ci) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "border border-border px-3 py-2", children: renderInline(cell) }, ci)) }, ri)) })
1090
+ ] }) });
1091
+ }
1092
+ function renderList(content) {
1093
+ const lines = content.split("\n");
1094
+ const items = [];
1095
+ for (const line of lines) {
1096
+ if (!line.trim()) continue;
1097
+ const match = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/);
1098
+ if (match) {
1099
+ items.push({
1100
+ indent: match[1].length,
1101
+ marker: match[2],
1102
+ text: match[3]
1103
+ });
1104
+ }
1105
+ }
1106
+ if (items.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: content });
1107
+ const isOrdered = /^\d+\.$/.test(items[0].marker);
1108
+ const Tag = isOrdered ? "ol" : "ul";
1109
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Tag, { className: `${isOrdered ? "list-decimal" : "list-disc"} pl-6 my-3 space-y-1 text-sm sm:text-base`, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { className: "leading-relaxed", children: renderInline(item.text) }, index)) });
1110
+ }
1111
+ function extractHeaders(elements) {
1112
+ return elements.filter((el) => el.type === "header");
1113
+ }
1114
+
1115
+ // directives/AdmonitionDirective.tsx
1116
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1117
+ var AdmonitionDirective = ({
1118
+ directiveType,
1119
+ props,
1120
+ renderSlot
1121
+ }) => {
1122
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1123
+ Admonition,
1124
+ {
1125
+ type: directiveType,
1126
+ title: props.title,
1127
+ icon: props.icon,
1128
+ className: props.class,
1129
+ style: props.style ? parseCssString(props.style) : void 0,
1130
+ children: renderSlot("default")
1131
+ }
1132
+ );
1133
+ };
1134
+ var AdmonitionDirective_default = AdmonitionDirective;
1135
+
1136
+ // directives/CardDirective.tsx
1137
+ var import_react3 = __toESM(require("react"));
1138
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1139
+ var CardDirective = ({
1140
+ directiveType,
1141
+ props,
1142
+ slots,
1143
+ renderSlot,
1144
+ context,
1145
+ options = {}
1146
+ }) => {
1147
+ const stableId = (0, import_react3.useId)();
1148
+ const { title, image, icon, class: customClass, url, target } = props;
1149
+ const hasDescription = !!slots.description;
1150
+ const { isSingleCard } = options;
1151
+ const isModal = directiveType === "card-m";
1152
+ const isLink = directiveType === "card-b";
1153
+ const modalId = `modal-card-${props.id || stableId}`;
1154
+ const wrapperClass = customClass || "";
1155
+ const inlineStyles = props.style ? parseCssString(props.style) : {};
1156
+ const description = hasDescription ? renderSlot("description") : null;
1157
+ const content = renderSlot("content") || renderSlot("default");
1158
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react3.default.Fragment, { children: [
1159
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1160
+ "div",
1161
+ {
1162
+ className: `flex flex-col h-full rounded-3xl transition-all relative overflow-hidden group border min-w-[18rem] w-[18rem] max-w-[20rem] ${isModal || isLink ? "cursor-pointer !border-accent-primary/10 hover:border-accent-primary/50" : "border-border"} ${wrapperClass}`,
1163
+ style: inlineStyles,
1164
+ onClick: isModal ? (e) => {
1165
+ e.preventDefault();
1166
+ e.stopPropagation();
1167
+ context.setModals((prev) => ({ ...prev, [modalId]: true }));
1168
+ } : isLink && url ? () => window.open(url, "_blank") : void 0,
1169
+ role: isModal ? "button" : void 0,
1170
+ tabIndex: isModal ? 0 : void 0,
1171
+ onKeyDown: isModal ? (e) => {
1172
+ if (e.key === "Enter" || e.key === " ") context.setModals((prev) => ({ ...prev, [modalId]: true }));
1173
+ } : void 0,
1174
+ children: [
1175
+ image && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `w-full ${isSingleCard ? "h-[240px]" : "h-[160px]"} overflow-hidden relative transition-all duration-500`, children: [
1176
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: image, alt: title || "", className: "w-full h-full object-cover !m-0" }),
1177
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute inset-0 bg-gradient-to-t from-background-primary/40 to-transparent" })
1178
+ ] }),
1179
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `flex flex-col flex-1 bg-background-primary/80 rounded-t-xl p-6 relative ${image ? "-mt-10" : ""} border-t border-white/5 shadow-2xl`, children: [
1180
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-3 mb-3", children: [
1181
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "w-10 h-10 text-[1.6em] rounded-xl bg-accent-primary/20 flex items-center justify-center shrink-0 text-accent-primary", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconRenderer, { iconName: icon }) }),
1182
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "text-base font-black tracking-tight leading-tight !m-0", children: title })
1183
+ ] }),
1184
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-1 flex flex-col gap-2", children: [
1185
+ description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-sm opacity-80 leading-relaxed font-medium", children: description }),
1186
+ directiveType === "card" && content && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-2", children: content })
1187
+ ] }),
1188
+ (isModal || isLink) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-6 flex justify-end", children: isLink && url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1189
+ "a",
1190
+ {
1191
+ href: url,
1192
+ target: "_blank",
1193
+ rel: "noopener noreferrer",
1194
+ className: "bg-accent-primary/20 hover:bg-accent-primary/30 px-4 py-2 rounded-xl flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest opacity-50 group-hover:opacity-100 group-hover:text-accent-primary transition-all no-underline",
1195
+ onClick: (e) => e.stopPropagation(),
1196
+ children: [
1197
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconRenderer, { iconName: "open_in_new" }),
1198
+ " Link"
1199
+ ]
1200
+ }
1201
+ ) : isModal ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "bg-accent-primary/20 hover:bg-accent-primary/30 px-4 py-2 cursor-pointer rounded-xl flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest opacity-50 group-hover:opacity-100 group-hover:text-accent-primary transition-all", children: [
1202
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconRenderer, { iconName: "arrow_forward" }),
1203
+ " Abrir"
1204
+ ] }) : null })
1205
+ ] })
1206
+ ]
1207
+ }
1208
+ ),
1209
+ isModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1210
+ Modal,
1211
+ {
1212
+ title: title || "Detalles",
1213
+ isOpen: !!context.modals[modalId],
1214
+ onClose: () => context.setModals((prev) => ({ ...prev, [modalId]: false })),
1215
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "prose prose-sm max-w-none", children: content })
1216
+ }
1217
+ )
1218
+ ] });
1219
+ };
1220
+ var CardDirective_default = CardDirective;
1221
+
1222
+ // directives/DetailsDirective.tsx
1223
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1224
+ var DetailsDirective = ({
1225
+ props,
1226
+ renderSlot
1227
+ }) => {
1228
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1229
+ Details,
1230
+ {
1231
+ title: props.title || "Details",
1232
+ icon: props.icon,
1233
+ defaultOpen: props.defaultOpen === "true",
1234
+ className: props.class,
1235
+ style: props.style ? parseCssString(props.style) : void 0,
1236
+ children: renderSlot("default")
1237
+ }
1238
+ );
1239
+ };
1240
+ var DetailsDirective_default = DetailsDirective;
1241
+
1242
+ // directives/ModalDirective.tsx
1243
+ var import_react4 = require("react");
1244
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1245
+ var ModalDirective = ({
1246
+ props,
1247
+ renderSlot,
1248
+ context
1249
+ }) => {
1250
+ const stableId = (0, import_react4.useId)();
1251
+ const modalId = `modal-${props.id || stableId}`;
1252
+ const label = props.label || props.title || "Open";
1253
+ const modalTitle = props.title || "Modal";
1254
+ const customClass = props.class || "";
1255
+ const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
1256
+ const sizeClass = hasSizeClass ? "" : "text-sm";
1257
+ const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
1258
+ const displayClass = hasDisplayClass ? "" : "inline-flex";
1259
+ const isInlineFlex = /\binline-flex\b/.test(customClass);
1260
+ const marginClass = isInlineFlex ? "my-1 mx-1" : "my-4";
1261
+ const btnBase = `${displayClass} items-center w-fit ${marginClass} ${sizeClass} px-4 py-2 rounded-xl font-bold no-underline gap-2 transition-all hover:scale-105 active:scale-95 border border-border bg-background-primary/5 hover:bg-background-primary/10 text-text-primary hover:text-text-primary`.replace(/\s+/g, " ");
1262
+ const btnClass = `${btnBase} ${customClass}`.trim();
1263
+ const positionMap = {
1264
+ "#left": "text-left",
1265
+ "#center": "text-center",
1266
+ "#right": "text-right"
1267
+ };
1268
+ const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
1269
+ const handleOpen = () => {
1270
+ context.setModals((prev) => ({ ...prev, [modalId]: true }));
1271
+ };
1272
+ const handleClose = () => {
1273
+ context.setModals((prev) => ({ ...prev, [modalId]: false }));
1274
+ };
1275
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `not-prose ${wrapperClass}`.trim(), children: [
1276
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: btnClass, onClick: handleOpen, children: [
1277
+ props.icon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconRenderer, { iconName: props.icon }),
1278
+ label
1279
+ ] }),
1280
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1281
+ Modal,
1282
+ {
1283
+ title: modalTitle,
1284
+ isOpen: !!context.modals[modalId],
1285
+ onClose: handleClose,
1286
+ children: renderSlot("default")
1287
+ }
1288
+ )
1289
+ ] });
1290
+ };
1291
+ var ModalDirective_default = ModalDirective;
1292
+
1293
+ // directives/ButtonDirective.tsx
1294
+ var import_react5 = __toESM(require("react"));
1295
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1296
+ var ButtonDirective = ({
1297
+ props,
1298
+ renderSlot
1299
+ }) => {
1300
+ const url = props.url || props.href || "#";
1301
+ const label = props.label;
1302
+ const icon = props.icon || "near_me";
1303
+ const target = props.target || "_blank";
1304
+ const customClass = props.class || "";
1305
+ const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
1306
+ const sizeClass = hasSizeClass ? "" : "text-sm";
1307
+ const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
1308
+ const displayClass = hasDisplayClass ? "" : "inline-flex";
1309
+ const isInline = !customClass || !/\b(flex|block|grid)\b/.test(customClass) || /\binline-flex\b/.test(customClass);
1310
+ const marginClass = isInline ? "my-1 mx-1" : "my-4";
1311
+ const btnBase = `${displayClass} items-center w-fit ${marginClass} ${sizeClass} px-4 py-2 rounded-xl font-bold no-underline gap-2 transition-all hover:scale-105 active:scale-95 border border-border bg-background-primary/5 hover:bg-background-primary/10 text-text-primary hover:text-text-primary`.replace(/\s+/g, " ");
1312
+ const btnClass = `${btnBase} ${customClass}`.trim();
1313
+ const positionMap = {
1314
+ "#left": "flex justify-start",
1315
+ "#center": "flex justify-center",
1316
+ "#right": "flex justify-end"
1317
+ };
1318
+ const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
1319
+ if (label) {
1320
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `not-prose ${wrapperClass}`.trim(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1321
+ "a",
1322
+ {
1323
+ href: url,
1324
+ target,
1325
+ rel: "noopener noreferrer",
1326
+ className: btnClass,
1327
+ children: [
1328
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconRenderer, { iconName: icon }),
1329
+ label
1330
+ ]
1331
+ }
1332
+ ) });
1333
+ }
1334
+ const slotContent = renderSlot("default");
1335
+ const findLinks = (element) => {
1336
+ if (!element) return [];
1337
+ if (import_react5.default.isValidElement(element) && element.type === "a") {
1338
+ return [element];
1339
+ }
1340
+ if (Array.isArray(element)) {
1341
+ return element.flatMap(findLinks);
1342
+ }
1343
+ if (import_react5.default.isValidElement(element) && element.props.children) {
1344
+ return findLinks(element.props.children);
1345
+ }
1346
+ return [];
1347
+ };
1348
+ const links = findLinks(slotContent);
1349
+ if (links.length > 0) {
1350
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `not-prose ${wrapperClass}`.trim(), children: links.map(
1351
+ (link, index) => import_react5.default.cloneElement(
1352
+ link,
1353
+ {
1354
+ key: index,
1355
+ className: `${link.props.className || ""} ${btnClass}`.trim(),
1356
+ target,
1357
+ rel: "noopener noreferrer"
1358
+ },
1359
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1360
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconRenderer, { iconName: icon }),
1361
+ link.props.children
1362
+ ] })
1363
+ )
1364
+ ) });
1365
+ }
1366
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `not-prose ${wrapperClass}`.trim(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href: url, target, rel: "noopener noreferrer", className: btnClass, children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconRenderer, { iconName: icon }),
1368
+ slotContent
1369
+ ] }) });
1370
+ };
1371
+ var ButtonDirective_default = ButtonDirective;
1372
+
1373
+ // directives/WrapperDirective.tsx
1374
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1375
+ var WrapperDirective = ({
1376
+ props,
1377
+ renderSlot
1378
+ }) => {
1379
+ const className = props.class || "";
1380
+ const id = props.id || "";
1381
+ const inlineStyle = props.style ? parseCssString(props.style) : {};
1382
+ const wrapperProps = {};
1383
+ if (className) wrapperProps.className = className;
1384
+ if (id) wrapperProps.id = id;
1385
+ if (Object.keys(inlineStyle).length > 0) wrapperProps.style = inlineStyle;
1386
+ for (const [key, value] of Object.entries(props)) {
1387
+ if (key.startsWith("data-")) {
1388
+ wrapperProps[key] = value;
1389
+ }
1390
+ }
1391
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ...wrapperProps, children: renderSlot("default") });
1392
+ };
1393
+ var WrapperDirective_default = WrapperDirective;
1394
+
1395
+ // directives/SlideDirective.tsx
1396
+ var import_react6 = require("react");
1397
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1398
+ var slideCounter = 0;
1399
+ var SlideDirective = ({
1400
+ props,
1401
+ context,
1402
+ slots
1403
+ }) => {
1404
+ const rawContent = slots.default || "";
1405
+ const lines = rawContent.split("\n").map((l) => l.trim()).filter(Boolean);
1406
+ const elements = lines.map((line) => context.parseMarkdown(line));
1407
+ const [current, setCurrent] = (0, import_react6.useState)(0);
1408
+ const interval = parseInt(props.interval || "3000", 10);
1409
+ const speed = parseInt(props.speed || "500", 10);
1410
+ const elRefs = (0, import_react6.useRef)([]);
1411
+ const [maxH, setMaxH] = (0, import_react6.useState)(0);
1412
+ (0, import_react6.useLayoutEffect)(() => {
1413
+ let h = 0;
1414
+ elRefs.current.forEach((el) => {
1415
+ if (el) h = Math.max(h, el.offsetHeight);
1416
+ });
1417
+ if (h > 0) setMaxH(h);
1418
+ }, [elements]);
1419
+ const cycle = (0, import_react6.useCallback)(() => {
1420
+ if (elements.length <= 1) return;
1421
+ setCurrent((prev) => (prev + 1) % elements.length);
1422
+ }, [elements.length]);
1423
+ (0, import_react6.useEffect)(() => {
1424
+ if (elements.length <= 1) return;
1425
+ const id = setInterval(cycle, interval);
1426
+ return () => clearInterval(id);
1427
+ }, [cycle, interval, elements.length]);
1428
+ if (elements.length === 0) return null;
1429
+ const rawClass = props.class || "";
1430
+ const inlineStyle = props.style ? parseCssString(props.style) : {};
1431
+ const textSizeMap = {
1432
+ "text-xs": "0.75rem",
1433
+ "text-sm": "0.875rem",
1434
+ "text-base": "1rem",
1435
+ "text-lg": "1.125rem",
1436
+ "text-xl": "1.25rem",
1437
+ "text-2xl": "1.5rem",
1438
+ "text-3xl": "1.875rem",
1439
+ "text-4xl": "2.25rem",
1440
+ "text-5xl": "3rem",
1441
+ "text-6xl": "3.75rem",
1442
+ "text-7xl": "4.5rem",
1443
+ "text-8xl": "6rem",
1444
+ "text-9xl": "8rem"
1445
+ };
1446
+ const textSizeMatch = rawClass.match(/\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/);
1447
+ const forcedFontSize = textSizeMatch ? textSizeMap[textSizeMatch[0]] : null;
1448
+ const scopeClass = `sld-${++slideCounter}`;
1449
+ const className = textSizeMatch ? rawClass.replace(textSizeMatch[0], "").replace(/\s+/g, " ").trim() : rawClass;
1450
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1451
+ "div",
1452
+ {
1453
+ className: "not-prose",
1454
+ style: { height: maxH || "auto", position: "relative", overflow: "hidden", ...inlineStyle },
1455
+ children: [
1456
+ forcedFontSize && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `.${scopeClass} * { font-size: ${forcedFontSize} !important; line-height: normal !important; }` }),
1457
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1458
+ "div",
1459
+ {
1460
+ style: {
1461
+ position: "absolute",
1462
+ left: 0,
1463
+ right: 0,
1464
+ top: 0,
1465
+ transition: `transform ${speed}ms cubic-bezier(0.16, 1, 0.3, 1)`,
1466
+ transform: `translateY(${-current * maxH}px)`
1467
+ },
1468
+ children: elements.map((tokens, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1469
+ "div",
1470
+ {
1471
+ ref: (el) => {
1472
+ elRefs.current[i] = el;
1473
+ },
1474
+ style: maxH ? { height: maxH, display: "flex", alignItems: "center", overflow: "hidden" } : { display: "flex", alignItems: "center" },
1475
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `${scopeClass} ${className}`, style: { width: "100%" }, children: context.processAndRenderElements(tokens) })
1476
+ },
1477
+ i
1478
+ ))
1479
+ }
1480
+ )
1481
+ ]
1482
+ }
1483
+ );
1484
+ };
1485
+ var SlideDirective_default = SlideDirective;
1486
+
1487
+ // directives/index.ts
1488
+ var directiveRegistry = {
1489
+ // Admonitions
1490
+ note: AdmonitionDirective_default,
1491
+ info: AdmonitionDirective_default,
1492
+ warning: AdmonitionDirective_default,
1493
+ danger: AdmonitionDirective_default,
1494
+ greentext: AdmonitionDirective_default,
1495
+ // Cards
1496
+ card: CardDirective_default,
1497
+ "card-m": CardDirective_default,
1498
+ "card-b": CardDirective_default,
1499
+ // Interactive
1500
+ details: DetailsDirective_default,
1501
+ modal: ModalDirective_default,
1502
+ button: ButtonDirective_default,
1503
+ // Layout / generic wrappers
1504
+ div: WrapperDirective_default,
1505
+ style: WrapperDirective_default,
1506
+ custom: WrapperDirective_default,
1507
+ raw: WrapperDirective_default,
1508
+ // Animation
1509
+ slide: SlideDirective_default
1510
+ };
1511
+ var directives_default = directiveRegistry;
1512
+
1513
+ // DirectiveRenderer.tsx
1514
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1515
+ var DirectiveRenderer = ({
1516
+ element,
1517
+ context,
1518
+ index,
1519
+ allElements
1520
+ }) => {
1521
+ const { directiveType, props, slots, scopeId } = element;
1522
+ const Component = directives_default[directiveType];
1523
+ const renderSlot = (name) => {
1524
+ const slotContent = slots[name];
1525
+ if (!slotContent) return null;
1526
+ const parsed = context.parseMarkdown(slotContent);
1527
+ return context.processAndRenderElements(parsed);
1528
+ };
1529
+ const directiveProps = {
1530
+ directiveType,
1531
+ props,
1532
+ slots,
1533
+ renderSlot,
1534
+ context,
1535
+ index,
1536
+ allElements
1537
+ };
1538
+ if (Component) {
1539
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Component, { ...directiveProps }, index);
1540
+ }
1541
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: `my-4 p-4 rounded-2xl border border-border bg-background-primary/5`, children: renderSlot("default") }, index);
1542
+ };
1543
+ var DirectiveRenderer_default = DirectiveRenderer;
1544
+
1545
+ // RawHtmlRenderer.tsx
1546
+ var import_react8 = require("react");
1547
+
1548
+ // useTailwindCDN.ts
1549
+ var import_react7 = require("react");
1550
+ function scanTailwindCDN() {
1551
+ const tw = window.tailwind;
1552
+ if (tw?.scan) tw.scan();
1553
+ }
1554
+
1555
+ // RawHtmlRenderer.tsx
1556
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1557
+ var RawHtmlRenderer = ({
1558
+ content,
1559
+ globalStyles,
1560
+ wrapperClassName
1561
+ }) => {
1562
+ const containerRef = (0, import_react8.useRef)(null);
1563
+ (0, import_react8.useEffect)(() => {
1564
+ if (!containerRef.current) return;
1565
+ const scripts = containerRef.current.querySelectorAll("script");
1566
+ scripts.forEach((oldScript) => {
1567
+ const newScript = document.createElement("script");
1568
+ Array.from(oldScript.attributes).forEach(
1569
+ (attr) => newScript.setAttribute(attr.name, attr.value)
1570
+ );
1571
+ newScript.textContent = oldScript.textContent;
1572
+ oldScript.parentNode?.replaceChild(newScript, oldScript);
1573
+ });
1574
+ scanTailwindCDN();
1575
+ }, [content]);
1576
+ (0, import_react8.useEffect)(() => {
1577
+ if (!globalStyles) return;
1578
+ const styleEl = document.createElement("style");
1579
+ styleEl.setAttribute("data-global", "");
1580
+ styleEl.textContent = globalStyles;
1581
+ document.head.appendChild(styleEl);
1582
+ return () => {
1583
+ if (styleEl.parentNode) document.head.removeChild(styleEl);
1584
+ };
1585
+ }, [globalStyles]);
1586
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: wrapperClassName, ref: containerRef, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { dangerouslySetInnerHTML: { __html: content } }) });
1587
+ };
1588
+ var RawHtmlRenderer_default = RawHtmlRenderer;
1589
+
1590
+ // context.tsx
1591
+ var import_react9 = require("react");
1592
+ var RenderCtx = (0, import_react9.createContext)(null);
1593
+ var RenderContextProvider = RenderCtx.Provider;
1594
+
1595
+ // CustomMarkdownRenderer.tsx
1596
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1597
+ var CustomMarkdownRenderer = ({ content: initialContent }) => {
1598
+ const [modals, setModals] = (0, import_react10.useState)({});
1599
+ const baseId = (0, import_react10.useId)().replace(/:/g, "");
1600
+ const articleClass = `scope-${baseId}`;
1601
+ const contextRef = (0, import_react10.useRef)(null);
1602
+ resetScopeCounter();
1603
+ const allElements = (0, import_react10.useMemo)(() => parseMarkdown(initialContent), [initialContent]);
1604
+ (0, import_react10.useEffect)(() => {
1605
+ const handleHashChange = () => {
1606
+ const hash = window.location.hash;
1607
+ if (hash) {
1608
+ const parts = hash.split("#");
1609
+ const id = parts[parts.length - 1];
1610
+ scrollToId(id);
1611
+ }
1612
+ };
1613
+ handleHashChange();
1614
+ window.addEventListener("hashchange", handleHashChange);
1615
+ return () => window.removeEventListener("hashchange", handleHashChange);
1616
+ }, [initialContent]);
1617
+ const renderElement = (0, import_react10.useCallback)(
1618
+ (element, index, _depth = 0) => {
1619
+ switch (element.type) {
1620
+ case "header": {
1621
+ const HeaderTag = `h${element.level}`;
1622
+ let text = element.text;
1623
+ const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
1624
+ const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
1625
+ if (alignCenter) {
1626
+ text = alignCenter[1];
1627
+ } else if (alignRight) {
1628
+ text = alignRight[1];
1629
+ }
1630
+ const userClasses = element.classes || "";
1631
+ let headerClasses = `md-h${element.level}`;
1632
+ if (alignCenter) headerClasses += " text-center";
1633
+ if (alignRight) headerClasses += " text-right";
1634
+ if (userClasses) headerClasses += ` ${userClasses}`;
1635
+ return import_react10.default.createElement(
1636
+ HeaderTag,
1637
+ { key: index, id: element.id, className: headerClasses },
1638
+ renderInline(text)
1639
+ );
1640
+ }
1641
+ case "paragraph": {
1642
+ const lines = element.content.split("\n");
1643
+ const processedContent = lines.map((line, lineIndex) => {
1644
+ const hardBreakMatch = line.match(/^(.*?)(\s{2,})$/);
1645
+ if (hardBreakMatch) {
1646
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react10.default.Fragment, { children: [
1647
+ renderInline(hardBreakMatch[1]),
1648
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("br", {})
1649
+ ] }, lineIndex);
1650
+ }
1651
+ const isLastLine = lineIndex === lines.length - 1;
1652
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react10.default.Fragment, { children: [
1653
+ renderInline(line),
1654
+ !isLastLine && " "
1655
+ ] }, lineIndex);
1656
+ });
1657
+ const pUserClasses = element.classes || "";
1658
+ let pClasses = "md-p";
1659
+ if (pUserClasses) pClasses += ` ${pUserClasses}`;
1660
+ if (element.align) pClasses += ` text-${element.align}`;
1661
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { id: element.id, className: pClasses, children: processedContent }, index);
1662
+ }
1663
+ case "codeblock":
1664
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1665
+ CodeBlock,
1666
+ {
1667
+ code: element.content,
1668
+ language: element.language,
1669
+ title: element.title
1670
+ },
1671
+ index
1672
+ );
1673
+ case "directive":
1674
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1675
+ DirectiveRenderer_default,
1676
+ {
1677
+ element,
1678
+ context: contextRef.current,
1679
+ index,
1680
+ allElements
1681
+ },
1682
+ index
1683
+ );
1684
+ case "html": {
1685
+ let processedContent = element.content;
1686
+ let globalStyles = "";
1687
+ processedContent = processedContent.replace(
1688
+ /<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
1689
+ (_match, cssContent) => {
1690
+ globalStyles += cssContent + "\n";
1691
+ return "";
1692
+ }
1693
+ );
1694
+ const wrapperClassName = "w-full my-4";
1695
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1696
+ RawHtmlRenderer_default,
1697
+ {
1698
+ content: processedContent,
1699
+ globalStyles: globalStyles || void 0,
1700
+ wrapperClassName
1701
+ },
1702
+ index
1703
+ );
1704
+ }
1705
+ case "html-block": {
1706
+ const htmlBlock = element;
1707
+ const props = parseHtmlAttrs(htmlBlock.attrs);
1708
+ return import_react10.default.createElement(
1709
+ htmlBlock.tag,
1710
+ { key: index, ...props },
1711
+ ...processAndRenderElements(htmlBlock.children, _depth + 1)
1712
+ );
1713
+ }
1714
+ case "image":
1715
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1716
+ "img",
1717
+ {
1718
+ alt: element.alt,
1719
+ src: element.src,
1720
+ style: element.style,
1721
+ className: "max-w-full h-auto"
1722
+ },
1723
+ index
1724
+ );
1725
+ case "table":
1726
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: renderTable(element.content) }, index);
1727
+ case "list":
1728
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: renderList(element.content) }, index);
1729
+ case "blockquote":
1730
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("blockquote", { className: `border-l-4 border-accent-primary/30 pl-4 italic text-text-secondary my-4 text-sm sm:text-base${element.classes ? ` ${element.classes}` : ""}`, children: renderInline(element.content) }, index);
1731
+ case "hr":
1732
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("hr", { className: "my-8 border-border" }, index);
1733
+ case "toc":
1734
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: generateToc(allElements) }, index);
1735
+ default:
1736
+ return null;
1737
+ }
1738
+ },
1739
+ [allElements]
1740
+ );
1741
+ const processAndRenderElements = (0, import_react10.useCallback)(
1742
+ (elements, depth = 0) => {
1743
+ const result = [];
1744
+ let i = 0;
1745
+ while (i < elements.length) {
1746
+ const el = elements[i];
1747
+ if (el.type === "directive" && ["card", "card-m", "card-b"].includes(el.directiveType)) {
1748
+ const cards = [];
1749
+ while (i < elements.length && elements[i].type === "directive" && ["card", "card-m", "card-b"].includes(elements[i].directiveType)) {
1750
+ cards.push(elements[i]);
1751
+ i++;
1752
+ }
1753
+ if (cards.length === 1 || cards[0].props?.batch === "off") {
1754
+ for (let c = 0; c < cards.length; c++) {
1755
+ result.push(renderElement(cards[c], result.length, depth));
1756
+ }
1757
+ } else {
1758
+ const firstCardClass = cards[0].props?.["class"] || "";
1759
+ const justifyClasses = firstCardClass.match(/\bjustify-\S+/g) || [];
1760
+ const wrapperJustify = justifyClasses.length > 0 ? justifyClasses.join(" ") : "";
1761
+ result.push(
1762
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `not-prose flex flex-wrap gap-6 my-6 ${wrapperJustify}`, children: cards.map((card, ci) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react10.default.Fragment, { children: renderElement(card, ci, depth) }, ci)) }, `card-grid-${result.length}`)
1763
+ );
1764
+ }
1765
+ } else {
1766
+ result.push(renderElement(el, result.length, depth));
1767
+ i++;
1768
+ }
1769
+ }
1770
+ return result;
1771
+ },
1772
+ [renderElement]
1773
+ );
1774
+ const generateToc = (elements) => {
1775
+ const headers = extractHeaders(elements);
1776
+ if (headers.length === 0) return null;
1777
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("nav", { className: "not-prose my-6 p-4 rounded-2xl border border-border bg-background-primary/5", children: [
1778
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-base font-bold mb-3", children: "Table of Contents" }),
1779
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className: "space-y-1 list-none p-0 m-0", children: headers.map((h, i) => {
1780
+ if (h.type !== "header") return null;
1781
+ const indentClass = h.level <= 2 ? "pl-0" : h.level === 3 ? "pl-4" : h.level === 4 ? "pl-8" : "pl-12";
1782
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("li", { className: `${indentClass} text-sm sm:text-base`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1783
+ "a",
1784
+ {
1785
+ href: `#${h.id}`,
1786
+ className: "text-accent-primary hover:text-accent-primary/80 no-underline hover:underline transition-colors",
1787
+ onClick: (e) => {
1788
+ e.preventDefault();
1789
+ scrollToId(h.id);
1790
+ },
1791
+ children: renderInline(h.text.replace(/->|<-/g, "").trim())
1792
+ }
1793
+ ) }, i);
1794
+ }) })
1795
+ ] });
1796
+ };
1797
+ const contextForDirectives = {
1798
+ modals,
1799
+ setModals,
1800
+ articleClass,
1801
+ allElements,
1802
+ parseMarkdown,
1803
+ renderElement,
1804
+ renderInline,
1805
+ processAndRenderElements
1806
+ };
1807
+ contextRef.current = contextForDirectives;
1808
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RenderContextProvider, { value: contextForDirectives, children: processAndRenderElements(allElements) });
1809
+ };
1810
+ var CustomMarkdownRenderer_default = CustomMarkdownRenderer;
1811
+
1812
+ // NReditor.tsx
1813
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1814
+ var customSyntaxHighlighting = import_language2.HighlightStyle.define([
1815
+ { tag: import_highlight2.tags.heading, fontWeight: "bold", color: "var(--tc-heading, #e2e8f0)" },
1816
+ { tag: import_highlight2.tags.quote, color: "var(--tc-quote, #94a3b8)", fontStyle: "italic" },
1817
+ { tag: import_highlight2.tags.meta, color: "var(--tc-meta, #64748b)" },
1818
+ { tag: import_highlight2.tags.variableName, color: "var(--tc-variable, #38bdf8)" },
1819
+ { tag: import_highlight2.tags.strong, fontWeight: "bold" },
1820
+ { tag: import_highlight2.tags.emphasis, fontStyle: "italic" },
1821
+ { tag: import_highlight2.tags.strikethrough, textDecoration: "line-through" },
1822
+ { tag: import_highlight2.tags.link, color: "var(--tc-link, #38bdf8)" },
1823
+ { tag: import_highlight2.tags.url, color: "var(--tc-link, #38bdf8)" },
1824
+ { tag: import_highlight2.tags.comment, color: "var(--tc-comment, #64748b)" },
1825
+ { tag: import_highlight2.tags.keyword, color: "var(--tc-heading, #e2e8f0)", fontWeight: "bold" },
1826
+ { tag: import_highlight2.tags.typeName, color: "var(--tc-type, #a78bfa)" },
1827
+ { tag: import_highlight2.tags.string, color: "var(--tc-string, #4ade80)" },
1828
+ { tag: import_highlight2.tags.attributeName, color: "var(--tc-attribute, #fb923c)" },
1829
+ { tag: import_highlight2.tags.propertyName, color: "#0ea5e9" },
1830
+ { tag: import_highlight2.tags.className, color: "#f59e0b", fontStyle: "italic" },
1831
+ { tag: import_highlight2.tags.special(import_highlight2.tags.emphasis), textDecoration: "underline" },
1832
+ { tag: import_highlight2.tags.special(import_highlight2.tags.comment), backgroundColor: "var(--tc-highlight-bg, rgba(255,255,255,0.05))", padding: "0 2px", borderRadius: "2px" }
1833
+ ]);
1834
+ var customEditorTheme = import_view.EditorView.theme({
1835
+ "&": {
1836
+ color: "var(--color-text-primary, #e2e8f0)",
1837
+ backgroundColor: "transparent !important",
1838
+ height: "100%",
1839
+ position: "relative",
1840
+ display: "flex",
1841
+ flexDirection: "column",
1842
+ minHeight: "0"
1843
+ },
1844
+ "&.cm-focused": { outline: "none" },
1845
+ ".cm-scroller": {
1846
+ overflow: "auto !important",
1847
+ flex: "1",
1848
+ minHeight: "0",
1849
+ WebkitOverflowScrolling: "touch"
1850
+ },
1851
+ ".cm-gutters": {
1852
+ backgroundColor: "transparent !important",
1853
+ borderRight: "1px solid var(--color-border, #334155)",
1854
+ color: "var(--color-text-secondary, #94a3b8)",
1855
+ opacity: 0.6,
1856
+ border: "none"
1857
+ },
1858
+ ".cm-activeLineGutter": { backgroundColor: "transparent" },
1859
+ ".cm-lineNumbers": { color: "inherit" },
1860
+ ".cm-foldGutter": { padding: "0px", cursor: "pointer" },
1861
+ ".cm-foldPlaceholder": {
1862
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
1863
+ border: "1px solid var(--color-border, #334155)",
1864
+ color: "var(--tc-heading, #e2e8f0)",
1865
+ padding: "0 6px",
1866
+ borderRadius: "4px",
1867
+ margin: "0 4px",
1868
+ fontSize: "0.9em",
1869
+ fontWeight: "bold"
1870
+ },
1871
+ ".dark .cm-foldPlaceholder": {
1872
+ backgroundColor: "rgba(255, 255, 255, 0.1)"
1873
+ },
1874
+ ".cm-activeLine": { backgroundColor: "transparent" },
1875
+ ".cm-cursor": { borderLeftColor: "var(--color-text-primary, #e2e8f0)" },
1876
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground": {
1877
+ backgroundColor: "var(--tc-selection-bg, rgba(56, 189, 248, 0.2)) !important"
1878
+ },
1879
+ ".cm-blockquote-line": {
1880
+ color: "var(--tc-blockquote-color, #94a3b8)",
1881
+ fontStyle: "italic",
1882
+ borderLeft: "2px solid var(--tc-blockquote-border, #334155)",
1883
+ paddingLeft: "10px"
1884
+ },
1885
+ ".cm-spoiler": {
1886
+ backgroundColor: "var(--color-text-secondary, #94a3b8)",
1887
+ color: "var(--color-text-secondary, #94a3b8)",
1888
+ borderRadius: "3px",
1889
+ padding: "0 2px",
1890
+ cursor: "pointer",
1891
+ transition: "background-color 0.2s, color 0.2s"
1892
+ },
1893
+ ".cm-spoiler:hover": {
1894
+ backgroundColor: "transparent",
1895
+ color: "var(--color-text-primary, #e2e8f0)"
1896
+ },
1897
+ ".cm-admonition-bg": {
1898
+ borderLeft: "none !important",
1899
+ marginLeft: "0px"
1900
+ },
1901
+ ".cm-admonition-button": { borderLeftColor: "var(--tc-attribute, #fb923c)" },
1902
+ ".cm-admonition-modal": { borderLeftColor: "var(--tc-variable, #38bdf8)" },
1903
+ ".cm-admonition-warning": { borderLeftColor: "#f59e0b" },
1904
+ ".cm-admonition-danger": { borderLeftColor: "#ef4444" },
1905
+ ".cm-raw-block": {
1906
+ fontFamily: "monospace",
1907
+ backgroundColor: "rgba(0, 0, 0, 0.1)"
1908
+ },
1909
+ ".dark .cm-raw-block": {
1910
+ backgroundColor: "rgba(255, 255, 255, 0.05)"
1911
+ },
1912
+ ".cm-admonition-depth-1": {
1913
+ boxShadow: "inset 4px 0 0 hsl(20, 70%, 50%)",
1914
+ backgroundColor: "hsla(20, 70%, 50%, 0.05)",
1915
+ paddingLeft: "12px !important"
1916
+ },
1917
+ ".cm-admonition-depth-2": {
1918
+ boxShadow: "inset 4px 0 0 hsl(20, 70%, 50%), inset 8px 0 0 hsl(140, 70%, 50%)",
1919
+ backgroundColor: "hsla(140, 70%, 50%, 0.05)",
1920
+ paddingLeft: "16px !important"
1921
+ },
1922
+ ".cm-admonition-depth-3": {
1923
+ boxShadow: "inset 4px 0 0 hsl(20, 70%, 50%), inset 8px 0 0 hsl(140, 70%, 50%), inset 12px 0 0 hsl(200, 70%, 50%)",
1924
+ backgroundColor: "hsla(200, 70%, 50%, 0.05)",
1925
+ paddingLeft: "20px !important"
1926
+ },
1927
+ ".cm-admonition-depth-4": {
1928
+ boxShadow: "inset 4px 0 0 hsl(20, 70%, 50%), inset 8px 0 0 hsl(140, 70%, 50%), inset 12px 0 0 hsl(200, 70%, 50%), inset 16px 0 0 hsl(280, 70%, 50%)",
1929
+ backgroundColor: "hsla(280, 70%, 50%, 0.05)",
1930
+ paddingLeft: "24px !important"
1931
+ },
1932
+ ".cm-admonition-depth-5": {
1933
+ boxShadow: "inset 4px 0 0 hsl(340, 70%, 50%), inset 8px 0 0 hsl(140, 70%, 50%), inset 12px 0 0 hsl(200, 70%, 50%), inset 16px 0 0 hsl(280, 70%, 50%), inset 20px 0 0 hsl(340, 70%, 50%)",
1934
+ backgroundColor: "hsla(340, 70%, 50%, 0.05)",
1935
+ paddingLeft: "28px !important"
1936
+ },
1937
+ ".cm-panels": {
1938
+ position: "static !important",
1939
+ backgroundColor: "transparent !important",
1940
+ border: "none !important"
1941
+ },
1942
+ ".cm-panel.cm-search": {
1943
+ position: "fixed !important",
1944
+ top: "20px !important",
1945
+ right: "20px !important",
1946
+ zIndex: 100,
1947
+ backgroundColor: "var(--color-background-primary, #0f172a)",
1948
+ border: "1px solid var(--color-border, #334155)",
1949
+ borderRadius: "12px",
1950
+ padding: "12px",
1951
+ boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.3), 0 8px 10px -6px rgba(0, 0, 0, 0.3)",
1952
+ display: "flex",
1953
+ flexDirection: "column",
1954
+ gap: "8px",
1955
+ backdropFilter: "blur(8px)",
1956
+ minWidth: "280px"
1957
+ },
1958
+ ".cm-search [name=close]": {
1959
+ position: "absolute",
1960
+ right: "8px",
1961
+ top: "8px",
1962
+ cursor: "pointer",
1963
+ opacity: 0.6,
1964
+ border: "none",
1965
+ background: "transparent",
1966
+ color: "var(--color-text-primary, #e2e8f0)",
1967
+ fontSize: "18px"
1968
+ },
1969
+ ".cm-search [name=close]:hover": { opacity: 1 },
1970
+ ".cm-textfield": {
1971
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
1972
+ border: "1px solid var(--color-border, #334155)",
1973
+ borderRadius: "6px",
1974
+ color: "var(--color-text-primary, #e2e8f0)",
1975
+ padding: "4px 8px",
1976
+ outline: "none",
1977
+ width: "100%",
1978
+ marginBottom: "4px"
1979
+ },
1980
+ ".cm-textfield:focus": {
1981
+ borderColor: "var(--color-accent-primary, #38bdf8)",
1982
+ backgroundColor: "rgba(255, 255, 255, 0.08)"
1983
+ },
1984
+ ".cm-panel.cm-search input[type=checkbox]:checked": {
1985
+ backgroundColor: "var(--color-accent-primary, #38bdf8)"
1986
+ },
1987
+ ".cm-panel.cm-search input[type=checkbox]": {
1988
+ backgroundColor: "rgba(255, 255, 255, 0.08)"
1989
+ },
1990
+ ".cm-button": {
1991
+ backgroundImage: "linear-gradient(135deg, var(--color-accent-primary, #38bdf8), var(--color-accent-hover, #7dd3fc))",
1992
+ color: "var(--color-accent-text, #0f172a)",
1993
+ border: "none",
1994
+ borderRadius: "6px",
1995
+ padding: "4px 10px",
1996
+ cursor: "pointer",
1997
+ fontSize: "0.85em",
1998
+ fontWeight: "600",
1999
+ textTransform: "uppercase",
2000
+ letterSpacing: "0.05em",
2001
+ transition: "transform 0.1s, opacity 0.2s",
2002
+ marginRight: "4px",
2003
+ boxShadow: "0 4px 12px -2px rgba(0, 0, 0, 0.2)"
2004
+ },
2005
+ ".cm-button:hover": {
2006
+ opacity: 0.95,
2007
+ transform: "translateY(-1px)",
2008
+ boxShadow: "0 6px 14px -2px rgba(0, 0, 0, 0.25)"
2009
+ },
2010
+ ".cm-button:active": { transform: "translateY(0)" },
2011
+ ".cm-search label": {
2012
+ display: "inline-flex",
2013
+ alignItems: "center",
2014
+ gap: "4px",
2015
+ fontSize: "0.8em",
2016
+ color: "var(--color-text-secondary, #94a3b8)",
2017
+ marginRight: "8px",
2018
+ cursor: "pointer"
2019
+ },
2020
+ ".cm-search input[type=checkbox]": {
2021
+ cursor: "pointer",
2022
+ accentColor: "var(--color-accent-primary, #38bdf8)"
2023
+ }
2024
+ });
2025
+ var customFoldService = import_language2.foldService.of((state, lineStart) => {
2026
+ const line = state.doc.lineAt(lineStart);
2027
+ const trimmed = line.text.trim();
2028
+ const dirMatch = trimmed.match(/^:::(.+)/);
2029
+ if (dirMatch) {
2030
+ let stack = 1;
2031
+ for (let i = line.number + 1; i <= state.doc.lines; i++) {
2032
+ const nextLine = state.doc.line(i);
2033
+ const nextText = nextLine.text.trim();
2034
+ if (nextText.match(/^:::(.+)/)) {
2035
+ stack++;
2036
+ } else if (nextText === ":::") {
2037
+ stack--;
2038
+ if (stack === 0) {
2039
+ return { from: line.to, to: nextLine.to };
2040
+ }
2041
+ }
2042
+ }
2043
+ return null;
2044
+ }
2045
+ const htmlMatch = trimmed.match(/^<([a-zA-Z][\w-]*)\b/);
2046
+ if (htmlMatch) {
2047
+ const tagName = htmlMatch[1].toLowerCase();
2048
+ const voidElements = /* @__PURE__ */ new Set([
2049
+ "area",
2050
+ "base",
2051
+ "br",
2052
+ "col",
2053
+ "embed",
2054
+ "hr",
2055
+ "img",
2056
+ "input",
2057
+ "link",
2058
+ "meta",
2059
+ "param",
2060
+ "source",
2061
+ "track",
2062
+ "wbr"
2063
+ ]);
2064
+ if (voidElements.has(tagName) || trimmed.endsWith("/>")) return null;
2065
+ let stack = 1;
2066
+ for (let i = line.number + 1; i <= state.doc.lines; i++) {
2067
+ const nextLine = state.doc.line(i);
2068
+ const nextText = nextLine.text;
2069
+ let match;
2070
+ const tagRegex = new RegExp(`</?${tagName}\\b[^>]*>`, "gi");
2071
+ while ((match = tagRegex.exec(nextText)) !== null) {
2072
+ if (match[0].startsWith("</")) {
2073
+ stack--;
2074
+ if (stack === 0) {
2075
+ return { from: line.to, to: nextLine.to };
2076
+ }
2077
+ } else {
2078
+ if (!match[0].endsWith("/>")) {
2079
+ stack++;
2080
+ }
2081
+ }
2082
+ }
2083
+ }
2084
+ return null;
2085
+ }
2086
+ return null;
2087
+ });
2088
+ var directivePlugin = import_view.ViewPlugin.fromClass(
2089
+ class {
2090
+ constructor(view) {
2091
+ this.decorations = this.getDecorations(view);
2092
+ }
2093
+ update(update) {
2094
+ if (update.docChanged || update.viewportChanged) {
2095
+ this.decorations = this.getDecorations(update.view);
2096
+ }
2097
+ }
2098
+ getDecorations(view) {
2099
+ const builder = new import_state.RangeSetBuilder();
2100
+ const doc = view.state.doc;
2101
+ const visibleRanges = view.visibleRanges;
2102
+ if (visibleRanges.length === 0) return builder.finish();
2103
+ const maxTo = visibleRanges[visibleRanges.length - 1].to;
2104
+ const admonitionStack = [];
2105
+ for (let i = 1; i <= doc.lines; i++) {
2106
+ const line = doc.line(i);
2107
+ if (line.from > maxTo) break;
2108
+ const trimmedLine = line.text.trim();
2109
+ let isClosingLine = false;
2110
+ let closingTargetIdx = -1;
2111
+ const match = trimmedLine.match(/^:::(.*)/);
2112
+ if (match) {
2113
+ const rest = match[1].trim();
2114
+ if (rest === "") {
2115
+ if (admonitionStack.length > 0) {
2116
+ isClosingLine = true;
2117
+ closingTargetIdx = admonitionStack.length - 1;
2118
+ }
2119
+ } else {
2120
+ const typeMatch = rest.match(/^(\w+|\{)/);
2121
+ const type = typeMatch && typeMatch[1] !== "{" ? typeMatch[1].toLowerCase() : "generic";
2122
+ admonitionStack.push(type);
2123
+ }
2124
+ }
2125
+ const isVisible = visibleRanges.some(
2126
+ (r) => line.to >= r.from && line.from <= r.to
2127
+ );
2128
+ if (isVisible && admonitionStack.length > 0) {
2129
+ const targetIdx = isClosingLine ? closingTargetIdx : admonitionStack.length - 1;
2130
+ const currentType = admonitionStack[targetIdx];
2131
+ const depth = targetIdx + 1;
2132
+ const lineClasses = ["cm-admonition-bg"];
2133
+ if (currentType === "raw") {
2134
+ lineClasses.push("cm-raw-block");
2135
+ lineClasses.push(`cm-admonition-depth-${Math.min(depth, 5)}`);
2136
+ } else {
2137
+ lineClasses.push(`cm-admonition-${currentType}`);
2138
+ lineClasses.push(`cm-admonition-depth-${Math.min(depth, 5)}`);
2139
+ }
2140
+ builder.add(
2141
+ line.from,
2142
+ line.from,
2143
+ import_view.Decoration.line({ class: lineClasses.join(" ") })
2144
+ );
2145
+ }
2146
+ if (isClosingLine) {
2147
+ admonitionStack.pop();
2148
+ }
2149
+ }
2150
+ return builder.finish();
2151
+ }
2152
+ },
2153
+ { decorations: (v) => v.decorations }
2154
+ );
2155
+ var blockquotePlugin = import_view.ViewPlugin.fromClass(
2156
+ class {
2157
+ constructor(view) {
2158
+ this.decorations = this.getDecorations(view);
2159
+ }
2160
+ update(update) {
2161
+ if (update.docChanged || update.viewportChanged) {
2162
+ this.decorations = this.getDecorations(update.view);
2163
+ }
2164
+ }
2165
+ getDecorations(view) {
2166
+ const builder = new import_state.RangeSetBuilder();
2167
+ for (const { from, to } of view.visibleRanges) {
2168
+ for (let pos = from; pos <= to; ) {
2169
+ const line = view.state.doc.lineAt(pos);
2170
+ if (line.text.trim().startsWith(">")) {
2171
+ builder.add(
2172
+ line.from,
2173
+ line.from,
2174
+ import_view.Decoration.line({ class: "cm-blockquote-line" })
2175
+ );
2176
+ }
2177
+ pos = line.to + 1;
2178
+ }
2179
+ }
2180
+ return builder.finish();
2181
+ }
2182
+ },
2183
+ { decorations: (v) => v.decorations }
2184
+ );
2185
+ var spoilerPlugin = import_view.ViewPlugin.fromClass(
2186
+ class {
2187
+ constructor(view) {
2188
+ this.decorations = this.getDecorations(view);
2189
+ }
2190
+ update(update) {
2191
+ if (update.docChanged || update.viewportChanged) {
2192
+ this.decorations = this.getDecorations(update.view);
2193
+ }
2194
+ }
2195
+ getDecorations(view) {
2196
+ const builder = new import_state.RangeSetBuilder();
2197
+ const spoilerRegex = /!>([\s\S]+?)<!(?=\s|$)/g;
2198
+ const ranges = [];
2199
+ for (const { from, to } of view.visibleRanges) {
2200
+ const text = view.state.doc.sliceString(from, to);
2201
+ spoilerRegex.lastIndex = 0;
2202
+ let match;
2203
+ while (match = spoilerRegex.exec(text)) {
2204
+ const start = from + match.index;
2205
+ const end = start + match[0].length;
2206
+ const contentStart = start + 2;
2207
+ const contentEnd = end - 2;
2208
+ if (contentStart >= contentEnd) continue;
2209
+ ranges.push({ from: start, to: contentStart, dec: import_view.Decoration.replace({}) });
2210
+ ranges.push({
2211
+ from: contentStart,
2212
+ to: contentEnd,
2213
+ dec: import_view.Decoration.mark({ class: "cm-spoiler" })
2214
+ });
2215
+ ranges.push({ from: contentEnd, to: end, dec: import_view.Decoration.replace({}) });
2216
+ }
2217
+ }
2218
+ ranges.sort((a, b) => a.from - b.from || a.to - b.to);
2219
+ for (const { from, to, dec } of ranges) builder.add(from, to, dec);
2220
+ return builder.finish();
2221
+ }
2222
+ },
2223
+ { decorations: (v) => v.decorations }
2224
+ );
2225
+ var colorTextPlugin = import_view.ViewPlugin.fromClass(
2226
+ class {
2227
+ constructor(view) {
2228
+ this.decorations = this.getDecorations(view);
2229
+ }
2230
+ update(update) {
2231
+ if (update.docChanged || update.viewportChanged) {
2232
+ this.decorations = this.getDecorations(update.view);
2233
+ }
2234
+ }
2235
+ getDecorations(view) {
2236
+ const builder = new import_state.RangeSetBuilder();
2237
+ const colorRegex = /%([^%\s]+?)%((?:(?!%%).)*)%%/g;
2238
+ for (const { from, to } of view.visibleRanges) {
2239
+ const text = view.state.doc.sliceString(from, to);
2240
+ let match;
2241
+ while (match = colorRegex.exec(text)) {
2242
+ const color = match[1];
2243
+ const startPos = from + match.index;
2244
+ const endPos = startPos + match[0].length;
2245
+ builder.add(
2246
+ startPos,
2247
+ endPos,
2248
+ import_view.Decoration.mark({ attributes: { style: `color: ${color}` } })
2249
+ );
2250
+ }
2251
+ }
2252
+ return builder.finish();
2253
+ }
2254
+ },
2255
+ { decorations: (v) => v.decorations }
2256
+ );
2257
+ var NReditor = ({
2258
+ value,
2259
+ onChange,
2260
+ className,
2261
+ debounceMs = 300,
2262
+ tailwindCDN = false
2263
+ }) => {
2264
+ const editorRef = (0, import_react11.useRef)(null);
2265
+ const [isAllFolded, setIsAllFolded] = (0, import_react11.useState)(false);
2266
+ const [editorMode, setEditorMode] = (0, import_react11.useState)("editor");
2267
+ const debouncedContent = useDebounce(value, debounceMs);
2268
+ const handleToggleFold = () => {
2269
+ if (!editorRef.current) return;
2270
+ if (isAllFolded) {
2271
+ (0, import_language2.unfoldAll)(editorRef.current);
2272
+ setIsAllFolded(false);
2273
+ } else {
2274
+ (0, import_language2.foldAll)(editorRef.current);
2275
+ setIsAllFolded(true);
2276
+ }
2277
+ };
2278
+ const extensions = import_react11.default.useMemo(
2279
+ () => [
2280
+ customStreamParserV2,
2281
+ (0, import_view.lineNumbers)(),
2282
+ (0, import_language2.foldGutter)({
2283
+ markerDOM: (open) => {
2284
+ const span = document.createElement("span");
2285
+ span.style.cursor = "pointer";
2286
+ span.style.padding = "0 4px";
2287
+ span.style.fontSize = "12px";
2288
+ span.style.display = "inline-block";
2289
+ span.style.transition = "transform 0.2s";
2290
+ span.textContent = open ? "\u25BC" : "\u25B6";
2291
+ return span;
2292
+ }
2293
+ }),
2294
+ customFoldService,
2295
+ customEditorTheme,
2296
+ (0, import_language2.syntaxHighlighting)(customSyntaxHighlighting),
2297
+ import_view.EditorView.lineWrapping,
2298
+ (0, import_view.scrollPastEnd)(),
2299
+ import_view.keymap.of([
2300
+ { key: "Ctrl-Shift-[", run: import_language2.foldAll },
2301
+ { key: "Ctrl-Shift-]", run: import_language2.unfoldAll }
2302
+ ]),
2303
+ directivePlugin,
2304
+ blockquotePlugin,
2305
+ spoilerPlugin,
2306
+ colorTextPlugin
2307
+ ],
2308
+ []
2309
+ );
2310
+ const modeButtons = [
2311
+ { key: "editor", icon: "code", label: "Editor" },
2312
+ { key: "split", icon: "vertical_split", label: "Split" },
2313
+ { key: "preview", icon: "visibility", label: "Preview" }
2314
+ ];
2315
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: `relative flex-1 flex flex-col min-h-0 ${className || ""}`, children: [
2316
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between px-2 py-1.5 border-b border-border/30 bg-background-secondary-solid/50 rounded-t-2xl shrink-0", children: [
2317
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2318
+ "button",
2319
+ {
2320
+ onClick: handleToggleFold,
2321
+ className: "p-1 px-2 text-xs font-bold bg-background-secondary-solid border border-border rounded hover:bg-border text-accent-primary transition-colors",
2322
+ title: isAllFolded ? "Expand all" : "Collapse all",
2323
+ children: isAllFolded ? "\u2569" : "\u2566"
2324
+ }
2325
+ ),
2326
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center gap-0.5 bg-black/10 dark:bg-white/5 rounded-lg p-0.5", children: modeButtons.map((btn) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2327
+ "button",
2328
+ {
2329
+ onClick: () => setEditorMode(btn.key),
2330
+ className: `flex items-center gap-1 px-2.5 py-1 text-xs rounded-md transition-colors ${editorMode === btn.key ? "bg-accent-primary/20 text-accent-primary font-semibold" : "text-text-secondary hover:text-text-primary hover:bg-white/5"}`,
2331
+ title: btn.label,
2332
+ children: [
2333
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "material-symbols-rounded text-sm", children: btn.icon }),
2334
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "hidden sm:inline", children: btn.label })
2335
+ ]
2336
+ },
2337
+ btn.key
2338
+ )) })
2339
+ ] }),
2340
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex-1 min-h-0 flex", children: [
2341
+ (editorMode === "editor" || editorMode === "split") && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2342
+ "div",
2343
+ {
2344
+ className: `${editorMode === "split" ? "w-1/2 border-r border-border/30" : "w-full"} flex-1 flex flex-col min-h-0 min-w-0`,
2345
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2346
+ import_react_codemirror.default,
2347
+ {
2348
+ value,
2349
+ onChange,
2350
+ className: "flex-1 min-h-0 min-w-0",
2351
+ height: "100%",
2352
+ onCreateEditor: (view) => {
2353
+ editorRef.current = view;
2354
+ },
2355
+ basicSetup: {
2356
+ lineNumbers: false,
2357
+ foldGutter: false
2358
+ },
2359
+ extensions
2360
+ }
2361
+ )
2362
+ }
2363
+ ),
2364
+ (editorMode === "preview" || editorMode === "split") && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2365
+ "div",
2366
+ {
2367
+ className: `${editorMode === "split" ? "w-1/2" : "w-full"} flex-1 min-h-0 overflow-auto min-w-0`,
2368
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "nr-prose h-full shadow-xs overflow-auto p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CustomMarkdownRenderer_default, { content: debouncedContent }) })
2369
+ }
2370
+ )
2371
+ ] })
2372
+ ] });
2373
+ };
2374
+ var NReditor_default = NReditor;
2375
+ //# sourceMappingURL=NReditor.js.map