@vizejs/vite-plugin-musea 0.373.0 → 0.375.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/art-processing-e4a94Wa4.mjs +1045 -0
- package/dist/art-processing-e4a94Wa4.mjs.map +1 -0
- package/dist/cli/index.mjs +5 -39
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{gallery-3Sqabvai.mjs → gallery-BWCgs-NF.mjs} +2 -2
- package/dist/{gallery-3Sqabvai.mjs.map → gallery-BWCgs-NF.mjs.map} +1 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -884
- package/dist/index.mjs.map +1 -1
- package/dist/{template-ByMVejqE.mjs → template-CrnwdQfB.mjs} +3 -155
- package/dist/template-CrnwdQfB.mjs.map +1 -0
- package/package.json +4 -4
- package/dist/template-ByMVejqE.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"art-processing-e4a94Wa4.mjs","names":["componentNameFromSource"],"sources":["../src/with-defaults.ts","../src/native-loader.ts","../src/utils.ts","../src/security.ts","../src/component-source.ts","../src/art-module-vue2.ts","../src/art-component.ts","../src/art-module.ts","../src/plugin/art-processing.ts"],"sourcesContent":["/**\n * Parsing helpers for extracting prop defaults from a Vue SFC `<script setup>`\n * block. Defaults are read only from `withDefaults(defineProps(...), { ... })`\n * so unrelated local identifiers are never treated as prop defaults.\n */\n\nexport function extractWithDefaults(scriptContent: string): Map<string, string> {\n const defaults = new Map<string, string>();\n let searchIndex = 0;\n\n while (searchIndex < scriptContent.length) {\n const calleeIndex = scriptContent.indexOf(\"withDefaults\", searchIndex);\n if (calleeIndex === -1) break;\n searchIndex = calleeIndex + \"withDefaults\".length;\n\n if (!isIdentifierBoundary(scriptContent[calleeIndex - 1])) continue;\n if (!isIdentifierBoundary(scriptContent[searchIndex])) continue;\n\n const parenIndex = skipWhitespace(scriptContent, searchIndex);\n if (scriptContent[parenIndex] !== \"(\") continue;\n\n const endParen = findMatching(scriptContent, parenIndex, \"(\", \")\");\n if (endParen === -1) continue;\n\n const args = splitTopLevel(scriptContent.slice(parenIndex + 1, endParen));\n const defaultsArg = args[1]?.trim();\n if (!defaultsArg?.startsWith(\"{\")) continue;\n\n const objectStart = scriptContent.indexOf(defaultsArg, parenIndex + 1);\n const objectEnd = findMatching(scriptContent, objectStart, \"{\", \"}\");\n if (objectEnd === -1) continue;\n\n for (const [name, value] of objectProperties(scriptContent.slice(objectStart + 1, objectEnd))) {\n defaults.set(name, value);\n }\n }\n\n return defaults;\n}\n\nfunction objectProperties(objectBody: string): Array<[string, string]> {\n const properties: Array<[string, string]> = [];\n\n for (const item of splitTopLevel(objectBody)) {\n const colonIndex = topLevelColon(item);\n if (colonIndex === -1) continue;\n\n const rawKey = item.slice(0, colonIndex).trim();\n const key = rawKey.match(/^[$A-Z_a-z][$\\w]*$/)?.[0] ?? rawKey.match(/^[\"']([^\"']+)[\"']$/)?.[1];\n if (!key) continue;\n\n const value = item.slice(colonIndex + 1).trim();\n if (value) properties.push([key, value]);\n }\n\n return properties;\n}\n\nfunction splitTopLevel(source: string): string[] {\n const parts: string[] = [];\n let start = 0;\n let round = 0;\n let curly = 0;\n let square = 0;\n let quote: '\"' | \"'\" | \"`\" | null = null;\n let escaped = false;\n\n for (let index = 0; index < source.length; index++) {\n const char = source[index]!;\n\n if (quote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n quote = null;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n continue;\n }\n if (char === \"(\") round++;\n else if (char === \")\") round--;\n else if (char === \"{\") curly++;\n else if (char === \"}\") curly--;\n else if (char === \"[\") square++;\n else if (char === \"]\") square--;\n else if (char === \",\" && round === 0 && curly === 0 && square === 0) {\n parts.push(source.slice(start, index).trim());\n start = index + 1;\n }\n }\n\n const tail = source.slice(start).trim();\n if (tail) parts.push(tail);\n return parts;\n}\n\nfunction topLevelColon(source: string): number {\n let round = 0;\n let curly = 0;\n let square = 0;\n let quote: '\"' | \"'\" | \"`\" | null = null;\n let escaped = false;\n\n for (let index = 0; index < source.length; index++) {\n const char = source[index]!;\n\n if (quote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n quote = null;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n continue;\n }\n if (char === \"(\") round++;\n else if (char === \")\") round--;\n else if (char === \"{\") curly++;\n else if (char === \"}\") curly--;\n else if (char === \"[\") square++;\n else if (char === \"]\") square--;\n else if (char === \":\" && round === 0 && curly === 0 && square === 0) {\n return index;\n }\n }\n\n return -1;\n}\n\nfunction findMatching(source: string, start: number, open: string, close: string): number {\n let depth = 0;\n let quote: '\"' | \"'\" | \"`\" | null = null;\n let escaped = false;\n\n for (let index = start; index < source.length; index++) {\n const char = source[index]!;\n\n if (quote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n quote = null;\n }\n continue;\n }\n\n if (char === '\"' || char === \"'\" || char === \"`\") {\n quote = char;\n continue;\n }\n if (char === open) depth++;\n if (char === close) {\n depth--;\n if (depth === 0) return index;\n }\n }\n\n return -1;\n}\n\nfunction skipWhitespace(source: string, index: number): number {\n while (index < source.length && /\\s/.test(source[index]!)) index++;\n return index;\n}\n\nfunction isIdentifierBoundary(char: string | undefined): boolean {\n return char === undefined || !/[$\\w]/.test(char);\n}\n","/**\n * Native binding loader for @vizejs/native.\n *\n * Provides lazy-loading of the native Rust-based parser and a JS fallback\n * for SFC analysis when the native `analyzeSfc` function is unavailable.\n */\n\nimport { createRequire } from \"node:module\";\n\nimport { extractWithDefaults } from \"./with-defaults.js\";\n\n// Native binding types\nexport interface NativeBinding {\n parseArtStatusWarnings?: (source: string, options?: { filename?: string }) => string[];\n parseArt: (\n source: string,\n options?: { filename?: string },\n ) => {\n filename: string;\n metadata: {\n title: string;\n description?: string;\n component?: string;\n category?: string;\n tags: string[];\n status: string;\n order?: number;\n actionEvents?: string[];\n };\n variants: Array<{\n name: string;\n template: string;\n isDefault: boolean;\n skipVrt: boolean;\n }>;\n hasScriptSetup: boolean;\n hasScript: boolean;\n styleCount: number;\n };\n /** Compile a Vue SFC the same way the enclosing `.art.vue` file is compiled. */\n compileSfc: (\n source: string,\n options?: { filename?: string },\n ) => {\n code?: string;\n errors?: Array<string | { message?: string }>;\n };\n artToCsf: (\n source: string,\n options?: { filename?: string },\n ) => {\n code: string;\n filename: string;\n };\n generateArtPalette?: (\n source: string,\n artOptions?: { filename?: string },\n paletteOptions?: { infer_options?: boolean; group_by_type?: boolean },\n ) => {\n title: string;\n controls: Array<{\n name: string;\n control: string;\n default_value?: unknown;\n description?: string;\n required: boolean;\n options: Array<{ label: string; value: unknown }>;\n range?: { min: number; max: number; step?: number };\n group?: string;\n }>;\n groups: string[];\n json: string;\n typescript: string;\n };\n generateArtDoc?: (\n source: string,\n artOptions?: { filename?: string },\n docOptions?: {\n include_source?: boolean;\n include_templates?: boolean;\n include_metadata?: boolean;\n },\n ) => {\n markdown: string;\n filename: string;\n title: string;\n category?: string;\n variant_count: number;\n };\n parseDesignTokensFromPath?: (path: string) => unknown;\n buildDesignTokenMap?: (categories: unknown) => Record<string, unknown>;\n resolveDesignTokenReferences?: (categories: unknown) => unknown;\n flattenDesignTokenCategories?: (categories: unknown) => unknown[];\n generateDesignTokensMarkdown?: (categories: unknown, generatedAt?: string) => string;\n validateDesignTokenReference?: (\n tokenMap: Record<string, unknown>,\n reference: string,\n selfPath?: string,\n ) => { valid: boolean; error?: string };\n findDependentDesignTokens?: (tokenMap: Record<string, unknown>, targetPath: string) => string[];\n analyzeSfc?: (\n source: string,\n options?: { filename?: string },\n ) => {\n props: Array<{\n name: string;\n type: string;\n required: boolean;\n default_value?: unknown;\n }>;\n emits: string[];\n };\n}\n\n// Lazy-load native binding\nlet native: NativeBinding | null = null;\n\nexport function loadNative(): NativeBinding {\n if (native) return native;\n\n const require = createRequire(import.meta.url);\n try {\n native = require(\"@vizejs/native\") as NativeBinding;\n return native;\n } catch (e) {\n throw new Error(\n `Failed to load @vizejs/native. Make sure it's installed and built:\\n${String(e)}`,\n );\n }\n}\n\n/**\n * JS-based fallback for SFC analysis when native `analyzeSfc` is not available.\n * Uses regex parsing to extract props and emits from Vue SFC source.\n */\nexport function analyzeSfcFallback(\n source: string,\n _options?: { filename?: string },\n): {\n props: Array<{\n name: string;\n type: string;\n required: boolean;\n default_value?: unknown;\n }>;\n emits: string[];\n} {\n try {\n const props: Array<{\n name: string;\n type: string;\n required: boolean;\n default_value?: unknown;\n }> = [];\n const emits: string[] = [];\n\n // Extract the <script setup> block\n const scriptSetupMatch = source.match(/<script\\s+[^>]*setup[^>]*>([\\s\\S]*?)<\\/script>/);\n if (!scriptSetupMatch) {\n // Try regular <script> block\n const scriptMatch = source.match(/<script[^>]*>([\\s\\S]*?)<\\/script>/);\n if (!scriptMatch) return { props: [], emits: [] };\n }\n const scriptContent = scriptSetupMatch?.[1] || \"\";\n\n // Extract defineProps type parameter\n // Handles: defineProps<{ ... }>() and defineProps<{ ... }>\n const propsMatch = scriptContent.match(/defineProps\\s*<\\s*\\{([\\s\\S]*?)\\}>\\s*\\(/);\n const propsMatch2 = scriptContent.match(/defineProps\\s*<\\s*\\{([\\s\\S]*?)\\}>/);\n const propsBody = propsMatch?.[1] || propsMatch2?.[1];\n const withDefaults = extractWithDefaults(scriptContent);\n\n if (propsBody) {\n // Parse each prop line: name?: Type; or name: Type;\n // Handle multiline JSDoc comments before props\n const lines = propsBody.split(\"\\n\");\n let i = 0;\n while (i < lines.length) {\n const line = lines[i].trim();\n // Skip JSDoc comments\n if (line.startsWith(\"/**\") || line.startsWith(\"*\") || line.startsWith(\"*/\")) {\n i++;\n continue;\n }\n\n // Match prop definition: name?: Type or name: Type\n const propMatch = line.match(/^(\\w+)(\\?)?:\\s*(.+?)(?:;?\\s*)$/);\n if (propMatch) {\n const name = propMatch[1];\n const optional = !!propMatch[2];\n let type = propMatch[3].replace(/;$/, \"\").trim();\n\n const defaultValue = withDefaults.get(name);\n\n props.push({\n name,\n type,\n required: !optional && defaultValue === undefined,\n ...(defaultValue !== undefined ? { default_value: defaultValue } : {}),\n });\n }\n i++;\n }\n }\n\n // Extract defineEmits\n const emitsMatch = scriptContent.match(/defineEmits\\s*<\\s*\\{([\\s\\S]*?)\\}>/);\n if (emitsMatch) {\n const emitsBody = emitsMatch[1];\n const emitRegex = /(\\w+)\\s*:/g;\n let match;\n while ((match = emitRegex.exec(emitsBody)) !== null) {\n emits.push(match[1]);\n }\n }\n\n return { props, emits };\n } catch {\n return { props: [], emits: [] };\n }\n}\n","/**\n * Shared utility functions for the Musea Vite plugin.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { ArtFileInfo } from \"./types/index.js\";\nimport { loadNative } from \"./native-loader.js\";\n\nfunction normalizeGlobPath(filepath: string): string {\n return filepath.split(path.sep).join(\"/\");\n}\n\nfunction matchesPattern(file: string, pattern: string, root: string): boolean {\n const normalizedPattern = normalizeGlobPath(pattern);\n const candidate = path.isAbsolute(pattern) ? path.resolve(file) : path.relative(root, file);\n return matchGlob(candidate, normalizedPattern);\n}\n\nexport function shouldProcess(\n file: string,\n include: string[],\n exclude: string[],\n root: string,\n): boolean {\n // Check exclude patterns\n for (const pattern of exclude) {\n if (matchesPattern(file, pattern, root)) {\n return false;\n }\n }\n\n // Check include patterns\n for (const pattern of include) {\n if (matchesPattern(file, pattern, root)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function matchGlob(filepath: string, pattern: string): boolean {\n const normalizedFilepath = normalizeGlobPath(filepath);\n const normalizedPattern = normalizeGlobPath(pattern);\n\n // Simple glob matching (supports * and **)\n // Use placeholder for ** to avoid * replacement interfering\n const PLACEHOLDER = \"<<GLOBSTAR>>\";\n const SEGMENT_PLACEHOLDER = \"<<GLOBSTAR_SEGMENT>>\";\n const regex = normalizedPattern\n .replaceAll(\"**/\", SEGMENT_PLACEHOLDER)\n .replaceAll(\"**\", PLACEHOLDER)\n .replace(/[|\\\\{}()[\\]^$+?.]/g, \"\\\\$&\")\n .replace(/\\*/g, \"[^/]*\")\n .replaceAll(SEGMENT_PLACEHOLDER, \"(?:.*/)?\")\n .replaceAll(PLACEHOLDER, \".*\");\n\n return new RegExp(`^${regex}$`).test(normalizedFilepath);\n}\n\nfunction resolveScanRoot(root: string, pattern: string): string {\n const absolutePattern = path.isAbsolute(pattern) ? pattern : path.resolve(root, pattern);\n const normalizedPattern = normalizeGlobPath(absolutePattern);\n const globIndex = normalizedPattern.search(/[*[{]/);\n\n if (globIndex === -1) {\n return path.dirname(absolutePattern);\n }\n\n const staticPrefix = normalizedPattern.slice(0, globIndex);\n if (!staticPrefix) {\n return root;\n }\n\n if (staticPrefix.endsWith(\"/\")) {\n return path.resolve(staticPrefix.slice(0, -1));\n }\n\n return path.resolve(path.dirname(staticPrefix));\n}\n\nexport function resolveScanRoots(root: string, include: string[]): string[] {\n const roots = new Set<string>();\n\n for (const pattern of include) {\n roots.add(resolveScanRoot(root, pattern));\n }\n\n if (roots.size === 0) {\n roots.add(root);\n }\n\n return [...roots];\n}\n\nexport async function scanArtFiles(\n root: string,\n include: string[],\n exclude: string[],\n scanInlineArt = false,\n): Promise<string[]> {\n const files = new Set<string>();\n const scanRoots = resolveScanRoots(root, include);\n const visitedDirs = new Set<string>();\n\n async function scan(dir: string): Promise<void> {\n const resolvedDir = path.resolve(dir);\n if (visitedDirs.has(resolvedDir)) {\n return;\n }\n visitedDirs.add(resolvedDir);\n\n let entries: fs.Dirent[];\n try {\n entries = await fs.promises.readdir(resolvedDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(resolvedDir, entry.name);\n\n // Check exclude\n let excluded = false;\n for (const pattern of exclude) {\n if (matchesPattern(fullPath, pattern, root) || matchGlob(entry.name, pattern)) {\n excluded = true;\n break;\n }\n }\n\n if (excluded) continue;\n\n if (entry.isDirectory()) {\n await scan(fullPath);\n } else if (entry.isFile() && entry.name.endsWith(\".art.vue\")) {\n if (shouldProcess(fullPath, include, exclude, root)) {\n files.add(fullPath);\n }\n } else if (\n scanInlineArt &&\n entry.isFile() &&\n entry.name.endsWith(\".vue\") &&\n !entry.name.endsWith(\".art.vue\")\n ) {\n // Inline art: check if .vue file contains <art block\n const content = await fs.promises.readFile(fullPath, \"utf-8\");\n if (content.includes(\"<art\")) {\n files.add(fullPath);\n }\n }\n }\n }\n\n for (const scanRoot of scanRoots) {\n await scan(scanRoot);\n }\n\n return [...files];\n}\n\nexport async function generateStorybookFiles(\n artFiles: Map<string, ArtFileInfo>,\n root: string,\n outDir: string,\n): Promise<void> {\n const binding = loadNative();\n const outputDir = path.resolve(root, outDir);\n\n // Ensure output directory exists\n await fs.promises.mkdir(outputDir, { recursive: true });\n\n for (const [filePath, art] of artFiles) {\n try {\n const source = await fs.promises.readFile(filePath, \"utf-8\");\n const csf = binding.artToCsf(source, { filename: filePath });\n\n const outputPath = path.join(outputDir, csf.filename);\n const rewritten = rewriteStorybookComponentImport(csf.code, art, filePath, outputPath);\n const code = rewriteStorybookScriptImports(rewritten, filePath, outputPath);\n await fs.promises.writeFile(outputPath, code, \"utf-8\");\n\n console.log(`[musea] Generated: ${path.relative(root, outputPath)}`);\n } catch (e) {\n console.error(`[musea] Failed to generate CSF for ${filePath}:`, e);\n }\n }\n}\n\nexport function rewriteStorybookComponentImport(\n code: string,\n art: ArtFileInfo,\n artPath: string,\n outputPath: string,\n): string {\n const component = art.isInline && art.componentPath ? art.componentPath : art.metadata.component;\n if (!component || isBareImport(component)) {\n return code;\n }\n\n const resolvedComponent = path.isAbsolute(component)\n ? component\n : path.resolve(path.dirname(artPath), component);\n let relativeComponent = normalizeGlobPath(\n path.relative(path.dirname(outputPath), resolvedComponent),\n );\n if (!relativeComponent.startsWith(\".\")) {\n relativeComponent = `./${relativeComponent}`;\n }\n\n return code.replace(\n /import\\s+(__museaComponent)\\s+from\\s+(['\"])([^'\"]+)\\2;/,\n `import $1 from $2${relativeComponent}$2;`,\n );\n}\n\nfunction isBareImport(source: string): boolean {\n return !source.startsWith(\".\") && !path.isAbsolute(source);\n}\n\n/**\n * Rewrite relative import specifiers in the generated Storybook CSF file so that\n * imports lifted verbatim from the art file's `<script setup>` resolve against\n * the generated file's location instead of the original art file's directory.\n *\n * The `__museaComponent` import is already rebased by\n * `rewriteStorybookComponentImport` and is skipped here.\n */\nexport function rewriteStorybookScriptImports(\n code: string,\n artPath: string,\n outputPath: string,\n): string {\n const artDir = path.dirname(artPath);\n const outDir = path.dirname(outputPath);\n\n // Matches: import <clause> from '<specifier>'; (single or double quotes)\n // `<clause>` is a non-greedy capture so we keep the original binding text intact.\n const importRe = /(import\\s+(?:[\\s\\S]*?)\\s+from\\s+)(['\"])([^'\"]+)\\2(\\s*;?)/g;\n\n return code.replace(importRe, (match, head, quote, specifier, tail) => {\n // Skip bare specifiers (npm packages, virtual modules, etc.).\n if (!specifier.startsWith(\".\")) {\n return match;\n }\n\n // Skip the `__museaComponent` import — it is rebased separately by\n // `rewriteStorybookComponentImport` against the metadata component path.\n if (/\\b__museaComponent\\b/.test(head)) {\n return match;\n }\n\n const resolved = path.resolve(artDir, specifier);\n let rebased = normalizeGlobPath(path.relative(outDir, resolved));\n if (!rebased.startsWith(\".\")) {\n rebased = `./${rebased}`;\n }\n\n return `${head}${quote}${rebased}${quote}${tail}`;\n });\n}\n\nexport function toPascalCase(str: string): string {\n const normalized = str\n .normalize(\"NFKD\")\n .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n .trim();\n const pascal = normalized\n .split(/\\s+/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n\n if (!pascal) {\n return \"Variant\";\n }\n\n return /^[\\p{L}_$]/u.test(pascal) ? pascal : `Variant${pascal}`;\n}\n\nexport function escapeTemplate(str: string): string {\n return str.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"\\\\'\").replace(/\\n/g, \"\\\\n\");\n}\n\nexport function escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/**\n * Build the theme config object from plugin options for runtime injection.\n */\nexport function buildThemeConfig(\n theme?:\n | string\n | { name: string; base?: \"dark\" | \"light\"; colors: Record<string, string> }\n | Array<{ name: string; base?: \"dark\" | \"light\"; colors: Record<string, string> }>,\n):\n | {\n default: string;\n custom?: Record<string, { base?: \"dark\" | \"light\"; colors: Record<string, string> }>;\n }\n | undefined {\n if (!theme) return undefined;\n\n if (typeof theme === \"string\") {\n // 'dark' | 'light' | 'system'\n return { default: theme };\n }\n\n // Single custom theme or array of custom themes\n const themes = Array.isArray(theme) ? theme : [theme];\n const custom: Record<string, { base?: \"dark\" | \"light\"; colors: Record<string, string> }> = {};\n for (const t of themes) {\n custom[t.name] = {\n base: t.base,\n colors: t.colors as Record<string, string>,\n };\n }\n return {\n default: themes[0].name,\n custom,\n };\n}\n","import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport type { IncomingMessage } from \"node:http\";\nimport path from \"node:path\";\n\nexport const DEFAULT_API_BODY_LIMIT_BYTES = 1024 * 1024;\n\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.name = \"HttpError\";\n this.status = status;\n }\n}\n\nexport function createDevSessionToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nfunction realpathNearest(targetPath: string): string {\n let current = path.resolve(targetPath);\n const missingParts: string[] = [];\n\n while (true) {\n try {\n const real = fs.realpathSync.native(current);\n return missingParts.length > 0 ? path.join(real, ...missingParts.reverse()) : real;\n } catch {\n const parent = path.dirname(current);\n if (parent === current) {\n return path.resolve(targetPath);\n }\n missingParts.push(path.basename(current));\n current = parent;\n }\n }\n}\n\nfunction isResolvedPathInside(parentDir: string, candidatePath: string): boolean {\n const parent = path.resolve(parentDir);\n const candidate = path.resolve(candidatePath);\n const relative = path.relative(parent, candidate);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nexport function isPathInside(parentDir: string, candidatePath: string): boolean {\n return isResolvedPathInside(realpathNearest(parentDir), realpathNearest(candidatePath));\n}\n\nexport function isPathInsideAny(parentDirs: string[], candidatePath: string): boolean {\n const candidate = realpathNearest(candidatePath);\n return parentDirs.some((parentDir) =>\n isResolvedPathInside(realpathNearest(parentDir), candidate),\n );\n}\n\nexport function resolveInside(parentDir: string, candidatePath: string, label = \"path\"): string {\n return resolveInsideAny([parentDir], candidatePath, label);\n}\n\nexport function resolveInsideAny(\n parentDirs: string[],\n candidatePath: string,\n label = \"path\",\n): string {\n if (candidatePath.includes(\"\\0\")) {\n throw new HttpError(`${label} contains an invalid character`, 400);\n }\n\n if (parentDirs.length === 0) {\n throw new HttpError(`No allowed directories configured for ${label}`, 500);\n }\n\n const parent = path.resolve(parentDirs[0] ?? \".\");\n const resolved = path.isAbsolute(candidatePath)\n ? path.resolve(candidatePath)\n : path.resolve(parent, candidatePath);\n\n if (!isPathInsideAny(parentDirs, resolved)) {\n throw new HttpError(`${label} escapes the allowed directory`, 400);\n }\n\n return resolved;\n}\n\nexport function resolveUrlPathInside(\n parentDir: string,\n requestUrl: string,\n label = \"path\",\n): string {\n const rawPath = requestUrl.split(/[?#]/, 1)[0] || \"/\";\n let pathname = decodeUrlComponent(rawPath, label);\n\n pathname = pathname.replaceAll(\"\\\\\", \"/\");\n if (pathname.split(\"/\").includes(\"..\")) {\n throw new HttpError(`${label} must not contain parent directory segments`, 400);\n }\n\n const relativePath = `.${pathname}`;\n return resolveInside(parentDir, relativePath, label);\n}\n\nexport function decodeUrlComponent(value: string, label = \"path\"): string {\n try {\n return decodeURIComponent(value);\n } catch {\n throw new HttpError(`${label} is not valid URL encoding`, 400);\n }\n}\n\nexport function collectRequestBody(\n req: IncomingMessage,\n limit = DEFAULT_API_BODY_LIMIT_BYTES,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = \"\";\n let size = 0;\n let completed = false;\n\n req.on(\"data\", (chunk: Buffer | string) => {\n if (completed) return;\n\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.byteLength;\n if (size > limit) {\n completed = true;\n reject(new HttpError(`Request body exceeds ${limit} bytes`, 413));\n return;\n }\n\n body += buffer.toString(\"utf-8\");\n });\n\n req.on(\"end\", () => {\n if (!completed) {\n completed = true;\n resolve(body);\n }\n });\n\n req.on(\"error\", (error) => {\n if (!completed) {\n completed = true;\n reject(error);\n }\n });\n });\n}\n\nexport function parseJsonBody<T = unknown>(body: string): T {\n try {\n return JSON.parse(body) as T;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new HttpError(\"Malformed JSON body\", 400);\n }\n throw error;\n }\n}\n\nexport function validateDevApiRequest(\n req: IncomingMessage,\n sessionToken: string,\n): HttpError | null {\n const originError = validateOrigin(req);\n if (originError) return originError;\n\n if (!isUnsafeMethod(req.method)) {\n return null;\n }\n\n if (!hasValidSessionToken(req, sessionToken)) {\n return new HttpError(\"Invalid Musea dev session token\", 403);\n }\n\n if (!isJsonRequest(req)) {\n return new HttpError(\"Content-Type must be application/json\", 415);\n }\n\n return null;\n}\n\nexport function serializeScriptValue(value: unknown): string {\n return (JSON.stringify(value) ?? \"undefined\").replace(/[<>&\\u2028\\u2029]/g, (char) => {\n switch (char) {\n case \"<\":\n return \"\\\\u003C\";\n case \">\":\n return \"\\\\u003E\";\n case \"&\":\n return \"\\\\u0026\";\n case \"\\u2028\":\n return \"\\\\u2028\";\n case \"\\u2029\":\n return \"\\\\u2029\";\n default:\n return char;\n }\n });\n}\n\nfunction isUnsafeMethod(method: string | undefined): boolean {\n return method === \"POST\" || method === \"PUT\" || method === \"PATCH\" || method === \"DELETE\";\n}\n\nfunction isJsonRequest(req: IncomingMessage): boolean {\n const contentType = getHeader(req, \"content-type\");\n return contentType?.split(\";\")[0]?.trim().toLowerCase() === \"application/json\";\n}\n\nfunction validateOrigin(req: IncomingMessage): HttpError | null {\n const secFetchSite = getHeader(req, \"sec-fetch-site\");\n if (secFetchSite === \"cross-site\") {\n return new HttpError(\"Cross-origin Musea API requests are not allowed\", 403);\n }\n\n const origin = getHeader(req, \"origin\");\n if (!origin) return null;\n\n const host = getHeader(req, \"host\");\n if (!host) {\n return new HttpError(\"Missing Host header\", 400);\n }\n\n try {\n const originUrl = new URL(origin);\n if (originUrl.host !== host) {\n return new HttpError(\"Cross-origin Musea API requests are not allowed\", 403);\n }\n } catch {\n return new HttpError(\"Invalid Origin header\", 400);\n }\n\n return null;\n}\n\nfunction hasValidSessionToken(req: IncomingMessage, expectedToken: string): boolean {\n const actualToken = getHeader(req, \"x-musea-session\");\n if (!actualToken) return false;\n\n const actual = Buffer.from(actualToken);\n const expected = Buffer.from(expectedToken);\n return actual.length === expected.length && timingSafeEqual(actual, expected);\n}\n\nfunction getHeader(req: IncomingMessage, name: string): string | undefined {\n const value = req.headers[name];\n if (Array.isArray(value)) return value[0];\n return value;\n}\n","import path from \"node:path\";\n\nimport { resolveInsideAny } from \"./security.js\";\nimport type { ArtFileInfo } from \"./types/index.js\";\n\nexport function allowedSourceRoots(root: string, scanRoots: string[] = []): string[] {\n return [...new Set([root, ...scanRoots].map((sourceRoot) => path.resolve(sourceRoot)))];\n}\n\nexport function resolveComponentSourcePath(\n art: ArtFileInfo,\n artPath: string,\n sourceRoots: string[],\n): string | null {\n const componentPath =\n art.isInline && art.componentPath\n ? art.componentPath\n : art.metadata.component\n ? path.isAbsolute(art.metadata.component)\n ? art.metadata.component\n : path.resolve(path.dirname(artPath), art.metadata.component)\n : null;\n\n return componentPath ? resolveInsideAny(sourceRoots, componentPath, \"component path\") : null;\n}\n","/**\n * Legacy Vue 2 variant emission.\n *\n * Vue 2 has no `openBlock`/`createElementBlock` runtime, so the compiled Vue 3\n * render functions the SFC pipeline produces cannot load there. Vue 2 galleries\n * keep the runtime-compiled `template:` string they always had — the TypeScript\n * fix in #3857 applies to Vue 3, which is what `.art.vue` with\n * `<script setup lang=\"ts\">` targets.\n */\n\nimport { escapeHtml } from \"./utils.js\";\n\nexport function escapeTemplateLiteral(str: string): string {\n return str.replace(/\\\\/g, \"\\\\\\\\\").replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\");\n}\n\nexport type LegacyVariantContext = {\n variantComponentName: string;\n variantName: string;\n template: string;\n componentTagName?: string;\n componentBindingName: string;\n scriptSetup: { setupBody: string[]; returnNames: string[]; imports: string[] } | null;\n hasSetup: boolean;\n isolatedSetup: boolean;\n setupReturn: string;\n importDeclaresName: (statement: string, name: string) => boolean;\n};\n\nexport function emitLegacyVariant(context: LegacyVariantContext): string {\n const {\n variantComponentName,\n variantName,\n template,\n componentTagName,\n componentBindingName,\n scriptSetup,\n hasSetup,\n isolatedSetup,\n setupReturn,\n importDeclaresName,\n } = context;\n\n const escapedTemplate = escapeTemplateLiteral(template);\n const escapedVariantName = escapeTemplateLiteral(escapeHtml(variantName));\n const fullTemplate = `<div data-variant=\"${escapedVariantName}\">${escapedTemplate}</div>`;\n\n // Runtime-compiled templates use resolveComponent(), which checks the\n // `components` option rather than setup return values.\n const componentNames = new Map<string, string>();\n if (componentTagName) componentNames.set(componentTagName, componentBindingName);\n if (scriptSetup) {\n for (const name of scriptSetup.returnNames)\n if (/^[A-Z]/.test(name) && scriptSetup.imports.some((imp) => importDeclaresName(imp, name)))\n componentNames.set(name, name);\n }\n const components =\n componentNames.size > 0\n ? ` components: { ${[...componentNames]\n .map(([name, value]) => `${JSON.stringify(name)}: ${value}`)\n .join(\", \")} },\\n`\n : \"\";\n\n if (scriptSetup && hasSetup && isolatedSetup) {\n return `\nexport const ${variantComponentName} = __museaDefineComponent({\n name: '${variantComponentName}',\n${components} setup() {\n${scriptSetup.setupBody.join(\"\\n\")}\n return ${setupReturn};\n },\n template: \\`${fullTemplate}\\`,\n});\n`;\n }\n if (scriptSetup && hasSetup) {\n return `\nexport const ${variantComponentName} = __museaDefineComponent({\n name: '${variantComponentName}',\n${components} setup() {\n return __museaSharedSetup;\n },\n template: \\`${fullTemplate}\\`,\n});\n`;\n }\n // Without a setup block `components` is empty unless a component tag was\n // resolved, so one template covers both cases.\n return `\nexport const ${variantComponentName} = {\n name: '${variantComponentName}',\n${components} template: \\`${fullTemplate}\\`,\n};\n`;\n}\n","/**\n * Resolve which component an art file demonstrates, and under what tag.\n *\n * Shared by the art module and by the per-variant SFC compiler (#3857) so both\n * agree on the import path, the tag `<Self>` expands to, and the binding name.\n * The parsed `<script setup>` is passed in rather than parsed here, so this\n * module does not have to import back from `art-module.ts`.\n */\n\nimport path from \"node:path\";\n\nimport { allowedSourceRoots, resolveComponentSourcePath } from \"./component-source.js\";\nimport type { ArtFileInfo } from \"./types/index.js\";\nimport { toPascalCase } from \"./utils.js\";\n\nexport type ArtScriptSetupInfo = {\n defineArtComponentName?: string;\n defineArtComponentSource?: string;\n} | null;\n\nexport type ResolvedArtComponent = {\n componentImportPath?: string;\n componentTagName?: string;\n componentBindingName: string;\n};\n\nexport function componentNameFromSource(source: string): string {\n const withoutQuery = source.split(/[?#]/, 1)[0] || source;\n const filename = path.basename(withoutQuery);\n const extension = path.extname(filename);\n const stem = extension ? filename.slice(0, -extension.length) : filename;\n const name = toPascalCase(stem);\n return name === \"Variant\" ? \"MuseaComponent\" : name;\n}\n\nexport function resolveArtComponent(\n art: ArtFileInfo,\n filePath: string,\n scriptSetup: ArtScriptSetupInfo,\n options: { root?: string; scanRoots?: string[] } = {},\n): ResolvedArtComponent {\n let componentImportPath: string | undefined;\n let componentTagName: string | undefined;\n let componentBindingName = \"__MuseaComponent\";\n const defineArtComponentName = scriptSetup?.defineArtComponentName;\n const defineArtComponentSource = scriptSetup?.defineArtComponentSource;\n\n if (art.isInline && art.componentPath) {\n // Inline art: import the host .vue file itself as the component\n componentImportPath = options.root\n ? (resolveComponentSourcePath(\n art,\n filePath,\n allowedSourceRoots(options.root, options.scanRoots ?? []),\n ) ?? undefined)\n : art.componentPath;\n componentTagName = \"MuseaComponent\";\n } else if (defineArtComponentSource || art.metadata.component) {\n // .art.vue: resolve component from defineArt(source, ...) or the legacy component attribute.\n const componentSource = defineArtComponentSource ?? art.metadata.component;\n if (componentSource) {\n const sourceArt =\n componentSource === art.metadata.component\n ? art\n : { ...art, metadata: { ...art.metadata, component: componentSource } };\n componentImportPath = options.root\n ? (resolveComponentSourcePath(\n sourceArt,\n filePath,\n allowedSourceRoots(options.root, options.scanRoots ?? []),\n ) ?? undefined)\n : path.isAbsolute(componentSource)\n ? componentSource\n : path.resolve(path.dirname(filePath), componentSource);\n }\n componentTagName =\n defineArtComponentName ??\n (art.metadata.component ? componentNameFromSource(art.metadata.component) : \"MuseaComponent\");\n componentBindingName = componentTagName;\n }\n\n return { componentImportPath, componentTagName, componentBindingName };\n}\n\n/** Expand `<Self>` in a variant template to the resolved component tag. */\nexport function expandSelfTag(template: string, componentTagName: string | undefined): string {\n if (!componentTagName) return template;\n // Match the complete tag name only, so `<Selfish>` and `<Self-Preview>` are\n // left alone while `<Self>`, `<Self />`, and `<Self ...>` expand.\n return template\n .replace(/<Self(?=[\\s/>])/g, `<${componentTagName}`)\n .replace(/<\\/Self\\s*>/g, `</${componentTagName}>`);\n}\n","/**\n * Art module generation for Musea.\n *\n * Generates the virtual ES modules that represent parsed `.art.vue` files,\n * including variant component definitions and script setup handling.\n */\n\nimport path from \"node:path\";\n\nimport { allowedSourceRoots, resolveComponentSourcePath } from \"./component-source.js\";\nimport type { ArtFileInfo } from \"./types/index.js\";\nimport { toPascalCase } from \"./utils.js\";\nimport { emitLegacyVariant } from \"./art-module-vue2.js\";\nimport { expandSelfTag } from \"./art-component.js\";\n\n/**\n * Extract the content of the first <script setup> block from a Vue SFC source.\n */\nexport function extractScriptSetupContent(source: string): string | undefined {\n const match = source.match(/<script\\s+[^>]*setup[^>]*>([\\s\\S]*?)<\\/script>/);\n return match?.[1]?.trim();\n}\n\nexport function extractScriptSetupIsolated(source: string): boolean {\n const match = source.match(/<script\\s+([^>]*)\\bsetup\\b([^>]*)>/);\n if (!match) return true;\n const attrs = `${match[1] ?? \"\"} ${match[2] ?? \"\"}`;\n const isolate = attrs.match(/\\bisolate\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))/);\n return (isolate?.[1] ?? isolate?.[2] ?? isolate?.[3]) !== \"false\";\n}\n\nfunction resolveRelativeSpecifier(specifier: string, artDir: string): string {\n if (!specifier.startsWith(\".\")) {\n return specifier;\n }\n\n return path.resolve(artDir, specifier);\n}\n\nexport function rewriteRelativeImportStatement(statement: string, artDir: string): string {\n const rewrittenFromImports = statement.replace(\n /\\bfrom\\s+(['\"])([^'\"]+)\\1/g,\n (_match, quote: string, specifier: string) =>\n `from ${quote}${resolveRelativeSpecifier(specifier, artDir)}${quote}`,\n );\n\n return rewrittenFromImports.replace(\n /^(\\s*import\\s+)(['\"])([^'\"]+)\\2(\\s*;?\\s*)$/s,\n (_match, prefix: string, quote: string, specifier: string, suffix: string) =>\n `${prefix}${quote}${resolveRelativeSpecifier(specifier, artDir)}${quote}${suffix}`,\n );\n}\n\nfunction countCharBalance(source: string, openChar: string, closeChar: string): number {\n let balance = 0;\n for (const char of source) {\n if (char === openChar) balance++;\n else if (char === closeChar) balance--;\n }\n return balance;\n}\n\nfunction isCompleteImportStatement(statement: string): boolean {\n const trimmed = statement.trim();\n if (!trimmed.startsWith(\"import \")) {\n return false;\n }\n\n if (countCharBalance(statement, \"{\", \"}\") > 0) {\n return false;\n }\n\n return (\n /^import\\s+[\\s\\S]+?\\s+from\\s+['\"][^'\"]+['\"]\\s*;?$/s.test(trimmed) ||\n /^import\\s+['\"][^'\"]+['\"]\\s*;?$/s.test(trimmed)\n );\n}\n\nfunction splitTopLevelCommaList(source: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let braceDepth = 0;\n let bracketDepth = 0;\n let parenDepth = 0;\n\n for (const char of source) {\n if (char === \",\" && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {\n const trimmed = current.trim();\n if (trimmed) {\n parts.push(trimmed);\n }\n current = \"\";\n continue;\n }\n\n current += char;\n\n if (char === \"{\") braceDepth++;\n else if (char === \"}\") braceDepth--;\n else if (char === \"[\") bracketDepth++;\n else if (char === \"]\") bracketDepth--;\n else if (char === \"(\") parenDepth++;\n else if (char === \")\") parenDepth--;\n }\n\n const trimmed = current.trim();\n if (trimmed) {\n parts.push(trimmed);\n }\n\n return parts;\n}\n\nfunction collectImportedNames(statement: string, returnNames: Set<string>): void {\n const normalized = statement.replace(/\\s+/g, \" \").trim().replace(/;$/, \"\");\n const fromMatch = normalized.match(/^import\\s+(type\\s+)?(.+?)\\s+from\\s+['\"][^'\"]+['\"]$/);\n\n if (!fromMatch) {\n return;\n }\n\n if (fromMatch[1]) {\n return;\n }\n\n const specifiers = fromMatch[2].trim();\n const specifierParts = splitTopLevelCommaList(specifiers);\n const defaultOrNamespace = specifierParts[0]?.trim() ?? \"\";\n const trailing = specifierParts.slice(1).join(\", \").trim();\n\n if (defaultOrNamespace && !defaultOrNamespace.startsWith(\"{\")) {\n const namespaceMatch = defaultOrNamespace.match(/^\\*\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (namespaceMatch) {\n returnNames.add(namespaceMatch[1]);\n } else if (!defaultOrNamespace.startsWith(\"type \")) {\n returnNames.add(defaultOrNamespace);\n }\n }\n\n const namedBlock = defaultOrNamespace.startsWith(\"{\")\n ? defaultOrNamespace\n : trailing.startsWith(\"{\")\n ? trailing\n : \"\";\n\n if (!namedBlock) {\n return;\n }\n\n const namedContent = namedBlock.slice(1, -1);\n for (const part of splitTopLevelCommaList(namedContent)) {\n const trimmed = part.trim();\n if (!trimmed || trimmed.startsWith(\"type \")) {\n continue;\n }\n\n const alias = trimmed\n .split(/\\s+as\\s+/)\n .pop()\n ?.trim();\n if (alias) {\n returnNames.add(alias);\n }\n }\n}\n\nfunction importDeclaresName(statement: string, name: string): boolean {\n const names = new Set<string>();\n collectImportedNames(statement, names);\n return names.has(name);\n}\n\nfunction collectObjectDestructuredNames(statement: string, returnNames: Set<string>): void {\n const match = statement.match(/^(?:export\\s+)?(?:const|let|var)\\s+\\{([\\s\\S]*?)\\}\\s*=/);\n if (!match) {\n return;\n }\n\n for (const part of splitTopLevelCommaList(match[1])) {\n let name = part.trim();\n if (!name) {\n continue;\n }\n\n if (name.startsWith(\"...\")) {\n name = name.slice(3).trim();\n } else if (name.includes(\":\")) {\n name = name.split(\":\").pop()!.trim();\n } else if (name.includes(\"=\")) {\n name = name.split(\"=\")[0].trim();\n }\n\n if (name.includes(\"=\")) {\n name = name.split(\"=\")[0].trim();\n }\n\n if (/^[A-Za-z_$][\\w$]*$/.test(name)) {\n returnNames.add(name);\n }\n }\n}\n\nfunction collectArrayDestructuredNames(statement: string, returnNames: Set<string>): void {\n const match = statement.match(/^(?:export\\s+)?(?:const|let|var)\\s+\\[([\\s\\S]*?)\\]\\s*=/);\n if (!match) {\n return;\n }\n\n for (const part of splitTopLevelCommaList(match[1])) {\n let name = part.trim();\n if (!name) {\n continue;\n }\n\n if (name.startsWith(\"...\")) {\n name = name.slice(3).trim();\n }\n\n if (name.includes(\"=\")) {\n name = name.split(\"=\")[0].trim();\n }\n\n if (/^[A-Za-z_$][\\w$]*$/.test(name)) {\n returnNames.add(name);\n }\n }\n}\n\nfunction collectTopLevelReturnNames(setupBody: string[], returnNames: Set<string>): void {\n let braceDepth = 0;\n\n for (let i = 0; i < setupBody.length; i++) {\n const line = setupBody[i];\n const trimmed = line.trim();\n\n if (braceDepth === 0) {\n if (/^(?:export\\s+)?(?:const|let|var)\\s+\\{/.test(trimmed)) {\n const statementLines = [line];\n let balance =\n countCharBalance(line, \"{\", \"}\") +\n countCharBalance(line, \"[\", \"]\") +\n countCharBalance(line, \"(\", \")\");\n\n while (balance > 0 && i + 1 < setupBody.length) {\n i++;\n statementLines.push(setupBody[i]);\n balance +=\n countCharBalance(setupBody[i], \"{\", \"}\") +\n countCharBalance(setupBody[i], \"[\", \"]\") +\n countCharBalance(setupBody[i], \"(\", \")\");\n }\n\n collectObjectDestructuredNames(statementLines.join(\"\\n\"), returnNames);\n continue;\n }\n\n if (/^(?:export\\s+)?(?:const|let|var)\\s+\\[/.test(trimmed)) {\n const statementLines = [line];\n let balance =\n countCharBalance(line, \"{\", \"}\") +\n countCharBalance(line, \"[\", \"]\") +\n countCharBalance(line, \"(\", \")\");\n\n while (balance > 0 && i + 1 < setupBody.length) {\n i++;\n statementLines.push(setupBody[i]);\n balance +=\n countCharBalance(setupBody[i], \"{\", \"}\") +\n countCharBalance(setupBody[i], \"[\", \"]\") +\n countCharBalance(setupBody[i], \"(\", \")\");\n }\n\n collectArrayDestructuredNames(statementLines.join(\"\\n\"), returnNames);\n continue;\n }\n\n const constMatch = trimmed.match(/^(?:export\\s+)?(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)/);\n if (constMatch) {\n returnNames.add(constMatch[1]);\n }\n\n const functionMatch = trimmed.match(\n /^(?:export\\s+)?(?:async\\s+)?function\\s+([A-Za-z_$][\\w$]*)\\s*\\(/,\n );\n if (functionMatch) {\n returnNames.add(functionMatch[1]);\n }\n\n const classMatch = trimmed.match(/^(?:export\\s+)?class\\s+([A-Za-z_$][\\w$]*)\\b/);\n if (classMatch) {\n returnNames.add(classMatch[1]);\n }\n }\n\n braceDepth += countCharBalance(line, \"{\", \"}\");\n }\n}\n\n/**\n * Parse script setup content into imports and setup body.\n * Returns the import lines, setup body lines, and all identifiers to expose.\n */\nexport function parseScriptSetupForArt(content: string): {\n imports: string[];\n setupBody: string[];\n returnNames: string[];\n defineArtComponentName?: string;\n defineArtComponentSource?: string;\n} {\n const lines = content.split(\"\\n\");\n const imports: string[] = [];\n const setupBody: string[] = [];\n const returnNames: Set<string> = new Set();\n let currentImport: string[] | null = null;\n const defineArtComponent = extractDefineArtComponent(content);\n let defineArtBalance = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (defineArtBalance > 0) {\n defineArtBalance += countCharBalance(line, \"(\", \")\");\n continue;\n }\n\n if (currentImport) {\n currentImport.push(line);\n const statement = currentImport.join(\"\\n\");\n if (isCompleteImportStatement(statement)) {\n imports.push(statement);\n collectImportedNames(statement, returnNames);\n currentImport = null;\n }\n continue;\n }\n\n if (trimmed.startsWith(\"import \")) {\n currentImport = [line];\n const statement = currentImport.join(\"\\n\");\n if (isCompleteImportStatement(statement)) {\n imports.push(statement);\n collectImportedNames(statement, returnNames);\n currentImport = null;\n }\n continue;\n }\n\n if (isDefineArtLine(trimmed)) {\n defineArtBalance = Math.max(0, countCharBalance(line, \"(\", \")\"));\n continue;\n }\n\n setupBody.push(line);\n }\n\n if (currentImport) {\n const statement = currentImport.join(\"\\n\");\n imports.push(statement);\n collectImportedNames(statement, returnNames);\n }\n\n collectTopLevelReturnNames(setupBody, returnNames);\n\n // Remove 'type' keyword imports and common Vue utilities that shouldn't be returned\n returnNames.delete(\"type\");\n if (defineArtComponent.name) {\n returnNames.delete(defineArtComponent.name);\n }\n\n return {\n imports,\n setupBody,\n returnNames: [...returnNames],\n defineArtComponentName: defineArtComponent.name,\n defineArtComponentSource: defineArtComponent.source,\n };\n}\n\nfunction extractDefineArtComponent(content: string): { name?: string; source?: string } {\n const sourceMatch = content.match(/\\bdefineArt\\s*\\(\\s*(['\"])([^'\"]+)\\1/);\n if (sourceMatch) {\n return {\n name: componentNameFromSource(sourceMatch[2]),\n source: sourceMatch[2],\n };\n }\n\n const identifierMatch = content.match(/\\bdefineArt\\s*\\(\\s*([A-Za-z_$][\\w$]*)/);\n return { name: identifierMatch?.[1] };\n}\n\nfunction componentNameFromSource(source: string): string {\n const withoutQuery = source.split(/[?#]/, 1)[0] || source;\n const filename = path.basename(withoutQuery);\n const extension = path.extname(filename);\n const stem = extension ? filename.slice(0, -extension.length) : filename;\n const name = toPascalCase(stem);\n return name === \"Variant\" ? \"MuseaComponent\" : name;\n}\n\nfunction isDefineArtLine(trimmed: string): boolean {\n return /\\bdefineArt\\s*\\(/.test(trimmed);\n}\n\ninterface GenerateArtModuleOptions {\n /** Legacy galleries keep runtime-compiled templates; see the Vue 2 branch below. */\n vueVersion?: 2 | 3;\n root?: string;\n scanRoots?: string[];\n}\n\nexport function generateArtModule(\n art: ArtFileInfo,\n filePath: string,\n options: GenerateArtModuleOptions = {},\n): string {\n let componentImportPath: string | undefined;\n let componentTagName: string | undefined;\n let componentBindingName = \"__MuseaComponent\";\n const scriptSetup = art.scriptSetupContent\n ? parseScriptSetupForArt(art.scriptSetupContent)\n : null;\n const defineArtComponentName = scriptSetup?.defineArtComponentName;\n const defineArtComponentSource = scriptSetup?.defineArtComponentSource;\n\n if (art.isInline && art.componentPath) {\n // Inline art: import the host .vue file itself as the component\n componentImportPath = options.root\n ? (resolveComponentSourcePath(\n art,\n filePath,\n allowedSourceRoots(options.root, options.scanRoots ?? []),\n ) ?? undefined)\n : art.componentPath;\n componentTagName = \"MuseaComponent\";\n } else if (defineArtComponentSource || art.metadata.component) {\n // .art.vue: resolve component from defineArt(source, ...) or the legacy component attribute.\n const componentSource = defineArtComponentSource ?? art.metadata.component;\n if (componentSource) {\n const sourceArt =\n componentSource === art.metadata.component\n ? art\n : { ...art, metadata: { ...art.metadata, component: componentSource } };\n componentImportPath = options.root\n ? (resolveComponentSourcePath(\n sourceArt,\n filePath,\n allowedSourceRoots(options.root, options.scanRoots ?? []),\n ) ?? undefined)\n : path.isAbsolute(componentSource)\n ? componentSource\n : path.resolve(path.dirname(filePath), componentSource);\n }\n componentTagName =\n defineArtComponentName ??\n (art.metadata.component ? componentNameFromSource(art.metadata.component) : \"MuseaComponent\");\n componentBindingName = componentTagName;\n }\n\n const hasSetupBody = scriptSetup?.setupBody.some((line) => line.trim().length > 0) ?? false;\n const hasSetup = !!scriptSetup && (hasSetupBody || scriptSetup.returnNames.length > 0);\n\n let code = `\n// Auto-generated module for: ${path.basename(filePath)}\n`;\n\n // Vue 2 variants stay runtime-compiled (see art-module-vue2.ts), and only a\n // variant with a setup block is wrapped in `defineComponent`, a Vue 2.7+\n // export that therefore stays unimported otherwise. The alias keeps it from\n // colliding with an art file that imports `defineComponent` itself.\n if (options.vueVersion === 2 && hasSetup) {\n code += `import { defineComponent as __museaDefineComponent } from 'vue';\\n`;\n }\n\n // Add script setup imports at module level\n // Resolve relative paths to absolute since this code runs inside a virtual module\n if (scriptSetup) {\n const artDir = path.dirname(filePath);\n for (const imp of scriptSetup.imports) {\n const resolved = rewriteRelativeImportStatement(imp, artDir);\n code += `${resolved}\\n`;\n }\n }\n\n if (componentImportPath && componentTagName) {\n // Only add component import if not already imported by script setup\n const alreadyImported = scriptSetup?.imports.some((imp) =>\n importDeclaresName(imp, componentBindingName),\n );\n if (!alreadyImported) {\n code += `import ${componentBindingName} from ${JSON.stringify(componentImportPath)};\\n`;\n }\n code += `export const __component__ = ${componentBindingName};\\n`;\n }\n\n code += `\nexport const metadata = ${JSON.stringify(art.metadata)};\nexport const variants = ${JSON.stringify(art.variants)};\nexport const __styles__ = ${JSON.stringify(art.styleBlocks ?? [])};\n`;\n\n const setupReturn = `{ ${scriptSetup?.returnNames.join(\", \") ?? \"\"} }`;\n const isolatedSetup = art.scriptSetupIsolated !== false;\n\n if (scriptSetup && hasSetup && !isolatedSetup) {\n code += `\nconst __museaSharedSetup = (() => {\n${scriptSetup.setupBody.join(\"\\n\")}\n return ${setupReturn};\n})();\n`;\n }\n\n // Generate variant components\n for (const variant of art.variants) {\n const variantComponentName = toPascalCase(variant.name);\n\n // Replace <Self> with the actual component name (for inline art)\n const template = expandSelfTag(variant.template, componentTagName);\n\n // Vue 2 keeps the runtime-compiled `template:` string; see art-module-vue2.ts (#3857).\n if (options.vueVersion === 2) {\n code += emitLegacyVariant({\n variantComponentName,\n variantName: variant.name,\n template,\n componentTagName,\n componentBindingName,\n scriptSetup,\n hasSetup,\n isolatedSetup,\n setupReturn,\n importDeclaresName,\n });\n continue;\n }\n\n // Each variant is compiled through the SFC pipeline in its own virtual\n // module (#3857): `compileSfc` emits a complete module with its own default\n // export, so it cannot be inlined here, and only that pipeline strips the\n // TypeScript in template expressions and resolves bindings correctly.\n // Variant names are free-form author text, so encode the name to keep the\n // path/name delimiter unambiguous for the resolver, which splits on the last\n // colon. A name containing one would otherwise move the split point and the\n // art path would never match.\n const variantModuleId = `virtual:musea-variant:${filePath}:${encodeURIComponent(variant.name)}`;\n code += `\nimport ${variantComponentName} from ${JSON.stringify(variantModuleId)};\nexport { ${variantComponentName} };\n`;\n }\n\n // Default export\n const defaultVariant = art.variants.find((v) => v.isDefault) || art.variants[0];\n if (defaultVariant) {\n code += `\nexport default ${toPascalCase(defaultVariant.name)};\n`;\n }\n\n return code;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { extractScriptSetupContent, extractScriptSetupIsolated } from \"../art-module.js\";\nimport { loadNative } from \"../native-loader.js\";\nimport type { NativeBinding } from \"../native-loader.js\";\nimport type { ArtFileInfo, ArtMetadata } from \"../types/index.js\";\n\nexport interface ArtProcessingContext {\n root: string;\n command: string;\n onError?: (message: string) => void;\n}\n\nfunction extractArtTagAttributes(source: string): Record<string, string | true> {\n const artTagMatch = source.match(/<art\\b([\\s\\S]*?)>/i);\n if (!artTagMatch) return {};\n\n const attributes: Record<string, string | true> = {};\n const attrPattern = /([^\\s=/>]+)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'))?/g;\n\n for (const match of artTagMatch[1].matchAll(attrPattern)) {\n const name = match[1];\n if (!name || name === \"/\") continue;\n attributes[name] = match[2] ?? match[3] ?? true;\n }\n\n return attributes;\n}\n\nfunction parseActionEvents(value: string | true | undefined): string[] | undefined {\n if (typeof value !== \"string\") return undefined;\n\n const events = value\n .split(\",\")\n .map((eventName) => eventName.trim().toLowerCase())\n .filter(Boolean);\n\n return events.length > 0 ? [...new Set(events)] : undefined;\n}\n\nfunction extractCustomArtMetadata(source: string): Pick<ArtMetadata, \"actionEvents\"> {\n const attrs = extractArtTagAttributes(source);\n const actionEvents = new Set(parseActionEvents(attrs[\"action-events\"]) ?? []);\n const captureMousemove = attrs[\"capture-mousemove\"];\n\n if (captureMousemove === true || captureMousemove === \"true\") {\n actionEvents.add(\"mousemove\");\n }\n\n return {\n actionEvents: actionEvents.size > 0 ? [...actionEvents] : undefined,\n };\n}\n\nfunction extractStyleBlocks(source: string): string[] {\n const styles: string[] = [];\n\n for (const match of source.matchAll(/<style\\b([^>]*)>([\\s\\S]*?)<\\/style>/gi)) {\n const attrs = match[1] ?? \"\";\n const content = match[2]?.trim();\n const lang = attrs.match(/\\blang\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1]?.toLowerCase();\n\n if (!content) continue;\n if (lang && lang !== \"css\") continue;\n\n styles.push(content);\n }\n\n return styles;\n}\n\nfunction formatArtProcessingError(root: string, filePath: string, error: unknown): string {\n const detail =\n error instanceof Error\n ? error.message || error.name\n : error == null\n ? \"unknown error\"\n : stringifyUnknown(error);\n const relativePath = path.relative(root, filePath) || filePath;\n return `[musea] Failed to process ${relativePath}: ${detail}`;\n}\n\nfunction stringifyUnknown(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return value.toString();\n }\n try {\n return JSON.stringify(value) ?? \"unknown error\";\n } catch {\n return \"unknown error\";\n }\n}\n\nexport function reportArtStatusWarnings(\n binding: Pick<NativeBinding, \"parseArtStatusWarnings\">,\n source: string,\n filename: string,\n warn: (message: string) => void = console.warn,\n): void {\n const warnings = binding.parseArtStatusWarnings?.(source, { filename });\n if (warnings == null) return;\n for (const warning of warnings) {\n warn(`[musea] ${warning}`);\n }\n}\n\nexport async function processMuseaArtFile(\n filePath: string,\n ctx: ArtProcessingContext,\n): Promise<ArtFileInfo | null> {\n try {\n const source = await fs.promises.readFile(filePath, \"utf-8\");\n const binding = loadNative();\n const parsed = binding.parseArt(source, { filename: filePath });\n reportArtStatusWarnings(binding, source, filePath);\n const customMetadata = extractCustomArtMetadata(source);\n\n if (!parsed.variants || parsed.variants.length === 0) return null;\n\n const isInline = !filePath.endsWith(\".art.vue\");\n\n return {\n path: filePath,\n metadata: {\n title: parsed.metadata.title || (isInline ? path.basename(filePath, \".vue\") : \"\"),\n description: parsed.metadata.description,\n component: isInline ? undefined : parsed.metadata.component,\n category: parsed.metadata.category,\n tags: parsed.metadata.tags,\n status: parsed.metadata.status as \"draft\" | \"ready\" | \"deprecated\",\n order: parsed.metadata.order,\n actionEvents: customMetadata.actionEvents ?? parsed.metadata.actionEvents,\n },\n variants: parsed.variants.map((v) => ({\n name: v.name,\n template: v.template,\n isDefault: v.isDefault,\n skipVrt: v.skipVrt,\n })),\n hasScriptSetup: isInline ? false : parsed.hasScriptSetup,\n scriptSetupContent:\n !isInline && parsed.hasScriptSetup ? extractScriptSetupContent(source) : undefined,\n scriptSetupIsolated:\n !isInline && parsed.hasScriptSetup ? extractScriptSetupIsolated(source) : true,\n hasScript: parsed.hasScript,\n styleCount: parsed.styleCount,\n styleBlocks: isInline ? [] : extractStyleBlocks(source),\n isInline,\n componentPath: isInline ? filePath : undefined,\n };\n } catch (error) {\n const message = formatArtProcessingError(ctx.root, filePath, error);\n if (ctx.command === \"build\") throw new Error(message);\n (ctx.onError ?? console.error)(message);\n return null;\n }\n}\n"],"mappings":"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"}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { t as processMuseaArtFile } from "../art-processing-e4a94Wa4.mjs";
|
|
2
3
|
import { i as MuseaVrtRunner, n as generateVrtJsonReport, r as generateVrtReport } from "../vrt-DgVSWKGl.mjs";
|
|
3
4
|
import fs from "node:fs";
|
|
4
5
|
import path from "node:path";
|
|
@@ -31,45 +32,10 @@ async function scanArtFiles(root) {
|
|
|
31
32
|
}
|
|
32
33
|
/** Parse a single .art.vue file into an ArtFileInfo structure. */
|
|
33
34
|
async function parseArtFile(filePath) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const categoryMatch = source.match(/<art[^>]*\scategory=["']([^"']+)["']/);
|
|
39
|
-
const variants = [];
|
|
40
|
-
const variantRegex = /<variant\s+([^>]*)>([\s\S]*?)<\/variant>/g;
|
|
41
|
-
let match;
|
|
42
|
-
while ((match = variantRegex.exec(source)) !== null) {
|
|
43
|
-
const attrs = match[1];
|
|
44
|
-
const template = match[2].trim();
|
|
45
|
-
const nameMatch = attrs.match(/name=["']([^"']+)["']/);
|
|
46
|
-
const isDefault = /\bdefault\b/.test(attrs);
|
|
47
|
-
const skipVrt = /\bskip-vrt\b/.test(attrs);
|
|
48
|
-
if (nameMatch) variants.push({
|
|
49
|
-
name: nameMatch[1],
|
|
50
|
-
template,
|
|
51
|
-
isDefault,
|
|
52
|
-
skipVrt
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
path: filePath,
|
|
57
|
-
metadata: {
|
|
58
|
-
title: titleMatch?.[1] || path.basename(filePath, ".art.vue"),
|
|
59
|
-
component: componentMatch?.[1],
|
|
60
|
-
category: categoryMatch?.[1],
|
|
61
|
-
tags: [],
|
|
62
|
-
status: "ready"
|
|
63
|
-
},
|
|
64
|
-
variants,
|
|
65
|
-
hasScriptSetup: /<script\s+setup/.test(source),
|
|
66
|
-
hasScript: /<script(?!\s+setup)/.test(source),
|
|
67
|
-
styleCount: (source.match(/<style/g) || []).length
|
|
68
|
-
};
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(`Failed to parse ${filePath}:`, error);
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
35
|
+
return processMuseaArtFile(filePath, {
|
|
36
|
+
root: path.dirname(filePath),
|
|
37
|
+
command: "serve"
|
|
38
|
+
});
|
|
73
39
|
}
|
|
74
40
|
//#endregion
|
|
75
41
|
//#region src/cli/commands.ts
|
package/dist/cli/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/cli/utils.ts","../../src/cli/commands.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * CLI utility functions for art file scanning and parsing.\n *\n * Extracted from cli.ts to keep file sizes manageable.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { ArtFileInfo } from \"../types/index.js\";\n\n/** Recursively scan a directory for .art.vue files. */\nexport async function scanArtFiles(root: string): Promise<string[]> {\n const files: string[] = [];\n\n async function scan(dir: string): Promise<void> {\n let entries: fs.Dirent[];\n try {\n entries = await fs.promises.readdir(dir, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EACCES\") {\n return;\n }\n throw error;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n // Skip node_modules and dist\n if (entry.name === \"node_modules\" || entry.name === \"dist\") {\n continue;\n }\n\n if (entry.isDirectory()) {\n await scan(fullPath);\n } else if (entry.isFile() && entry.name.endsWith(\".art.vue\")) {\n files.push(fullPath);\n }\n }\n }\n\n await scan(root);\n return files;\n}\n\n/** Parse a single .art.vue file into an ArtFileInfo structure. */\nexport async function parseArtFile(filePath: string): Promise<ArtFileInfo | null> {\n try {\n const source = await fs.promises.readFile(filePath, \"utf-8\");\n\n // Simple parsing - in production, use @vizejs/native\n const titleMatch = source.match(/<art[^>]*\\stitle=[\"']([^\"']+)[\"']/);\n const componentMatch = source.match(/<art[^>]*\\scomponent=[\"']([^\"']+)[\"']/);\n const categoryMatch = source.match(/<art[^>]*\\scategory=[\"']([^\"']+)[\"']/);\n\n const variants: ArtFileInfo[\"variants\"] = [];\n const variantRegex = /<variant\\s+([^>]*)>([\\s\\S]*?)<\\/variant>/g;\n let match;\n\n while ((match = variantRegex.exec(source)) !== null) {\n const attrs = match[1];\n const template = match[2].trim();\n\n const nameMatch = attrs.match(/name=[\"']([^\"']+)[\"']/);\n const isDefault = /\\bdefault\\b/.test(attrs);\n const skipVrt = /\\bskip-vrt\\b/.test(attrs);\n\n if (nameMatch) {\n variants.push({\n name: nameMatch[1],\n template,\n isDefault,\n skipVrt,\n });\n }\n }\n\n return {\n path: filePath,\n metadata: {\n title: titleMatch?.[1] || path.basename(filePath, \".art.vue\"),\n component: componentMatch?.[1],\n category: categoryMatch?.[1],\n tags: [],\n status: \"ready\",\n },\n variants,\n hasScriptSetup: /<script\\s+setup/.test(source),\n hasScript: /<script(?!\\s+setup)/.test(source),\n styleCount: (source.match(/<style/g) || []).length,\n };\n } catch (error) {\n console.error(`Failed to parse ${filePath}:`, error);\n return null;\n }\n}\n","/**\n * CLI command handlers for the Musea VRT tool.\n *\n * Extracted from cli.ts to keep file sizes manageable.\n * Contains the runVrt, runApprove, runClean, and runGenerate command implementations.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { MuseaVrtRunner, generateVrtReport, generateVrtJsonReport } from \"../vrt.js\";\nimport type { VrtSummary } from \"../vrt.js\";\nimport type { ArtFileInfo, VrtOptions } from \"../types/index.js\";\n\nimport type { CliOptions } from \"./index.js\";\n\nexport function hasCiBlockingVrtResult(summary: VrtSummary): boolean {\n return summary.failed > 0 || summary.skipped > 0;\n}\n\nexport function isArtFileInput(filePath: string): boolean {\n return filePath.endsWith(\".art.vue\");\n}\n\nexport async function runVrt(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const totalVariants = artFiles.reduce(\n (sum, art) => sum + art.variants.filter((v) => !v.skipVrt).length,\n 0,\n );\n\n console.log(` Testing ${totalVariants} variant(s) across ${artFiles.length} art file(s)\\n`);\n\n // Initialize VRT runner\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner({\n ...vrtOptions,\n ci: options.ci ? { failOnDiff: true, jsonReport: options.json } : undefined,\n });\n\n try {\n console.log(\" Launching browser...\");\n await runner.init();\n\n console.log(\" Running visual regression tests...\\n\");\n\n // Run tests\n const results = await runner.runAllTests(artFiles, options.baseUrl);\n const summary = runner.getSummary(results);\n\n // Print results\n console.log(\" Results:\");\n console.log(\" ---------\");\n console.log(` Passed: ${summary.passed}`);\n console.log(` Failed: ${summary.failed}`);\n console.log(` New: ${summary.new}`);\n console.log(` Skipped: ${summary.skipped}`);\n console.log(` Total: ${summary.total}`);\n console.log(` Duration: ${(summary.duration / 1000).toFixed(2)}s\\n`);\n\n // Run a11y audits if requested\n if (options.a11y) {\n console.log(\" Running accessibility audits...\\n\");\n try {\n const { MuseaA11yRunner } = await import(\"../a11y/index.js\");\n const a11yRunner = new MuseaA11yRunner();\n const a11yResults = await a11yRunner.runAudits(artFiles, options.baseUrl, runner);\n const a11ySummary = a11yRunner.getSummary(a11yResults);\n\n console.log(\" A11y Results:\");\n console.log(\" -------------\");\n console.log(` Components: ${a11ySummary.totalComponents}`);\n console.log(` Variants: ${a11ySummary.totalVariants}`);\n console.log(` Violations: ${a11ySummary.totalViolations}`);\n console.log(` Critical: ${a11ySummary.criticalCount}`);\n console.log(` Serious: ${a11ySummary.seriousCount}\\n`);\n\n // Generate a11y report\n const reportDir = options.output;\n await fs.promises.mkdir(reportDir, { recursive: true });\n\n if (options.json) {\n const a11yJson = a11yRunner.generateJsonReport(a11yResults);\n const a11yPath = path.join(reportDir, \"a11y-report.json\");\n await fs.promises.writeFile(a11yPath, a11yJson);\n console.log(` A11y JSON report: ${a11yPath}\\n`);\n } else {\n const a11yHtml = a11yRunner.generateHtmlReport(a11yResults);\n const a11yPath = path.join(reportDir, \"a11y-report.html\");\n await fs.promises.writeFile(a11yPath, a11yHtml);\n console.log(` A11y HTML report: ${a11yPath}\\n`);\n }\n\n // CI mode - exit with error on critical/serious violations\n if (options.ci && (a11ySummary.criticalCount > 0 || a11ySummary.seriousCount > 0)) {\n console.log(\" CI mode: Accessibility violations found\\n\");\n process.exit(1);\n }\n } catch (e) {\n console.warn(\" A11y audits skipped:\", e instanceof Error ? e.message : String(e));\n console.warn(\" Make sure axe-core is installed: npm install axe-core\\n\");\n }\n }\n\n // Update baselines if requested\n if (options.update) {\n console.log(\" Updating baselines...\");\n const updated = await runner.updateBaselines(results);\n console.log(` Updated ${updated} baseline(s)\\n`);\n }\n\n // Generate VRT report\n const reportDir = options.output;\n await fs.promises.mkdir(reportDir, { recursive: true });\n\n if (options.json) {\n const jsonReport = generateVrtJsonReport(results, summary);\n const jsonPath = path.join(reportDir, \"vrt-report.json\");\n await fs.promises.writeFile(jsonPath, jsonReport);\n console.log(` JSON report: ${jsonPath}\\n`);\n } else {\n const htmlReport = generateVrtReport(results, summary);\n const htmlPath = path.join(reportDir, \"vrt-report.html\");\n await fs.promises.writeFile(htmlPath, htmlReport);\n console.log(` HTML report: ${htmlPath}\\n`);\n }\n\n // CI mode - exit with error if visual diffs or capture/runtime errors occurred.\n if (options.ci && hasCiBlockingVrtResult(summary)) {\n console.log(\" CI mode: Exiting with error due to failures\\n\");\n process.exit(1);\n }\n } finally {\n await runner.close();\n }\n}\n\nexport async function runApprove(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner(vrtOptions);\n\n try {\n console.log(\" Launching browser...\");\n await runner.init();\n\n console.log(\" Running tests to find diffs...\\n\");\n\n const results = await runner.runAllTests(artFiles, options.baseUrl);\n const failed = results.filter((r) => !r.passed && !r.error);\n\n if (failed.length === 0) {\n console.log(\" No failed tests to approve.\\n\");\n return;\n }\n\n const pattern = options.pattern;\n if (pattern) {\n console.log(` Approving snapshots matching: ${pattern}\\n`);\n } else {\n console.log(` Approving all ${failed.length} failed snapshot(s)...\\n`);\n }\n\n const approved = await runner.approveResults(results, pattern);\n console.log(` Approved ${approved} snapshot(s)\\n`);\n } finally {\n await runner.close();\n }\n}\n\nexport async function runClean(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner(vrtOptions);\n\n console.log(\" Scanning for orphaned snapshots...\\n\");\n\n const cleaned = await runner.cleanOrphans(artFiles);\n\n if (cleaned === 0) {\n console.log(\" No orphaned snapshots found.\\n\");\n } else {\n console.log(`\\n Cleaned ${cleaned} orphaned snapshot(s)\\n`);\n }\n}\n\nexport async function runGenerate(options: CliOptions): Promise<void> {\n if (!options.componentPath) {\n console.error(\" Error: Missing component path.\");\n console.error(\" Usage: musea-vrt generate <component.vue>\\n\");\n process.exit(1);\n }\n\n const componentPath = path.resolve(options.componentPath);\n if (isArtFileInput(componentPath)) {\n console.error(\n \" Error: musea-vrt generate expects a source .vue component, not a .art.vue file.\",\n );\n console.error(\" Pass the component file that the art file should wrap.\\n\");\n process.exit(1);\n }\n\n // Check file exists\n try {\n await fs.promises.access(componentPath);\n } catch {\n console.error(` Error: File not found: ${componentPath}\\n`);\n process.exit(1);\n }\n\n console.log(` Generating art file for: ${path.relative(process.cwd(), componentPath)}\\n`);\n\n try {\n const { writeArtFile } = await import(\"../autogen/index.js\");\n const outputPath = await writeArtFile(componentPath);\n const relOutput = path.relative(process.cwd(), outputPath);\n\n console.log(` Generated: ${relOutput}\\n`);\n } catch (e) {\n console.error(\" Generation failed:\", e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n}\n","#!/usr/bin/env node\n/**\n * Musea CLI\n *\n * Usage:\n * musea-vrt [command] [options]\n *\n * Commands:\n * (default) Run VRT tests\n * approve [pat] Approve failed snapshots (optionally filtered by pattern)\n * clean Remove orphaned snapshots\n *\n * Options:\n * -u, --update Update baseline snapshots\n * -c, --config Path to vite config (default: vite.config.ts)\n * -o, --output Output directory for reports (default: .vize)\n * -t, --threshold Diff threshold percentage (default: 0.1)\n * --json Output JSON report instead of HTML\n * --ci CI mode - exit with non-zero code on failures\n * --a11y Run accessibility audits alongside VRT\n * -h, --help Show help\n */\n\nimport type { ArtFileInfo } from \"../types/index.js\";\nimport { scanArtFiles, parseArtFile } from \"./utils.js\";\nimport { runVrt, runApprove, runClean, runGenerate } from \"./commands.js\";\n\ntype Command = \"run\" | \"approve\" | \"clean\" | \"generate\";\n\nexport interface CliOptions {\n command: Command;\n update: boolean;\n config: string;\n output: string;\n threshold: number;\n json: boolean;\n ci: boolean;\n a11y: boolean;\n help: boolean;\n baseUrl: string;\n pattern?: string;\n componentPath?: string;\n}\n\nfunction parseArgs(args: string[]): CliOptions {\n const options: CliOptions = {\n command: \"run\",\n update: false,\n config: \"vite.config.ts\",\n output: \".vize\",\n threshold: 0.1,\n json: false,\n ci: false,\n a11y: false,\n help: false,\n baseUrl: \"http://localhost:5173\",\n };\n\n let i = 0;\n\n // Check for subcommand as first arg\n if (args.length > 0 && !args[0].startsWith(\"-\")) {\n const sub = args[0];\n if (sub === \"approve\") {\n options.command = \"approve\";\n i = 1;\n // Optional pattern argument after approve\n if (args.length > 1 && !args[1].startsWith(\"-\")) {\n options.pattern = args[1];\n i = 2;\n }\n } else if (sub === \"clean\") {\n options.command = \"clean\";\n i = 1;\n } else if (sub === \"generate\") {\n options.command = \"generate\";\n i = 1;\n // Required component path argument\n if (args.length > 1 && !args[1].startsWith(\"-\")) {\n options.componentPath = args[1];\n i = 2;\n }\n }\n }\n\n for (; i < args.length; i++) {\n const arg = args[i];\n switch (arg) {\n case \"-u\":\n case \"--update\":\n options.update = true;\n break;\n case \"-c\":\n case \"--config\":\n options.config = args[++i] || \"vite.config.ts\";\n break;\n case \"-o\":\n case \"--output\":\n options.output = args[++i] || \".vize\";\n break;\n case \"-t\":\n case \"--threshold\":\n options.threshold = parseFloat(args[++i]) || 0.1;\n break;\n case \"--json\":\n options.json = true;\n break;\n case \"--ci\":\n options.ci = true;\n break;\n case \"--a11y\":\n options.a11y = true;\n break;\n case \"-b\":\n case \"--base-url\":\n options.baseUrl = args[++i] || \"http://localhost:5173\";\n break;\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n console.log(`\nMusea VRT - Visual Regression Testing for Component Gallery\n\nUsage:\n musea-vrt [command] [options]\n\nCommands:\n (default) Run VRT tests\n approve [pattern] Approve failed snapshots and update baselines\n Optional pattern filters which snapshots to approve\n clean Remove orphaned snapshots (no matching art/variant)\n generate <component> Auto-generate .art.vue from a Vue component\n\nOptions:\n -u, --update Update baseline snapshots with current screenshots\n -c, --config <path> Path to vite config file (default: vite.config.ts)\n -o, --output <dir> Output directory for reports (default: .vize)\n -t, --threshold <n> Diff threshold percentage (default: 0.1)\n -b, --base-url <url> Base URL for dev server (default: http://localhost:5173)\n --json Output JSON report instead of HTML\n --ci CI mode - exit with non-zero code on failures\n --a11y Run accessibility audits alongside VRT\n -h, --help Show this help message\n\nExamples:\n # Run VRT tests\n musea-vrt\n\n # Update baseline snapshots\n musea-vrt -u\n\n # Run with custom threshold\n musea-vrt -t 0.5\n\n # CI mode with JSON output\n musea-vrt --ci --json\n\n # Run with accessibility audits\n musea-vrt --a11y\n\n # Approve all failed snapshots\n musea-vrt approve\n\n # Approve specific snapshots by pattern\n musea-vrt approve \"Button/*\"\n\n # Clean orphaned snapshots\n musea-vrt clean\n\n # Auto-generate .art.vue from component\n musea-vrt generate src/components/Button.vue\n\n # Custom base URL\n musea-vrt -b http://localhost:3000\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const options = parseArgs(args);\n\n if (options.help) {\n printHelp();\n process.exit(0);\n }\n\n const cwd = process.cwd();\n\n console.log(\"\\n Musea VRT\");\n console.log(\" =========\\n\");\n\n // Handle generate command early (doesn't need art file scanning)\n if (options.command === \"generate\") {\n try {\n await runGenerate(options);\n } catch (error) {\n console.error(\"\\n Error:\", error);\n process.exit(1);\n }\n return;\n }\n\n // Scan for art files\n console.log(\" Scanning for art files...\");\n const artFilePaths = await scanArtFiles(cwd);\n\n if (artFilePaths.length === 0) {\n console.log(\" No art files found.\\n\");\n process.exit(0);\n }\n\n console.log(` Found ${artFilePaths.length} art file(s)\\n`);\n\n // Parse art files\n const artFiles: ArtFileInfo[] = [];\n for (const filePath of artFilePaths) {\n const art = await parseArtFile(filePath);\n if (art) {\n artFiles.push(art);\n }\n }\n\n try {\n switch (options.command) {\n case \"run\":\n await runVrt(options, artFiles);\n break;\n case \"approve\":\n await runApprove(options, artFiles);\n break;\n case \"clean\":\n await runClean(options, artFiles);\n break;\n case \"generate\":\n // Handled above before art file scanning\n break;\n }\n } catch (error) {\n console.error(\"\\n Error:\", error);\n process.exit(1);\n }\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/cli/utils.ts","../../src/cli/commands.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * CLI utility functions for art file scanning and parsing.\n *\n * Extracted from cli.ts to keep file sizes manageable.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { processMuseaArtFile } from \"../plugin/art-processing.js\";\nimport type { ArtFileInfo } from \"../types/index.js\";\n\n/** Recursively scan a directory for .art.vue files. */\nexport async function scanArtFiles(root: string): Promise<string[]> {\n const files: string[] = [];\n\n async function scan(dir: string): Promise<void> {\n let entries: fs.Dirent[];\n try {\n entries = await fs.promises.readdir(dir, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EACCES\") {\n return;\n }\n throw error;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n // Skip node_modules and dist\n if (entry.name === \"node_modules\" || entry.name === \"dist\") {\n continue;\n }\n\n if (entry.isDirectory()) {\n await scan(fullPath);\n } else if (entry.isFile() && entry.name.endsWith(\".art.vue\")) {\n files.push(fullPath);\n }\n }\n }\n\n await scan(root);\n return files;\n}\n\n/** Parse a single .art.vue file into an ArtFileInfo structure. */\nexport async function parseArtFile(filePath: string): Promise<ArtFileInfo | null> {\n return processMuseaArtFile(filePath, {\n root: path.dirname(filePath),\n command: \"serve\",\n });\n}\n","/**\n * CLI command handlers for the Musea VRT tool.\n *\n * Extracted from cli.ts to keep file sizes manageable.\n * Contains the runVrt, runApprove, runClean, and runGenerate command implementations.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { MuseaVrtRunner, generateVrtReport, generateVrtJsonReport } from \"../vrt.js\";\nimport type { VrtSummary } from \"../vrt.js\";\nimport type { ArtFileInfo, VrtOptions } from \"../types/index.js\";\n\nimport type { CliOptions } from \"./index.js\";\n\nexport function hasCiBlockingVrtResult(summary: VrtSummary): boolean {\n return summary.failed > 0 || summary.skipped > 0;\n}\n\nexport function isArtFileInput(filePath: string): boolean {\n return filePath.endsWith(\".art.vue\");\n}\n\nexport async function runVrt(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const totalVariants = artFiles.reduce(\n (sum, art) => sum + art.variants.filter((v) => !v.skipVrt).length,\n 0,\n );\n\n console.log(` Testing ${totalVariants} variant(s) across ${artFiles.length} art file(s)\\n`);\n\n // Initialize VRT runner\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner({\n ...vrtOptions,\n ci: options.ci ? { failOnDiff: true, jsonReport: options.json } : undefined,\n });\n\n try {\n console.log(\" Launching browser...\");\n await runner.init();\n\n console.log(\" Running visual regression tests...\\n\");\n\n // Run tests\n const results = await runner.runAllTests(artFiles, options.baseUrl);\n const summary = runner.getSummary(results);\n\n // Print results\n console.log(\" Results:\");\n console.log(\" ---------\");\n console.log(` Passed: ${summary.passed}`);\n console.log(` Failed: ${summary.failed}`);\n console.log(` New: ${summary.new}`);\n console.log(` Skipped: ${summary.skipped}`);\n console.log(` Total: ${summary.total}`);\n console.log(` Duration: ${(summary.duration / 1000).toFixed(2)}s\\n`);\n\n // Run a11y audits if requested\n if (options.a11y) {\n console.log(\" Running accessibility audits...\\n\");\n try {\n const { MuseaA11yRunner } = await import(\"../a11y/index.js\");\n const a11yRunner = new MuseaA11yRunner();\n const a11yResults = await a11yRunner.runAudits(artFiles, options.baseUrl, runner);\n const a11ySummary = a11yRunner.getSummary(a11yResults);\n\n console.log(\" A11y Results:\");\n console.log(\" -------------\");\n console.log(` Components: ${a11ySummary.totalComponents}`);\n console.log(` Variants: ${a11ySummary.totalVariants}`);\n console.log(` Violations: ${a11ySummary.totalViolations}`);\n console.log(` Critical: ${a11ySummary.criticalCount}`);\n console.log(` Serious: ${a11ySummary.seriousCount}\\n`);\n\n // Generate a11y report\n const reportDir = options.output;\n await fs.promises.mkdir(reportDir, { recursive: true });\n\n if (options.json) {\n const a11yJson = a11yRunner.generateJsonReport(a11yResults);\n const a11yPath = path.join(reportDir, \"a11y-report.json\");\n await fs.promises.writeFile(a11yPath, a11yJson);\n console.log(` A11y JSON report: ${a11yPath}\\n`);\n } else {\n const a11yHtml = a11yRunner.generateHtmlReport(a11yResults);\n const a11yPath = path.join(reportDir, \"a11y-report.html\");\n await fs.promises.writeFile(a11yPath, a11yHtml);\n console.log(` A11y HTML report: ${a11yPath}\\n`);\n }\n\n // CI mode - exit with error on critical/serious violations\n if (options.ci && (a11ySummary.criticalCount > 0 || a11ySummary.seriousCount > 0)) {\n console.log(\" CI mode: Accessibility violations found\\n\");\n process.exit(1);\n }\n } catch (e) {\n console.warn(\" A11y audits skipped:\", e instanceof Error ? e.message : String(e));\n console.warn(\" Make sure axe-core is installed: npm install axe-core\\n\");\n }\n }\n\n // Update baselines if requested\n if (options.update) {\n console.log(\" Updating baselines...\");\n const updated = await runner.updateBaselines(results);\n console.log(` Updated ${updated} baseline(s)\\n`);\n }\n\n // Generate VRT report\n const reportDir = options.output;\n await fs.promises.mkdir(reportDir, { recursive: true });\n\n if (options.json) {\n const jsonReport = generateVrtJsonReport(results, summary);\n const jsonPath = path.join(reportDir, \"vrt-report.json\");\n await fs.promises.writeFile(jsonPath, jsonReport);\n console.log(` JSON report: ${jsonPath}\\n`);\n } else {\n const htmlReport = generateVrtReport(results, summary);\n const htmlPath = path.join(reportDir, \"vrt-report.html\");\n await fs.promises.writeFile(htmlPath, htmlReport);\n console.log(` HTML report: ${htmlPath}\\n`);\n }\n\n // CI mode - exit with error if visual diffs or capture/runtime errors occurred.\n if (options.ci && hasCiBlockingVrtResult(summary)) {\n console.log(\" CI mode: Exiting with error due to failures\\n\");\n process.exit(1);\n }\n } finally {\n await runner.close();\n }\n}\n\nexport async function runApprove(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner(vrtOptions);\n\n try {\n console.log(\" Launching browser...\");\n await runner.init();\n\n console.log(\" Running tests to find diffs...\\n\");\n\n const results = await runner.runAllTests(artFiles, options.baseUrl);\n const failed = results.filter((r) => !r.passed && !r.error);\n\n if (failed.length === 0) {\n console.log(\" No failed tests to approve.\\n\");\n return;\n }\n\n const pattern = options.pattern;\n if (pattern) {\n console.log(` Approving snapshots matching: ${pattern}\\n`);\n } else {\n console.log(` Approving all ${failed.length} failed snapshot(s)...\\n`);\n }\n\n const approved = await runner.approveResults(results, pattern);\n console.log(` Approved ${approved} snapshot(s)\\n`);\n } finally {\n await runner.close();\n }\n}\n\nexport async function runClean(options: CliOptions, artFiles: ArtFileInfo[]): Promise<void> {\n const vrtOptions: VrtOptions = {\n snapshotDir: path.join(options.output, \"snapshots\"),\n threshold: options.threshold,\n };\n\n const runner = new MuseaVrtRunner(vrtOptions);\n\n console.log(\" Scanning for orphaned snapshots...\\n\");\n\n const cleaned = await runner.cleanOrphans(artFiles);\n\n if (cleaned === 0) {\n console.log(\" No orphaned snapshots found.\\n\");\n } else {\n console.log(`\\n Cleaned ${cleaned} orphaned snapshot(s)\\n`);\n }\n}\n\nexport async function runGenerate(options: CliOptions): Promise<void> {\n if (!options.componentPath) {\n console.error(\" Error: Missing component path.\");\n console.error(\" Usage: musea-vrt generate <component.vue>\\n\");\n process.exit(1);\n }\n\n const componentPath = path.resolve(options.componentPath);\n if (isArtFileInput(componentPath)) {\n console.error(\n \" Error: musea-vrt generate expects a source .vue component, not a .art.vue file.\",\n );\n console.error(\" Pass the component file that the art file should wrap.\\n\");\n process.exit(1);\n }\n\n // Check file exists\n try {\n await fs.promises.access(componentPath);\n } catch {\n console.error(` Error: File not found: ${componentPath}\\n`);\n process.exit(1);\n }\n\n console.log(` Generating art file for: ${path.relative(process.cwd(), componentPath)}\\n`);\n\n try {\n const { writeArtFile } = await import(\"../autogen/index.js\");\n const outputPath = await writeArtFile(componentPath);\n const relOutput = path.relative(process.cwd(), outputPath);\n\n console.log(` Generated: ${relOutput}\\n`);\n } catch (e) {\n console.error(\" Generation failed:\", e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n}\n","#!/usr/bin/env node\n/**\n * Musea CLI\n *\n * Usage:\n * musea-vrt [command] [options]\n *\n * Commands:\n * (default) Run VRT tests\n * approve [pat] Approve failed snapshots (optionally filtered by pattern)\n * clean Remove orphaned snapshots\n *\n * Options:\n * -u, --update Update baseline snapshots\n * -c, --config Path to vite config (default: vite.config.ts)\n * -o, --output Output directory for reports (default: .vize)\n * -t, --threshold Diff threshold percentage (default: 0.1)\n * --json Output JSON report instead of HTML\n * --ci CI mode - exit with non-zero code on failures\n * --a11y Run accessibility audits alongside VRT\n * -h, --help Show help\n */\n\nimport type { ArtFileInfo } from \"../types/index.js\";\nimport { scanArtFiles, parseArtFile } from \"./utils.js\";\nimport { runVrt, runApprove, runClean, runGenerate } from \"./commands.js\";\n\ntype Command = \"run\" | \"approve\" | \"clean\" | \"generate\";\n\nexport interface CliOptions {\n command: Command;\n update: boolean;\n config: string;\n output: string;\n threshold: number;\n json: boolean;\n ci: boolean;\n a11y: boolean;\n help: boolean;\n baseUrl: string;\n pattern?: string;\n componentPath?: string;\n}\n\nfunction parseArgs(args: string[]): CliOptions {\n const options: CliOptions = {\n command: \"run\",\n update: false,\n config: \"vite.config.ts\",\n output: \".vize\",\n threshold: 0.1,\n json: false,\n ci: false,\n a11y: false,\n help: false,\n baseUrl: \"http://localhost:5173\",\n };\n\n let i = 0;\n\n // Check for subcommand as first arg\n if (args.length > 0 && !args[0].startsWith(\"-\")) {\n const sub = args[0];\n if (sub === \"approve\") {\n options.command = \"approve\";\n i = 1;\n // Optional pattern argument after approve\n if (args.length > 1 && !args[1].startsWith(\"-\")) {\n options.pattern = args[1];\n i = 2;\n }\n } else if (sub === \"clean\") {\n options.command = \"clean\";\n i = 1;\n } else if (sub === \"generate\") {\n options.command = \"generate\";\n i = 1;\n // Required component path argument\n if (args.length > 1 && !args[1].startsWith(\"-\")) {\n options.componentPath = args[1];\n i = 2;\n }\n }\n }\n\n for (; i < args.length; i++) {\n const arg = args[i];\n switch (arg) {\n case \"-u\":\n case \"--update\":\n options.update = true;\n break;\n case \"-c\":\n case \"--config\":\n options.config = args[++i] || \"vite.config.ts\";\n break;\n case \"-o\":\n case \"--output\":\n options.output = args[++i] || \".vize\";\n break;\n case \"-t\":\n case \"--threshold\":\n options.threshold = parseFloat(args[++i]) || 0.1;\n break;\n case \"--json\":\n options.json = true;\n break;\n case \"--ci\":\n options.ci = true;\n break;\n case \"--a11y\":\n options.a11y = true;\n break;\n case \"-b\":\n case \"--base-url\":\n options.baseUrl = args[++i] || \"http://localhost:5173\";\n break;\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n console.log(`\nMusea VRT - Visual Regression Testing for Component Gallery\n\nUsage:\n musea-vrt [command] [options]\n\nCommands:\n (default) Run VRT tests\n approve [pattern] Approve failed snapshots and update baselines\n Optional pattern filters which snapshots to approve\n clean Remove orphaned snapshots (no matching art/variant)\n generate <component> Auto-generate .art.vue from a Vue component\n\nOptions:\n -u, --update Update baseline snapshots with current screenshots\n -c, --config <path> Path to vite config file (default: vite.config.ts)\n -o, --output <dir> Output directory for reports (default: .vize)\n -t, --threshold <n> Diff threshold percentage (default: 0.1)\n -b, --base-url <url> Base URL for dev server (default: http://localhost:5173)\n --json Output JSON report instead of HTML\n --ci CI mode - exit with non-zero code on failures\n --a11y Run accessibility audits alongside VRT\n -h, --help Show this help message\n\nExamples:\n # Run VRT tests\n musea-vrt\n\n # Update baseline snapshots\n musea-vrt -u\n\n # Run with custom threshold\n musea-vrt -t 0.5\n\n # CI mode with JSON output\n musea-vrt --ci --json\n\n # Run with accessibility audits\n musea-vrt --a11y\n\n # Approve all failed snapshots\n musea-vrt approve\n\n # Approve specific snapshots by pattern\n musea-vrt approve \"Button/*\"\n\n # Clean orphaned snapshots\n musea-vrt clean\n\n # Auto-generate .art.vue from component\n musea-vrt generate src/components/Button.vue\n\n # Custom base URL\n musea-vrt -b http://localhost:3000\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const options = parseArgs(args);\n\n if (options.help) {\n printHelp();\n process.exit(0);\n }\n\n const cwd = process.cwd();\n\n console.log(\"\\n Musea VRT\");\n console.log(\" =========\\n\");\n\n // Handle generate command early (doesn't need art file scanning)\n if (options.command === \"generate\") {\n try {\n await runGenerate(options);\n } catch (error) {\n console.error(\"\\n Error:\", error);\n process.exit(1);\n }\n return;\n }\n\n // Scan for art files\n console.log(\" Scanning for art files...\");\n const artFilePaths = await scanArtFiles(cwd);\n\n if (artFilePaths.length === 0) {\n console.log(\" No art files found.\\n\");\n process.exit(0);\n }\n\n console.log(` Found ${artFilePaths.length} art file(s)\\n`);\n\n // Parse art files\n const artFiles: ArtFileInfo[] = [];\n for (const filePath of artFilePaths) {\n const art = await parseArtFile(filePath);\n if (art) {\n artFiles.push(art);\n }\n }\n\n try {\n switch (options.command) {\n case \"run\":\n await runVrt(options, artFiles);\n break;\n case \"approve\":\n await runApprove(options, artFiles);\n break;\n case \"clean\":\n await runClean(options, artFiles);\n break;\n case \"generate\":\n // Handled above before art file scanning\n break;\n }\n } catch (error) {\n console.error(\"\\n Error:\", error);\n process.exit(1);\n }\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as generateGalleryGlobalsScript, n as generateGalleryScript, t as generateGalleryBody } from "./template-
|
|
1
|
+
import { a as generateGalleryGlobalsScript, n as generateGalleryScript, t as generateGalleryBody } from "./template-CrnwdQfB.mjs";
|
|
2
2
|
//#region src/gallery/styles-base.css?inline
|
|
3
3
|
var styles_base_default = ":root {\n --musea-bg-primary: #e6e2d6;\n --musea-bg-secondary: #ddd9cd;\n --musea-bg-tertiary: #d4d0c4;\n --musea-bg-elevated: #e6e2d6;\n --musea-accent: #121212;\n --musea-accent-hover: #2a2a2a;\n --musea-accent-subtle: #12121214;\n --musea-text: #121212;\n --musea-text-secondary: #3a3a3a;\n --musea-text-muted: #6b6b6b;\n --musea-border: #c8c4b8;\n --musea-border-subtle: #d4d0c4;\n --musea-success: #16a34a;\n --musea-shadow: 0 4px 24px #00000014;\n --musea-radius-sm: 4px;\n --musea-radius-md: 6px;\n --musea-radius-lg: 8px;\n --musea-transition: .15s ease;\n}\n\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\nbody {\n background: var(--musea-bg-primary);\n color: var(--musea-text);\n -webkit-font-smoothing: antialiased;\n min-height: 100vh;\n font-family: Helvetica Neue, Helvetica, Arial, sans-serif;\n line-height: 1.5;\n}\n";
|
|
4
4
|
//#endregion
|
|
@@ -58,4 +58,4 @@ function generateGalleryHtml(basePath, devSessionToken, themeConfig, tokenPrevie
|
|
|
58
58
|
//#endregion
|
|
59
59
|
export { generateGalleryHtml };
|
|
60
60
|
|
|
61
|
-
//# sourceMappingURL=gallery-
|
|
61
|
+
//# sourceMappingURL=gallery-BWCgs-NF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallery-3Sqabvai.mjs","names":["stylesBase","stylesLayout","stylesComponents"],"sources":["../src/gallery/styles-base.css?inline","../src/gallery/styles-layout.css?inline","../src/gallery/styles-components.css?inline","../src/gallery/styles.ts","../src/gallery/index.ts"],"sourcesContent":[":root {\n --musea-bg-primary: #e6e2d6;\n --musea-bg-secondary: #ddd9cd;\n --musea-bg-tertiary: #d4d0c4;\n --musea-bg-elevated: #e6e2d6;\n --musea-accent: #121212;\n --musea-accent-hover: #2a2a2a;\n --musea-accent-subtle: rgba(18, 18, 18, 0.08);\n --musea-text: #121212;\n --musea-text-secondary: #3a3a3a;\n --musea-text-muted: #6b6b6b;\n --musea-border: #c8c4b8;\n --musea-border-subtle: #d4d0c4;\n --musea-success: #16a34a;\n --musea-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);\n --musea-radius-sm: 4px;\n --musea-radius-md: 6px;\n --musea-radius-lg: 8px;\n --musea-transition: 0.15s ease;\n}\n\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n background: var(--musea-bg-primary);\n color: var(--musea-text);\n min-height: 100vh;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n","/* Header */\n.header {\n background: var(--musea-bg-secondary);\n border-bottom: 1px solid var(--musea-border);\n padding: 0 1.5rem;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n}\n\n.logo {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1.125rem;\n font-weight: 700;\n color: var(--musea-accent);\n text-decoration: none;\n}\n\n.logo-svg {\n width: 32px;\n height: 32px;\n flex-shrink: 0;\n}\n\n.logo-icon svg {\n width: 16px;\n height: 16px;\n color: var(--musea-text);\n}\n\n.header-subtitle {\n color: var(--musea-text-muted);\n font-size: 0.8125rem;\n font-weight: 500;\n padding-left: 1.5rem;\n border-left: 1px solid var(--musea-border);\n}\n\n.search-container {\n position: relative;\n width: 280px;\n}\n\n.search-input {\n width: 100%;\n background: var(--musea-bg-tertiary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-md);\n padding: 0.5rem 0.75rem 0.5rem 2.25rem;\n color: var(--musea-text);\n font-size: 0.8125rem;\n outline: none;\n transition:\n border-color var(--musea-transition),\n background var(--musea-transition);\n}\n\n.search-input::placeholder {\n color: var(--musea-text-muted);\n}\n\n.search-input:focus {\n border-color: var(--musea-accent);\n background: var(--musea-bg-elevated);\n}\n\n.search-icon {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--musea-text-muted);\n pointer-events: none;\n}\n\n/* Layout */\n.main {\n display: grid;\n grid-template-columns: 260px 1fr;\n min-height: calc(100vh - 56px);\n}\n\n/* Sidebar */\n.sidebar {\n background: var(--musea-bg-secondary);\n border-right: 1px solid var(--musea-border);\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.sidebar::-webkit-scrollbar {\n width: 6px;\n}\n\n.sidebar::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sidebar::-webkit-scrollbar-thumb {\n background: var(--musea-border);\n border-radius: 3px;\n}\n\n.sidebar-section {\n padding: 0.75rem;\n}\n\n.category-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.625rem 0.75rem;\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--musea-text-muted);\n cursor: pointer;\n user-select: none;\n border-radius: var(--musea-radius-sm);\n transition: background var(--musea-transition);\n}\n\n.category-header:hover {\n background: var(--musea-bg-tertiary);\n}\n\n.category-icon {\n width: 16px;\n height: 16px;\n transition: transform var(--musea-transition);\n}\n\n.category-header.collapsed .category-icon {\n transform: rotate(-90deg);\n}\n\n.category-count {\n margin-left: auto;\n background: var(--musea-bg-tertiary);\n padding: 0.125rem 0.375rem;\n border-radius: 4px;\n font-size: 0.625rem;\n}\n\n.art-list {\n list-style: none;\n margin-top: 0.25rem;\n}\n\n.art-item {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.5rem 0.75rem 0.5rem 1.75rem;\n border-radius: var(--musea-radius-sm);\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--musea-text-secondary);\n transition: all var(--musea-transition);\n position: relative;\n}\n\n.art-item::before {\n content: \"\";\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--musea-border);\n transition: background var(--musea-transition);\n}\n\n.art-item:hover {\n background: var(--musea-bg-tertiary);\n color: var(--musea-text);\n}\n\n.art-item:hover::before {\n background: var(--musea-text-muted);\n}\n\n.art-item.active {\n background: var(--musea-accent-subtle);\n color: var(--musea-accent-hover);\n}\n\n.art-item.active::before {\n background: var(--musea-accent);\n}\n\n.art-variant-count {\n margin-left: auto;\n font-size: 0.6875rem;\n color: var(--musea-text-muted);\n opacity: 0;\n transition: opacity var(--musea-transition);\n}\n\n.art-item:hover .art-variant-count {\n opacity: 1;\n}\n\n/* Content */\n.content {\n background: var(--musea-bg-primary);\n overflow-y: auto;\n}\n\n.content-inner {\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.content-header {\n margin-bottom: 2rem;\n}\n\n.content-title {\n font-size: 1.5rem;\n font-weight: 700;\n margin-bottom: 0.5rem;\n}\n\n.content-description {\n color: var(--musea-text-muted);\n font-size: 0.9375rem;\n max-width: 600px;\n}\n\n.content-meta {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-top: 1rem;\n}\n\n.meta-tag {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.625rem;\n background: var(--musea-bg-secondary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-sm);\n font-size: 0.75rem;\n color: var(--musea-text-muted);\n}\n\n.meta-tag svg {\n width: 12px;\n height: 12px;\n}\n","/* Gallery Grid */\n.gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 1.25rem;\n}\n\n/* Variant Card */\n.variant-card {\n background: var(--musea-bg-secondary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-lg);\n overflow: hidden;\n}\n\n.variant-preview {\n aspect-ratio: 16 / 7;\n background: var(--musea-bg-tertiary);\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n}\n\n.variant-preview iframe {\n width: 70%;\n height: 100%;\n max-width: 100%;\n max-height: 100%;\n border: none;\n background: white;\n border-radius: var(--musea-radius-md);\n box-shadow: 0 12px 30px rgba(13, 13, 13, 0.12);\n}\n\n.variant-preview-placeholder {\n color: var(--musea-text-muted);\n font-size: 0.8125rem;\n text-align: center;\n padding: 1rem;\n}\n\n.variant-preview-code {\n font-family: \"JetBrains Mono\", \"SF Mono\", \"Fira Code\", monospace;\n font-size: 0.75rem;\n color: var(--musea-text-muted);\n background: var(--musea-bg-primary);\n padding: 1rem;\n overflow: auto;\n max-height: 100%;\n width: 100%;\n}\n\n.variant-info {\n padding: 1rem;\n border-top: 1px solid var(--musea-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.variant-name {\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.variant-badge {\n font-size: 0.625rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 0.1875rem 0.5rem;\n border-radius: 4px;\n background: var(--musea-accent-subtle);\n color: var(--musea-accent);\n}\n\n.variant-actions {\n display: flex;\n gap: 0.5rem;\n}\n\n.variant-action-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: var(--musea-bg-tertiary);\n border-radius: var(--musea-radius-sm);\n color: var(--musea-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--musea-transition);\n}\n\n.variant-action-btn:hover {\n background: var(--musea-bg-elevated);\n color: var(--musea-text);\n}\n\n.variant-action-btn svg {\n width: 14px;\n height: 14px;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n text-align: center;\n padding: 2rem;\n}\n\n.empty-state-icon {\n width: 80px;\n height: 80px;\n background: var(--musea-bg-secondary);\n border-radius: var(--musea-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 1.5rem;\n}\n\n.empty-state-icon svg {\n width: 40px;\n height: 40px;\n color: var(--musea-text-muted);\n}\n\n.empty-state-title {\n font-size: 1.125rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n}\n\n.empty-state-text {\n color: var(--musea-text-muted);\n font-size: 0.875rem;\n max-width: 300px;\n}\n\n/* Loading */\n.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n color: var(--musea-text-muted);\n gap: 0.75rem;\n}\n\n.loading-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--musea-border);\n border-top-color: var(--musea-accent);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .main {\n grid-template-columns: 1fr;\n }\n .sidebar {\n display: none;\n }\n .header-subtitle {\n display: none;\n }\n}\n","/**\n * CSS theme variables and style definitions for the Musea gallery.\n *\n * CSS is split into separate .css files and imported as text\n * via tsdown's `?inline` support.\n */\n\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesBase from \"./styles-base.css?inline\";\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesLayout from \"./styles-layout.css?inline\";\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesComponents from \"./styles-components.css?inline\";\n\n/**\n * Generate the full gallery CSS styles string.\n */\nexport function generateGalleryStyles(): string {\n return `${stylesBase}\\n${stylesLayout}\\n${stylesComponents}`;\n}\n","/**\n * Gallery HTML generation for the Musea component gallery.\n *\n * Contains the inline gallery SPA template (used as a fallback when the\n * pre-built gallery is not available) and the gallery virtual module.\n */\n\nimport { generateGalleryStyles } from \"./styles.js\";\nimport { generateGalleryBody, generateGalleryScript } from \"./template.js\";\nimport { generateGalleryGlobalsScript } from \"./globals.js\";\nimport type { MuseaTokenPreviewConfig } from \"../tokens/preview.js\";\n\nexport { generateGalleryModule } from \"./module.js\";\n\n/**\n * Generate the inline gallery HTML page.\n */\nexport function generateGalleryHtml(\n basePath: string,\n devSessionToken: string,\n themeConfig?: { default: string; custom?: Record<string, unknown> },\n tokenPreviewConfig?: MuseaTokenPreviewConfig,\n): string {\n const globalsScript = generateGalleryGlobalsScript({\n basePath,\n devSessionToken,\n themeConfig,\n tokenPreviewConfig,\n });\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Musea - Component Gallery</title>\n <script>${globalsScript}${\"<\"}/script>\n <style>${generateGalleryStyles()}\n </style>\n</head>\n<body>${generateGalleryBody(basePath)}\n\n <script type=\"module\">${generateGalleryScript(basePath)}\n </script>\n</body>\n</html>`;\n}\n"],"mappings":";;AAAA,IAAA,sBAAM;;;ACAN,IAAA,wBAAG;;;ACAH,IAAA,4BAAG;;;;;;;;;;;;ACiBH,SAAgB,wBAAgC;CAC9C,OAAO,GAAGA,oBAAW,IAAIC,sBAAa,IAAIC;AAC5C;;;;;;;;;;;;ACFA,SAAgB,oBACd,UACA,iBACA,aACA,oBACQ;CAOR,OAAO;;;;;;YANe,6BAA6B;EACjD;EACA;EACA;EACA;CACF,CAOsB,EAAA;WACb,sBAAsB,EAAE;;;QAG3B,oBAAoB,QAAQ,EAAE;;0BAEZ,sBAAsB,QAAQ,EAAE;;;;AAI1D"}
|
|
1
|
+
{"version":3,"file":"gallery-BWCgs-NF.mjs","names":["stylesBase","stylesLayout","stylesComponents"],"sources":["../src/gallery/styles-base.css?inline","../src/gallery/styles-layout.css?inline","../src/gallery/styles-components.css?inline","../src/gallery/styles.ts","../src/gallery/index.ts"],"sourcesContent":[":root {\n --musea-bg-primary: #e6e2d6;\n --musea-bg-secondary: #ddd9cd;\n --musea-bg-tertiary: #d4d0c4;\n --musea-bg-elevated: #e6e2d6;\n --musea-accent: #121212;\n --musea-accent-hover: #2a2a2a;\n --musea-accent-subtle: rgba(18, 18, 18, 0.08);\n --musea-text: #121212;\n --musea-text-secondary: #3a3a3a;\n --musea-text-muted: #6b6b6b;\n --musea-border: #c8c4b8;\n --musea-border-subtle: #d4d0c4;\n --musea-success: #16a34a;\n --musea-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);\n --musea-radius-sm: 4px;\n --musea-radius-md: 6px;\n --musea-radius-lg: 8px;\n --musea-transition: 0.15s ease;\n}\n\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n background: var(--musea-bg-primary);\n color: var(--musea-text);\n min-height: 100vh;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n","/* Header */\n.header {\n background: var(--musea-bg-secondary);\n border-bottom: 1px solid var(--musea-border);\n padding: 0 1.5rem;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n}\n\n.logo {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1.125rem;\n font-weight: 700;\n color: var(--musea-accent);\n text-decoration: none;\n}\n\n.logo-svg {\n width: 32px;\n height: 32px;\n flex-shrink: 0;\n}\n\n.logo-icon svg {\n width: 16px;\n height: 16px;\n color: var(--musea-text);\n}\n\n.header-subtitle {\n color: var(--musea-text-muted);\n font-size: 0.8125rem;\n font-weight: 500;\n padding-left: 1.5rem;\n border-left: 1px solid var(--musea-border);\n}\n\n.search-container {\n position: relative;\n width: 280px;\n}\n\n.search-input {\n width: 100%;\n background: var(--musea-bg-tertiary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-md);\n padding: 0.5rem 0.75rem 0.5rem 2.25rem;\n color: var(--musea-text);\n font-size: 0.8125rem;\n outline: none;\n transition:\n border-color var(--musea-transition),\n background var(--musea-transition);\n}\n\n.search-input::placeholder {\n color: var(--musea-text-muted);\n}\n\n.search-input:focus {\n border-color: var(--musea-accent);\n background: var(--musea-bg-elevated);\n}\n\n.search-icon {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--musea-text-muted);\n pointer-events: none;\n}\n\n/* Layout */\n.main {\n display: grid;\n grid-template-columns: 260px 1fr;\n min-height: calc(100vh - 56px);\n}\n\n/* Sidebar */\n.sidebar {\n background: var(--musea-bg-secondary);\n border-right: 1px solid var(--musea-border);\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.sidebar::-webkit-scrollbar {\n width: 6px;\n}\n\n.sidebar::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sidebar::-webkit-scrollbar-thumb {\n background: var(--musea-border);\n border-radius: 3px;\n}\n\n.sidebar-section {\n padding: 0.75rem;\n}\n\n.category-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.625rem 0.75rem;\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--musea-text-muted);\n cursor: pointer;\n user-select: none;\n border-radius: var(--musea-radius-sm);\n transition: background var(--musea-transition);\n}\n\n.category-header:hover {\n background: var(--musea-bg-tertiary);\n}\n\n.category-icon {\n width: 16px;\n height: 16px;\n transition: transform var(--musea-transition);\n}\n\n.category-header.collapsed .category-icon {\n transform: rotate(-90deg);\n}\n\n.category-count {\n margin-left: auto;\n background: var(--musea-bg-tertiary);\n padding: 0.125rem 0.375rem;\n border-radius: 4px;\n font-size: 0.625rem;\n}\n\n.art-list {\n list-style: none;\n margin-top: 0.25rem;\n}\n\n.art-item {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.5rem 0.75rem 0.5rem 1.75rem;\n border-radius: var(--musea-radius-sm);\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--musea-text-secondary);\n transition: all var(--musea-transition);\n position: relative;\n}\n\n.art-item::before {\n content: \"\";\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--musea-border);\n transition: background var(--musea-transition);\n}\n\n.art-item:hover {\n background: var(--musea-bg-tertiary);\n color: var(--musea-text);\n}\n\n.art-item:hover::before {\n background: var(--musea-text-muted);\n}\n\n.art-item.active {\n background: var(--musea-accent-subtle);\n color: var(--musea-accent-hover);\n}\n\n.art-item.active::before {\n background: var(--musea-accent);\n}\n\n.art-variant-count {\n margin-left: auto;\n font-size: 0.6875rem;\n color: var(--musea-text-muted);\n opacity: 0;\n transition: opacity var(--musea-transition);\n}\n\n.art-item:hover .art-variant-count {\n opacity: 1;\n}\n\n/* Content */\n.content {\n background: var(--musea-bg-primary);\n overflow-y: auto;\n}\n\n.content-inner {\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.content-header {\n margin-bottom: 2rem;\n}\n\n.content-title {\n font-size: 1.5rem;\n font-weight: 700;\n margin-bottom: 0.5rem;\n}\n\n.content-description {\n color: var(--musea-text-muted);\n font-size: 0.9375rem;\n max-width: 600px;\n}\n\n.content-meta {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-top: 1rem;\n}\n\n.meta-tag {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.625rem;\n background: var(--musea-bg-secondary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-sm);\n font-size: 0.75rem;\n color: var(--musea-text-muted);\n}\n\n.meta-tag svg {\n width: 12px;\n height: 12px;\n}\n","/* Gallery Grid */\n.gallery {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 1.25rem;\n}\n\n/* Variant Card */\n.variant-card {\n background: var(--musea-bg-secondary);\n border: 1px solid var(--musea-border);\n border-radius: var(--musea-radius-lg);\n overflow: hidden;\n}\n\n.variant-preview {\n aspect-ratio: 16 / 7;\n background: var(--musea-bg-tertiary);\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n}\n\n.variant-preview iframe {\n width: 70%;\n height: 100%;\n max-width: 100%;\n max-height: 100%;\n border: none;\n background: white;\n border-radius: var(--musea-radius-md);\n box-shadow: 0 12px 30px rgba(13, 13, 13, 0.12);\n}\n\n.variant-preview-placeholder {\n color: var(--musea-text-muted);\n font-size: 0.8125rem;\n text-align: center;\n padding: 1rem;\n}\n\n.variant-preview-code {\n font-family: \"JetBrains Mono\", \"SF Mono\", \"Fira Code\", monospace;\n font-size: 0.75rem;\n color: var(--musea-text-muted);\n background: var(--musea-bg-primary);\n padding: 1rem;\n overflow: auto;\n max-height: 100%;\n width: 100%;\n}\n\n.variant-info {\n padding: 1rem;\n border-top: 1px solid var(--musea-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.variant-name {\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.variant-badge {\n font-size: 0.625rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 0.1875rem 0.5rem;\n border-radius: 4px;\n background: var(--musea-accent-subtle);\n color: var(--musea-accent);\n}\n\n.variant-actions {\n display: flex;\n gap: 0.5rem;\n}\n\n.variant-action-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: var(--musea-bg-tertiary);\n border-radius: var(--musea-radius-sm);\n color: var(--musea-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--musea-transition);\n}\n\n.variant-action-btn:hover {\n background: var(--musea-bg-elevated);\n color: var(--musea-text);\n}\n\n.variant-action-btn svg {\n width: 14px;\n height: 14px;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n text-align: center;\n padding: 2rem;\n}\n\n.empty-state-icon {\n width: 80px;\n height: 80px;\n background: var(--musea-bg-secondary);\n border-radius: var(--musea-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 1.5rem;\n}\n\n.empty-state-icon svg {\n width: 40px;\n height: 40px;\n color: var(--musea-text-muted);\n}\n\n.empty-state-title {\n font-size: 1.125rem;\n font-weight: 600;\n margin-bottom: 0.5rem;\n}\n\n.empty-state-text {\n color: var(--musea-text-muted);\n font-size: 0.875rem;\n max-width: 300px;\n}\n\n/* Loading */\n.loading {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n color: var(--musea-text-muted);\n gap: 0.75rem;\n}\n\n.loading-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--musea-border);\n border-top-color: var(--musea-accent);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .main {\n grid-template-columns: 1fr;\n }\n .sidebar {\n display: none;\n }\n .header-subtitle {\n display: none;\n }\n}\n","/**\n * CSS theme variables and style definitions for the Musea gallery.\n *\n * CSS is split into separate .css files and imported as text\n * via tsdown's `?inline` support.\n */\n\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesBase from \"./styles-base.css?inline\";\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesLayout from \"./styles-layout.css?inline\";\n// @ts-expect-error -- CSS imported as text via tsdown `?inline`\nimport stylesComponents from \"./styles-components.css?inline\";\n\n/**\n * Generate the full gallery CSS styles string.\n */\nexport function generateGalleryStyles(): string {\n return `${stylesBase}\\n${stylesLayout}\\n${stylesComponents}`;\n}\n","/**\n * Gallery HTML generation for the Musea component gallery.\n *\n * Contains the inline gallery SPA template (used as a fallback when the\n * pre-built gallery is not available) and the gallery virtual module.\n */\n\nimport { generateGalleryStyles } from \"./styles.js\";\nimport { generateGalleryBody, generateGalleryScript } from \"./template.js\";\nimport { generateGalleryGlobalsScript } from \"./globals.js\";\nimport type { MuseaTokenPreviewConfig } from \"../tokens/preview.js\";\n\nexport { generateGalleryModule } from \"./module.js\";\n\n/**\n * Generate the inline gallery HTML page.\n */\nexport function generateGalleryHtml(\n basePath: string,\n devSessionToken: string,\n themeConfig?: { default: string; custom?: Record<string, unknown> },\n tokenPreviewConfig?: MuseaTokenPreviewConfig,\n): string {\n const globalsScript = generateGalleryGlobalsScript({\n basePath,\n devSessionToken,\n themeConfig,\n tokenPreviewConfig,\n });\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Musea - Component Gallery</title>\n <script>${globalsScript}${\"<\"}/script>\n <style>${generateGalleryStyles()}\n </style>\n</head>\n<body>${generateGalleryBody(basePath)}\n\n <script type=\"module\">${generateGalleryScript(basePath)}\n </script>\n</body>\n</html>`;\n}\n"],"mappings":";;AAAA,IAAA,sBAAM;;;ACAN,IAAA,wBAAG;;;ACAH,IAAA,4BAAG;;;;;;;;;;;;ACiBH,SAAgB,wBAAgC;CAC9C,OAAO,GAAGA,oBAAW,IAAIC,sBAAa,IAAIC;AAC5C;;;;;;;;;;;;ACFA,SAAgB,oBACd,UACA,iBACA,aACA,oBACQ;CAOR,OAAO;;;;;;YANe,6BAA6B;EACjD;EACA;EACA;EACA;CACF,CAOsB,EAAA;WACb,sBAAsB,EAAE;;;QAG3B,oBAAoB,QAAQ,EAAE;;0BAEZ,sBAAsB,QAAQ,EAAE;;;;AAI1D"}
|
package/dist/index.d.mts
CHANGED
|
@@ -221,8 +221,10 @@ interface MuseaOptions {
|
|
|
221
221
|
* Useful for loading global styles (custom properties, resets, fonts, etc.)
|
|
222
222
|
* that components depend on.
|
|
223
223
|
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
224
|
+
* Project-relative and `./` paths resolve against the project root.
|
|
225
|
+
* Bare specifiers (`normalize.css`, `@fontsource/inter/index.css`) are
|
|
226
|
+
* left for Vite to resolve.
|
|
227
|
+
* @example ['app/assets/styles/main.css', 'normalize.css']
|
|
226
228
|
*/
|
|
227
229
|
previewCss?: string[];
|
|
228
230
|
/**
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/tokens/parser.ts","../src/tokens/preview.ts","../src/types/plugin.ts","../src/plugin/index.ts","../src/tokens/usage.ts","../src/tokens/resolver.ts","../src/tokens/generator.ts"],"mappings":";;;;;;;;;;;;AAYA;;UAAiB,WAAA;EACf,KAAA;EACA,IAAA;EACA,WAAA;EACA,UAAA,GAAa,MAAM;EACnB,KAAA;EACA,UAAA;EACA,cAAA;AAAA;;;AAAc;UAMC,aAAA;EACf,IAAA;EACA,MAAA,EAAQ,MAAA,SAAe,WAAA;EACvB,aAAA,GAAgB,aAAA;AAAA;;;;UAMD,qBAAA;EACf,UAAA,EAAY,aAAa;EACzB,QAAA;IACE,IAAA;IACA,OAAA;IACA,WAAA;EAAA;AAAA;AALJ;;;AAAA,UAYiB,qBAAA;EAXf;;;EAeA,UAAA;EAZE;;;AACW;EAiBb,YAAA;EAVoC;;;;EAgBpC,SAAA;EAAA;;;EAKA,UAAA,GAAa,cAAc;AAAA;AAM7B;;;AAAA,KAAY,cAAA,IAAkB,KAAA,EAAO,WAAA,EAAa,IAAA,eAAmB,WAAW;;;;iBAK1D,WAAA,CAAY,UAAA,WAAqB,OAAO,CAAC,aAAA;;;KC5EnD,qBAAA;AAAA,UAaK,qBAAA;EACf,IAAA,EAAM,qBAAqB;EAC3B,IAAA;EACA,YAAA;EACA,YAAA;EACA,qBAAA;AAAA;AAAA,UAGe,uBAAA;EDVf;;;;ECeA,KAAA,GAAQ,qBAAA;EDXR;ECaA,aAAA,GAAgB,qBAAqB;AAAA;AAAA,UAGtB,oBAAA;EACf,IAAA,EAAM,qBAAA;EACN,KAAA;EACA,SAAA;EACA,SAAA;IACE,IAAA;IACA,KAAA,GAAQ,WAAW;IACnB,KAAA;EAAA;AAAA;AAAA,UAIa,wBAAA;EACf,SAAA;EACA,KAAA,EAAO,WAAA;EACP,QAAA,GAAW,MAAA,SAAe,WAAA;EAC1B,MAAA,GAAS,uBAAA;AAAA;AAAA,iBASK,mBAAA,CAAoB,KAAA,EAAO,wBAAA,GAA2B,oBAAoB;;;KCtD9E,eAAA;;;;AFSZ;UEHiB,gBAAA;EACf,SAAA;EACA,WAAA;EACA,UAAA;EACA,UAAA;EACA,MAAA;EACA,WAAA;EACA,cAAA;EACA,YAAA;EACA,IAAA;EACA,aAAA;EACA,SAAA;EACA,MAAA;EACA,YAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA;EACA,OAAA;EACA,MAAA;AAAA;;;;UAMe,UAAA;EFNQ;EEQvB,IAAA;EFPgB;EEShB,IAAA;EFT6B;EEW7B,MAAA,EAAQ,gBAAgB;AAAA;;;;UAMT,YAAA;EFTf;;;;EEcA,OAAA;EFXa;AAOf;;;EEUE,OAAA;EFNA;;;;EEYA,QAAA;EFK2B;AAAA;AAM7B;;EELE,eAAA;EFK8E;;;;EEC9E,eAAA;EFD8E;AAAA;AAKhF;;;;EEIE,SAAA;EFJqD;;;EESrD,GAAA,GAAM,UAAA;;;;ADrFR;;EC4FE,UAAA;ED5F+B;AAAA;AAajC;;ECqFE,aAAA,GAAgB,uBAAA;EDpFW;;;;;;;;AAIN;AAGvB;ECyFE,WAAA;;;;;;;;ADlFqC;EC4FrC,KAAA,iCAAsC,UAAA,GAAa,UAAA;EDzFhB
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/tokens/parser.ts","../src/tokens/preview.ts","../src/types/plugin.ts","../src/plugin/index.ts","../src/tokens/usage.ts","../src/tokens/resolver.ts","../src/tokens/generator.ts"],"mappings":"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"}
|