@noirmd/previewer 1.2.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/NReditor.cjs +928 -895
- package/dist/NReditor.cjs.map +1 -1
- package/dist/NReditor.d.cts +1 -1
- package/dist/NReditor.d.ts +1 -1
- package/dist/NReditor.js +929 -896
- package/dist/NReditor.js.map +1 -1
- package/dist/admonition.css +55 -0
- package/dist/{markdown.css → base.css} +96 -126
- package/dist/blockquote.css +16 -0
- package/dist/button.css +32 -0
- package/dist/card.css +143 -0
- package/dist/codeblock.css +59 -0
- package/dist/core.cjs +9 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +9 -1
- package/dist/core.js.map +1 -1
- package/dist/details.css +45 -0
- package/dist/editor.css +56 -9
- package/dist/fonts/material-icons-round.woff2 +0 -0
- package/dist/index.cjs +929 -882
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -70
- package/dist/index.d.ts +41 -70
- package/dist/index.js +928 -876
- package/dist/index.js.map +1 -1
- package/dist/list.css +18 -0
- package/dist/modal.css +82 -0
- package/dist/react.cjs +929 -885
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +44 -73
- package/dist/react.d.ts +44 -73
- package/dist/react.js +928 -879
- package/dist/react.js.map +1 -1
- package/dist/slide.css +21 -0
- package/dist/table.css +36 -0
- package/dist/toc.css +45 -0
- package/dist/vanilla.cjs +123 -31
- package/dist/vanilla.cjs.map +1 -1
- package/dist/vanilla.css +32 -677
- package/dist/vanilla.d.cts +24 -2
- package/dist/vanilla.d.ts +24 -2
- package/dist/vanilla.js +119 -31
- package/dist/vanilla.js.map +1 -1
- package/dist/variables.css +90 -0
- package/dist/vue.cjs +1007 -1120
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +63 -214
- package/dist/vue.d.ts +63 -214
- package/dist/vue.js +1006 -1119
- package/dist/vue.js.map +1 -1
- package/editor.css +56 -9
- package/package.json +5 -10
- package/markdown.css +0 -344
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 let i = 0;\r\n\r\n while (i < lines.length) {\r\n const line = lines[i];\r\n const trimmed = line.trim();\r\n let match: RegExpMatchArray | null;\r\n\r\n // ── Headers: ## Title ──\r\n if ((match = trimmed.match(/^(#{1,6})\\s+(.+)$/))) {\r\n const level = match[1].length;\r\n const rawText = match[2];\r\n const { text, classes, id: customId } = extractAttributes(rawText);\r\n const id = customId || generateId(text.replace(/->|<-/g, ''));\r\n result.push({ type: 'header', level, text, id, classes: classes || undefined });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Aligned paragraph: -> text <- or -> text -> ──\r\n if ((match = trimmed.match(/^->\\s*(.+?)\\s*(<-|->)\\s*$/))) {\r\n const content = match[1];\r\n const align = match[2] === '<-' ? 'center' : 'right';\r\n result.push({ type: 'paragraph', content, align });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Code block: ```lang title=\"name\" ──\r\n if (trimmed.startsWith('```')) {\r\n const fenceHeader = trimmed.slice(3).trim();\r\n const titleMatch = fenceHeader.match(/title=[\"']([^\"']*)[\"']/);\r\n const lang = fenceHeader.replace(/title=[\"'][^\"']*[\"']/, '').trim();\r\n const title = titleMatch ? titleMatch[1] : undefined;\r\n const content: string[] = [];\r\n i++;\r\n while (i < lines.length && !lines[i].trim().startsWith('```')) {\r\n content.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'codeblock', language: lang, title, content: content.join('\\n') });\r\n i++; // skip closing ```\r\n continue;\r\n }\r\n\r\n // ── Directive: :::type {props} ... ::: ──\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n\r\n // Bare closing marker\r\n if (rest === '') {\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n\r\n const typeMatch = rest.match(/^([\\w-]+)/);\r\n const directiveType = typeMatch ? typeMatch[1] : 'custom';\r\n\r\n // Lookahead: find the matching closing :::\r\n let j = i + 1;\r\n let nestedLevel = 0;\r\n let foundClose = false;\r\n\r\n while (j < lines.length) {\r\n const currentTrimmed = lines[j].trim();\r\n if (currentTrimmed === ':::') {\r\n if (nestedLevel === 0) {\r\n foundClose = true;\r\n break;\r\n } else {\r\n nestedLevel--;\r\n }\r\n } else if (currentTrimmed.startsWith(':::')) {\r\n // Opening a nested directive\r\n nestedLevel++;\r\n }\r\n j++;\r\n }\r\n\r\n if (foundClose) {\r\n // Collect raw content lines (between opening and closing)\r\n const contentLines: string[] = [];\r\n for (let k = i + 1; k < j; k++) {\r\n contentLines.push(lines[k]);\r\n }\r\n const rawContent = contentLines.join('\\n');\r\n\r\n // Parse the directive header (everything after the type name)\r\n const headerRest = typeMatch ? rest.slice(directiveType.length).trim() : rest;\r\n\r\n // Extract {props} block\r\n let propsString = '';\r\n let shortForm = '';\r\n const propsBlockMatch = headerRest.match(/^\\{([^]*)\\}\\s*$/);\r\n if (propsBlockMatch) {\r\n propsString = propsBlockMatch[1];\r\n } else if (headerRest) {\r\n // Short-form: bare text after type → becomes title prop\r\n shortForm = headerRest;\r\n }\r\n\r\n const props = parseProps(propsString);\r\n if (shortForm && !props['title']) {\r\n props['title'] = shortForm;\r\n }\r\n\r\n // Split content into slots\r\n const slots = splitSlots(rawContent);\r\n\r\n result.push({\r\n type: 'directive',\r\n directiveType,\r\n props,\r\n slots,\r\n scopeId: generateScopeId(),\r\n } as DirectiveToken);\r\n\r\n i = j + 1;\r\n continue;\r\n } else {\r\n // Unclosed directive — render as plain text\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n }\r\n\r\n // ── Image: {w:h} ──\r\n if ((match = trimmed.match(/^(.*?)!\\[([^\\]]*)\\]\\(([^)]+?)\\)(?:\\{([^}]+?)\\})?(.*)$/))) {\r\n const [, preText, alt, srcAndFloat, size, postText] = match;\r\n\r\n if (preText.trim()) {\r\n result.push({ type: 'paragraph', content: preText.trim() });\r\n }\r\n\r\n let src = srcAndFloat;\r\n const style: CSSProperties = {};\r\n if (src.includes('#left')) {\r\n src = src.replace('#left', '');\r\n style.float = 'left';\r\n style.margin = '0 1em 1em 0';\r\n } else if (src.includes('#right')) {\r\n src = src.replace('#right', '');\r\n style.float = 'right';\r\n style.margin = '0 0 1em 1em';\r\n } else if (src.includes('#center')) {\r\n src = src.replace('#center', '');\r\n style.display = 'block';\r\n style.margin = '0 auto 1em auto';\r\n }\r\n if (size) {\r\n const [width, height] = size.split(':');\r\n if (width) style.width = width.trim();\r\n if (height) style.height = height.trim();\r\n }\r\n result.push({ type: 'image', alt, src, style });\r\n\r\n if (postText.trim()) {\r\n result.push({ type: 'paragraph', content: postText.trim() });\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Table: | cell | cell | ──\r\n if (trimmed.includes('|') && i + 1 < lines.length && lines[i + 1].includes('---')) {\r\n const tableLines = [line];\r\n i++;\r\n tableLines.push(lines[i]);\r\n i++;\r\n while (i < lines.length && lines[i].trim().includes('|')) {\r\n tableLines.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'table', content: tableLines.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── List: - item or 1. item ──\r\n if ((match = trimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/))) {\r\n const listItems = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/) ||\r\n nextTrimmed === '' ||\r\n nextLine.startsWith(' ')\r\n ) {\r\n listItems.push(nextLine);\r\n i++;\r\n } else {\r\n break;\r\n }\r\n }\r\n result.push({ type: 'list', content: listItems.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── Blockquote: > text ──\r\n if (trimmed.startsWith('>')) {\r\n const quoteLines = [line];\r\n i++;\r\n while (i < lines.length && (lines[i].trim().startsWith('>') || lines[i].trim() === '')) {\r\n quoteLines.push(lines[i]);\r\n i++;\r\n }\r\n const rawQuote = quoteLines.join('\\n').replace(/^>\\s?/gm, '');\r\n const { text, classes, id } = extractAttributes(rawQuote);\r\n result.push({ type: 'blockquote', content: text, classes: classes || undefined, id });\r\n continue;\r\n }\r\n\r\n // ── Horizontal rule: --- or ___ or *** ──\r\n if (/^(---|___|(\\*\\s*){3,})\\s*$/.test(trimmed)) {\r\n result.push({ type: 'hr' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── TOC: [TOC] or [TOC2] ──\r\n if (/^\\[TOC\\d?\\]\\s*$/.test(trimmed)) {\r\n result.push({ type: 'toc' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Empty line ──\r\n if (trimmed === '') {\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── HTML Block: <tag ...> ──\r\n let tagStartMatch = trimmed.match(/^<([a-zA-Z][\\w-]*)/);\r\n if (tagStartMatch) {\r\n const tagName = tagStartMatch[1].toLowerCase();\r\n\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n\r\n const remainingText = lines.slice(i).join('\\n');\r\n\r\n // Find the full opening tag even with multi-line attributes\r\n const openTagRegex = new RegExp(`^\\\\s*<${tagName}\\\\b([^>]*?)>`, 'i');\r\n const openTagMatch = remainingText.match(openTagRegex);\r\n\r\n if (openTagMatch) {\r\n const fullOpenTag = openTagMatch[0];\r\n const attrs = openTagMatch[1].replace(/\\s+/g, ' ').trim();\r\n\r\n const isSelfClosing = fullOpenTag.endsWith('/>') || voidElements.has(tagName);\r\n\r\n if (isSelfClosing) {\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: [] // No children\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Tag with content — search for its closing tag\r\n let nestedLevel = 0;\r\n let closeIndex = -1;\r\n let closeTagLength = 0;\r\n\r\n const tagRegex = new RegExp(`</?${tagName}\\\\b[^>]*>`, 'gi');\r\n tagRegex.lastIndex = openTagMatch.index! + fullOpenTag.length;\r\n\r\n let execMatch;\r\n while ((execMatch = tagRegex.exec(remainingText)) !== null) {\r\n if (execMatch[0].startsWith('</')) {\r\n nestedLevel--;\r\n if (nestedLevel < 0) {\r\n closeIndex = execMatch.index;\r\n closeTagLength = execMatch[0].length;\r\n break;\r\n }\r\n } else {\r\n if (!execMatch[0].endsWith('/>')) {\r\n nestedLevel++;\r\n }\r\n }\r\n }\r\n\r\n if (closeIndex !== -1) {\r\n const fullBlock = remainingText.substring(0, closeIndex + closeTagLength);\r\n const consumedLines = fullBlock.split('\\n').length;\r\n\r\n // style/script blocks should not be parsed as Markdown\r\n if (tagName === 'style' || tagName === 'script') {\r\n result.push({\r\n type: 'html',\r\n content: fullBlock,\r\n scopeId: generateScopeId(),\r\n });\r\n } else {\r\n const innerContent = remainingText.substring(openTagMatch.index! + fullOpenTag.length, closeIndex);\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: parseMarkdown(innerContent)\r\n } as HtmlBlockToken);\r\n }\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Fallback: unclosed tag → treat as self-closing to avoid consuming the whole document\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: []\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ── Paragraph (default) ──\r\n const paragraphLines = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed === '' ||\r\n nextTrimmed.startsWith('#') ||\r\n nextTrimmed.startsWith(':::') ||\r\n nextTrimmed.includes('|') ||\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+/) ||\r\n nextTrimmed.startsWith('>') ||\r\n nextTrimmed.startsWith('```') ||\r\n nextTrimmed.startsWith('->') ||\r\n nextTrimmed.match(/^<([a-zA-Z][\\w-]*)\\b/)\r\n ) {\r\n break;\r\n }\r\n paragraphLines.push(nextLine);\r\n i++;\r\n }\r\n const rawParagraph = paragraphLines.join('\\n').trim();\r\n const { text, classes, id } = extractAttributes(rawParagraph);\r\n result.push({ type: 'paragraph', content: text, classes: classes || undefined, id });\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────\r\n// Slot splitting\r\n// ─────────────────────────────────────────────\r\n\r\n/**\r\n * Split directive content into named slots.\r\n * A line that is exactly `#slotname` starts a new slot.\r\n * Content before any `#slotname` goes into the \"default\" slot.\r\n *\r\n * IMPORTANT: This is nesting-aware — `#slotname` markers inside nested\r\n * directives (:::child ... :::) are NOT treated as slot boundaries of\r\n * the outer directive. Only `#slotname` at depth 0 are considered.\r\n */\r\nfunction splitSlots(rawContent: string): Record<string, string> {\r\n const slots: Record<string, string> = {};\r\n const lines = rawContent.split('\\n');\r\n let currentSlot = 'default';\r\n let buffer: string[] = [];\r\n let nestingDepth = 0;\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n\r\n // Track nesting of directives\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n if (rest === '') {\r\n // Closing marker (bare :::)\r\n nestingDepth = Math.max(0, nestingDepth - 1);\r\n } else {\r\n nestingDepth++;\r\n }\r\n }\r\n\r\n // Only consider slot boundaries at depth 0\r\n if (nestingDepth === 0 && trimmed.match(/^#([\\w-]+)$/)) {\r\n // Save previous slot\r\n if (buffer.length > 0 || currentSlot !== 'default') {\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n }\r\n currentSlot = trimmed.slice(1);\r\n buffer = [];\r\n } else {\r\n buffer.push(line);\r\n }\r\n }\r\n\r\n // Save last slot\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n\r\n return slots;\r\n}\r\n"],"mappings":"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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: {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
CHANGED
|
@@ -92,6 +92,7 @@ function parseMarkdown(markdown) {
|
|
|
92
92
|
if (!markdown) return [];
|
|
93
93
|
const lines = markdown.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
94
94
|
const result = [];
|
|
95
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
95
96
|
let i = 0;
|
|
96
97
|
while (i < lines.length) {
|
|
97
98
|
const line = lines[i];
|
|
@@ -101,7 +102,14 @@ function parseMarkdown(markdown) {
|
|
|
101
102
|
const level = match[1].length;
|
|
102
103
|
const rawText = match[2];
|
|
103
104
|
const { text: text2, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
104
|
-
const
|
|
105
|
+
const baseId = customId || generateId(text2.replace(/->|<-/g, ""));
|
|
106
|
+
let id2 = baseId;
|
|
107
|
+
let n = 1;
|
|
108
|
+
while (usedIds.has(id2)) {
|
|
109
|
+
n++;
|
|
110
|
+
id2 = `${baseId}-${n}`;
|
|
111
|
+
}
|
|
112
|
+
usedIds.add(id2);
|
|
105
113
|
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
106
114
|
i++;
|
|
107
115
|
continue;
|
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 let i = 0;\r\n\r\n while (i < lines.length) {\r\n const line = lines[i];\r\n const trimmed = line.trim();\r\n let match: RegExpMatchArray | null;\r\n\r\n // ── Headers: ## Title ──\r\n if ((match = trimmed.match(/^(#{1,6})\\s+(.+)$/))) {\r\n const level = match[1].length;\r\n const rawText = match[2];\r\n const { text, classes, id: customId } = extractAttributes(rawText);\r\n const id = customId || generateId(text.replace(/->|<-/g, ''));\r\n result.push({ type: 'header', level, text, id, classes: classes || undefined });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Aligned paragraph: -> text <- or -> text -> ──\r\n if ((match = trimmed.match(/^->\\s*(.+?)\\s*(<-|->)\\s*$/))) {\r\n const content = match[1];\r\n const align = match[2] === '<-' ? 'center' : 'right';\r\n result.push({ type: 'paragraph', content, align });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Code block: ```lang title=\"name\" ──\r\n if (trimmed.startsWith('```')) {\r\n const fenceHeader = trimmed.slice(3).trim();\r\n const titleMatch = fenceHeader.match(/title=[\"']([^\"']*)[\"']/);\r\n const lang = fenceHeader.replace(/title=[\"'][^\"']*[\"']/, '').trim();\r\n const title = titleMatch ? titleMatch[1] : undefined;\r\n const content: string[] = [];\r\n i++;\r\n while (i < lines.length && !lines[i].trim().startsWith('```')) {\r\n content.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'codeblock', language: lang, title, content: content.join('\\n') });\r\n i++; // skip closing ```\r\n continue;\r\n }\r\n\r\n // ── Directive: :::type {props} ... ::: ──\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n\r\n // Bare closing marker\r\n if (rest === '') {\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n\r\n const typeMatch = rest.match(/^([\\w-]+)/);\r\n const directiveType = typeMatch ? typeMatch[1] : 'custom';\r\n\r\n // Lookahead: find the matching closing :::\r\n let j = i + 1;\r\n let nestedLevel = 0;\r\n let foundClose = false;\r\n\r\n while (j < lines.length) {\r\n const currentTrimmed = lines[j].trim();\r\n if (currentTrimmed === ':::') {\r\n if (nestedLevel === 0) {\r\n foundClose = true;\r\n break;\r\n } else {\r\n nestedLevel--;\r\n }\r\n } else if (currentTrimmed.startsWith(':::')) {\r\n // Opening a nested directive\r\n nestedLevel++;\r\n }\r\n j++;\r\n }\r\n\r\n if (foundClose) {\r\n // Collect raw content lines (between opening and closing)\r\n const contentLines: string[] = [];\r\n for (let k = i + 1; k < j; k++) {\r\n contentLines.push(lines[k]);\r\n }\r\n const rawContent = contentLines.join('\\n');\r\n\r\n // Parse the directive header (everything after the type name)\r\n const headerRest = typeMatch ? rest.slice(directiveType.length).trim() : rest;\r\n\r\n // Extract {props} block\r\n let propsString = '';\r\n let shortForm = '';\r\n const propsBlockMatch = headerRest.match(/^\\{([^]*)\\}\\s*$/);\r\n if (propsBlockMatch) {\r\n propsString = propsBlockMatch[1];\r\n } else if (headerRest) {\r\n // Short-form: bare text after type → becomes title prop\r\n shortForm = headerRest;\r\n }\r\n\r\n const props = parseProps(propsString);\r\n if (shortForm && !props['title']) {\r\n props['title'] = shortForm;\r\n }\r\n\r\n // Split content into slots\r\n const slots = splitSlots(rawContent);\r\n\r\n result.push({\r\n type: 'directive',\r\n directiveType,\r\n props,\r\n slots,\r\n scopeId: generateScopeId(),\r\n } as DirectiveToken);\r\n\r\n i = j + 1;\r\n continue;\r\n } else {\r\n // Unclosed directive — render as plain text\r\n result.push({ type: 'paragraph', content: line });\r\n i++;\r\n continue;\r\n }\r\n }\r\n\r\n // ── Image: {w:h} ──\r\n if ((match = trimmed.match(/^(.*?)!\\[([^\\]]*)\\]\\(([^)]+?)\\)(?:\\{([^}]+?)\\})?(.*)$/))) {\r\n const [, preText, alt, srcAndFloat, size, postText] = match;\r\n\r\n if (preText.trim()) {\r\n result.push({ type: 'paragraph', content: preText.trim() });\r\n }\r\n\r\n let src = srcAndFloat;\r\n const style: CSSProperties = {};\r\n if (src.includes('#left')) {\r\n src = src.replace('#left', '');\r\n style.float = 'left';\r\n style.margin = '0 1em 1em 0';\r\n } else if (src.includes('#right')) {\r\n src = src.replace('#right', '');\r\n style.float = 'right';\r\n style.margin = '0 0 1em 1em';\r\n } else if (src.includes('#center')) {\r\n src = src.replace('#center', '');\r\n style.display = 'block';\r\n style.margin = '0 auto 1em auto';\r\n }\r\n if (size) {\r\n const [width, height] = size.split(':');\r\n if (width) style.width = width.trim();\r\n if (height) style.height = height.trim();\r\n }\r\n result.push({ type: 'image', alt, src, style });\r\n\r\n if (postText.trim()) {\r\n result.push({ type: 'paragraph', content: postText.trim() });\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Table: | cell | cell | ──\r\n if (trimmed.includes('|') && i + 1 < lines.length && lines[i + 1].includes('---')) {\r\n const tableLines = [line];\r\n i++;\r\n tableLines.push(lines[i]);\r\n i++;\r\n while (i < lines.length && lines[i].trim().includes('|')) {\r\n tableLines.push(lines[i]);\r\n i++;\r\n }\r\n result.push({ type: 'table', content: tableLines.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── List: - item or 1. item ──\r\n if ((match = trimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/))) {\r\n const listItems = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/) ||\r\n nextTrimmed === '' ||\r\n nextLine.startsWith(' ')\r\n ) {\r\n listItems.push(nextLine);\r\n i++;\r\n } else {\r\n break;\r\n }\r\n }\r\n result.push({ type: 'list', content: listItems.join('\\n') });\r\n continue;\r\n }\r\n\r\n // ── Blockquote: > text ──\r\n if (trimmed.startsWith('>')) {\r\n const quoteLines = [line];\r\n i++;\r\n while (i < lines.length && (lines[i].trim().startsWith('>') || lines[i].trim() === '')) {\r\n quoteLines.push(lines[i]);\r\n i++;\r\n }\r\n const rawQuote = quoteLines.join('\\n').replace(/^>\\s?/gm, '');\r\n const { text, classes, id } = extractAttributes(rawQuote);\r\n result.push({ type: 'blockquote', content: text, classes: classes || undefined, id });\r\n continue;\r\n }\r\n\r\n // ── Horizontal rule: --- or ___ or *** ──\r\n if (/^(---|___|(\\*\\s*){3,})\\s*$/.test(trimmed)) {\r\n result.push({ type: 'hr' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── TOC: [TOC] or [TOC2] ──\r\n if (/^\\[TOC\\d?\\]\\s*$/.test(trimmed)) {\r\n result.push({ type: 'toc' });\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── Empty line ──\r\n if (trimmed === '') {\r\n i++;\r\n continue;\r\n }\r\n\r\n // ── HTML Block: <tag ...> ──\r\n let tagStartMatch = trimmed.match(/^<([a-zA-Z][\\w-]*)/);\r\n if (tagStartMatch) {\r\n const tagName = tagStartMatch[1].toLowerCase();\r\n\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n\r\n const remainingText = lines.slice(i).join('\\n');\r\n\r\n // Find the full opening tag even with multi-line attributes\r\n const openTagRegex = new RegExp(`^\\\\s*<${tagName}\\\\b([^>]*?)>`, 'i');\r\n const openTagMatch = remainingText.match(openTagRegex);\r\n\r\n if (openTagMatch) {\r\n const fullOpenTag = openTagMatch[0];\r\n const attrs = openTagMatch[1].replace(/\\s+/g, ' ').trim();\r\n\r\n const isSelfClosing = fullOpenTag.endsWith('/>') || voidElements.has(tagName);\r\n\r\n if (isSelfClosing) {\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: [] // No children\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Tag with content — search for its closing tag\r\n let nestedLevel = 0;\r\n let closeIndex = -1;\r\n let closeTagLength = 0;\r\n\r\n const tagRegex = new RegExp(`</?${tagName}\\\\b[^>]*>`, 'gi');\r\n tagRegex.lastIndex = openTagMatch.index! + fullOpenTag.length;\r\n\r\n let execMatch;\r\n while ((execMatch = tagRegex.exec(remainingText)) !== null) {\r\n if (execMatch[0].startsWith('</')) {\r\n nestedLevel--;\r\n if (nestedLevel < 0) {\r\n closeIndex = execMatch.index;\r\n closeTagLength = execMatch[0].length;\r\n break;\r\n }\r\n } else {\r\n if (!execMatch[0].endsWith('/>')) {\r\n nestedLevel++;\r\n }\r\n }\r\n }\r\n\r\n if (closeIndex !== -1) {\r\n const fullBlock = remainingText.substring(0, closeIndex + closeTagLength);\r\n const consumedLines = fullBlock.split('\\n').length;\r\n\r\n // style/script blocks should not be parsed as Markdown\r\n if (tagName === 'style' || tagName === 'script') {\r\n result.push({\r\n type: 'html',\r\n content: fullBlock,\r\n scopeId: generateScopeId(),\r\n });\r\n } else {\r\n const innerContent = remainingText.substring(openTagMatch.index! + fullOpenTag.length, closeIndex);\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: parseMarkdown(innerContent)\r\n } as HtmlBlockToken);\r\n }\r\n\r\n i += consumedLines;\r\n continue;\r\n } else {\r\n // Fallback: unclosed tag → treat as self-closing to avoid consuming the whole document\r\n const blockText = remainingText.substring(0, openTagMatch.index! + fullOpenTag.length);\r\n const consumedLines = blockText.split('\\n').length;\r\n\r\n result.push({\r\n type: 'html-block',\r\n tag: tagName,\r\n attrs: attrs,\r\n children: []\r\n } as HtmlBlockToken);\r\n\r\n i += consumedLines;\r\n continue;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ── Paragraph (default) ──\r\n const paragraphLines = [line];\r\n i++;\r\n while (i < lines.length) {\r\n const nextLine = lines[i];\r\n const nextTrimmed = nextLine.trim();\r\n if (\r\n nextTrimmed === '' ||\r\n nextTrimmed.startsWith('#') ||\r\n nextTrimmed.startsWith(':::') ||\r\n nextTrimmed.includes('|') ||\r\n nextTrimmed.match(/^(\\s*)([-*+]|\\d+\\.)\\s+/) ||\r\n nextTrimmed.startsWith('>') ||\r\n nextTrimmed.startsWith('```') ||\r\n nextTrimmed.startsWith('->') ||\r\n nextTrimmed.match(/^<([a-zA-Z][\\w-]*)\\b/)\r\n ) {\r\n break;\r\n }\r\n paragraphLines.push(nextLine);\r\n i++;\r\n }\r\n const rawParagraph = paragraphLines.join('\\n').trim();\r\n const { text, classes, id } = extractAttributes(rawParagraph);\r\n result.push({ type: 'paragraph', content: text, classes: classes || undefined, id });\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────\r\n// Slot splitting\r\n// ─────────────────────────────────────────────\r\n\r\n/**\r\n * Split directive content into named slots.\r\n * A line that is exactly `#slotname` starts a new slot.\r\n * Content before any `#slotname` goes into the \"default\" slot.\r\n *\r\n * IMPORTANT: This is nesting-aware — `#slotname` markers inside nested\r\n * directives (:::child ... :::) are NOT treated as slot boundaries of\r\n * the outer directive. Only `#slotname` at depth 0 are considered.\r\n */\r\nfunction splitSlots(rawContent: string): Record<string, string> {\r\n const slots: Record<string, string> = {};\r\n const lines = rawContent.split('\\n');\r\n let currentSlot = 'default';\r\n let buffer: string[] = [];\r\n let nestingDepth = 0;\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n\r\n // Track nesting of directives\r\n if (trimmed.startsWith(':::')) {\r\n const rest = trimmed.slice(3).trim();\r\n if (rest === '') {\r\n // Closing marker (bare :::)\r\n nestingDepth = Math.max(0, nestingDepth - 1);\r\n } else {\r\n nestingDepth++;\r\n }\r\n }\r\n\r\n // Only consider slot boundaries at depth 0\r\n if (nestingDepth === 0 && trimmed.match(/^#([\\w-]+)$/)) {\r\n // Save previous slot\r\n if (buffer.length > 0 || currentSlot !== 'default') {\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n }\r\n currentSlot = trimmed.slice(1);\r\n buffer = [];\r\n } else {\r\n buffer.push(line);\r\n }\r\n }\r\n\r\n // Save last slot\r\n slots[currentSlot] = buffer.join('\\n').trim();\r\n\r\n return slots;\r\n}\r\n"],"mappings":"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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: {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/details.css
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
NoirMD Vanilla — Details (Collapsible)
|
|
3
|
+
============================================================ */
|
|
4
|
+
|
|
5
|
+
.nr-details {
|
|
6
|
+
border-radius: var(--nr-radius);
|
|
7
|
+
border: 1px solid var(--nr-border);
|
|
8
|
+
margin-bottom: 1rem;
|
|
9
|
+
background: color-mix(in srgb, var(--nr-bg) 5%, transparent);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.nr-details__summary {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
padding: 1rem;
|
|
15
|
+
font-weight: 700;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
gap: 0.5rem;
|
|
19
|
+
list-style: none;
|
|
20
|
+
}
|
|
21
|
+
.nr-details__summary::-webkit-details-marker {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
.nr-details__summary:hover {
|
|
25
|
+
color: var(--nr-accent);
|
|
26
|
+
transition: color 0.15s;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.nr-details__icon {
|
|
30
|
+
transition: transform 0.2s;
|
|
31
|
+
}
|
|
32
|
+
.nr-details__icon--open {
|
|
33
|
+
transform: rotate(90deg);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.nr-details__body {
|
|
37
|
+
padding: 0 1rem 1rem;
|
|
38
|
+
border-top: 1px solid var(--nr-border);
|
|
39
|
+
padding-top: 0.75rem;
|
|
40
|
+
font-size: 0.875rem;
|
|
41
|
+
line-height: 1.625;
|
|
42
|
+
opacity: 0.9;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
min-width: 0;
|
|
45
|
+
}
|
package/dist/editor.css
CHANGED
|
@@ -13,7 +13,34 @@
|
|
|
13
13
|
import '@noirmd/previewer/editor.css';
|
|
14
14
|
============================================================ */
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/* ── Material Icons Round (self-hosted) ────────────────────
|
|
17
|
+
Toolbar buttons render icons via `material-icons-round`
|
|
18
|
+
ligatures. Self-hosted so icons work offline and without
|
|
19
|
+
host dependencies. */
|
|
20
|
+
|
|
21
|
+
@font-face {
|
|
22
|
+
font-family: 'Material Icons Round';
|
|
23
|
+
font-style: normal;
|
|
24
|
+
font-weight: 400;
|
|
25
|
+
font-display: block;
|
|
26
|
+
src: url('./fonts/material-icons-round.woff2') format('woff2');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.material-icons-round {
|
|
30
|
+
font-family: 'Material Icons Round';
|
|
31
|
+
font-weight: 400;
|
|
32
|
+
font-style: normal;
|
|
33
|
+
font-size: 24px;
|
|
34
|
+
line-height: 1;
|
|
35
|
+
letter-spacing: normal;
|
|
36
|
+
text-transform: none;
|
|
37
|
+
display: inline-block;
|
|
38
|
+
white-space: nowrap;
|
|
39
|
+
word-wrap: normal;
|
|
40
|
+
direction: ltr;
|
|
41
|
+
font-feature-settings: 'liga';
|
|
42
|
+
-webkit-font-smoothing: antialiased;
|
|
43
|
+
}
|
|
17
44
|
|
|
18
45
|
/* ── Editor root layout ───────────────────────────────────── */
|
|
19
46
|
|
|
@@ -21,8 +48,9 @@
|
|
|
21
48
|
position: relative;
|
|
22
49
|
display: flex;
|
|
23
50
|
flex-direction: column;
|
|
24
|
-
flex: 1 1
|
|
25
|
-
|
|
51
|
+
flex: 1 1 auto;
|
|
52
|
+
height: auto;
|
|
53
|
+
min-height: var(--nr-editor-min-height, 300px);
|
|
26
54
|
}
|
|
27
55
|
|
|
28
56
|
/* ── Toolbar ──────────────────────────────────────────────── */
|
|
@@ -81,7 +109,7 @@
|
|
|
81
109
|
.nr-toolbar-btn-fold {
|
|
82
110
|
padding: 0.25rem;
|
|
83
111
|
}
|
|
84
|
-
.nr-toolbar-btn-fold .material-
|
|
112
|
+
.nr-toolbar-btn-fold .material-icons-round {
|
|
85
113
|
font-size: 15px;
|
|
86
114
|
}
|
|
87
115
|
.nr-toolbar-btn-fold:hover {
|
|
@@ -104,7 +132,7 @@
|
|
|
104
132
|
gap: 0.25rem;
|
|
105
133
|
font-weight: 500;
|
|
106
134
|
}
|
|
107
|
-
.nr-toolbar-btn-mode .material-
|
|
135
|
+
.nr-toolbar-btn-mode .material-icons-round {
|
|
108
136
|
font-size: 13px;
|
|
109
137
|
}
|
|
110
138
|
.nr-toolbar-btn-mode--active {
|
|
@@ -125,7 +153,7 @@
|
|
|
125
153
|
gap: 0.25rem;
|
|
126
154
|
font-weight: 500;
|
|
127
155
|
}
|
|
128
|
-
.nr-toolbar-btn-sm .material-
|
|
156
|
+
.nr-toolbar-btn-sm .material-icons-round {
|
|
129
157
|
font-size: 13px;
|
|
130
158
|
}
|
|
131
159
|
.nr-toolbar-btn-guide:hover,
|
|
@@ -146,14 +174,14 @@
|
|
|
146
174
|
|
|
147
175
|
.nr-editor-body {
|
|
148
176
|
display: flex;
|
|
149
|
-
flex: 1 1
|
|
177
|
+
flex: 1 1 auto;
|
|
150
178
|
min-height: 0;
|
|
151
179
|
}
|
|
152
180
|
|
|
153
181
|
.nr-editor-pane {
|
|
154
182
|
display: flex;
|
|
155
183
|
flex-direction: column;
|
|
156
|
-
flex: 1 1
|
|
184
|
+
flex: 1 1 auto;
|
|
157
185
|
min-width: 0;
|
|
158
186
|
min-height: 0;
|
|
159
187
|
}
|
|
@@ -162,8 +190,27 @@
|
|
|
162
190
|
border-right: 1px solid color-mix(in srgb, var(--color-border, #334155) 30%, transparent);
|
|
163
191
|
}
|
|
164
192
|
|
|
193
|
+
/* CodeMirror grows with its content — no fixed height. The uiw wrapper
|
|
194
|
+
is a plain block with no height of its own, so let the whole chain
|
|
195
|
+
size to the content and the root `min-height` (--nr-editor-min-height)
|
|
196
|
+
guarantees the editor never collapses. Self-contained: works in any
|
|
197
|
+
host, no Tailwind required. */
|
|
198
|
+
.nr-editor-pane .cm-theme {
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-direction: column;
|
|
201
|
+
flex: 1 1 auto;
|
|
202
|
+
height: auto;
|
|
203
|
+
min-width: 0;
|
|
204
|
+
min-height: 0;
|
|
205
|
+
}
|
|
206
|
+
.nr-editor-pane .cm-editor {
|
|
207
|
+
flex: 1 1 auto;
|
|
208
|
+
height: auto;
|
|
209
|
+
min-height: 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
165
212
|
.nr-editor-preview {
|
|
166
|
-
flex: 1 1
|
|
213
|
+
flex: 1 1 auto;
|
|
167
214
|
min-width: 0;
|
|
168
215
|
min-height: 0;
|
|
169
216
|
overflow: auto;
|
|
Binary file
|