@noirmd/previewer 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../core.ts","../core/utils.ts","../core/parser.ts"],"sourcesContent":["// ============================================================\r\n// @noirmd/previewer/core — Framework-agnostic entry point\r\n//\r\n// Usage:\r\n// import { parseMarkdown, Token } from '@noirmd/previewer/core';\r\n//\r\n// This module has ZERO dependency on React (or any UI framework).\r\n// ============================================================\r\n\r\nexport {\r\n parseMarkdown,\r\n type Token,\r\n type CSSProperties,\r\n type HeaderToken,\r\n type ParagraphToken,\r\n type CodeblockToken,\r\n type DirectiveToken,\r\n type HtmlToken,\r\n type HtmlBlockToken,\r\n type ImageToken,\r\n type TableToken,\r\n type ListToken,\r\n type BlockquoteToken,\r\n type HrToken,\r\n type TocToken,\r\n parseCssString,\r\n generateId,\r\n generateScopeId,\r\n resetScopeCounter,\r\n scrollToId,\r\n extractAttributes,\r\n parseProps,\r\n parseHtmlAttrs,\r\n} from './core/index';\r\n","import type { CSSProperties } from './types';\r\n\r\n/**\r\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\r\n */\r\nexport function parseCssString(cssText: string): CSSProperties {\r\n if (!cssText) return {};\r\n return cssText\r\n .split(';')\r\n .filter(Boolean)\r\n .reduce<CSSProperties>((styleObj, styleString) => {\r\n const parts = styleString.split(':');\r\n if (parts.length < 2) return styleObj;\r\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\r\n const value = parts.slice(1).join(':').trim();\r\n styleObj[key] = value;\r\n return styleObj;\r\n }, {});\r\n}\r\n\r\n/**\r\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\r\n */\r\nexport function generateId(text: string): string {\r\n return text\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/\\s+/g, '-');\r\n}\r\n\r\n/**\r\n * Smooth-scroll to an element by its ID.\r\n */\r\nexport function scrollToId(id: string): void {\r\n if (typeof document === 'undefined') return;\r\n const element = document.getElementById(id);\r\n if (element) {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n }\r\n}\r\n\r\n/**\r\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\r\n * Returns the cleaned text, extracted classes, and id.\r\n */\r\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\r\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\r\n if (!match) return { text, classes: '', id: '' };\r\n\r\n const rawAttrs = match[2];\r\n const cleanedText = match[1];\r\n\r\n const classList: string[] = [];\r\n let id = '';\r\n\r\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\r\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\r\n if (key === 'class') {\r\n classList.push(...value.split(/\\s+/).filter(Boolean));\r\n } else if (key === 'id') {\r\n id = value;\r\n }\r\n }\r\n\r\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\r\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\r\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\r\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\r\n if (token.startsWith('.')) classList.push(token.slice(1));\r\n else if (token.startsWith('#') && !id) id = token.slice(1);\r\n }\r\n\r\n return { text: cleanedText, classes: classList.join(' '), id };\r\n}\r\n\r\nlet _scopeCounter = 0;\r\nexport function resetScopeCounter(): void {\r\n _scopeCounter = 0;\r\n}\r\n\r\n/**\r\n * Generate a unique scope ID for CSS isolation.\r\n */\r\nexport function generateScopeId(): string {\r\n return `scope-${++_scopeCounter}`;\r\n}\r\n\r\n/**\r\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\r\n * Also supports `.className` shorthand → adds to `class` prop.\r\n * Also supports `#id` shorthand → adds to `id` prop.\r\n */\r\nexport function parseProps(propsString: string): Record<string, string> {\r\n const props: Record<string, string> = {};\r\n if (!propsString?.trim()) return props;\r\n\r\n // Match key=\"value\" or key='value' pairs\r\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\r\n let match;\r\n while ((match = pairRegex.exec(propsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? '';\r\n props[key] = value;\r\n }\r\n\r\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\r\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\r\n if (classMatches) {\r\n const existing = props['class'] || '';\r\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\r\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\r\n }\r\n\r\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\r\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\r\n if (idMatch && !props['id']) {\r\n props['id'] = idMatch[1];\r\n }\r\n\r\n return props;\r\n}\r\n\r\n/**\r\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\r\n * into a plain props object.\r\n *\r\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\r\n * (React, Vue, etc.) should handle their own attribute name mapping.\r\n */\r\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\r\n const props: Record<string, any> = {};\r\n if (!attrsString?.trim()) return props;\r\n\r\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\r\n let match;\r\n while ((match = pairRegex.exec(attrsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? match[4] ?? true;\r\n\r\n // Parse style strings into objects\r\n if (key === 'style' && typeof value === 'string') {\r\n props[key] = parseCssString(value);\r\n } else {\r\n props[key] = value;\r\n }\r\n }\r\n\r\n return props;\r\n}\r\n","import type { Token, DirectiveToken, HtmlBlockToken, CSSProperties } from './types';\r\nimport { generateId, generateScopeId, parseProps, extractAttributes } from './utils';\r\n\r\n/**\r\n * V2 Markdown Parser — line-by-line state machine (framework-agnostic).\r\n */\r\nexport function parseMarkdown(markdown: string): Token[] {\r\n if (!markdown) return [];\r\n const lines = markdown.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '').split('\\n');\r\n const result: Token[] = [];\r\n 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: ![alt](src#float#3d){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/**\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: ![alt](src#float#3d){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"]}
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../core/utils.ts","../core/parser.ts"],"sourcesContent":["import type { CSSProperties } from './types';\r\n\r\n/**\r\n * Parse an inline CSS string (e.g. \"color: red; padding: 1rem\") into a CSSProperties object.\r\n */\r\nexport function parseCssString(cssText: string): CSSProperties {\r\n if (!cssText) return {};\r\n return cssText\r\n .split(';')\r\n .filter(Boolean)\r\n .reduce<CSSProperties>((styleObj, styleString) => {\r\n const parts = styleString.split(':');\r\n if (parts.length < 2) return styleObj;\r\n const key = parts[0].trim().replace(/-([a-z])/g, (_, g) => g.toUpperCase());\r\n const value = parts.slice(1).join(':').trim();\r\n styleObj[key] = value;\r\n return styleObj;\r\n }, {});\r\n}\r\n\r\n/**\r\n * Generate a URL-safe slug from text (NFD decomposition, strip accents, lowercase, hyphenate).\r\n */\r\nexport function generateId(text: string): string {\r\n return text\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/\\s+/g, '-');\r\n}\r\n\r\n/**\r\n * Smooth-scroll to an element by its ID.\r\n */\r\nexport function scrollToId(id: string): void {\r\n if (typeof document === 'undefined') return;\r\n const element = document.getElementById(id);\r\n if (element) {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n }\r\n}\r\n\r\n/**\r\n * Parse attribute suffix like `##{.my-class #my-id}` from a text line.\r\n * Returns the cleaned text, extracted classes, and id.\r\n */\r\nexport function extractAttributes(text: string): { text: string; classes: string; id: string } {\r\n const match = text.match(/^(.*?)\\s*##\\{([^}]*)\\}\\s*$/);\r\n if (!match) return { text, classes: '', id: '' };\r\n\r\n const rawAttrs = match[2];\r\n const cleanedText = match[1];\r\n\r\n const classList: string[] = [];\r\n let id = '';\r\n\r\n // 1. Parse key=\"value\" attributes (e.g., class=\"mt-0 px-4\", id=\"section\")\r\n for (const [, key, value] of rawAttrs.matchAll(/([\\w-]+)=\"([^\"]*)\"/g)) {\r\n if (key === 'class') {\r\n classList.push(...value.split(/\\s+/).filter(Boolean));\r\n } else if (key === 'id') {\r\n id = value;\r\n }\r\n }\r\n\r\n // 2. Parse shorthand tokens: .className and #id (from remaining content)\r\n // Supports classes with / (opacity), ! (important), . (arbitrary values)\r\n const stripped = rawAttrs.replace(/[\\w-]+=\"[^\"]*\"/g, '');\r\n for (const token of stripped.split(/\\s+/).filter(Boolean)) {\r\n if (token.startsWith('.')) classList.push(token.slice(1));\r\n else if (token.startsWith('#') && !id) id = token.slice(1);\r\n }\r\n\r\n return { text: cleanedText, classes: classList.join(' '), id };\r\n}\r\n\r\nlet _scopeCounter = 0;\r\nexport function resetScopeCounter(): void {\r\n _scopeCounter = 0;\r\n}\r\n\r\n/**\r\n * Generate a unique scope ID for CSS isolation.\r\n */\r\nexport function generateScopeId(): string {\r\n return `scope-${++_scopeCounter}`;\r\n}\r\n\r\n/**\r\n * Parse props from a `{key=\"value\" key2=\"value2\"}` string.\r\n * Also supports `.className` shorthand → adds to `class` prop.\r\n * Also supports `#id` shorthand → adds to `id` prop.\r\n */\r\nexport function parseProps(propsString: string): Record<string, string> {\r\n const props: Record<string, string> = {};\r\n if (!propsString?.trim()) return props;\r\n\r\n // Match key=\"value\" or key='value' pairs\r\n const pairRegex = /(\\w[\\w-]*)=(?:\"([^\"]*)\"|'([^']*)')/g;\r\n let match;\r\n while ((match = pairRegex.exec(propsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? '';\r\n props[key] = value;\r\n }\r\n\r\n // Extract .className shorthand (supports / for opacity, ! for important, . for arbitrary values)\r\n const classMatches = propsString.match(/\\.([a-zA-Z0-9_!/.\\-]+)/g);\r\n if (classMatches) {\r\n const existing = props['class'] || '';\r\n const newClasses = classMatches.map(c => c.substring(1)).join(' ');\r\n props['class'] = existing ? `${existing} ${newClasses}` : newClasses;\r\n }\r\n\r\n // Extract #id shorthand (only if not inside a key=\"value\" pair)\r\n const idMatch = propsString.match(/#([a-zA-Z0-9_-]+)(?=\\s|}|$)/);\r\n if (idMatch && !props['id']) {\r\n props['id'] = idMatch[1];\r\n }\r\n\r\n return props;\r\n}\r\n\r\n/**\r\n * Parse raw HTML attributes string (e.g. `class=\"...\" style=\"...\" data-foo=\"...\"`)\r\n * into a plain props object.\r\n *\r\n * NOTE: This does NOT rename `class` → `className`. Framework adapters\r\n * (React, Vue, etc.) should handle their own attribute name mapping.\r\n */\r\nexport function parseHtmlAttrs(attrsString: string): Record<string, any> {\r\n const props: Record<string, any> = {};\r\n if (!attrsString?.trim()) return props;\r\n\r\n const pairRegex = /([a-zA-Z0-9_-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\r\n let match;\r\n while ((match = pairRegex.exec(attrsString)) !== null) {\r\n const key = match[1];\r\n const value = match[2] ?? match[3] ?? match[4] ?? true;\r\n\r\n // Parse style strings into objects\r\n if (key === 'style' && typeof value === 'string') {\r\n props[key] = parseCssString(value);\r\n } else {\r\n props[key] = value;\r\n }\r\n }\r\n\r\n return props;\r\n}\r\n","import type { Token, DirectiveToken, HtmlBlockToken, CSSProperties } from './types';\r\nimport { generateId, generateScopeId, parseProps, extractAttributes } from './utils';\r\n\r\n/**\r\n * V2 Markdown Parser — line-by-line state machine (framework-agnostic).\r\n */\r\nexport function parseMarkdown(markdown: string): Token[] {\r\n if (!markdown) return [];\r\n const lines = markdown.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '').split('\\n');\r\n const result: Token[] = [];\r\n 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: ![alt](src#float#3d){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/**\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: ![alt](src#float#3d){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"]}
package/dist/index.cjs CHANGED
@@ -11344,7 +11344,10 @@ var modalDirective = ({ props, renderSlot }) => {
11344
11344
  const dialog = createModal(modalTitle);
11345
11345
  const body = dialog.querySelector(".nr-modal__body");
11346
11346
  if (body) {
11347
- body.appendChild(renderSlot("default"));
11347
+ const prose = document.createElement("div");
11348
+ prose.className = "nr-prose";
11349
+ prose.appendChild(renderSlot("default"));
11350
+ body.appendChild(prose);
11348
11351
  }
11349
11352
  btn.addEventListener("click", () => {
11350
11353
  if (!dialog.open) {
@@ -11498,8 +11501,10 @@ var cardDirective = ({
11498
11501
  const dialog = createModal(title || "Detalles");
11499
11502
  const modalBody = dialog.querySelector(".nr-modal__body");
11500
11503
  if (modalBody) {
11501
- const contentSlot = renderSlot("content") || renderSlot("default");
11502
- modalBody.appendChild(contentSlot);
11504
+ const prose = document.createElement("div");
11505
+ prose.className = "nr-prose";
11506
+ prose.appendChild(renderSlot("content") || renderSlot("default"));
11507
+ modalBody.appendChild(prose);
11503
11508
  }
11504
11509
  card.addEventListener("click", () => {
11505
11510
  if (!dialog.open) {
@@ -11856,6 +11861,75 @@ function renderDirective(element, ctx, allElements) {
11856
11861
 
11857
11862
  // react/useTailwindCDN.ts
11858
11863
  var import_react = require("react");
11864
+
11865
+ // vanilla/tailwindTheme.ts
11866
+ var THEME_STYLE_ID = "nr-tailwind-theme";
11867
+ var NR_THEME_CSS = `
11868
+ @theme {
11869
+ --color-primary: var(--color-accent-primary, oklch(var(--p, 55% 0.3 240) / 1));
11870
+ --color-primary-content: #ffffff;
11871
+ --color-secondary: oklch(var(--s, 55% 0.25 200) / 1);
11872
+ --color-secondary-content: #ffffff;
11873
+ --color-accent: var(--color-accent-primary, oklch(var(--a, 65% 0.25 160) / 1));
11874
+ --color-accent-content: #ffffff;
11875
+ --color-neutral: oklch(var(--n, 50% 0.05 240) / 1);
11876
+ --color-neutral-content: var(--color-text-primary, oklch(var(--nc, 92% 0.02 240) / 1));
11877
+ --color-base-100: var(--color-background-primary, oklch(var(--b1, 15% 0.01 260) / 1));
11878
+ --color-base-200: var(--color-background-secondary-solid, oklch(var(--b2, 20% 0.02 260) / 1));
11879
+ --color-base-300: var(--color-border, oklch(var(--b3, 25% 0.03 260) / 1));
11880
+ --color-base-content: var(--color-text-primary, oklch(var(--bc, 92% 0.02 260) / 1));
11881
+ --color-info: oklch(var(--in, 70% 0.2 220) / 1);
11882
+ --color-info-content: #ffffff;
11883
+ --color-success: oklch(var(--su, 65% 0.25 140) / 1);
11884
+ --color-success-content: #ffffff;
11885
+ --color-warning: oklch(var(--wa, 80% 0.25 80) / 1);
11886
+ --color-warning-content: #1f2937;
11887
+ --color-error: oklch(var(--er, 65% 0.3 30) / 1);
11888
+ --color-error-content: #ffffff;
11889
+ }
11890
+ `;
11891
+ function getVar(root, name) {
11892
+ return getComputedStyle(root).getPropertyValue(name).trim();
11893
+ }
11894
+ function stylesheetHasTheme() {
11895
+ for (const sheet of Array.from(document.styleSheets)) {
11896
+ let rules = null;
11897
+ try {
11898
+ rules = sheet.cssRules;
11899
+ } catch {
11900
+ continue;
11901
+ }
11902
+ if (!rules) continue;
11903
+ for (const rule of Array.from(rules)) {
11904
+ const css2 = rule.cssText || "";
11905
+ if (css2.includes("@theme") || css2.includes('@plugin "daisyui"')) return true;
11906
+ }
11907
+ }
11908
+ return false;
11909
+ }
11910
+ function hasHostTheme() {
11911
+ if (typeof window === "undefined" || typeof document === "undefined") return true;
11912
+ if (getVar(document.documentElement, "--color-primary")) return true;
11913
+ if (getVar(document.documentElement, "--color-base-100")) return true;
11914
+ if (document.body && (getVar(document.body, "--color-primary") || getVar(document.body, "--color-base-100"))) return true;
11915
+ return stylesheetHasTheme();
11916
+ }
11917
+ function injectNRTailwindTheme() {
11918
+ if (typeof document === "undefined") return;
11919
+ if (document.getElementById(THEME_STYLE_ID)) return;
11920
+ if (hasHostTheme()) return;
11921
+ const style = document.createElement("style");
11922
+ style.id = THEME_STYLE_ID;
11923
+ style.setAttribute("type", "text/tailwindcss");
11924
+ style.textContent = NR_THEME_CSS;
11925
+ document.head.appendChild(style);
11926
+ }
11927
+ function removeNRTailwindTheme() {
11928
+ if (typeof document === "undefined") return;
11929
+ document.getElementById(THEME_STYLE_ID)?.remove();
11930
+ }
11931
+
11932
+ // react/useTailwindCDN.ts
11859
11933
  var CDN_URL = "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4";
11860
11934
  var SCRIPT_ID = "tailwind-cdn-v4-runtime";
11861
11935
  var CONFIG_ID = "tailwind-cdn-v4-config";
@@ -11875,6 +11949,7 @@ function useLazyTailwindCDN(enabled) {
11875
11949
  if ((window.__twCDNRefs ?? 0) <= 0) {
11876
11950
  document.getElementById(SCRIPT_ID)?.remove();
11877
11951
  document.getElementById(CONFIG_ID)?.remove();
11952
+ removeNRTailwindTheme();
11878
11953
  window.__twCDNRefs = 0;
11879
11954
  loadedRef.current = false;
11880
11955
  }
@@ -11887,6 +11962,7 @@ function useLazyTailwindCDN(enabled) {
11887
11962
  configScript.textContent = TAILWIND_CDN_CONFIG;
11888
11963
  document.head.appendChild(configScript);
11889
11964
  }
11965
+ injectNRTailwindTheme();
11890
11966
  if (!document.getElementById(SCRIPT_ID)) {
11891
11967
  const script = document.createElement("script");
11892
11968
  script.id = SCRIPT_ID;
@@ -11899,6 +11975,7 @@ function useLazyTailwindCDN(enabled) {
11899
11975
  if ((window.__twCDNRefs ?? 0) <= 0) {
11900
11976
  document.getElementById(SCRIPT_ID)?.remove();
11901
11977
  document.getElementById(CONFIG_ID)?.remove();
11978
+ removeNRTailwindTheme();
11902
11979
  window.__twCDNRefs = 0;
11903
11980
  loadedRef.current = false;
11904
11981
  }
@@ -11919,6 +11996,7 @@ function preloadTailwindCDN() {
11919
11996
  configScript.textContent = TAILWIND_CDN_CONFIG;
11920
11997
  document.head.appendChild(configScript);
11921
11998
  }
11999
+ injectNRTailwindTheme();
11922
12000
  const script = document.createElement("script");
11923
12001
  script.id = SCRIPT_ID;
11924
12002
  script.src = CDN_URL;