@noirmd/previewer 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NReditor.cjs +42 -39
- package/dist/NReditor.cjs.map +1 -1
- package/dist/NReditor.js +42 -39
- package/dist/NReditor.js.map +1 -1
- package/dist/core.cjs +464 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +118 -0
- package/dist/core.d.ts +118 -0
- package/dist/core.js +429 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +57 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -73
- package/dist/index.d.ts +120 -73
- package/dist/index.js +49 -38
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +12044 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +225 -0
- package/dist/react.d.ts +225 -0
- package/dist/react.js +12018 -0
- package/dist/react.js.map +1 -0
- package/dist/vanilla.cjs +11844 -0
- package/dist/vanilla.cjs.map +1 -0
- package/dist/vanilla.css +677 -0
- package/dist/vanilla.d.cts +173 -0
- package/dist/vanilla.d.ts +173 -0
- package/dist/vanilla.js +11818 -0
- package/dist/vanilla.js.map +1 -0
- package/dist/vue.cjs +12218 -0
- package/dist/vue.cjs.map +1 -0
- package/dist/vue.d.cts +389 -0
- package/dist/vue.d.ts +389 -0
- package/dist/vue.js +12208 -0
- package/dist/vue.js.map +1 -0
- package/package.json +37 -6
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic CSSProperties — framework-agnostic equivalent of React.CSSProperties.
|
|
3
|
+
* Used for inline styles on tokens (e.g. images).
|
|
4
|
+
*/
|
|
5
|
+
type CSSProperties = Record<string, string | number>;
|
|
6
|
+
interface HeaderToken {
|
|
7
|
+
type: 'header';
|
|
8
|
+
level: number;
|
|
9
|
+
text: string;
|
|
10
|
+
id: string;
|
|
11
|
+
classes?: string;
|
|
12
|
+
}
|
|
13
|
+
interface ParagraphToken {
|
|
14
|
+
type: 'paragraph';
|
|
15
|
+
content: string;
|
|
16
|
+
align?: 'center' | 'right';
|
|
17
|
+
classes?: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
}
|
|
20
|
+
interface CodeblockToken {
|
|
21
|
+
type: 'codeblock';
|
|
22
|
+
language: string;
|
|
23
|
+
content: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
}
|
|
26
|
+
interface DirectiveToken {
|
|
27
|
+
type: 'directive';
|
|
28
|
+
directiveType: string;
|
|
29
|
+
props: Record<string, string>;
|
|
30
|
+
slots: Record<string, string>;
|
|
31
|
+
scopeId: string;
|
|
32
|
+
}
|
|
33
|
+
interface HtmlToken {
|
|
34
|
+
type: 'html';
|
|
35
|
+
content: string;
|
|
36
|
+
scopeId: string;
|
|
37
|
+
}
|
|
38
|
+
interface HtmlBlockToken {
|
|
39
|
+
type: 'html-block';
|
|
40
|
+
tag: string;
|
|
41
|
+
attrs: string;
|
|
42
|
+
children: Token[];
|
|
43
|
+
}
|
|
44
|
+
interface ImageToken {
|
|
45
|
+
type: 'image';
|
|
46
|
+
alt: string;
|
|
47
|
+
src: string;
|
|
48
|
+
style: CSSProperties;
|
|
49
|
+
}
|
|
50
|
+
interface TableToken {
|
|
51
|
+
type: 'table';
|
|
52
|
+
content: string;
|
|
53
|
+
}
|
|
54
|
+
interface ListToken {
|
|
55
|
+
type: 'list';
|
|
56
|
+
content: string;
|
|
57
|
+
}
|
|
58
|
+
interface BlockquoteToken {
|
|
59
|
+
type: 'blockquote';
|
|
60
|
+
content: string;
|
|
61
|
+
classes?: string;
|
|
62
|
+
id?: string;
|
|
63
|
+
}
|
|
64
|
+
interface HrToken {
|
|
65
|
+
type: 'hr';
|
|
66
|
+
}
|
|
67
|
+
interface TocToken {
|
|
68
|
+
type: 'toc';
|
|
69
|
+
}
|
|
70
|
+
type Token = HeaderToken | ParagraphToken | CodeblockToken | DirectiveToken | HtmlToken | HtmlBlockToken | ImageToken | TableToken | ListToken | BlockquoteToken | HrToken | TocToken;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* V2 Markdown Parser — line-by-line state machine (framework-agnostic).
|
|
74
|
+
*/
|
|
75
|
+
declare function parseMarkdown(markdown: string): Token[];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse an inline CSS string (e.g. "color: red; padding: 1rem") into a CSSProperties object.
|
|
79
|
+
*/
|
|
80
|
+
declare function parseCssString(cssText: string): CSSProperties;
|
|
81
|
+
/**
|
|
82
|
+
* Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).
|
|
83
|
+
*/
|
|
84
|
+
declare function generateId(text: string): string;
|
|
85
|
+
/**
|
|
86
|
+
* Smooth-scroll to an element by its ID.
|
|
87
|
+
*/
|
|
88
|
+
declare function scrollToId(id: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Parse attribute suffix like `##{.my-class #my-id}` from a text line.
|
|
91
|
+
* Returns the cleaned text, extracted classes, and id.
|
|
92
|
+
*/
|
|
93
|
+
declare function extractAttributes(text: string): {
|
|
94
|
+
text: string;
|
|
95
|
+
classes: string;
|
|
96
|
+
id: string;
|
|
97
|
+
};
|
|
98
|
+
declare function resetScopeCounter(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Generate a unique scope ID for CSS isolation.
|
|
101
|
+
*/
|
|
102
|
+
declare function generateScopeId(): string;
|
|
103
|
+
/**
|
|
104
|
+
* Parse props from a `{key="value" key2="value2"}` string.
|
|
105
|
+
* Also supports `.className` shorthand → adds to `class` prop.
|
|
106
|
+
* Also supports `#id` shorthand → adds to `id` prop.
|
|
107
|
+
*/
|
|
108
|
+
declare function parseProps(propsString: string): Record<string, string>;
|
|
109
|
+
/**
|
|
110
|
+
* Parse raw HTML attributes string (e.g. `class="..." style="..." data-foo="..."`)
|
|
111
|
+
* into a plain props object.
|
|
112
|
+
*
|
|
113
|
+
* NOTE: This does NOT rename `class` → `className`. Framework adapters
|
|
114
|
+
* (React, Vue, etc.) should handle their own attribute name mapping.
|
|
115
|
+
*/
|
|
116
|
+
declare function parseHtmlAttrs(attrsString: string): Record<string, any>;
|
|
117
|
+
|
|
118
|
+
export { type BlockquoteToken, type CSSProperties, type CodeblockToken, type DirectiveToken, type HeaderToken, type HrToken, type HtmlBlockToken, type HtmlToken, type ImageToken, type ListToken, type ParagraphToken, type TableToken, type TocToken, type Token, extractAttributes, generateId, generateScopeId, parseCssString, parseHtmlAttrs, parseMarkdown, parseProps, resetScopeCounter, scrollToId };
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// core/utils.ts
|
|
2
|
+
function parseCssString(cssText) {
|
|
3
|
+
if (!cssText) return {};
|
|
4
|
+
return cssText.split(";").filter(Boolean).reduce((styleObj, styleString) => {
|
|
5
|
+
const parts = styleString.split(":");
|
|
6
|
+
if (parts.length < 2) return styleObj;
|
|
7
|
+
const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());
|
|
8
|
+
const value = parts.slice(1).join(":").trim();
|
|
9
|
+
styleObj[key] = value;
|
|
10
|
+
return styleObj;
|
|
11
|
+
}, {});
|
|
12
|
+
}
|
|
13
|
+
function generateId(text) {
|
|
14
|
+
return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-");
|
|
15
|
+
}
|
|
16
|
+
function scrollToId(id) {
|
|
17
|
+
if (typeof document === "undefined") return;
|
|
18
|
+
const element = document.getElementById(id);
|
|
19
|
+
if (element) {
|
|
20
|
+
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function extractAttributes(text) {
|
|
24
|
+
const match = text.match(/^(.*?)\s*##\{([^}]*)\}\s*$/);
|
|
25
|
+
if (!match) return { text, classes: "", id: "" };
|
|
26
|
+
const rawAttrs = match[2];
|
|
27
|
+
const cleanedText = match[1];
|
|
28
|
+
const classList = [];
|
|
29
|
+
let id = "";
|
|
30
|
+
for (const [, key, value] of rawAttrs.matchAll(/([\w-]+)="([^"]*)"/g)) {
|
|
31
|
+
if (key === "class") {
|
|
32
|
+
classList.push(...value.split(/\s+/).filter(Boolean));
|
|
33
|
+
} else if (key === "id") {
|
|
34
|
+
id = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const stripped = rawAttrs.replace(/[\w-]+="[^"]*"/g, "");
|
|
38
|
+
for (const token of stripped.split(/\s+/).filter(Boolean)) {
|
|
39
|
+
if (token.startsWith(".")) classList.push(token.slice(1));
|
|
40
|
+
else if (token.startsWith("#") && !id) id = token.slice(1);
|
|
41
|
+
}
|
|
42
|
+
return { text: cleanedText, classes: classList.join(" "), id };
|
|
43
|
+
}
|
|
44
|
+
var _scopeCounter = 0;
|
|
45
|
+
function resetScopeCounter() {
|
|
46
|
+
_scopeCounter = 0;
|
|
47
|
+
}
|
|
48
|
+
function generateScopeId() {
|
|
49
|
+
return `scope-${++_scopeCounter}`;
|
|
50
|
+
}
|
|
51
|
+
function parseProps(propsString) {
|
|
52
|
+
const props = {};
|
|
53
|
+
if (!propsString?.trim()) return props;
|
|
54
|
+
const pairRegex = /(\w[\w-]*)=(?:"([^"]*)"|'([^']*)')/g;
|
|
55
|
+
let match;
|
|
56
|
+
while ((match = pairRegex.exec(propsString)) !== null) {
|
|
57
|
+
const key = match[1];
|
|
58
|
+
const value = match[2] ?? match[3] ?? "";
|
|
59
|
+
props[key] = value;
|
|
60
|
+
}
|
|
61
|
+
const classMatches = propsString.match(/\.([a-zA-Z0-9_!/.\-]+)/g);
|
|
62
|
+
if (classMatches) {
|
|
63
|
+
const existing = props["class"] || "";
|
|
64
|
+
const newClasses = classMatches.map((c) => c.substring(1)).join(" ");
|
|
65
|
+
props["class"] = existing ? `${existing} ${newClasses}` : newClasses;
|
|
66
|
+
}
|
|
67
|
+
const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\s|}|$)/);
|
|
68
|
+
if (idMatch && !props["id"]) {
|
|
69
|
+
props["id"] = idMatch[1];
|
|
70
|
+
}
|
|
71
|
+
return props;
|
|
72
|
+
}
|
|
73
|
+
function parseHtmlAttrs(attrsString) {
|
|
74
|
+
const props = {};
|
|
75
|
+
if (!attrsString?.trim()) return props;
|
|
76
|
+
const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
|
|
77
|
+
let match;
|
|
78
|
+
while ((match = pairRegex.exec(attrsString)) !== null) {
|
|
79
|
+
const key = match[1];
|
|
80
|
+
const value = match[2] ?? match[3] ?? match[4] ?? true;
|
|
81
|
+
if (key === "style" && typeof value === "string") {
|
|
82
|
+
props[key] = parseCssString(value);
|
|
83
|
+
} else {
|
|
84
|
+
props[key] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return props;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// core/parser.ts
|
|
91
|
+
function parseMarkdown(markdown) {
|
|
92
|
+
if (!markdown) return [];
|
|
93
|
+
const lines = markdown.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
94
|
+
const result = [];
|
|
95
|
+
let i = 0;
|
|
96
|
+
while (i < lines.length) {
|
|
97
|
+
const line = lines[i];
|
|
98
|
+
const trimmed = line.trim();
|
|
99
|
+
let match;
|
|
100
|
+
if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
|
|
101
|
+
const level = match[1].length;
|
|
102
|
+
const rawText = match[2];
|
|
103
|
+
const { text: text2, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
104
|
+
const id2 = customId || generateId(text2.replace(/->|<-/g, ""));
|
|
105
|
+
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
106
|
+
i++;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (match = trimmed.match(/^->\s*(.+?)\s*(<-|->)\s*$/)) {
|
|
110
|
+
const content = match[1];
|
|
111
|
+
const align = match[2] === "<-" ? "center" : "right";
|
|
112
|
+
result.push({ type: "paragraph", content, align });
|
|
113
|
+
i++;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (trimmed.startsWith("```")) {
|
|
117
|
+
const fenceHeader = trimmed.slice(3).trim();
|
|
118
|
+
const titleMatch = fenceHeader.match(/title=["']([^"']*)["']/);
|
|
119
|
+
const lang = fenceHeader.replace(/title=["'][^"']*["']/, "").trim();
|
|
120
|
+
const title = titleMatch ? titleMatch[1] : void 0;
|
|
121
|
+
const content = [];
|
|
122
|
+
i++;
|
|
123
|
+
while (i < lines.length && !lines[i].trim().startsWith("```")) {
|
|
124
|
+
content.push(lines[i]);
|
|
125
|
+
i++;
|
|
126
|
+
}
|
|
127
|
+
result.push({ type: "codeblock", language: lang, title, content: content.join("\n") });
|
|
128
|
+
i++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (trimmed.startsWith(":::")) {
|
|
132
|
+
const rest = trimmed.slice(3).trim();
|
|
133
|
+
if (rest === "") {
|
|
134
|
+
result.push({ type: "paragraph", content: line });
|
|
135
|
+
i++;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const typeMatch = rest.match(/^([\w-]+)/);
|
|
139
|
+
const directiveType = typeMatch ? typeMatch[1] : "custom";
|
|
140
|
+
let j = i + 1;
|
|
141
|
+
let nestedLevel = 0;
|
|
142
|
+
let foundClose = false;
|
|
143
|
+
while (j < lines.length) {
|
|
144
|
+
const currentTrimmed = lines[j].trim();
|
|
145
|
+
if (currentTrimmed === ":::") {
|
|
146
|
+
if (nestedLevel === 0) {
|
|
147
|
+
foundClose = true;
|
|
148
|
+
break;
|
|
149
|
+
} else {
|
|
150
|
+
nestedLevel--;
|
|
151
|
+
}
|
|
152
|
+
} else if (currentTrimmed.startsWith(":::")) {
|
|
153
|
+
nestedLevel++;
|
|
154
|
+
}
|
|
155
|
+
j++;
|
|
156
|
+
}
|
|
157
|
+
if (foundClose) {
|
|
158
|
+
const contentLines = [];
|
|
159
|
+
for (let k = i + 1; k < j; k++) {
|
|
160
|
+
contentLines.push(lines[k]);
|
|
161
|
+
}
|
|
162
|
+
const rawContent = contentLines.join("\n");
|
|
163
|
+
const headerRest = typeMatch ? rest.slice(directiveType.length).trim() : rest;
|
|
164
|
+
let propsString = "";
|
|
165
|
+
let shortForm = "";
|
|
166
|
+
const propsBlockMatch = headerRest.match(/^\{([^]*)\}\s*$/);
|
|
167
|
+
if (propsBlockMatch) {
|
|
168
|
+
propsString = propsBlockMatch[1];
|
|
169
|
+
} else if (headerRest) {
|
|
170
|
+
shortForm = headerRest;
|
|
171
|
+
}
|
|
172
|
+
const props = parseProps(propsString);
|
|
173
|
+
if (shortForm && !props["title"]) {
|
|
174
|
+
props["title"] = shortForm;
|
|
175
|
+
}
|
|
176
|
+
const slots = splitSlots(rawContent);
|
|
177
|
+
result.push({
|
|
178
|
+
type: "directive",
|
|
179
|
+
directiveType,
|
|
180
|
+
props,
|
|
181
|
+
slots,
|
|
182
|
+
scopeId: generateScopeId()
|
|
183
|
+
});
|
|
184
|
+
i = j + 1;
|
|
185
|
+
continue;
|
|
186
|
+
} else {
|
|
187
|
+
result.push({ type: "paragraph", content: line });
|
|
188
|
+
i++;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (match = trimmed.match(/^(.*?)!\[([^\]]*)\]\(([^)]+?)\)(?:\{([^}]+?)\})?(.*)$/)) {
|
|
193
|
+
const [, preText, alt, srcAndFloat, size, postText] = match;
|
|
194
|
+
if (preText.trim()) {
|
|
195
|
+
result.push({ type: "paragraph", content: preText.trim() });
|
|
196
|
+
}
|
|
197
|
+
let src = srcAndFloat;
|
|
198
|
+
const style = {};
|
|
199
|
+
if (src.includes("#left")) {
|
|
200
|
+
src = src.replace("#left", "");
|
|
201
|
+
style.float = "left";
|
|
202
|
+
style.margin = "0 1em 1em 0";
|
|
203
|
+
} else if (src.includes("#right")) {
|
|
204
|
+
src = src.replace("#right", "");
|
|
205
|
+
style.float = "right";
|
|
206
|
+
style.margin = "0 0 1em 1em";
|
|
207
|
+
} else if (src.includes("#center")) {
|
|
208
|
+
src = src.replace("#center", "");
|
|
209
|
+
style.display = "block";
|
|
210
|
+
style.margin = "0 auto 1em auto";
|
|
211
|
+
}
|
|
212
|
+
if (size) {
|
|
213
|
+
const [width, height] = size.split(":");
|
|
214
|
+
if (width) style.width = width.trim();
|
|
215
|
+
if (height) style.height = height.trim();
|
|
216
|
+
}
|
|
217
|
+
result.push({ type: "image", alt, src, style });
|
|
218
|
+
if (postText.trim()) {
|
|
219
|
+
result.push({ type: "paragraph", content: postText.trim() });
|
|
220
|
+
}
|
|
221
|
+
i++;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (trimmed.includes("|") && i + 1 < lines.length && lines[i + 1].includes("---")) {
|
|
225
|
+
const tableLines = [line];
|
|
226
|
+
i++;
|
|
227
|
+
tableLines.push(lines[i]);
|
|
228
|
+
i++;
|
|
229
|
+
while (i < lines.length && lines[i].trim().includes("|")) {
|
|
230
|
+
tableLines.push(lines[i]);
|
|
231
|
+
i++;
|
|
232
|
+
}
|
|
233
|
+
result.push({ type: "table", content: tableLines.join("\n") });
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (match = trimmed.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/)) {
|
|
237
|
+
const listItems = [line];
|
|
238
|
+
i++;
|
|
239
|
+
while (i < lines.length) {
|
|
240
|
+
const nextLine = lines[i];
|
|
241
|
+
const nextTrimmed = nextLine.trim();
|
|
242
|
+
if (nextTrimmed.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/) || nextTrimmed === "" || nextLine.startsWith(" ")) {
|
|
243
|
+
listItems.push(nextLine);
|
|
244
|
+
i++;
|
|
245
|
+
} else {
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
result.push({ type: "list", content: listItems.join("\n") });
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (trimmed.startsWith(">")) {
|
|
253
|
+
const quoteLines = [line];
|
|
254
|
+
i++;
|
|
255
|
+
while (i < lines.length && (lines[i].trim().startsWith(">") || lines[i].trim() === "")) {
|
|
256
|
+
quoteLines.push(lines[i]);
|
|
257
|
+
i++;
|
|
258
|
+
}
|
|
259
|
+
const rawQuote = quoteLines.join("\n").replace(/^>\s?/gm, "");
|
|
260
|
+
const { text: text2, classes: classes2, id: id2 } = extractAttributes(rawQuote);
|
|
261
|
+
result.push({ type: "blockquote", content: text2, classes: classes2 || void 0, id: id2 });
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (/^(---|___|(\*\s*){3,})\s*$/.test(trimmed)) {
|
|
265
|
+
result.push({ type: "hr" });
|
|
266
|
+
i++;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (/^\[TOC\d?\]\s*$/.test(trimmed)) {
|
|
270
|
+
result.push({ type: "toc" });
|
|
271
|
+
i++;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (trimmed === "") {
|
|
275
|
+
i++;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
|
|
279
|
+
if (tagStartMatch) {
|
|
280
|
+
const tagName = tagStartMatch[1].toLowerCase();
|
|
281
|
+
const voidElements = /* @__PURE__ */ new Set([
|
|
282
|
+
"area",
|
|
283
|
+
"base",
|
|
284
|
+
"br",
|
|
285
|
+
"col",
|
|
286
|
+
"embed",
|
|
287
|
+
"hr",
|
|
288
|
+
"img",
|
|
289
|
+
"input",
|
|
290
|
+
"link",
|
|
291
|
+
"meta",
|
|
292
|
+
"param",
|
|
293
|
+
"source",
|
|
294
|
+
"track",
|
|
295
|
+
"wbr"
|
|
296
|
+
]);
|
|
297
|
+
const remainingText = lines.slice(i).join("\n");
|
|
298
|
+
const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
|
|
299
|
+
const openTagMatch = remainingText.match(openTagRegex);
|
|
300
|
+
if (openTagMatch) {
|
|
301
|
+
const fullOpenTag = openTagMatch[0];
|
|
302
|
+
const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
|
|
303
|
+
const isSelfClosing = fullOpenTag.endsWith("/>") || voidElements.has(tagName);
|
|
304
|
+
if (isSelfClosing) {
|
|
305
|
+
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
306
|
+
const consumedLines = blockText.split("\n").length;
|
|
307
|
+
result.push({
|
|
308
|
+
type: "html-block",
|
|
309
|
+
tag: tagName,
|
|
310
|
+
attrs,
|
|
311
|
+
children: []
|
|
312
|
+
// No children
|
|
313
|
+
});
|
|
314
|
+
i += consumedLines;
|
|
315
|
+
continue;
|
|
316
|
+
} else {
|
|
317
|
+
let nestedLevel = 0;
|
|
318
|
+
let closeIndex = -1;
|
|
319
|
+
let closeTagLength = 0;
|
|
320
|
+
const tagRegex = new RegExp(`</?${tagName}\\b[^>]*>`, "gi");
|
|
321
|
+
tagRegex.lastIndex = openTagMatch.index + fullOpenTag.length;
|
|
322
|
+
let execMatch;
|
|
323
|
+
while ((execMatch = tagRegex.exec(remainingText)) !== null) {
|
|
324
|
+
if (execMatch[0].startsWith("</")) {
|
|
325
|
+
nestedLevel--;
|
|
326
|
+
if (nestedLevel < 0) {
|
|
327
|
+
closeIndex = execMatch.index;
|
|
328
|
+
closeTagLength = execMatch[0].length;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
if (!execMatch[0].endsWith("/>")) {
|
|
333
|
+
nestedLevel++;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (closeIndex !== -1) {
|
|
338
|
+
const fullBlock = remainingText.substring(0, closeIndex + closeTagLength);
|
|
339
|
+
const consumedLines = fullBlock.split("\n").length;
|
|
340
|
+
if (tagName === "style" || tagName === "script") {
|
|
341
|
+
result.push({
|
|
342
|
+
type: "html",
|
|
343
|
+
content: fullBlock,
|
|
344
|
+
scopeId: generateScopeId()
|
|
345
|
+
});
|
|
346
|
+
} else {
|
|
347
|
+
const innerContent = remainingText.substring(openTagMatch.index + fullOpenTag.length, closeIndex);
|
|
348
|
+
result.push({
|
|
349
|
+
type: "html-block",
|
|
350
|
+
tag: tagName,
|
|
351
|
+
attrs,
|
|
352
|
+
children: parseMarkdown(innerContent)
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
i += consumedLines;
|
|
356
|
+
continue;
|
|
357
|
+
} else {
|
|
358
|
+
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
359
|
+
const consumedLines = blockText.split("\n").length;
|
|
360
|
+
result.push({
|
|
361
|
+
type: "html-block",
|
|
362
|
+
tag: tagName,
|
|
363
|
+
attrs,
|
|
364
|
+
children: []
|
|
365
|
+
});
|
|
366
|
+
i += consumedLines;
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const paragraphLines = [line];
|
|
373
|
+
i++;
|
|
374
|
+
while (i < lines.length) {
|
|
375
|
+
const nextLine = lines[i];
|
|
376
|
+
const nextTrimmed = nextLine.trim();
|
|
377
|
+
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/)) {
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
paragraphLines.push(nextLine);
|
|
381
|
+
i++;
|
|
382
|
+
}
|
|
383
|
+
const rawParagraph = paragraphLines.join("\n").trim();
|
|
384
|
+
const { text, classes, id } = extractAttributes(rawParagraph);
|
|
385
|
+
result.push({ type: "paragraph", content: text, classes: classes || void 0, id });
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
function splitSlots(rawContent) {
|
|
390
|
+
const slots = {};
|
|
391
|
+
const lines = rawContent.split("\n");
|
|
392
|
+
let currentSlot = "default";
|
|
393
|
+
let buffer = [];
|
|
394
|
+
let nestingDepth = 0;
|
|
395
|
+
for (const line of lines) {
|
|
396
|
+
const trimmed = line.trim();
|
|
397
|
+
if (trimmed.startsWith(":::")) {
|
|
398
|
+
const rest = trimmed.slice(3).trim();
|
|
399
|
+
if (rest === "") {
|
|
400
|
+
nestingDepth = Math.max(0, nestingDepth - 1);
|
|
401
|
+
} else {
|
|
402
|
+
nestingDepth++;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (nestingDepth === 0 && trimmed.match(/^#([\w-]+)$/)) {
|
|
406
|
+
if (buffer.length > 0 || currentSlot !== "default") {
|
|
407
|
+
slots[currentSlot] = buffer.join("\n").trim();
|
|
408
|
+
}
|
|
409
|
+
currentSlot = trimmed.slice(1);
|
|
410
|
+
buffer = [];
|
|
411
|
+
} else {
|
|
412
|
+
buffer.push(line);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
slots[currentSlot] = buffer.join("\n").trim();
|
|
416
|
+
return slots;
|
|
417
|
+
}
|
|
418
|
+
export {
|
|
419
|
+
extractAttributes,
|
|
420
|
+
generateId,
|
|
421
|
+
generateScopeId,
|
|
422
|
+
parseCssString,
|
|
423
|
+
parseHtmlAttrs,
|
|
424
|
+
parseMarkdown,
|
|
425
|
+
parseProps,
|
|
426
|
+
resetScopeCounter,
|
|
427
|
+
scrollToId
|
|
428
|
+
};
|
|
429
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../core/utils.ts","../core/parser.ts"],"sourcesContent":["import type { CSSProperties } from './types';\r\n\r\n/**\r\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\r\n */\r\nexport function parseCssString(cssText: string): CSSProperties {\r\n if (!cssText) return {};\r\n return cssText\r\n .split(';')\r\n .filter(Boolean)\r\n .reduce<CSSProperties>((styleObj, styleString) => {\r\n const parts = styleString.split(':');\r\n if (parts.length < 2) return styleObj;\r\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\r\n const value = parts.slice(1).join(':').trim();\r\n styleObj[key] = value;\r\n return styleObj;\r\n }, {});\r\n}\r\n\r\n/**\r\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\r\n */\r\nexport function generateId(text: string): string {\r\n return text\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/\\s+/g, '-');\r\n}\r\n\r\n/**\r\n * Smooth-scroll to an element by its ID.\r\n */\r\nexport function scrollToId(id: string): void {\r\n if (typeof document === 'undefined') return;\r\n const element = document.getElementById(id);\r\n if (element) {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n }\r\n}\r\n\r\n/**\r\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\r\n * Returns the cleaned text, extracted classes, and id.\r\n */\r\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\r\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\r\n if (!match) return { text, classes: '', id: '' };\r\n\r\n const rawAttrs = match[2];\r\n const cleanedText = match[1];\r\n\r\n const classList: string[] = [];\r\n let id = '';\r\n\r\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\r\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\r\n if (key === 'class') {\r\n classList.push(...value.split(/\\s+/).filter(Boolean));\r\n } else if (key === 'id') {\r\n id = value;\r\n }\r\n }\r\n\r\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\r\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\r\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\r\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\r\n if (token.startsWith('.')) classList.push(token.slice(1));\r\n else if (token.startsWith('#') && !id) id = token.slice(1);\r\n }\r\n\r\n return { text: cleanedText, classes: classList.join(' '), id };\r\n}\r\n\r\nlet _scopeCounter = 0;\r\nexport function resetScopeCounter(): void {\r\n _scopeCounter = 0;\r\n}\r\n\r\n/**\r\n * Generate a unique scope ID for CSS isolation.\r\n */\r\nexport function generateScopeId(): string {\r\n return `scope-${++_scopeCounter}`;\r\n}\r\n\r\n/**\r\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\r\n * Also supports `.className` shorthand → adds to `class` prop.\r\n * Also supports `#id` shorthand → adds to `id` prop.\r\n */\r\nexport function parseProps(propsString: string): Record<string, string> {\r\n const props: Record<string, string> = {};\r\n if (!propsString?.trim()) return props;\r\n\r\n // Match key=\"value\" or key='value' pairs\r\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\r\n let match;\r\n while ((match = pairRegex.exec(propsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? '';\r\n props[key] = value;\r\n }\r\n\r\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\r\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\r\n if (classMatches) {\r\n const existing = props['class'] || '';\r\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\r\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\r\n }\r\n\r\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\r\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\r\n if (idMatch && !props['id']) {\r\n props['id'] = idMatch[1];\r\n }\r\n\r\n return props;\r\n}\r\n\r\n/**\r\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\r\n * into a plain props object.\r\n *\r\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\r\n * (React, Vue, etc.) should handle their own attribute name mapping.\r\n */\r\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\r\n const props: Record<string, any> = {};\r\n if (!attrsString?.trim()) return props;\r\n\r\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\r\n let match;\r\n while ((match = pairRegex.exec(attrsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? match[4] ?? true;\r\n\r\n // Parse style strings into objects\r\n if (key === 'style' && typeof value === 'string') {\r\n props[key] = parseCssString(value);\r\n } else {\r\n props[key] = value;\r\n }\r\n }\r\n\r\n return props;\r\n}\r\n","import type { Token, DirectiveToken, HtmlBlockToken, CSSProperties } from './types';\r\nimport { generateId, generateScopeId, parseProps, extractAttributes } from './utils';\r\n\r\n/**\r\n * V2 Markdown Parser — line-by-line state machine (framework-agnostic).\r\n */\r\nexport function parseMarkdown(markdown: string): Token[] {\r\n if (!markdown) return [];\r\n const lines = markdown.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '').split('\\n');\r\n const result: Token[] = [];\r\n let i = 0;\r\n\r\n while (i < lines.length) {\r\n const line = lines[i];\r\n const trimmed = line.trim();\r\n let match: RegExpMatchArray | null;\r\n\r\n // ── Headers: ## Title ──\r\n if ((match = trimmed.match(/^(#{1,6})\\s+(.+)$/))) {\r\n const level = match[1].length;\r\n const rawText = match[2];\r\n const { text, classes, id: customId } = extractAttributes(rawText);\r\n const id = customId || generateId(text.replace(/->|<-/g, ''));\r\n result.push({ type: 'header', level, text, id, classes: classes || undefined });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Aligned paragraph: -> text <- or -> text -> ──\r\n if ((match = trimmed.match(/^->\\s*(.+?)\\s*(<-|->)\\s*$/))) {\r\n const content = match[1];\r\n const align = match[2] === '<-' ? 'center' : 'right';\r\n result.push({ type: 'paragraph', content, align });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Code block: ```lang title=\"name\" ──\r\n if (trimmed.startsWith('```')) {\r\n const fenceHeader = trimmed.slice(3).trim();\r\n const titleMatch = fenceHeader.match(/title=[\"']([^\"']*)[\"']/);\r\n const lang = fenceHeader.replace(/title=[\"'][^\"']*[\"']/, '').trim();\r\n const title = titleMatch ? titleMatch[1] : undefined;\r\n const content: string[] = [];\r\n i++;\r\n while (i < lines.length && !lines[i].trim().startsWith('```')) {\r\n content.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'codeblock', language: lang, title, content: content.join('\\n') });\r\n i++; // skip closing ```\r\n continue;\r\n }\r\n\r\n // ── Directive: :::type {props} ... ::: ──\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n\r\n // Bare closing marker\r\n if (rest === '') {\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n\r\n const typeMatch = rest.match(/^([\\w-]+)/);\r\n const directiveType = typeMatch ? typeMatch[1] : 'custom';\r\n\r\n // Lookahead: find the matching closing :::\r\n let j = i + 1;\r\n let nestedLevel = 0;\r\n let foundClose = false;\r\n\r\n while (j < lines.length) {\r\n const currentTrimmed = lines[j].trim();\r\n if (currentTrimmed === ':::') {\r\n if (nestedLevel === 0) {\r\n foundClose = true;\r\n break;\r\n } else {\r\n nestedLevel--;\r\n }\r\n } else if (currentTrimmed.startsWith(':::')) {\r\n // Opening a nested directive\r\n nestedLevel++;\r\n }\r\n j++;\r\n }\r\n\r\n if (foundClose) {\r\n // Collect raw content lines (between opening and closing)\r\n const contentLines: string[] = [];\r\n for (let k = i + 1; k < j; k++) {\r\n contentLines.push(lines[k]);\r\n }\r\n const rawContent = contentLines.join('\\n');\r\n\r\n // Parse the directive header (everything after the type name)\r\n const headerRest = typeMatch ? rest.slice(directiveType.length).trim() : rest;\r\n\r\n // Extract {props} block\r\n let propsString = '';\r\n let shortForm = '';\r\n const propsBlockMatch = headerRest.match(/^\\{([^]*)\\}\\s*$/);\r\n if (propsBlockMatch) {\r\n propsString = propsBlockMatch[1];\r\n } else if (headerRest) {\r\n // Short-form: bare text after type → becomes title prop\r\n shortForm = headerRest;\r\n }\r\n\r\n const props = parseProps(propsString);\r\n if (shortForm && !props['title']) {\r\n props['title'] = shortForm;\r\n }\r\n\r\n // Split content into slots\r\n const slots = splitSlots(rawContent);\r\n\r\n result.push({\r\n type: 'directive',\r\n directiveType,\r\n props,\r\n slots,\r\n scopeId: generateScopeId(),\r\n } as DirectiveToken);\r\n\r\n i = j + 1;\r\n continue;\r\n } else {\r\n // Unclosed directive — render as plain text\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n }\r\n\r\n // ── Image: {w:h} ──\r\n if ((match = trimmed.match(/^(.*?)!\\[([^\\]]*)\\]\\(([^)]+?)\\)(?:\\{([^}]+?)\\})?(.*)$/))) {\r\n const [, preText, alt, srcAndFloat, size, postText] = match;\r\n\r\n if (preText.trim()) {\r\n result.push({ type: 'paragraph', content: preText.trim() });\r\n }\r\n\r\n let src = srcAndFloat;\r\n const style: CSSProperties = {};\r\n if (src.includes('#left')) {\r\n src = src.replace('#left', '');\r\n style.float = 'left';\r\n style.margin = '0 1em 1em 0';\r\n } else if (src.includes('#right')) {\r\n src = src.replace('#right', '');\r\n style.float = 'right';\r\n style.margin = '0 0 1em 1em';\r\n } else if (src.includes('#center')) {\r\n src = src.replace('#center', '');\r\n style.display = 'block';\r\n style.margin = '0 auto 1em auto';\r\n }\r\n if (size) {\r\n const [width, height] = size.split(':');\r\n if (width) style.width = width.trim();\r\n if (height) style.height = height.trim();\r\n }\r\n result.push({ type: 'image', alt, src, style });\r\n\r\n if (postText.trim()) {\r\n result.push({ type: 'paragraph', content: postText.trim() });\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Table: | cell | cell | ──\r\n if (trimmed.includes('|') && i + 1 < lines.length && lines[i + 1].includes('---')) {\r\n const tableLines = [line];\r\n i++;\r\n tableLines.push(lines[i]);\r\n i++;\r\n while (i < lines.length && lines[i].trim().includes('|')) {\r\n tableLines.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'table', content: tableLines.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── List: - item or 1. item ──\r\n if ((match = trimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/))) {\r\n const listItems = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/) ||\r\n nextTrimmed === '' ||\r\n nextLine.startsWith(' ')\r\n ) {\r\n listItems.push(nextLine);\r\n i++;\r\n } else {\r\n break;\r\n }\r\n }\r\n result.push({ type: 'list', content: listItems.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── Blockquote: > text ──\r\n if (trimmed.startsWith('>')) {\r\n const quoteLines = [line];\r\n i++;\r\n while (i < lines.length && (lines[i].trim().startsWith('>') || lines[i].trim() === '')) {\r\n quoteLines.push(lines[i]);\r\n i++;\r\n }\r\n const rawQuote = quoteLines.join('\\n').replace(/^>\\s?/gm, '');\r\n const { text, classes, id } = extractAttributes(rawQuote);\r\n result.push({ type: 'blockquote', content: text, classes: classes || undefined, id });\r\n continue;\r\n }\r\n\r\n // ── Horizontal rule: --- or ___ or *** ──\r\n if (/^(---|___|(\\*\\s*){3,})\\s*$/.test(trimmed)) {\r\n result.push({ type: 'hr' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── TOC: [TOC] or [TOC2] ──\r\n if (/^\\[TOC\\d?\\]\\s*$/.test(trimmed)) {\r\n result.push({ type: 'toc' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Empty line ──\r\n if (trimmed === '') {\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── HTML Block: <tag ...> ──\r\n let tagStartMatch = trimmed.match(/^<([a-zA-Z][\\w-]*)/);\r\n if (tagStartMatch) {\r\n const tagName = tagStartMatch[1].toLowerCase();\r\n\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n\r\n const remainingText = lines.slice(i).join('\\n');\r\n\r\n // Find the full opening tag even with multi-line attributes\r\n const openTagRegex = new RegExp(`^\\\\s*<${tagName}\\\\b([^>]*?)>`, 'i');\r\n const openTagMatch = remainingText.match(openTagRegex);\r\n\r\n if (openTagMatch) {\r\n const fullOpenTag = openTagMatch[0];\r\n const attrs = openTagMatch[1].replace(/\\s+/g, ' ').trim();\r\n\r\n const isSelfClosing = fullOpenTag.endsWith('/>') || voidElements.has(tagName);\r\n\r\n if (isSelfClosing) {\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: [] // No children\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Tag with content — search for its closing tag\r\n let nestedLevel = 0;\r\n let closeIndex = -1;\r\n let closeTagLength = 0;\r\n\r\n const tagRegex = new RegExp(`</?${tagName}\\\\b[^>]*>`, 'gi');\r\n tagRegex.lastIndex = openTagMatch.index! + fullOpenTag.length;\r\n\r\n let execMatch;\r\n while ((execMatch = tagRegex.exec(remainingText)) !== null) {\r\n if (execMatch[0].startsWith('</')) {\r\n nestedLevel--;\r\n if (nestedLevel < 0) {\r\n closeIndex = execMatch.index;\r\n closeTagLength = execMatch[0].length;\r\n break;\r\n }\r\n } else {\r\n if (!execMatch[0].endsWith('/>')) {\r\n nestedLevel++;\r\n }\r\n }\r\n }\r\n\r\n if (closeIndex !== -1) {\r\n const fullBlock = remainingText.substring(0, closeIndex + closeTagLength);\r\n const consumedLines = fullBlock.split('\\n').length;\r\n\r\n // style/script blocks should not be parsed as Markdown\r\n if (tagName === 'style' || tagName === 'script') {\r\n result.push({\r\n type: 'html',\r\n content: fullBlock,\r\n scopeId: generateScopeId(),\r\n });\r\n } else {\r\n const innerContent = remainingText.substring(openTagMatch.index! + fullOpenTag.length, closeIndex);\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: parseMarkdown(innerContent)\r\n } as HtmlBlockToken);\r\n }\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Fallback: unclosed tag → treat as self-closing to avoid consuming the whole document\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: []\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ── Paragraph (default) ──\r\n const paragraphLines = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed === '' ||\r\n nextTrimmed.startsWith('#') ||\r\n nextTrimmed.startsWith(':::') ||\r\n nextTrimmed.includes('|') ||\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+/) ||\r\n nextTrimmed.startsWith('>') ||\r\n nextTrimmed.startsWith('```') ||\r\n nextTrimmed.startsWith('->') ||\r\n nextTrimmed.match(/^<([a-zA-Z][\\w-]*)\\b/)\r\n ) {\r\n break;\r\n }\r\n paragraphLines.push(nextLine);\r\n i++;\r\n }\r\n const rawParagraph = paragraphLines.join('\\n').trim();\r\n const { text, classes, id } = extractAttributes(rawParagraph);\r\n result.push({ type: 'paragraph', content: text, classes: classes || undefined, id });\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────\r\n// Slot splitting\r\n// ─────────────────────────────────────────────\r\n\r\n/**\r\n * Split directive content into named slots.\r\n * A line that is exactly `#slotname` starts a new slot.\r\n * Content before any `#slotname` goes into the \"default\" slot.\r\n *\r\n * IMPORTANT: This is nesting-aware — `#slotname` markers inside nested\r\n * directives (:::child ... :::) are NOT treated as slot boundaries of\r\n * the outer directive. Only `#slotname` at depth 0 are considered.\r\n */\r\nfunction splitSlots(rawContent: string): Record<string, string> {\r\n const slots: Record<string, string> = {};\r\n const lines = rawContent.split('\\n');\r\n let currentSlot = 'default';\r\n let buffer: string[] = [];\r\n let nestingDepth = 0;\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n\r\n // Track nesting of directives\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n if (rest === '') {\r\n // Closing marker (bare :::)\r\n nestingDepth = Math.max(0, nestingDepth - 1);\r\n } else {\r\n nestingDepth++;\r\n }\r\n }\r\n\r\n // Only consider slot boundaries at depth 0\r\n if (nestingDepth === 0 && trimmed.match(/^#([\\w-]+)$/)) {\r\n // Save previous slot\r\n if (buffer.length > 0 || currentSlot !== 'default') {\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n }\r\n currentSlot = trimmed.slice(1);\r\n buffer = [];\r\n } else {\r\n buffer.push(line);\r\n }\r\n }\r\n\r\n // Save last slot\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n\r\n return slots;\r\n}\r\n"],"mappings":";AAKO,SAAS,eAAe,SAAgC;AAC7D,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,SAAO,QACJ,MAAM,GAAG,EACT,OAAO,OAAO,EACd,OAAsB,CAAC,UAAU,gBAAgB;AAChD,UAAM,QAAQ,YAAY,MAAM,GAAG;AACnC,QAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,UAAM,MAAM,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAY,CAAC;AAC1E,UAAM,QAAQ,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK;AAC5C,aAAS,GAAG,IAAI;AAChB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACT;AAKO,SAAS,WAAW,MAAsB;AAC/C,SAAO,KACJ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,YAAY,EACZ,QAAQ,aAAa,EAAE,EACvB,QAAQ,QAAQ,GAAG;AACxB;AAKO,SAAS,WAAW,IAAkB;AAC3C,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,UAAU,SAAS,eAAe,EAAE;AAC1C,MAAI,SAAS;AACX,YAAQ,eAAe,EAAE,UAAU,UAAU,OAAO,QAAQ,CAAC;AAAA,EAC/D;AACF;AAMO,SAAS,kBAAkB,MAA6D;AAC7F,QAAM,QAAQ,KAAK,MAAM,4BAA4B;AACrD,MAAI,CAAC,MAAO,QAAO,EAAE,MAAM,SAAS,IAAI,IAAI,GAAG;AAE/C,QAAM,WAAW,MAAM,CAAC;AACxB,QAAM,cAAc,MAAM,CAAC;AAE3B,QAAM,YAAsB,CAAC;AAC7B,MAAI,KAAK;AAGT,aAAW,CAAC,EAAE,KAAK,KAAK,KAAK,SAAS,SAAS,qBAAqB,GAAG;AACrE,QAAI,QAAQ,SAAS;AACnB,gBAAU,KAAK,GAAG,MAAM,MAAM,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,IACtD,WAAW,QAAQ,MAAM;AACvB,WAAK;AAAA,IACP;AAAA,EACF;AAIA,QAAM,WAAW,SAAS,QAAQ,mBAAmB,EAAE;AACvD,aAAW,SAAS,SAAS,MAAM,KAAK,EAAE,OAAO,OAAO,GAAG;AACzD,QAAI,MAAM,WAAW,GAAG,EAAG,WAAU,KAAK,MAAM,MAAM,CAAC,CAAC;AAAA,aAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,GAAI,MAAK,MAAM,MAAM,CAAC;AAAA,EAC3D;AAEA,SAAO,EAAE,MAAM,aAAa,SAAS,UAAU,KAAK,GAAG,GAAG,GAAG;AAC/D;AAEA,IAAI,gBAAgB;AACb,SAAS,oBAA0B;AACxC,kBAAgB;AAClB;AAKO,SAAS,kBAA0B;AACxC,SAAO,SAAS,EAAE,aAAa;AACjC;AAOO,SAAS,WAAW,aAA6C;AACtE,QAAM,QAAgC,CAAC;AACvC,MAAI,CAAC,aAAa,KAAK,EAAG,QAAO;AAGjC,QAAM,YAAY;AAClB,MAAI;AACJ,UAAQ,QAAQ,UAAU,KAAK,WAAW,OAAO,MAAM;AACrD,UAAM,MAAM,MAAM,CAAC;AACnB,UAAM,QAAQ,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK;AACtC,UAAM,GAAG,IAAI;AAAA,EACf;AAGA,QAAM,eAAe,YAAY,MAAM,yBAAyB;AAChE,MAAI,cAAc;AAChB,UAAM,WAAW,MAAM,OAAO,KAAK;AACnC,UAAM,aAAa,aAAa,IAAI,OAAK,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG;AACjE,UAAM,OAAO,IAAI,WAAW,GAAG,QAAQ,IAAI,UAAU,KAAK;AAAA,EAC5D;AAGA,QAAM,UAAU,YAAY,MAAM,6BAA6B;AAC/D,MAAI,WAAW,CAAC,MAAM,IAAI,GAAG;AAC3B,UAAM,IAAI,IAAI,QAAQ,CAAC;AAAA,EACzB;AAEA,SAAO;AACT;AASO,SAAS,eAAe,aAA0C;AACvE,QAAM,QAA6B,CAAC;AACpC,MAAI,CAAC,aAAa,KAAK,EAAG,QAAO;AAEjC,QAAM,YAAY;AAClB,MAAI;AACJ,UAAQ,QAAQ,UAAU,KAAK,WAAW,OAAO,MAAM;AACrD,UAAM,MAAM,MAAM,CAAC;AACnB,UAAM,QAAQ,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK;AAGlD,QAAI,QAAQ,WAAW,OAAO,UAAU,UAAU;AAChD,YAAM,GAAG,IAAI,eAAe,KAAK;AAAA,IACnC,OAAO;AACL,YAAM,GAAG,IAAI;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;;;AChJO,SAAS,cAAc,UAA2B;AACvD,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,QAAQ,SAAS,QAAQ,SAAS,IAAI,EAAE,QAAQ,OAAO,EAAE,EAAE,MAAM,IAAI;AAC3E,QAAM,SAAkB,CAAC;AACzB,MAAI,IAAI;AAER,SAAO,IAAI,MAAM,QAAQ;AACvB,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI;AAGJ,QAAK,QAAQ,QAAQ,MAAM,mBAAmB,GAAI;AAChD,YAAM,QAAQ,MAAM,CAAC,EAAE;AACvB,YAAM,UAAU,MAAM,CAAC;AACvB,YAAM,EAAE,MAAAA,OAAM,SAAAC,UAAS,IAAI,SAAS,IAAI,kBAAkB,OAAO;AACjE,YAAMC,MAAK,YAAY,WAAWF,MAAK,QAAQ,UAAU,EAAE,CAAC;AAC5D,aAAO,KAAK,EAAE,MAAM,UAAU,OAAO,MAAAA,OAAM,IAAAE,KAAI,SAASD,YAAW,OAAU,CAAC;AAC9E;AACA;AAAA,IACF;AAGA,QAAK,QAAQ,QAAQ,MAAM,2BAA2B,GAAI;AACxD,YAAM,UAAU,MAAM,CAAC;AACvB,YAAM,QAAQ,MAAM,CAAC,MAAM,OAAO,WAAW;AAC7C,aAAO,KAAK,EAAE,MAAM,aAAa,SAAS,MAAM,CAAC;AACjD;AACA;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW,KAAK,GAAG;AAC7B,YAAM,cAAc,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC1C,YAAM,aAAa,YAAY,MAAM,wBAAwB;AAC7D,YAAM,OAAO,YAAY,QAAQ,wBAAwB,EAAE,EAAE,KAAK;AAClE,YAAM,QAAQ,aAAa,WAAW,CAAC,IAAI;AAC3C,YAAM,UAAoB,CAAC;AAC3B;AACA,aAAO,IAAI,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,GAAG;AAC7D,gBAAQ,KAAK,MAAM,CAAC,CAAC;AACrB;AAAA,MACF;AACA,aAAO,KAAK,EAAE,MAAM,aAAa,UAAU,MAAM,OAAO,SAAS,QAAQ,KAAK,IAAI,EAAE,CAAC;AACrF;AACA;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW,KAAK,GAAG;AAC7B,YAAM,OAAO,QAAQ,MAAM,CAAC,EAAE,KAAK;AAGnC,UAAI,SAAS,IAAI;AACf,eAAO,KAAK,EAAE,MAAM,aAAa,SAAS,KAAK,CAAC;AAChD;AACA;AAAA,MACF;AAEA,YAAM,YAAY,KAAK,MAAM,WAAW;AACxC,YAAM,gBAAgB,YAAY,UAAU,CAAC,IAAI;AAGjD,UAAI,IAAI,IAAI;AACZ,UAAI,cAAc;AAClB,UAAI,aAAa;AAEjB,aAAO,IAAI,MAAM,QAAQ;AACvB,cAAM,iBAAiB,MAAM,CAAC,EAAE,KAAK;AACrC,YAAI,mBAAmB,OAAO;AAC5B,cAAI,gBAAgB,GAAG;AACrB,yBAAa;AACb;AAAA,UACF,OAAO;AACL;AAAA,UACF;AAAA,QACF,WAAW,eAAe,WAAW,KAAK,GAAG;AAE3C;AAAA,QACF;AACA;AAAA,MACF;AAEA,UAAI,YAAY;AAEd,cAAM,eAAyB,CAAC;AAChC,iBAAS,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;AAC9B,uBAAa,KAAK,MAAM,CAAC,CAAC;AAAA,QAC5B;AACA,cAAM,aAAa,aAAa,KAAK,IAAI;AAGzC,cAAM,aAAa,YAAY,KAAK,MAAM,cAAc,MAAM,EAAE,KAAK,IAAI;AAGzE,YAAI,cAAc;AAClB,YAAI,YAAY;AAChB,cAAM,kBAAkB,WAAW,MAAM,iBAAiB;AAC1D,YAAI,iBAAiB;AACnB,wBAAc,gBAAgB,CAAC;AAAA,QACjC,WAAW,YAAY;AAErB,sBAAY;AAAA,QACd;AAEA,cAAM,QAAQ,WAAW,WAAW;AACpC,YAAI,aAAa,CAAC,MAAM,OAAO,GAAG;AAChC,gBAAM,OAAO,IAAI;AAAA,QACnB;AAGA,cAAM,QAAQ,WAAW,UAAU;AAEnC,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,SAAS,gBAAgB;AAAA,QAC3B,CAAmB;AAEnB,YAAI,IAAI;AACR;AAAA,MACF,OAAO;AAEL,eAAO,KAAK,EAAE,MAAM,aAAa,SAAS,KAAK,CAAC;AAChD;AACA;AAAA,MACF;AAAA,IACF;AAGA,QAAK,QAAQ,QAAQ,MAAM,uDAAuD,GAAI;AACpF,YAAM,CAAC,EAAE,SAAS,KAAK,aAAa,MAAM,QAAQ,IAAI;AAEtD,UAAI,QAAQ,KAAK,GAAG;AAClB,eAAO,KAAK,EAAE,MAAM,aAAa,SAAS,QAAQ,KAAK,EAAE,CAAC;AAAA,MAC5D;AAEA,UAAI,MAAM;AACV,YAAM,QAAuB,CAAC;AAC9B,UAAI,IAAI,SAAS,OAAO,GAAG;AACzB,cAAM,IAAI,QAAQ,SAAS,EAAE;AAC7B,cAAM,QAAQ;AACd,cAAM,SAAS;AAAA,MACjB,WAAW,IAAI,SAAS,QAAQ,GAAG;AACjC,cAAM,IAAI,QAAQ,UAAU,EAAE;AAC9B,cAAM,QAAQ;AACd,cAAM,SAAS;AAAA,MACjB,WAAW,IAAI,SAAS,SAAS,GAAG;AAClC,cAAM,IAAI,QAAQ,WAAW,EAAE;AAC/B,cAAM,UAAU;AAChB,cAAM,SAAS;AAAA,MACjB;AACA,UAAI,MAAM;AACR,cAAM,CAAC,OAAO,MAAM,IAAI,KAAK,MAAM,GAAG;AACtC,YAAI,MAAO,OAAM,QAAQ,MAAM,KAAK;AACpC,YAAI,OAAQ,OAAM,SAAS,OAAO,KAAK;AAAA,MACzC;AACA,aAAO,KAAK,EAAE,MAAM,SAAS,KAAK,KAAK,MAAM,CAAC;AAE9C,UAAI,SAAS,KAAK,GAAG;AACnB,eAAO,KAAK,EAAE,MAAM,aAAa,SAAS,SAAS,KAAK,EAAE,CAAC;AAAA,MAC7D;AACA;AACA;AAAA,IACF;AAGA,QAAI,QAAQ,SAAS,GAAG,KAAK,IAAI,IAAI,MAAM,UAAU,MAAM,IAAI,CAAC,EAAE,SAAS,KAAK,GAAG;AACjF,YAAM,aAAa,CAAC,IAAI;AACxB;AACA,iBAAW,KAAK,MAAM,CAAC,CAAC;AACxB;AACA,aAAO,IAAI,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,GAAG,GAAG;AACxD,mBAAW,KAAK,MAAM,CAAC,CAAC;AACxB;AAAA,MACF;AACA,aAAO,KAAK,EAAE,MAAM,SAAS,SAAS,WAAW,KAAK,IAAI,EAAE,CAAC;AAC7D;AAAA,IACF;AAGA,QAAK,QAAQ,QAAQ,MAAM,6BAA6B,GAAI;AAC1D,YAAM,YAAY,CAAC,IAAI;AACvB;AACA,aAAO,IAAI,MAAM,QAAQ;AACvB,cAAM,WAAW,MAAM,CAAC;AACxB,cAAM,cAAc,SAAS,KAAK;AAClC,YACE,YAAY,MAAM,6BAA6B,KAC/C,gBAAgB,MAChB,SAAS,WAAW,IAAI,GACxB;AACA,oBAAU,KAAK,QAAQ;AACvB;AAAA,QACF,OAAO;AACL;AAAA,QACF;AAAA,MACF;AACA,aAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,UAAU,KAAK,IAAI,EAAE,CAAC;AAC3D;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,YAAM,aAAa,CAAC,IAAI;AACxB;AACA,aAAO,IAAI,MAAM,WAAW,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,KAAK,MAAM,CAAC,EAAE,KAAK,MAAM,KAAK;AACtF,mBAAW,KAAK,MAAM,CAAC,CAAC;AACxB;AAAA,MACF;AACA,YAAM,WAAW,WAAW,KAAK,IAAI,EAAE,QAAQ,WAAW,EAAE;AAC5D,YAAM,EAAE,MAAAD,OAAM,SAAAC,UAAS,IAAAC,IAAG,IAAI,kBAAkB,QAAQ;AACxD,aAAO,KAAK,EAAE,MAAM,cAAc,SAASF,OAAM,SAASC,YAAW,QAAW,IAAAC,IAAG,CAAC;AACpF;AAAA,IACF;AAGA,QAAI,6BAA6B,KAAK,OAAO,GAAG;AAC9C,aAAO,KAAK,EAAE,MAAM,KAAK,CAAC;AAC1B;AACA;AAAA,IACF;AAGA,QAAI,kBAAkB,KAAK,OAAO,GAAG;AACnC,aAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAC3B;AACA;AAAA,IACF;AAGA,QAAI,YAAY,IAAI;AAClB;AACA;AAAA,IACF;AAGA,QAAI,gBAAgB,QAAQ,MAAM,oBAAoB;AACtD,QAAI,eAAe;AACjB,YAAM,UAAU,cAAc,CAAC,EAAE,YAAY;AAE7C,YAAM,eAAe,oBAAI,IAAI;AAAA,QAC3B;AAAA,QAAQ;AAAA,QAAQ;AAAA,QAAM;AAAA,QAAO;AAAA,QAAS;AAAA,QAAM;AAAA,QAAO;AAAA,QACnD;AAAA,QAAQ;AAAA,QAAQ;AAAA,QAAS;AAAA,QAAU;AAAA,QAAS;AAAA,MAC9C,CAAC;AAED,YAAM,gBAAgB,MAAM,MAAM,CAAC,EAAE,KAAK,IAAI;AAG9C,YAAM,eAAe,IAAI,OAAO,SAAS,OAAO,gBAAgB,GAAG;AACnE,YAAM,eAAe,cAAc,MAAM,YAAY;AAErD,UAAI,cAAc;AAChB,cAAM,cAAc,aAAa,CAAC;AAClC,cAAM,QAAQ,aAAa,CAAC,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAExD,cAAM,gBAAgB,YAAY,SAAS,IAAI,KAAK,aAAa,IAAI,OAAO;AAE5E,YAAI,eAAe;AACjB,gBAAM,YAAY,cAAc,UAAU,GAAG,aAAa,QAAS,YAAY,MAAM;AACrF,gBAAM,gBAAgB,UAAU,MAAM,IAAI,EAAE;AAE5C,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,KAAK;AAAA,YACL;AAAA,YACA,UAAU,CAAC;AAAA;AAAA,UACb,CAAmB;AAEnB,eAAK;AACL;AAAA,QACF,OAAO;AAEL,cAAI,cAAc;AAClB,cAAI,aAAa;AACjB,cAAI,iBAAiB;AAErB,gBAAM,WAAW,IAAI,OAAO,MAAM,OAAO,aAAa,IAAI;AAC1D,mBAAS,YAAY,aAAa,QAAS,YAAY;AAEvD,cAAI;AACJ,kBAAQ,YAAY,SAAS,KAAK,aAAa,OAAO,MAAM;AAC1D,gBAAI,UAAU,CAAC,EAAE,WAAW,IAAI,GAAG;AACjC;AACA,kBAAI,cAAc,GAAG;AACnB,6BAAa,UAAU;AACvB,iCAAiB,UAAU,CAAC,EAAE;AAC9B;AAAA,cACF;AAAA,YACF,OAAO;AACL,kBAAI,CAAC,UAAU,CAAC,EAAE,SAAS,IAAI,GAAG;AAChC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,cAAI,eAAe,IAAI;AACrB,kBAAM,YAAY,cAAc,UAAU,GAAG,aAAa,cAAc;AACxE,kBAAM,gBAAgB,UAAU,MAAM,IAAI,EAAE;AAG5C,gBAAI,YAAY,WAAW,YAAY,UAAU;AAC/C,qBAAO,KAAK;AAAA,gBACV,MAAM;AAAA,gBACN,SAAS;AAAA,gBACT,SAAS,gBAAgB;AAAA,cAC3B,CAAC;AAAA,YACH,OAAO;AACL,oBAAM,eAAe,cAAc,UAAU,aAAa,QAAS,YAAY,QAAQ,UAAU;AACjG,qBAAO,KAAK;AAAA,gBACV,MAAM;AAAA,gBACN,KAAK;AAAA,gBACL;AAAA,gBACA,UAAU,cAAc,YAAY;AAAA,cACtC,CAAmB;AAAA,YACrB;AAEA,iBAAK;AACL;AAAA,UACF,OAAO;AAEL,kBAAM,YAAY,cAAc,UAAU,GAAG,aAAa,QAAS,YAAY,MAAM;AACrF,kBAAM,gBAAgB,UAAU,MAAM,IAAI,EAAE;AAE5C,mBAAO,KAAK;AAAA,cACV,MAAM;AAAA,cACN,KAAK;AAAA,cACL;AAAA,cACA,UAAU,CAAC;AAAA,YACb,CAAmB;AAEnB,iBAAK;AACL;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAiB,CAAC,IAAI;AAC5B;AACA,WAAO,IAAI,MAAM,QAAQ;AACvB,YAAM,WAAW,MAAM,CAAC;AACxB,YAAM,cAAc,SAAS,KAAK;AAClC,UACE,gBAAgB,MAChB,YAAY,WAAW,GAAG,KAC1B,YAAY,WAAW,KAAK,KAC5B,YAAY,SAAS,GAAG,KACxB,YAAY,MAAM,wBAAwB,KAC1C,YAAY,WAAW,GAAG,KAC1B,YAAY,WAAW,KAAK,KAC5B,YAAY,WAAW,IAAI,KAC3B,YAAY,MAAM,sBAAsB,GACxC;AACA;AAAA,MACF;AACA,qBAAe,KAAK,QAAQ;AAC5B;AAAA,IACF;AACA,UAAM,eAAe,eAAe,KAAK,IAAI,EAAE,KAAK;AACpD,UAAM,EAAE,MAAM,SAAS,GAAG,IAAI,kBAAkB,YAAY;AAC5D,WAAO,KAAK,EAAE,MAAM,aAAa,SAAS,MAAM,SAAS,WAAW,QAAW,GAAG,CAAC;AAAA,EACrF;AAEA,SAAO;AACT;AAeA,SAAS,WAAW,YAA4C;AAC9D,QAAM,QAAgC,CAAC;AACvC,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,MAAI,cAAc;AAClB,MAAI,SAAmB,CAAC;AACxB,MAAI,eAAe;AAEnB,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAG1B,QAAI,QAAQ,WAAW,KAAK,GAAG;AAC7B,YAAM,OAAO,QAAQ,MAAM,CAAC,EAAE,KAAK;AACnC,UAAI,SAAS,IAAI;AAEf,uBAAe,KAAK,IAAI,GAAG,eAAe,CAAC;AAAA,MAC7C,OAAO;AACL;AAAA,MACF;AAAA,IACF;AAGA,QAAI,iBAAiB,KAAK,QAAQ,MAAM,aAAa,GAAG;AAEtD,UAAI,OAAO,SAAS,KAAK,gBAAgB,WAAW;AAClD,cAAM,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,KAAK;AAAA,MAC9C;AACA,oBAAc,QAAQ,MAAM,CAAC;AAC7B,eAAS,CAAC;AAAA,IACZ,OAAO;AACL,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AAGA,QAAM,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,KAAK;AAE5C,SAAO;AACT;","names":["text","classes","id"]}
|