@noirmd/previewer 2.1.3 → 2.1.5
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 +211 -171
- package/dist/NReditor.cjs.map +1 -1
- package/dist/NReditor.js +212 -172
- package/dist/NReditor.js.map +1 -1
- package/dist/button.css +6 -0
- package/dist/card.css +10 -10
- package/dist/core.cjs +31 -20
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +31 -20
- package/dist/core.js.map +1 -1
- package/dist/editor.css +58 -3
- package/dist/hover3d.css +1 -1
- package/dist/index.cjs +151 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +151 -159
- package/dist/index.js.map +1 -1
- package/dist/modal.css +7 -1
- package/dist/react.cjs +211 -171
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +212 -172
- package/dist/react.js.map +1 -1
- package/dist/vanilla.cjs +151 -159
- package/dist/vanilla.cjs.map +1 -1
- package/dist/vanilla.d.cts +1 -0
- package/dist/vanilla.d.ts +1 -0
- package/dist/vanilla.js +151 -159
- package/dist/vanilla.js.map +1 -1
- package/dist/vue.cjs +151 -159
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -0
- package/dist/vue.d.ts +1 -0
- package/dist/vue.js +151 -159
- package/dist/vue.js.map +1 -1
- package/editor.css +58 -3
- package/package.json +1 -1
package/dist/button.css
CHANGED
package/dist/card.css
CHANGED
|
@@ -3,40 +3,40 @@
|
|
|
3
3
|
============================================================ */
|
|
4
4
|
|
|
5
5
|
.nr-card-grid {
|
|
6
|
-
display:
|
|
7
|
-
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-wrap: wrap;
|
|
8
8
|
gap: 1.5rem;
|
|
9
9
|
margin: 1.5rem 0;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/* ── Alignment variants ── */
|
|
13
13
|
.nr-card-grid--center {
|
|
14
|
-
justify-
|
|
14
|
+
justify-content: center;
|
|
15
15
|
}
|
|
16
16
|
.nr-card-grid--right {
|
|
17
|
-
justify-
|
|
17
|
+
justify-content: flex-end;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
.nr-card {
|
|
21
21
|
display: flex;
|
|
22
22
|
flex-direction: column;
|
|
23
|
-
height: 100%;
|
|
24
23
|
border-radius: var(--nr-radius-lg);
|
|
25
24
|
border: 1px solid var(--nr-border);
|
|
26
25
|
transition: all 0.2s;
|
|
27
26
|
position: relative;
|
|
28
27
|
overflow: hidden;
|
|
29
28
|
min-width: 0;
|
|
29
|
+
flex: 1 1 18rem;
|
|
30
30
|
max-width: 20rem;
|
|
31
31
|
width: 100%;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.nr-card--interactive {
|
|
35
35
|
cursor: pointer;
|
|
36
|
-
border-color:
|
|
36
|
+
border-color: color-mix(in srgb, var(--nr-accent) 10%, transparent);
|
|
37
37
|
}
|
|
38
38
|
.nr-card--interactive:hover {
|
|
39
|
-
border-color:
|
|
39
|
+
border-color: color-mix(in srgb, var(--nr-accent) 50%, transparent);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
.nr-card__image {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
height: 2.5rem;
|
|
90
90
|
font-size: 1.6em;
|
|
91
91
|
border-radius: 0.75rem;
|
|
92
|
-
background:
|
|
92
|
+
background: color-mix(in srgb, var(--nr-accent) 20%, transparent);
|
|
93
93
|
display: flex;
|
|
94
94
|
align-items: center;
|
|
95
95
|
justify-content: center;
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
.nr-card__action-link {
|
|
130
|
-
background:
|
|
130
|
+
background: color-mix(in srgb, var(--nr-accent) 20%, transparent);
|
|
131
131
|
padding: 0.5rem 1rem;
|
|
132
132
|
border-radius: 0.75rem;
|
|
133
133
|
display: flex;
|
|
@@ -147,5 +147,5 @@
|
|
|
147
147
|
color: var(--nr-accent);
|
|
148
148
|
}
|
|
149
149
|
.nr-card__action-link:hover {
|
|
150
|
-
background:
|
|
150
|
+
background: color-mix(in srgb, var(--nr-accent) 30%, transparent);
|
|
151
151
|
}
|
package/dist/core.cjs
CHANGED
|
@@ -122,6 +122,22 @@ function parseHtmlAttrs(attrsString) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// core/parser.ts
|
|
125
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
126
|
+
"area",
|
|
127
|
+
"base",
|
|
128
|
+
"br",
|
|
129
|
+
"col",
|
|
130
|
+
"embed",
|
|
131
|
+
"hr",
|
|
132
|
+
"img",
|
|
133
|
+
"input",
|
|
134
|
+
"link",
|
|
135
|
+
"meta",
|
|
136
|
+
"param",
|
|
137
|
+
"source",
|
|
138
|
+
"track",
|
|
139
|
+
"wbr"
|
|
140
|
+
]);
|
|
125
141
|
function parseMarkdown(markdown) {
|
|
126
142
|
if (!markdown) return [];
|
|
127
143
|
const lines = markdown.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
@@ -135,8 +151,19 @@ function parseMarkdown(markdown) {
|
|
|
135
151
|
if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
|
|
136
152
|
const level = match[1].length;
|
|
137
153
|
const rawText = match[2];
|
|
138
|
-
const { text:
|
|
139
|
-
|
|
154
|
+
const { text: rawParsedText, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
155
|
+
let text2 = rawParsedText;
|
|
156
|
+
let align;
|
|
157
|
+
const alignCenter = text2.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
158
|
+
const alignRight = text2.match(/^->\s*(.+?)\s*->\s*$/);
|
|
159
|
+
if (alignCenter) {
|
|
160
|
+
text2 = alignCenter[1];
|
|
161
|
+
align = "center";
|
|
162
|
+
} else if (alignRight) {
|
|
163
|
+
text2 = alignRight[1];
|
|
164
|
+
align = "right";
|
|
165
|
+
}
|
|
166
|
+
const baseId = customId || generateId(text2);
|
|
140
167
|
let id2 = baseId;
|
|
141
168
|
let n = 1;
|
|
142
169
|
while (usedIds.has(id2)) {
|
|
@@ -144,7 +171,7 @@ function parseMarkdown(markdown) {
|
|
|
144
171
|
id2 = `${baseId}-${n}`;
|
|
145
172
|
}
|
|
146
173
|
usedIds.add(id2);
|
|
147
|
-
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
174
|
+
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0, align });
|
|
148
175
|
i++;
|
|
149
176
|
continue;
|
|
150
177
|
}
|
|
@@ -320,29 +347,13 @@ function parseMarkdown(markdown) {
|
|
|
320
347
|
let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
|
|
321
348
|
if (tagStartMatch) {
|
|
322
349
|
const tagName = tagStartMatch[1].toLowerCase();
|
|
323
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
324
|
-
"area",
|
|
325
|
-
"base",
|
|
326
|
-
"br",
|
|
327
|
-
"col",
|
|
328
|
-
"embed",
|
|
329
|
-
"hr",
|
|
330
|
-
"img",
|
|
331
|
-
"input",
|
|
332
|
-
"link",
|
|
333
|
-
"meta",
|
|
334
|
-
"param",
|
|
335
|
-
"source",
|
|
336
|
-
"track",
|
|
337
|
-
"wbr"
|
|
338
|
-
]);
|
|
339
350
|
const remainingText = lines.slice(i).join("\n");
|
|
340
351
|
const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
|
|
341
352
|
const openTagMatch = remainingText.match(openTagRegex);
|
|
342
353
|
if (openTagMatch) {
|
|
343
354
|
const fullOpenTag = openTagMatch[0];
|
|
344
355
|
const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
|
|
345
|
-
const isSelfClosing = fullOpenTag.endsWith("/>") ||
|
|
356
|
+
const isSelfClosing = fullOpenTag.endsWith("/>") || VOID_ELEMENTS.has(tagName);
|
|
346
357
|
if (isSelfClosing) {
|
|
347
358
|
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
348
359
|
const consumedLines = blockText.split("\n").length;
|
package/dist/core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../core.ts","../core/utils.ts","../core/parser.ts"],"sourcesContent":["// ============================================================\n// @noirmd/previewer/core — Framework-agnostic entry point\n//\n// Usage:\n// import { parseMarkdown, Token } from '@noirmd/previewer/core';\n//\n// This module has ZERO dependency on React (or any UI framework).\n// ============================================================\n\nexport {\n parseMarkdown,\n type Token,\n type CSSProperties,\n type HeaderToken,\n type ParagraphToken,\n type CodeblockToken,\n type DirectiveToken,\n type HtmlToken,\n type HtmlBlockToken,\n type ImageToken,\n type TableToken,\n type ListToken,\n type BlockquoteToken,\n type HrToken,\n type TocToken,\n parseCssString,\n generateId,\n generateScopeId,\n resetScopeCounter,\n scrollToId,\n extractAttributes,\n parseProps,\n parseHtmlAttrs,\n} from './core/index';\n","import type { CSSProperties } from './types';\n\n/**\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\n */\nexport function parseCssString(cssText: string): CSSProperties {\n if (!cssText) return {};\n return cssText\n .split(';')\n .filter(Boolean)\n .reduce<CSSProperties>((styleObj, styleString) => {\n const parts = styleString.split(':');\n if (parts.length < 2) return styleObj;\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\n const value = parts.slice(1).join(':').trim();\n styleObj[key] = value;\n return styleObj;\n }, {});\n}\n\n/**\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\n */\nexport function generateId(text: string): string {\n return text\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n}\n\n/**\n * Smooth-scroll to an element by its ID.\n */\nexport function scrollToId(id: string): void {\n if (typeof document === 'undefined') return;\n const element = document.getElementById(id);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n}\n\n/**\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\n * Returns the cleaned text, extracted classes, and id.\n */\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\n if (!match) return { text, classes: '', id: '' };\n\n const rawAttrs = match[2];\n const cleanedText = match[1];\n\n const classList: string[] = [];\n let id = '';\n\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\n if (key === 'class') {\n classList.push(...value.split(/\\s+/).filter(Boolean));\n } else if (key === 'id') {\n id = value;\n }\n }\n\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\n if (token.startsWith('.')) classList.push(token.slice(1));\n else if (token.startsWith('#') && !id) id = token.slice(1);\n }\n\n return { text: cleanedText, classes: classList.join(' '), id };\n}\n\nlet _scopeCounter = 0;\nexport function resetScopeCounter(): void {\n _scopeCounter = 0;\n}\n\n/**\n * Generate a unique scope ID for CSS isolation.\n */\nexport function generateScopeId(): string {\n return `scope-${++_scopeCounter}`;\n}\n\n/**\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\n * Also supports `.className` shorthand → adds to `class` prop.\n * Also supports `#id` shorthand → adds to `id` prop.\n */\nexport function parseProps(propsString: string): Record<string, string> {\n const props: Record<string, string> = {};\n if (!propsString?.trim()) return props;\n\n // Match key=\"value\" or key='value' pairs\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n let match;\n while ((match = pairRegex.exec(propsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? '';\n props[key] = value;\n }\n\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\n if (classMatches) {\n const existing = props['class'] || '';\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\n }\n\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\n if (idMatch && !props['id']) {\n props['id'] = idMatch[1];\n }\n\n return props;\n}\n\n/**\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\n * into a plain props object.\n *\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\n * (React, Vue, etc.) should handle their own attribute name mapping.\n */\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\n const props: Record<string, any> = {};\n if (!attrsString?.trim()) return props;\n\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\n let match;\n while ((match = pairRegex.exec(attrsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? match[4] ?? true;\n\n // Parse style strings into objects\n if (key === 'style' && typeof value === 'string') {\n props[key] = parseCssString(value);\n } else {\n props[key] = value;\n }\n }\n\n return props;\n}\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 const usedIds = new Set<string>();\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 baseId = customId || generateId(text.replace(/->|<-/g, ''));\r\n let id = baseId;\r\n let n = 1;\r\n while (usedIds.has(id)) {\r\n n++;\r\n id = `${baseId}-${n}`;\r\n }\r\n usedIds.add(id);\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":"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","names":["text","classes","id"]}
|
|
1
|
+
{"version":3,"sources":["../core.ts","../core/utils.ts","../core/parser.ts"],"sourcesContent":["// ============================================================\n// @noirmd/previewer/core — Framework-agnostic entry point\n//\n// Usage:\n// import { parseMarkdown, Token } from '@noirmd/previewer/core';\n//\n// This module has ZERO dependency on React (or any UI framework).\n// ============================================================\n\nexport {\n parseMarkdown,\n type Token,\n type CSSProperties,\n type HeaderToken,\n type ParagraphToken,\n type CodeblockToken,\n type DirectiveToken,\n type HtmlToken,\n type HtmlBlockToken,\n type ImageToken,\n type TableToken,\n type ListToken,\n type BlockquoteToken,\n type HrToken,\n type TocToken,\n parseCssString,\n generateId,\n generateScopeId,\n resetScopeCounter,\n scrollToId,\n extractAttributes,\n parseProps,\n parseHtmlAttrs,\n} from './core/index';\n","import type { CSSProperties } from './types';\n\n/**\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\n */\nexport function parseCssString(cssText: string): CSSProperties {\n if (!cssText) return {};\n return cssText\n .split(';')\n .filter(Boolean)\n .reduce<CSSProperties>((styleObj, styleString) => {\n const parts = styleString.split(':');\n if (parts.length < 2) return styleObj;\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\n const value = parts.slice(1).join(':').trim();\n styleObj[key] = value;\n return styleObj;\n }, {});\n}\n\n/**\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\n */\nexport function generateId(text: string): string {\n return text\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n}\n\n/**\n * Smooth-scroll to an element by its ID.\n */\nexport function scrollToId(id: string): void {\n if (typeof document === 'undefined') return;\n const element = document.getElementById(id);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n}\n\n/**\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\n * Returns the cleaned text, extracted classes, and id.\n */\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\n if (!match) return { text, classes: '', id: '' };\n\n const rawAttrs = match[2];\n const cleanedText = match[1];\n\n const classList: string[] = [];\n let id = '';\n\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\n if (key === 'class') {\n classList.push(...value.split(/\\s+/).filter(Boolean));\n } else if (key === 'id') {\n id = value;\n }\n }\n\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\n if (token.startsWith('.')) classList.push(token.slice(1));\n else if (token.startsWith('#') && !id) id = token.slice(1);\n }\n\n return { text: cleanedText, classes: classList.join(' '), id };\n}\n\nlet _scopeCounter = 0;\nexport function resetScopeCounter(): void {\n _scopeCounter = 0;\n}\n\n/**\n * Generate a unique scope ID for CSS isolation.\n */\nexport function generateScopeId(): string {\n return `scope-${++_scopeCounter}`;\n}\n\n/**\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\n * Also supports `.className` shorthand → adds to `class` prop.\n * Also supports `#id` shorthand → adds to `id` prop.\n */\nexport function parseProps(propsString: string): Record<string, string> {\n const props: Record<string, string> = {};\n if (!propsString?.trim()) return props;\n\n // Match key=\"value\" or key='value' pairs\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n let match;\n while ((match = pairRegex.exec(propsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? '';\n props[key] = value;\n }\n\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\n if (classMatches) {\n const existing = props['class'] || '';\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\n }\n\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\n if (idMatch && !props['id']) {\n props['id'] = idMatch[1];\n }\n\n return props;\n}\n\n/**\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\n * into a plain props object.\n *\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\n * (React, Vue, etc.) should handle their own attribute name mapping.\n */\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\n const props: Record<string, any> = {};\n if (!attrsString?.trim()) return props;\n\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\n let match;\n while ((match = pairRegex.exec(attrsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? match[4] ?? true;\n\n // Parse style strings into objects\n if (key === 'style' && typeof value === 'string') {\n props[key] = parseCssString(value);\n } else {\n props[key] = value;\n }\n }\n\n return props;\n}\n","import type { Token, DirectiveToken, HtmlBlockToken, CSSProperties } from './types';\r\nimport { generateId, generateScopeId, parseProps, extractAttributes } from './utils';\r\n\r\n/** HTML void elements that cannot have children (hoisted to module level for reuse). */\r\nconst VOID_ELEMENTS = 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/**\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 const usedIds = new Set<string>();\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: rawParsedText, classes, id: customId } = extractAttributes(rawText);\r\n\r\n // Detect alignment from raw text before stripping markers\r\n let text = rawParsedText;\r\n let align: 'center' | 'right' | undefined;\r\n const alignCenter = text.match(/^->\\s*(.+?)\\s*<-\\s*$/);\r\n const alignRight = text.match(/^->\\s*(.+?)\\s*->\\s*$/);\r\n if (alignCenter) { text = alignCenter[1]; align = 'center'; }\r\n else if (alignRight) { text = alignRight[1]; align = 'right'; }\r\n\r\n const baseId = customId || generateId(text);\r\n let id = baseId;\r\n let n = 1;\r\n while (usedIds.has(id)) {\r\n n++;\r\n id = `${baseId}-${n}`;\r\n }\r\n usedIds.add(id);\r\n result.push({ type: 'header', level, text, id, classes: classes || undefined, align });\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 // (voidElements set is defined at module level)\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('/>') || VOID_ELEMENTS.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":"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","names":["classes","text","id"]}
|
package/dist/core.d.cts
CHANGED
package/dist/core.d.ts
CHANGED
package/dist/core.js
CHANGED
|
@@ -88,6 +88,22 @@ function parseHtmlAttrs(attrsString) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// core/parser.ts
|
|
91
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
92
|
+
"area",
|
|
93
|
+
"base",
|
|
94
|
+
"br",
|
|
95
|
+
"col",
|
|
96
|
+
"embed",
|
|
97
|
+
"hr",
|
|
98
|
+
"img",
|
|
99
|
+
"input",
|
|
100
|
+
"link",
|
|
101
|
+
"meta",
|
|
102
|
+
"param",
|
|
103
|
+
"source",
|
|
104
|
+
"track",
|
|
105
|
+
"wbr"
|
|
106
|
+
]);
|
|
91
107
|
function parseMarkdown(markdown) {
|
|
92
108
|
if (!markdown) return [];
|
|
93
109
|
const lines = markdown.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
@@ -101,8 +117,19 @@ function parseMarkdown(markdown) {
|
|
|
101
117
|
if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
|
|
102
118
|
const level = match[1].length;
|
|
103
119
|
const rawText = match[2];
|
|
104
|
-
const { text:
|
|
105
|
-
|
|
120
|
+
const { text: rawParsedText, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
121
|
+
let text2 = rawParsedText;
|
|
122
|
+
let align;
|
|
123
|
+
const alignCenter = text2.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
124
|
+
const alignRight = text2.match(/^->\s*(.+?)\s*->\s*$/);
|
|
125
|
+
if (alignCenter) {
|
|
126
|
+
text2 = alignCenter[1];
|
|
127
|
+
align = "center";
|
|
128
|
+
} else if (alignRight) {
|
|
129
|
+
text2 = alignRight[1];
|
|
130
|
+
align = "right";
|
|
131
|
+
}
|
|
132
|
+
const baseId = customId || generateId(text2);
|
|
106
133
|
let id2 = baseId;
|
|
107
134
|
let n = 1;
|
|
108
135
|
while (usedIds.has(id2)) {
|
|
@@ -110,7 +137,7 @@ function parseMarkdown(markdown) {
|
|
|
110
137
|
id2 = `${baseId}-${n}`;
|
|
111
138
|
}
|
|
112
139
|
usedIds.add(id2);
|
|
113
|
-
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
140
|
+
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0, align });
|
|
114
141
|
i++;
|
|
115
142
|
continue;
|
|
116
143
|
}
|
|
@@ -286,29 +313,13 @@ function parseMarkdown(markdown) {
|
|
|
286
313
|
let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
|
|
287
314
|
if (tagStartMatch) {
|
|
288
315
|
const tagName = tagStartMatch[1].toLowerCase();
|
|
289
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
290
|
-
"area",
|
|
291
|
-
"base",
|
|
292
|
-
"br",
|
|
293
|
-
"col",
|
|
294
|
-
"embed",
|
|
295
|
-
"hr",
|
|
296
|
-
"img",
|
|
297
|
-
"input",
|
|
298
|
-
"link",
|
|
299
|
-
"meta",
|
|
300
|
-
"param",
|
|
301
|
-
"source",
|
|
302
|
-
"track",
|
|
303
|
-
"wbr"
|
|
304
|
-
]);
|
|
305
316
|
const remainingText = lines.slice(i).join("\n");
|
|
306
317
|
const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
|
|
307
318
|
const openTagMatch = remainingText.match(openTagRegex);
|
|
308
319
|
if (openTagMatch) {
|
|
309
320
|
const fullOpenTag = openTagMatch[0];
|
|
310
321
|
const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
|
|
311
|
-
const isSelfClosing = fullOpenTag.endsWith("/>") ||
|
|
322
|
+
const isSelfClosing = fullOpenTag.endsWith("/>") || VOID_ELEMENTS.has(tagName);
|
|
312
323
|
if (isSelfClosing) {
|
|
313
324
|
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
314
325
|
const consumedLines = blockText.split("\n").length;
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../core/utils.ts","../core/parser.ts"],"sourcesContent":["import type { CSSProperties } from './types';\n\n/**\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\n */\nexport function parseCssString(cssText: string): CSSProperties {\n if (!cssText) return {};\n return cssText\n .split(';')\n .filter(Boolean)\n .reduce<CSSProperties>((styleObj, styleString) => {\n const parts = styleString.split(':');\n if (parts.length < 2) return styleObj;\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\n const value = parts.slice(1).join(':').trim();\n styleObj[key] = value;\n return styleObj;\n }, {});\n}\n\n/**\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\n */\nexport function generateId(text: string): string {\n return text\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n}\n\n/**\n * Smooth-scroll to an element by its ID.\n */\nexport function scrollToId(id: string): void {\n if (typeof document === 'undefined') return;\n const element = document.getElementById(id);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n}\n\n/**\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\n * Returns the cleaned text, extracted classes, and id.\n */\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\n if (!match) return { text, classes: '', id: '' };\n\n const rawAttrs = match[2];\n const cleanedText = match[1];\n\n const classList: string[] = [];\n let id = '';\n\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\n if (key === 'class') {\n classList.push(...value.split(/\\s+/).filter(Boolean));\n } else if (key === 'id') {\n id = value;\n }\n }\n\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\n if (token.startsWith('.')) classList.push(token.slice(1));\n else if (token.startsWith('#') && !id) id = token.slice(1);\n }\n\n return { text: cleanedText, classes: classList.join(' '), id };\n}\n\nlet _scopeCounter = 0;\nexport function resetScopeCounter(): void {\n _scopeCounter = 0;\n}\n\n/**\n * Generate a unique scope ID for CSS isolation.\n */\nexport function generateScopeId(): string {\n return `scope-${++_scopeCounter}`;\n}\n\n/**\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\n * Also supports `.className` shorthand → adds to `class` prop.\n * Also supports `#id` shorthand → adds to `id` prop.\n */\nexport function parseProps(propsString: string): Record<string, string> {\n const props: Record<string, string> = {};\n if (!propsString?.trim()) return props;\n\n // Match key=\"value\" or key='value' pairs\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n let match;\n while ((match = pairRegex.exec(propsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? '';\n props[key] = value;\n }\n\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\n if (classMatches) {\n const existing = props['class'] || '';\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\n }\n\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\n if (idMatch && !props['id']) {\n props['id'] = idMatch[1];\n }\n\n return props;\n}\n\n/**\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\n * into a plain props object.\n *\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\n * (React, Vue, etc.) should handle their own attribute name mapping.\n */\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\n const props: Record<string, any> = {};\n if (!attrsString?.trim()) return props;\n\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\n let match;\n while ((match = pairRegex.exec(attrsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? match[4] ?? true;\n\n // Parse style strings into objects\n if (key === 'style' && typeof value === 'string') {\n props[key] = parseCssString(value);\n } else {\n props[key] = value;\n }\n }\n\n return props;\n}\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 const usedIds = new Set<string>();\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 baseId = customId || generateId(text.replace(/->|<-/g, ''));\r\n let id = baseId;\r\n let n = 1;\r\n while (usedIds.has(id)) {\r\n n++;\r\n id = `${baseId}-${n}`;\r\n }\r\n usedIds.add(id);\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":"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","names":["text","classes","id"]}
|
|
1
|
+
{"version":3,"sources":["../core/utils.ts","../core/parser.ts"],"sourcesContent":["import type { CSSProperties } from './types';\n\n/**\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\n */\nexport function parseCssString(cssText: string): CSSProperties {\n if (!cssText) return {};\n return cssText\n .split(';')\n .filter(Boolean)\n .reduce<CSSProperties>((styleObj, styleString) => {\n const parts = styleString.split(':');\n if (parts.length < 2) return styleObj;\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\n const value = parts.slice(1).join(':').trim();\n styleObj[key] = value;\n return styleObj;\n }, {});\n}\n\n/**\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\n */\nexport function generateId(text: string): string {\n return text\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n}\n\n/**\n * Smooth-scroll to an element by its ID.\n */\nexport function scrollToId(id: string): void {\n if (typeof document === 'undefined') return;\n const element = document.getElementById(id);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n}\n\n/**\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\n * Returns the cleaned text, extracted classes, and id.\n */\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\n if (!match) return { text, classes: '', id: '' };\n\n const rawAttrs = match[2];\n const cleanedText = match[1];\n\n const classList: string[] = [];\n let id = '';\n\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\n if (key === 'class') {\n classList.push(...value.split(/\\s+/).filter(Boolean));\n } else if (key === 'id') {\n id = value;\n }\n }\n\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\n if (token.startsWith('.')) classList.push(token.slice(1));\n else if (token.startsWith('#') && !id) id = token.slice(1);\n }\n\n return { text: cleanedText, classes: classList.join(' '), id };\n}\n\nlet _scopeCounter = 0;\nexport function resetScopeCounter(): void {\n _scopeCounter = 0;\n}\n\n/**\n * Generate a unique scope ID for CSS isolation.\n */\nexport function generateScopeId(): string {\n return `scope-${++_scopeCounter}`;\n}\n\n/**\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\n * Also supports `.className` shorthand → adds to `class` prop.\n * Also supports `#id` shorthand → adds to `id` prop.\n */\nexport function parseProps(propsString: string): Record<string, string> {\n const props: Record<string, string> = {};\n if (!propsString?.trim()) return props;\n\n // Match key=\"value\" or key='value' pairs\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n let match;\n while ((match = pairRegex.exec(propsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? '';\n props[key] = value;\n }\n\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\n if (classMatches) {\n const existing = props['class'] || '';\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\n }\n\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\n if (idMatch && !props['id']) {\n props['id'] = idMatch[1];\n }\n\n return props;\n}\n\n/**\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\n * into a plain props object.\n *\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\n * (React, Vue, etc.) should handle their own attribute name mapping.\n */\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\n const props: Record<string, any> = {};\n if (!attrsString?.trim()) return props;\n\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\n let match;\n while ((match = pairRegex.exec(attrsString)) !== null) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? match[4] ?? true;\n\n // Parse style strings into objects\n if (key === 'style' && typeof value === 'string') {\n props[key] = parseCssString(value);\n } else {\n props[key] = value;\n }\n }\n\n return props;\n}\n","import type { Token, DirectiveToken, HtmlBlockToken, CSSProperties } from './types';\r\nimport { generateId, generateScopeId, parseProps, extractAttributes } from './utils';\r\n\r\n/** HTML void elements that cannot have children (hoisted to module level for reuse). */\r\nconst VOID_ELEMENTS = 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/**\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 const usedIds = new Set<string>();\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: rawParsedText, classes, id: customId } = extractAttributes(rawText);\r\n\r\n // Detect alignment from raw text before stripping markers\r\n let text = rawParsedText;\r\n let align: 'center' | 'right' | undefined;\r\n const alignCenter = text.match(/^->\\s*(.+?)\\s*<-\\s*$/);\r\n const alignRight = text.match(/^->\\s*(.+?)\\s*->\\s*$/);\r\n if (alignCenter) { text = alignCenter[1]; align = 'center'; }\r\n else if (alignRight) { text = alignRight[1]; align = 'right'; }\r\n\r\n const baseId = customId || generateId(text);\r\n let id = baseId;\r\n let n = 1;\r\n while (usedIds.has(id)) {\r\n n++;\r\n id = `${baseId}-${n}`;\r\n }\r\n usedIds.add(id);\r\n result.push({ type: 'header', level, text, id, classes: classes || undefined, align });\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 // (voidElements set is defined at module level)\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('/>') || VOID_ELEMENTS.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;;;AClJA,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAM;AAAA,EAAO;AAAA,EAAS;AAAA,EAAM;AAAA,EAAO;AAAA,EACnD;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AAC9C,CAAC;AAKM,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,QAAM,UAAU,oBAAI,IAAY;AAChC,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,MAAM,eAAe,SAAAA,UAAS,IAAI,SAAS,IAAI,kBAAkB,OAAO;AAGhF,UAAIC,QAAO;AACX,UAAI;AACJ,YAAM,cAAcA,MAAK,MAAM,sBAAsB;AACrD,YAAM,aAAaA,MAAK,MAAM,sBAAsB;AACpD,UAAI,aAAa;AAAE,QAAAA,QAAO,YAAY,CAAC;AAAG,gBAAQ;AAAA,MAAU,WACnD,YAAY;AAAE,QAAAA,QAAO,WAAW,CAAC;AAAG,gBAAQ;AAAA,MAAS;AAE9D,YAAM,SAAS,YAAY,WAAWA,KAAI;AAC1C,UAAIC,MAAK;AACT,UAAI,IAAI;AACR,aAAO,QAAQ,IAAIA,GAAE,GAAG;AACtB;AACA,QAAAA,MAAK,GAAG,MAAM,IAAI,CAAC;AAAA,MACrB;AACA,cAAQ,IAAIA,GAAE;AACd,aAAO,KAAK,EAAE,MAAM,UAAU,OAAO,MAAAD,OAAM,IAAAC,KAAI,SAASF,YAAW,QAAW,MAAM,CAAC;AACrF;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,MAAAC,OAAM,SAAAD,UAAS,IAAAE,IAAG,IAAI,kBAAkB,QAAQ;AACxD,aAAO,KAAK,EAAE,MAAM,cAAc,SAASD,OAAM,SAASD,YAAW,QAAW,IAAAE,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;AAI7C,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,cAAc,IAAI,OAAO;AAE7E,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":["classes","text","id"]}
|