@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.
- package/dist/NReditor.d.mts +29 -0
- package/dist/NReditor.d.ts +29 -0
- package/dist/NReditor.js +2375 -0
- package/dist/NReditor.js.map +1 -0
- package/dist/NReditor.mjs +2344 -0
- package/dist/NReditor.mjs.map +1 -0
- package/dist/index.d.mts +219 -0
- package/dist/index.d.ts +219 -0
- package/dist/index.js +12041 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +12015 -0
- package/dist/index.mjs.map +1 -0
- package/dist/markdown.css +344 -0
- package/markdown.css +344 -0
- package/package.json +106 -0
package/dist/NReditor.js
ADDED
|
@@ -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
|