@fragments-sdk/cli 0.8.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +517 -77
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-WI6SLMSO.js → chunk-5GT62FCB.js} +2 -2
- package/dist/{chunk-CJEGT3WD.js → chunk-BW3ZATBW.js} +20 -3
- package/dist/chunk-BW3ZATBW.js.map +1 -0
- package/dist/{chunk-2JIKCJX3.js → chunk-D7372LQX.js} +13 -6
- package/dist/chunk-D7372LQX.js.map +1 -0
- package/dist/chunk-EZYXYWNF.js +131 -0
- package/dist/chunk-EZYXYWNF.js.map +1 -0
- package/dist/{chunk-NGIMCIK2.js → chunk-GF6OVPIN.js} +2 -2
- package/dist/{chunk-GOVI6COW.js → chunk-NVSPGSKB.js} +12 -4
- package/dist/chunk-NVSPGSKB.js.map +1 -0
- package/dist/core/index.d.ts +105 -3
- package/dist/core/index.js +12 -2
- package/dist/{defineFragment-D0UTve-I.d.ts → defineFragment-CBMS7Bab.d.ts} +21 -1
- package/dist/generate-LQA2R7FN.js +461 -0
- package/dist/generate-LQA2R7FN.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/{init-KFYN37ZY.js → init-2GEGVIUQ.js} +14 -76
- package/dist/init-2GEGVIUQ.js.map +1 -0
- package/dist/mcp-bin.js +4 -3
- package/dist/mcp-bin.js.map +1 -1
- package/dist/{scan-65RH3QMM.js → scan-JGS65S7P.js} +6 -5
- package/dist/{service-A5GIGGGK.js → service-XP2EAJXD.js} +4 -3
- package/dist/{static-viewer-NSODM5VX.js → static-viewer-XCS7UJTO.js} +4 -3
- package/dist/storyFilters-3LUYAFZF.js +15 -0
- package/dist/storyFilters-3LUYAFZF.js.map +1 -0
- package/dist/{test-RPWZAYSJ.js → test-TD6TJNVY.js} +3 -3
- package/dist/{tokens-NIXSZRX7.js → tokens-2EXPCVP3.js} +5 -4
- package/dist/{tokens-NIXSZRX7.js.map → tokens-2EXPCVP3.js.map} +1 -1
- package/dist/{viewer-HZK4BSDK.js → viewer-RFA2KVBG.js} +249 -22
- package/dist/viewer-RFA2KVBG.js.map +1 -0
- package/package.json +2 -2
- package/src/bin.ts +26 -0
- package/src/build.ts +12 -2
- package/src/commands/build.ts +16 -2
- package/src/commands/doctor.ts +498 -0
- package/src/commands/generate.ts +383 -68
- package/src/commands/init-framework.ts +1 -1
- package/src/commands/init.ts +9 -51
- package/src/core/config.ts +15 -2
- package/src/core/generators/typescript-extractor.ts +10 -0
- package/src/core/index.ts +15 -0
- package/src/core/schema.ts +10 -2
- package/src/core/storyFilters.test.ts +350 -0
- package/src/core/storyFilters.ts +253 -0
- package/src/core/types.ts +22 -0
- package/src/migrate/converter.ts +9 -1
- package/src/migrate/parser.ts +2 -0
- package/src/migrate/types.ts +2 -0
- package/src/setup.ts +69 -24
- package/src/viewer/__tests__/viewer-integration.test.ts +1 -1
- package/src/viewer/components/AccessibilityPanel.tsx +305 -312
- package/src/viewer/components/ActionsPanel.tsx +31 -29
- package/src/viewer/components/AllVariantsPreview.tsx +78 -0
- package/src/viewer/components/App.tsx +187 -740
- package/src/viewer/components/BottomPanel.tsx +228 -132
- package/src/viewer/components/CodePanel.tsx +1 -1
- package/src/viewer/components/CommandPalette.tsx +7 -10
- package/src/viewer/components/ComponentDocView.tsx +164 -0
- package/src/viewer/components/ComponentGraph.tsx +111 -142
- package/src/viewer/components/ContractPanel.tsx +6 -6
- package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
- package/src/viewer/components/FigmaEmbed.tsx +20 -18
- package/src/viewer/components/FragmentEditor.tsx +92 -115
- package/src/viewer/components/HeaderSearch.tsx +24 -0
- package/src/viewer/components/HealthDashboard.tsx +16 -2
- package/src/viewer/components/Icons.tsx +9 -0
- package/src/viewer/components/InteractionsPanel.tsx +101 -117
- package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
- package/src/viewer/components/LandingPage.tsx +3 -3
- package/src/viewer/components/LeftSidebar.tsx +141 -63
- package/src/viewer/components/LoadErrorMessage.tsx +102 -0
- package/src/viewer/components/MultiViewportPreview.tsx +61 -142
- package/src/viewer/components/NoVariantsMessage.tsx +59 -0
- package/src/viewer/components/PanelShell.tsx +161 -0
- package/src/viewer/components/PerformancePanel.tsx +31 -28
- package/src/viewer/components/PreviewArea.tsx +1 -1
- package/src/viewer/components/PreviewAside.tsx +168 -0
- package/src/viewer/components/PreviewFrameHost.tsx +3 -3
- package/src/viewer/components/PropsEditor.tsx +70 -156
- package/src/viewer/components/ResizablePanel.tsx +103 -263
- package/src/viewer/components/RightSidebar.tsx +3 -9
- package/src/viewer/components/SkeletonLoader.tsx +13 -13
- package/src/viewer/components/TokenStylePanel.tsx +182 -209
- package/src/viewer/components/TopToolbar.tsx +159 -0
- package/src/viewer/components/VariantMatrix.tsx +42 -86
- package/src/viewer/components/VariantTabs.tsx +3 -3
- package/src/viewer/components/ViewerHeader.tsx +69 -0
- package/src/viewer/components/WebMCPDevTools.tsx +17 -23
- package/src/viewer/components/viewer-utils.ts +16 -0
- package/src/viewer/entry.tsx +5 -0
- package/src/viewer/hooks/useAppState.ts +27 -4
- package/src/viewer/hooks/usePreviewBridge.ts +2 -2
- package/src/viewer/preview-frame.html +6 -12
- package/src/viewer/server.ts +184 -6
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
- package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
- package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
- package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +122 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
- package/src/viewer/vendor/shared/src/docs-data/index.ts +32 -0
- package/src/viewer/vendor/shared/src/docs-data/mcp-configs.ts +72 -0
- package/src/viewer/vendor/shared/src/docs-data/palettes.ts +75 -0
- package/src/viewer/vendor/shared/src/docs-data/setup-examples.ts +55 -0
- package/src/viewer/vendor/shared/src/index.ts +8 -0
- package/src/viewer/vendor/shared/src/types.ts +12 -0
- package/src/viewer/vite-plugin.ts +109 -4
- package/dist/chunk-2JIKCJX3.js.map +0 -1
- package/dist/chunk-CJEGT3WD.js.map +0 -1
- package/dist/chunk-GOVI6COW.js.map +0 -1
- package/dist/generate-35OIMW4Y.js +0 -252
- package/dist/generate-35OIMW4Y.js.map +0 -1
- package/dist/init-KFYN37ZY.js.map +0 -1
- package/dist/viewer-HZK4BSDK.js.map +0 -1
- /package/dist/{chunk-WI6SLMSO.js.map → chunk-5GT62FCB.js.map} +0 -0
- /package/dist/{chunk-NGIMCIK2.js.map → chunk-GF6OVPIN.js.map} +0 -0
- /package/dist/{scan-65RH3QMM.js.map → scan-JGS65S7P.js.map} +0 -0
- /package/dist/{service-A5GIGGGK.js.map → service-XP2EAJXD.js.map} +0 -0
- /package/dist/{static-viewer-NSODM5VX.js.map → static-viewer-XCS7UJTO.js.map} +0 -0
- /package/dist/{test-RPWZAYSJ.js.map → test-TD6TJNVY.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/tokens.ts"],"sourcesContent":["/**\n * CLI Tokens Command\n *\n * Discover and list design tokens from CSS/SCSS files.\n *\n * Usage:\n * fragments tokens # List all tokens\n * fragments tokens --json # Output as JSON\n * fragments tokens --categories # Group by category\n * fragments tokens --theme dark # Filter by theme\n */\n\nimport pc from \"picocolors\";\nimport { BRAND } from \"../core/index.js\";\nimport type { DesignToken, TokenCategory, TokenConfig } from \"../core/index.js\";\nimport { loadConfig } from \"../core/node.js\";\nimport { parseTokenFiles, createTokenRegistry } from \"../service/index.js\";\n\nexport interface TokensCommandOptions {\n config?: string;\n json?: boolean;\n categories?: boolean;\n theme?: string;\n category?: string;\n verbose?: boolean;\n}\n\nexport interface TokensCommandResult {\n success: boolean;\n tokenCount: number;\n errors: string[];\n}\n\n/**\n * Run the tokens command\n */\nexport async function tokens(\n options: TokensCommandOptions\n): Promise<TokensCommandResult> {\n const errors: string[] = [];\n\n try {\n console.log(pc.cyan(`\\n${BRAND.name} Token Discovery\\n`));\n\n // Load config\n const { config, configDir } = await loadConfig(options.config);\n\n // Check for token configuration\n if (!config.tokens || !config.tokens.include || config.tokens.include.length === 0) {\n console.log(pc.yellow(\"No token configuration found.\\n\"));\n console.log(pc.dim(\"Add 'tokens' config to fragments.config.ts:\"));\n console.log(pc.dim(`\n tokens: {\n include: ['src/styles/theme.scss', 'src/styles/variables.css'],\n themeSelectors: {\n ':root': 'default',\n '[data-theme=\"dark\"]': 'dark',\n },\n },\n`));\n return { success: false, tokenCount: 0, errors: [\"No token configuration\"] };\n }\n\n console.log(pc.dim(`Scanning files: ${config.tokens.include.join(\", \")}\\n`));\n\n // Parse token files\n const parseResult = await parseTokenFiles(config.tokens, configDir);\n\n if (parseResult.errors.length > 0) {\n console.log(pc.yellow(\"Parse errors:\"));\n for (const err of parseResult.errors) {\n console.log(pc.red(` ${err.file}: ${err.message}`));\n errors.push(`${err.file}: ${err.message}`);\n }\n console.log();\n }\n\n if (parseResult.warnings.length > 0 && options.verbose) {\n console.log(pc.yellow(\"Warnings:\"));\n for (const warning of parseResult.warnings) {\n console.log(pc.dim(` ${warning}`));\n }\n console.log();\n }\n\n let tokens = parseResult.tokens;\n\n // Filter by theme if specified\n if (options.theme) {\n tokens = tokens.filter(\n (t) => t.theme === options.theme || t.theme === \"default\"\n );\n }\n\n // Filter by category if specified\n if (options.category) {\n tokens = tokens.filter((t) => t.category === options.category);\n }\n\n if (tokens.length === 0) {\n console.log(pc.yellow(\"No tokens found.\\n\"));\n console.log(pc.dim(\"Make sure your CSS files contain CSS custom properties (--token-name: value;)\"));\n return { success: true, tokenCount: 0, errors };\n }\n\n // Output based on format\n if (options.json) {\n outputJson(tokens, parseResult.parseTimeMs);\n } else if (options.categories) {\n outputByCategory(tokens, parseResult.parseTimeMs);\n } else {\n outputList(tokens, parseResult.parseTimeMs, options.verbose);\n }\n\n return { success: true, tokenCount: tokens.length, errors };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n console.error(pc.red(\"Error:\"), message);\n errors.push(message);\n return { success: false, tokenCount: 0, errors };\n }\n}\n\n/**\n * Output tokens as JSON\n */\nfunction outputJson(tokens: DesignToken[], parseTimeMs: number): void {\n const output = {\n tokens,\n meta: {\n totalTokens: tokens.length,\n parseTimeMs,\n discoveredAt: new Date().toISOString(),\n },\n };\n\n console.log(JSON.stringify(output, null, 2));\n}\n\n/**\n * Output tokens grouped by category\n */\nfunction outputByCategory(tokens: DesignToken[], parseTimeMs: number): void {\n // Group by category\n const byCategory = new Map<TokenCategory, DesignToken[]>();\n\n for (const token of tokens) {\n const list = byCategory.get(token.category) || [];\n list.push(token);\n byCategory.set(token.category, list);\n }\n\n // Sort categories alphabetically\n const categories = Array.from(byCategory.keys()).sort();\n\n for (const category of categories) {\n const categoryTokens = byCategory.get(category) || [];\n console.log(pc.bold(`${category} (${categoryTokens.length})`));\n console.log(pc.dim(\"─\".repeat(40)));\n\n for (const token of categoryTokens.slice(0, 10)) {\n const levelLabel = token.level === 1 ? \"base\" : token.level === 2 ? \"semantic\" : \"component\";\n console.log(` ${pc.cyan(token.name)}`);\n console.log(` ${pc.dim(\"Value:\")} ${token.resolvedValue}`);\n console.log(` ${pc.dim(\"Level:\")} ${levelLabel} ${pc.dim(`(${token.theme})`)}`);\n }\n\n if (categoryTokens.length > 10) {\n console.log(pc.dim(` ... and ${categoryTokens.length - 10} more`));\n }\n console.log();\n }\n\n // Summary\n console.log(pc.dim(\"─\".repeat(40)));\n console.log(pc.green(`✓ Found ${tokens.length} token(s) in ${categories.length} categories`));\n console.log(pc.dim(` Parsed in ${parseTimeMs.toFixed(1)}ms\\n`));\n}\n\n/**\n * Output tokens as a simple list\n */\nfunction outputList(tokens: DesignToken[], parseTimeMs: number, verbose?: boolean): void {\n // Group by theme first\n const byTheme = new Map<string, DesignToken[]>();\n\n for (const token of tokens) {\n const list = byTheme.get(token.theme) || [];\n list.push(token);\n byTheme.set(token.theme, list);\n }\n\n const themes = Array.from(byTheme.keys()).sort();\n\n for (const theme of themes) {\n const themeTokens = byTheme.get(theme) || [];\n\n if (themes.length > 1) {\n console.log(pc.bold(`Theme: ${theme} (${themeTokens.length} tokens)`));\n console.log(pc.dim(\"─\".repeat(50)));\n }\n\n // Sort tokens by name\n themeTokens.sort((a, b) => a.name.localeCompare(b.name));\n\n // Table header\n console.log(\n pc.dim(\n `${\"Token Name\".padEnd(32)} ${\"Value\".padEnd(20)} ${\"Category\".padEnd(12)}`\n )\n );\n console.log(pc.dim(\"─\".repeat(70)));\n\n const displayTokens = verbose ? themeTokens : themeTokens.slice(0, 30);\n\n for (const token of displayTokens) {\n const name = token.name.length > 30 ? token.name.slice(0, 27) + \"...\" : token.name;\n const value = token.resolvedValue.length > 18 ? token.resolvedValue.slice(0, 15) + \"...\" : token.resolvedValue;\n\n console.log(\n `${pc.cyan(name.padEnd(32))} ${value.padEnd(20)} ${pc.dim(token.category.padEnd(12))}`\n );\n }\n\n if (!verbose && themeTokens.length > 30) {\n console.log(pc.dim(`\\n ... and ${themeTokens.length - 30} more (use --verbose to show all)`));\n }\n\n console.log();\n }\n\n // Summary\n console.log(pc.dim(\"─\".repeat(50)));\n console.log(pc.green(`✓ Found ${tokens.length} token(s)`));\n\n // Category breakdown\n const categoryCounts: Record<string, number> = {};\n for (const token of tokens) {\n categoryCounts[token.category] = (categoryCounts[token.category] || 0) + 1;\n }\n\n const breakdown = Object.entries(categoryCounts)\n .sort((a, b) => b[1] - a[1])\n .map(([cat, count]) => `${cat}: ${count}`)\n .join(\", \");\n\n console.log(pc.dim(` ${breakdown}`));\n console.log(pc.dim(` Parsed in ${parseTimeMs.toFixed(1)}ms\\n`));\n}\n\nexport default tokens;\n"],"mappings":"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","names":["tokens"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/tokens.ts"],"sourcesContent":["/**\n * CLI Tokens Command\n *\n * Discover and list design tokens from CSS/SCSS files.\n *\n * Usage:\n * fragments tokens # List all tokens\n * fragments tokens --json # Output as JSON\n * fragments tokens --categories # Group by category\n * fragments tokens --theme dark # Filter by theme\n */\n\nimport pc from \"picocolors\";\nimport { BRAND } from \"../core/index.js\";\nimport type { DesignToken, TokenCategory, TokenConfig } from \"../core/index.js\";\nimport { loadConfig } from \"../core/node.js\";\nimport { parseTokenFiles, createTokenRegistry } from \"../service/index.js\";\n\nexport interface TokensCommandOptions {\n config?: string;\n json?: boolean;\n categories?: boolean;\n theme?: string;\n category?: string;\n verbose?: boolean;\n}\n\nexport interface TokensCommandResult {\n success: boolean;\n tokenCount: number;\n errors: string[];\n}\n\n/**\n * Run the tokens command\n */\nexport async function tokens(\n options: TokensCommandOptions\n): Promise<TokensCommandResult> {\n const errors: string[] = [];\n\n try {\n console.log(pc.cyan(`\\n${BRAND.name} Token Discovery\\n`));\n\n // Load config\n const { config, configDir } = await loadConfig(options.config);\n\n // Check for token configuration\n if (!config.tokens || !config.tokens.include || config.tokens.include.length === 0) {\n console.log(pc.yellow(\"No token configuration found.\\n\"));\n console.log(pc.dim(\"Add 'tokens' config to fragments.config.ts:\"));\n console.log(pc.dim(`\n tokens: {\n include: ['src/styles/theme.scss', 'src/styles/variables.css'],\n themeSelectors: {\n ':root': 'default',\n '[data-theme=\"dark\"]': 'dark',\n },\n },\n`));\n return { success: false, tokenCount: 0, errors: [\"No token configuration\"] };\n }\n\n console.log(pc.dim(`Scanning files: ${config.tokens.include.join(\", \")}\\n`));\n\n // Parse token files\n const parseResult = await parseTokenFiles(config.tokens, configDir);\n\n if (parseResult.errors.length > 0) {\n console.log(pc.yellow(\"Parse errors:\"));\n for (const err of parseResult.errors) {\n console.log(pc.red(` ${err.file}: ${err.message}`));\n errors.push(`${err.file}: ${err.message}`);\n }\n console.log();\n }\n\n if (parseResult.warnings.length > 0 && options.verbose) {\n console.log(pc.yellow(\"Warnings:\"));\n for (const warning of parseResult.warnings) {\n console.log(pc.dim(` ${warning}`));\n }\n console.log();\n }\n\n let tokens = parseResult.tokens;\n\n // Filter by theme if specified\n if (options.theme) {\n tokens = tokens.filter(\n (t) => t.theme === options.theme || t.theme === \"default\"\n );\n }\n\n // Filter by category if specified\n if (options.category) {\n tokens = tokens.filter((t) => t.category === options.category);\n }\n\n if (tokens.length === 0) {\n console.log(pc.yellow(\"No tokens found.\\n\"));\n console.log(pc.dim(\"Make sure your CSS files contain CSS custom properties (--token-name: value;)\"));\n return { success: true, tokenCount: 0, errors };\n }\n\n // Output based on format\n if (options.json) {\n outputJson(tokens, parseResult.parseTimeMs);\n } else if (options.categories) {\n outputByCategory(tokens, parseResult.parseTimeMs);\n } else {\n outputList(tokens, parseResult.parseTimeMs, options.verbose);\n }\n\n return { success: true, tokenCount: tokens.length, errors };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown error\";\n console.error(pc.red(\"Error:\"), message);\n errors.push(message);\n return { success: false, tokenCount: 0, errors };\n }\n}\n\n/**\n * Output tokens as JSON\n */\nfunction outputJson(tokens: DesignToken[], parseTimeMs: number): void {\n const output = {\n tokens,\n meta: {\n totalTokens: tokens.length,\n parseTimeMs,\n discoveredAt: new Date().toISOString(),\n },\n };\n\n console.log(JSON.stringify(output, null, 2));\n}\n\n/**\n * Output tokens grouped by category\n */\nfunction outputByCategory(tokens: DesignToken[], parseTimeMs: number): void {\n // Group by category\n const byCategory = new Map<TokenCategory, DesignToken[]>();\n\n for (const token of tokens) {\n const list = byCategory.get(token.category) || [];\n list.push(token);\n byCategory.set(token.category, list);\n }\n\n // Sort categories alphabetically\n const categories = Array.from(byCategory.keys()).sort();\n\n for (const category of categories) {\n const categoryTokens = byCategory.get(category) || [];\n console.log(pc.bold(`${category} (${categoryTokens.length})`));\n console.log(pc.dim(\"─\".repeat(40)));\n\n for (const token of categoryTokens.slice(0, 10)) {\n const levelLabel = token.level === 1 ? \"base\" : token.level === 2 ? \"semantic\" : \"component\";\n console.log(` ${pc.cyan(token.name)}`);\n console.log(` ${pc.dim(\"Value:\")} ${token.resolvedValue}`);\n console.log(` ${pc.dim(\"Level:\")} ${levelLabel} ${pc.dim(`(${token.theme})`)}`);\n }\n\n if (categoryTokens.length > 10) {\n console.log(pc.dim(` ... and ${categoryTokens.length - 10} more`));\n }\n console.log();\n }\n\n // Summary\n console.log(pc.dim(\"─\".repeat(40)));\n console.log(pc.green(`✓ Found ${tokens.length} token(s) in ${categories.length} categories`));\n console.log(pc.dim(` Parsed in ${parseTimeMs.toFixed(1)}ms\\n`));\n}\n\n/**\n * Output tokens as a simple list\n */\nfunction outputList(tokens: DesignToken[], parseTimeMs: number, verbose?: boolean): void {\n // Group by theme first\n const byTheme = new Map<string, DesignToken[]>();\n\n for (const token of tokens) {\n const list = byTheme.get(token.theme) || [];\n list.push(token);\n byTheme.set(token.theme, list);\n }\n\n const themes = Array.from(byTheme.keys()).sort();\n\n for (const theme of themes) {\n const themeTokens = byTheme.get(theme) || [];\n\n if (themes.length > 1) {\n console.log(pc.bold(`Theme: ${theme} (${themeTokens.length} tokens)`));\n console.log(pc.dim(\"─\".repeat(50)));\n }\n\n // Sort tokens by name\n themeTokens.sort((a, b) => a.name.localeCompare(b.name));\n\n // Table header\n console.log(\n pc.dim(\n `${\"Token Name\".padEnd(32)} ${\"Value\".padEnd(20)} ${\"Category\".padEnd(12)}`\n )\n );\n console.log(pc.dim(\"─\".repeat(70)));\n\n const displayTokens = verbose ? themeTokens : themeTokens.slice(0, 30);\n\n for (const token of displayTokens) {\n const name = token.name.length > 30 ? token.name.slice(0, 27) + \"...\" : token.name;\n const value = token.resolvedValue.length > 18 ? token.resolvedValue.slice(0, 15) + \"...\" : token.resolvedValue;\n\n console.log(\n `${pc.cyan(name.padEnd(32))} ${value.padEnd(20)} ${pc.dim(token.category.padEnd(12))}`\n );\n }\n\n if (!verbose && themeTokens.length > 30) {\n console.log(pc.dim(`\\n ... and ${themeTokens.length - 30} more (use --verbose to show all)`));\n }\n\n console.log();\n }\n\n // Summary\n console.log(pc.dim(\"─\".repeat(50)));\n console.log(pc.green(`✓ Found ${tokens.length} token(s)`));\n\n // Category breakdown\n const categoryCounts: Record<string, number> = {};\n for (const token of tokens) {\n categoryCounts[token.category] = (categoryCounts[token.category] || 0) + 1;\n }\n\n const breakdown = Object.entries(categoryCounts)\n .sort((a, b) => b[1] - a[1])\n .map(([cat, count]) => `${cat}: ${count}`)\n .join(\", \");\n\n console.log(pc.dim(` ${breakdown}`));\n console.log(pc.dim(` Parsed in ${parseTimeMs.toFixed(1)}ms\\n`));\n}\n\nexport default tokens;\n"],"mappings":"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","names":["tokens"]}
|
|
@@ -5,15 +5,16 @@ import {
|
|
|
5
5
|
generatePreviewModule,
|
|
6
6
|
loadConfig,
|
|
7
7
|
parseFragmentFile
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BW3ZATBW.js";
|
|
9
9
|
import {
|
|
10
10
|
discoverFragmentFiles,
|
|
11
11
|
discoverInstalledFragments
|
|
12
12
|
} from "./chunk-AWYCDRPG.js";
|
|
13
13
|
import {
|
|
14
14
|
generateContext
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-GF6OVPIN.js";
|
|
16
|
+
import "./chunk-NVSPGSKB.js";
|
|
17
|
+
import "./chunk-EZYXYWNF.js";
|
|
17
18
|
import {
|
|
18
19
|
BRAND
|
|
19
20
|
} from "./chunk-EKLMXTWU.js";
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
import react from "@vitejs/plugin-react";
|
|
29
30
|
import { resolve as resolve2, dirname as dirname2, join } from "path";
|
|
30
31
|
import { existsSync, realpathSync } from "fs";
|
|
32
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
31
33
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32
34
|
|
|
33
35
|
// src/viewer/vite-plugin.ts
|
|
@@ -361,7 +363,7 @@ var sharedRenderPool = null;
|
|
|
361
363
|
var browserPoolModule = null;
|
|
362
364
|
async function getSharedRenderPool() {
|
|
363
365
|
if (!browserPoolModule) {
|
|
364
|
-
browserPoolModule = await import("./service-
|
|
366
|
+
browserPoolModule = await import("./service-XP2EAJXD.js");
|
|
365
367
|
}
|
|
366
368
|
if (!sharedRenderPool) {
|
|
367
369
|
sharedRenderPool = new browserPoolModule.BrowserPool({
|
|
@@ -604,7 +606,7 @@ function fragmentsPlugin(options) {
|
|
|
604
606
|
const address = _server.httpServer?.address();
|
|
605
607
|
const port = typeof address === "object" && address ? address.port : 6006;
|
|
606
608
|
const renderViewport = viewport || { width: 800, height: 600 };
|
|
607
|
-
const { FigmaClient, bufferToBase64Url } = await import("./service-
|
|
609
|
+
const { FigmaClient, bufferToBase64Url } = await import("./service-XP2EAJXD.js");
|
|
608
610
|
const figmaClient = new FigmaClient({
|
|
609
611
|
accessToken: figmaToken
|
|
610
612
|
});
|
|
@@ -695,7 +697,7 @@ function fragmentsPlugin(options) {
|
|
|
695
697
|
);
|
|
696
698
|
return;
|
|
697
699
|
}
|
|
698
|
-
const { FigmaClient } = await import("./service-
|
|
700
|
+
const { FigmaClient } = await import("./service-XP2EAJXD.js");
|
|
699
701
|
const figmaClient = new FigmaClient({ accessToken: figmaToken });
|
|
700
702
|
const { fileKey, nodeId } = figmaClient.parseUrl(figmaUrl);
|
|
701
703
|
const figmaDesignProps = await figmaClient.getNodeProperties(
|
|
@@ -736,7 +738,7 @@ function fragmentsPlugin(options) {
|
|
|
736
738
|
}));
|
|
737
739
|
return;
|
|
738
740
|
}
|
|
739
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
741
|
+
const { getSharedTokenRegistry } = await import("./service-XP2EAJXD.js");
|
|
740
742
|
const registry = getSharedTokenRegistry();
|
|
741
743
|
if (!registry.isInitialized()) {
|
|
742
744
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -796,7 +798,7 @@ function fragmentsPlugin(options) {
|
|
|
796
798
|
}));
|
|
797
799
|
return;
|
|
798
800
|
}
|
|
799
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
801
|
+
const { getSharedTokenRegistry } = await import("./service-XP2EAJXD.js");
|
|
800
802
|
const registry = getSharedTokenRegistry();
|
|
801
803
|
if (!registry.isInitialized()) {
|
|
802
804
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -858,7 +860,7 @@ function fragmentsPlugin(options) {
|
|
|
858
860
|
res.end(JSON.stringify({ error: "Could not resolve fragment file path" }));
|
|
859
861
|
return;
|
|
860
862
|
}
|
|
861
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
863
|
+
const { getSharedTokenRegistry } = await import("./service-XP2EAJXD.js");
|
|
862
864
|
const registry = getSharedTokenRegistry();
|
|
863
865
|
if (!registry.isInitialized()) {
|
|
864
866
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -1073,7 +1075,7 @@ function fragmentsPlugin(options) {
|
|
|
1073
1075
|
const {
|
|
1074
1076
|
getSharedTokenRegistry,
|
|
1075
1077
|
generateTokenPatches
|
|
1076
|
-
} = await import("./service-
|
|
1078
|
+
} = await import("./service-XP2EAJXD.js");
|
|
1077
1079
|
const registry = getSharedTokenRegistry();
|
|
1078
1080
|
if (!registry.isInitialized()) {
|
|
1079
1081
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -1370,7 +1372,7 @@ function fragmentsPlugin(options) {
|
|
|
1370
1372
|
// Load virtual modules
|
|
1371
1373
|
load(id) {
|
|
1372
1374
|
if (id === VIRTUAL_FRAGMENTS_RESOLVED) {
|
|
1373
|
-
return generateFragmentsModule(fragmentFiles, config, previewConfigPath);
|
|
1375
|
+
return generateFragmentsModule(fragmentFiles, config, previewConfigPath, projectRoot);
|
|
1374
1376
|
}
|
|
1375
1377
|
if (id === VIRTUAL_VIEWER_ENTRY_RESOLVED) {
|
|
1376
1378
|
return generateViewerEntry();
|
|
@@ -1455,6 +1457,14 @@ function extractComponentName(filePath) {
|
|
|
1455
1457
|
const match = filePath.match(/([^/\\]+)\.(fragment|stories)\.(tsx?|jsx?)$/);
|
|
1456
1458
|
return match ? match[1] : filePath.split("/").pop() || filePath;
|
|
1457
1459
|
}
|
|
1460
|
+
async function readProjectPackageName(root) {
|
|
1461
|
+
try {
|
|
1462
|
+
const pkgJson = JSON.parse(await readFile(resolve(root, "package.json"), "utf-8"));
|
|
1463
|
+
return pkgJson.name || null;
|
|
1464
|
+
} catch {
|
|
1465
|
+
return null;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1458
1468
|
async function extractDependenciesFromSource(absolutePath) {
|
|
1459
1469
|
try {
|
|
1460
1470
|
const source = await readFile(absolutePath, "utf-8");
|
|
@@ -1471,7 +1481,7 @@ async function extractDependenciesFromSource(absolutePath) {
|
|
|
1471
1481
|
return [];
|
|
1472
1482
|
}
|
|
1473
1483
|
}
|
|
1474
|
-
async function generateFragmentsModule(fragmentFiles, config, previewConfigPath) {
|
|
1484
|
+
async function generateFragmentsModule(fragmentFiles, config, previewConfigPath, projectRoot) {
|
|
1475
1485
|
const authoredVariantCodeCache = /* @__PURE__ */ new Map();
|
|
1476
1486
|
async function loadAuthoredVariantCode(fragmentFilePath) {
|
|
1477
1487
|
if (authoredVariantCodeCache.has(fragmentFilePath)) {
|
|
@@ -1494,6 +1504,9 @@ async function generateFragmentsModule(fragmentFiles, config, previewConfigPath)
|
|
|
1494
1504
|
return {};
|
|
1495
1505
|
}
|
|
1496
1506
|
}
|
|
1507
|
+
const storyOnlyFiles = fragmentFiles.filter((f) => isStoryFile(f.relativePath));
|
|
1508
|
+
const { detectSubComponentPaths: _detectSubs } = await import("./storyFilters-3LUYAFZF.js");
|
|
1509
|
+
const subComponentMap = _detectSubs(storyOnlyFiles);
|
|
1497
1510
|
const filesByBasePath = /* @__PURE__ */ new Map();
|
|
1498
1511
|
for (const file of fragmentFiles) {
|
|
1499
1512
|
const basePath = getBaseComponentPath(file.relativePath);
|
|
@@ -1517,11 +1530,14 @@ async function generateFragmentsModule(fragmentFiles, config, previewConfigPath)
|
|
|
1517
1530
|
const componentName = extractComponentName(primaryFile.relativePath);
|
|
1518
1531
|
const fragmentSource = files.fragmentFile || primaryFile;
|
|
1519
1532
|
const dependencies = await extractDependenciesFromSource(fragmentSource.absolutePath);
|
|
1533
|
+
const parentComponent = isStory ? subComponentMap.get(primaryFile.relativePath) : void 0;
|
|
1520
1534
|
return ` {
|
|
1521
1535
|
path: "${primaryFile.relativePath}",
|
|
1522
1536
|
isStory: ${isStory},
|
|
1523
1537
|
componentName: ${JSON.stringify(componentName)},
|
|
1524
1538
|
dependencies: ${JSON.stringify(dependencies)},
|
|
1539
|
+
isSubComponent: ${!!parentComponent},
|
|
1540
|
+
parentComponent: ${parentComponent ? JSON.stringify(parentComponent) : "null"},
|
|
1525
1541
|
loader: () => import("${primaryFile.absolutePath}"),
|
|
1526
1542
|
metadataLoader: ${metadataPath ? `() => import("${metadataPath}")` : "null"},
|
|
1527
1543
|
authoredVariantCode: ${JSON.stringify(authoredVariantCode)}
|
|
@@ -1541,10 +1557,14 @@ setPreviewConfig({
|
|
|
1541
1557
|
loaders: previewConfig.loaders,
|
|
1542
1558
|
});
|
|
1543
1559
|
` : "";
|
|
1560
|
+
const storybookFilterConfig = JSON.stringify(config.storybook ?? {});
|
|
1544
1561
|
return `
|
|
1545
|
-
import { storyModuleToFragment, setPreviewConfig } from "@fragments-sdk/cli/core";
|
|
1562
|
+
import { storyModuleToFragment, setPreviewConfig, checkStoryExclusion, isForceIncluded, isConfigExcluded } from "@fragments-sdk/cli/core";
|
|
1546
1563
|
${previewImport}
|
|
1547
1564
|
${previewSetup}
|
|
1565
|
+
// Storybook filter config (deep-merged with defaults at build time)
|
|
1566
|
+
const storybookFilterConfig = ${storybookFilterConfig};
|
|
1567
|
+
|
|
1548
1568
|
// Lazy fragment loaders (supports both .fragment.tsx and .stories.tsx)
|
|
1549
1569
|
const fragmentLoaders = [
|
|
1550
1570
|
${loaders}
|
|
@@ -1607,8 +1627,24 @@ function mergeAuthoredVariantCode(fragment, authoredVariantCode) {
|
|
|
1607
1627
|
return fragment;
|
|
1608
1628
|
}
|
|
1609
1629
|
|
|
1630
|
+
// Diagnostics: track exclusions for FRAGMENTS_DEBUG
|
|
1631
|
+
const exclusionLog = [];
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* Try to load a paired .fragment.tsx file as fallback when a story is excluded.
|
|
1635
|
+
* Returns the fragment if available, null otherwise.
|
|
1636
|
+
*/
|
|
1637
|
+
async function tryFallbackFragment(loader) {
|
|
1638
|
+
if (!loader.metadataLoader) return null;
|
|
1639
|
+
try {
|
|
1640
|
+
const mod = await loader.metadataLoader();
|
|
1641
|
+
return mod?.default ? { path: loader.path, fragment: mod.default } : null;
|
|
1642
|
+
} catch { return null; }
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1610
1645
|
// Load all fragments (for initial render)
|
|
1611
1646
|
// Gracefully handles individual failures - one bad story won't break all fragments
|
|
1647
|
+
// Applies smart filtering for Storybook stories (SVG icons, deprecated, test stories, sub-components)
|
|
1612
1648
|
export async function loadAllFragments() {
|
|
1613
1649
|
const results = await Promise.all(
|
|
1614
1650
|
fragmentLoaders.map(async (loader) => {
|
|
@@ -1618,6 +1654,30 @@ export async function loadAllFragments() {
|
|
|
1618
1654
|
return cached ? { path: loader.path, fragment: cached } : null;
|
|
1619
1655
|
}
|
|
1620
1656
|
|
|
1657
|
+
// --- Pre-load filtering (config-level and sub-component checks) ---
|
|
1658
|
+
if (loader.isStory) {
|
|
1659
|
+
// Force-include bypasses all filters
|
|
1660
|
+
if (!isForceIncluded(loader.componentName, storybookFilterConfig)) {
|
|
1661
|
+
// Config explicit exclude
|
|
1662
|
+
if (isConfigExcluded(loader.componentName, storybookFilterConfig)) {
|
|
1663
|
+
exclusionLog.push({ component: loader.componentName, reason: 'config-excluded', detail: 'Matches storybook.exclude pattern', path: loader.path });
|
|
1664
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1665
|
+
if (fallback) return fallback;
|
|
1666
|
+
loadedFragments.set(loader.path, null);
|
|
1667
|
+
return null;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// Sub-component check (directory-based, computed at build time)
|
|
1671
|
+
if (loader.isSubComponent && storybookFilterConfig.excludeSubComponents !== false) {
|
|
1672
|
+
exclusionLog.push({ component: loader.componentName, reason: 'sub-component', detail: 'Sub-component of ' + loader.parentComponent, path: loader.path });
|
|
1673
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1674
|
+
if (fallback) return fallback;
|
|
1675
|
+
loadedFragments.set(loader.path, null);
|
|
1676
|
+
return null;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1621
1681
|
const module = await loader.loader();
|
|
1622
1682
|
|
|
1623
1683
|
// Convert story modules to fragments at runtime
|
|
@@ -1629,6 +1689,29 @@ export async function loadAllFragments() {
|
|
|
1629
1689
|
loadedFragments.set(loader.path, null);
|
|
1630
1690
|
return null;
|
|
1631
1691
|
}
|
|
1692
|
+
|
|
1693
|
+
// --- Post-load filtering (needs loaded module data) ---
|
|
1694
|
+
if (!isForceIncluded(loader.componentName, storybookFilterConfig)) {
|
|
1695
|
+
const meta = module.default || {};
|
|
1696
|
+
const exclusion = checkStoryExclusion({
|
|
1697
|
+
storybookTitle: meta.title,
|
|
1698
|
+
componentName: fragment.meta?.name || loader.componentName,
|
|
1699
|
+
componentDisplayName: meta.component?.displayName,
|
|
1700
|
+
componentFunctionName: meta.component?.name,
|
|
1701
|
+
tags: meta.tags,
|
|
1702
|
+
variantCount: fragment.variants?.length || 0,
|
|
1703
|
+
filePath: loader.path,
|
|
1704
|
+
config: storybookFilterConfig,
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
if (exclusion.excluded) {
|
|
1708
|
+
exclusionLog.push({ component: fragment.meta?.name || loader.componentName, reason: exclusion.reason, detail: exclusion.detail, path: loader.path });
|
|
1709
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1710
|
+
if (fallback) return fallback;
|
|
1711
|
+
loadedFragments.set(loader.path, null);
|
|
1712
|
+
return null;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1632
1715
|
} else {
|
|
1633
1716
|
fragment = module.default;
|
|
1634
1717
|
}
|
|
@@ -1670,6 +1753,15 @@ export async function loadAllFragments() {
|
|
|
1670
1753
|
}
|
|
1671
1754
|
})
|
|
1672
1755
|
);
|
|
1756
|
+
|
|
1757
|
+
// Log exclusions in debug mode
|
|
1758
|
+
if (exclusionLog.length > 0) {
|
|
1759
|
+
console.log("[Fragments] Filtered " + exclusionLog.length + " component(s)");
|
|
1760
|
+
if (typeof process !== 'undefined' && process.env?.FRAGMENTS_DEBUG) {
|
|
1761
|
+
console.table(exclusionLog);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1673
1765
|
// Filter out nulls (fragments that had no component)
|
|
1674
1766
|
return results.filter(r => r !== null);
|
|
1675
1767
|
}
|
|
@@ -1718,9 +1810,12 @@ export async function loadFragment(path) {
|
|
|
1718
1810
|
let fragments = [];
|
|
1719
1811
|
const fragmentsPromise = loadAllFragments().then(s => { fragments = s; return s; });
|
|
1720
1812
|
|
|
1721
|
-
export { fragments, fragmentsPromise };
|
|
1813
|
+
export { fragments, fragmentsPromise, exclusionLog };
|
|
1722
1814
|
export const config = ${JSON.stringify(config)};
|
|
1723
1815
|
|
|
1816
|
+
// Auto-detect consumer package name from package.json
|
|
1817
|
+
export const projectPackageName = ${JSON.stringify(await readProjectPackageName(projectRoot))};
|
|
1818
|
+
|
|
1724
1819
|
// HMR support
|
|
1725
1820
|
if (import.meta.hot) {
|
|
1726
1821
|
import.meta.hot.accept();
|
|
@@ -2088,7 +2183,7 @@ async function loadFullFragmentForCompare(_server, _fragmentFiles, componentName
|
|
|
2088
2183
|
}
|
|
2089
2184
|
}
|
|
2090
2185
|
async function compareImages(image1Base64, image2Base64, threshold) {
|
|
2091
|
-
const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-
|
|
2186
|
+
const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-XP2EAJXD.js");
|
|
2092
2187
|
const { PNG } = await import("pngjs");
|
|
2093
2188
|
const buffer1 = base64UrlToBuffer(image1Base64);
|
|
2094
2189
|
const buffer2 = base64UrlToBuffer(image2Base64);
|
|
@@ -2308,6 +2403,100 @@ export function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServ
|
|
|
2308
2403
|
}
|
|
2309
2404
|
};
|
|
2310
2405
|
}
|
|
2406
|
+
function optionalPeerDepsPlugin(uiLibRoot) {
|
|
2407
|
+
const optionalDeps = [
|
|
2408
|
+
"@tanstack/react-table",
|
|
2409
|
+
"shiki",
|
|
2410
|
+
"recharts",
|
|
2411
|
+
"react-day-picker",
|
|
2412
|
+
"date-fns",
|
|
2413
|
+
"react-colorful",
|
|
2414
|
+
"react-markdown",
|
|
2415
|
+
"remark-gfm",
|
|
2416
|
+
"@tiptap/react",
|
|
2417
|
+
"@tiptap/starter-kit",
|
|
2418
|
+
"@tiptap/extension-link"
|
|
2419
|
+
];
|
|
2420
|
+
let resolvedUiRoot;
|
|
2421
|
+
try {
|
|
2422
|
+
resolvedUiRoot = realpathSync(uiLibRoot);
|
|
2423
|
+
} catch {
|
|
2424
|
+
resolvedUiRoot = uiLibRoot;
|
|
2425
|
+
}
|
|
2426
|
+
const availableDeps = /* @__PURE__ */ new Set();
|
|
2427
|
+
for (const dep of optionalDeps) {
|
|
2428
|
+
const depPath = join(uiLibRoot, "..", "node_modules", ...dep.split("/"));
|
|
2429
|
+
if (existsSync(depPath)) availableDeps.add(dep);
|
|
2430
|
+
}
|
|
2431
|
+
return {
|
|
2432
|
+
name: "fragments:optional-peer-deps",
|
|
2433
|
+
enforce: "pre",
|
|
2434
|
+
transform(code, id) {
|
|
2435
|
+
let resolvedId;
|
|
2436
|
+
try {
|
|
2437
|
+
resolvedId = realpathSync(id);
|
|
2438
|
+
} catch {
|
|
2439
|
+
resolvedId = id;
|
|
2440
|
+
}
|
|
2441
|
+
if (!resolvedId.startsWith(resolvedUiRoot)) return;
|
|
2442
|
+
if (!id.endsWith(".tsx") && !id.endsWith(".ts")) return;
|
|
2443
|
+
if (!code.includes("require(")) return;
|
|
2444
|
+
let transformed = code;
|
|
2445
|
+
const imports = [];
|
|
2446
|
+
let counter = 0;
|
|
2447
|
+
for (const dep of availableDeps) {
|
|
2448
|
+
const escapedDep = dep.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2449
|
+
const regex = new RegExp(`require\\(['"]${escapedDep}['"]\\)`, "g");
|
|
2450
|
+
if (regex.test(code)) {
|
|
2451
|
+
const varName = `__fui_dep_${counter++}`;
|
|
2452
|
+
imports.push(`import * as ${varName} from '${dep}';`);
|
|
2453
|
+
regex.lastIndex = 0;
|
|
2454
|
+
transformed = transformed.replace(regex, varName);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
if (imports.length > 0) {
|
|
2458
|
+
transformed = imports.join("\n") + "\n" + transformed;
|
|
2459
|
+
return { code: transformed, map: null };
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
async function detectTsconfigPaths(projectRoot) {
|
|
2465
|
+
const aliases = {};
|
|
2466
|
+
const tsconfigPath = join(projectRoot, "tsconfig.json");
|
|
2467
|
+
if (!existsSync(tsconfigPath)) return aliases;
|
|
2468
|
+
try {
|
|
2469
|
+
const content = await readFile2(tsconfigPath, "utf-8");
|
|
2470
|
+
const cleaned = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
2471
|
+
const tsconfig = JSON.parse(cleaned);
|
|
2472
|
+
const paths = tsconfig?.compilerOptions?.paths;
|
|
2473
|
+
const baseUrl = tsconfig?.compilerOptions?.baseUrl || ".";
|
|
2474
|
+
if (paths) {
|
|
2475
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
2476
|
+
const target = targets[0];
|
|
2477
|
+
if (target) {
|
|
2478
|
+
const cleanAlias = alias.replace("/*", "");
|
|
2479
|
+
const cleanTarget = target.replace("/*", "");
|
|
2480
|
+
aliases[cleanAlias] = resolve2(projectRoot, baseUrl, cleanTarget);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
} catch {
|
|
2485
|
+
}
|
|
2486
|
+
return aliases;
|
|
2487
|
+
}
|
|
2488
|
+
async function detectStorybookAliases(projectRoot) {
|
|
2489
|
+
const aliases = {};
|
|
2490
|
+
const assetsDir = resolve2(projectRoot, "assets");
|
|
2491
|
+
const fontsDir = resolve2(projectRoot, "assets/fonts");
|
|
2492
|
+
if (existsSync(fontsDir)) {
|
|
2493
|
+
aliases["/fonts"] = fontsDir;
|
|
2494
|
+
}
|
|
2495
|
+
if (existsSync(assetsDir)) {
|
|
2496
|
+
aliases["/assets"] = assetsDir;
|
|
2497
|
+
}
|
|
2498
|
+
return aliases;
|
|
2499
|
+
}
|
|
2311
2500
|
async function createDevServer(options = {}) {
|
|
2312
2501
|
const startTime = performance.now();
|
|
2313
2502
|
const {
|
|
@@ -2346,7 +2535,19 @@ async function createDevServer(options = {}) {
|
|
|
2346
2535
|
const sharedLibRoot = resolveSharedLib();
|
|
2347
2536
|
const webmcpLibRoot = resolveWebMCPLib(nodeModulesPath);
|
|
2348
2537
|
const contextLibRoot = resolveContextLib(nodeModulesPath);
|
|
2538
|
+
const isWebMCPSource = existsSync(join(webmcpLibRoot, "react/index.ts"));
|
|
2539
|
+
const isContextSource = existsSync(join(contextLibRoot, "types/index.ts"));
|
|
2349
2540
|
console.log(`\u{1F4C1} Using node_modules: ${nodeModulesPath}`);
|
|
2541
|
+
const tsconfigAliases = await detectTsconfigPaths(projectRoot);
|
|
2542
|
+
const storybookAliases = await detectStorybookAliases(projectRoot);
|
|
2543
|
+
const storybookDir = resolve2(projectRoot, ".storybook");
|
|
2544
|
+
const hasStorybookDir = existsSync(storybookDir);
|
|
2545
|
+
if (Object.keys(tsconfigAliases).length > 0) {
|
|
2546
|
+
console.log(`\u{1F4CE} Detected ${Object.keys(tsconfigAliases).length} tsconfig path alias(es)`);
|
|
2547
|
+
}
|
|
2548
|
+
if (hasStorybookDir) {
|
|
2549
|
+
console.log(`\u{1F4D8} Detected .storybook directory`);
|
|
2550
|
+
}
|
|
2350
2551
|
const installedPkgRoots = [...new Set(
|
|
2351
2552
|
installedFiles.map((f) => {
|
|
2352
2553
|
const idx = f.absolutePath.indexOf("/node_modules/");
|
|
@@ -2368,8 +2569,19 @@ async function createDevServer(options = {}) {
|
|
|
2368
2569
|
port,
|
|
2369
2570
|
open: open ? "/fragments/" : false,
|
|
2370
2571
|
fs: {
|
|
2371
|
-
// Allow serving files from viewer package, project, shared libs,
|
|
2372
|
-
allow: [
|
|
2572
|
+
// Allow serving files from viewer package, project, shared libs, node_modules root, and .storybook
|
|
2573
|
+
allow: [
|
|
2574
|
+
viewerRoot,
|
|
2575
|
+
uiLibRoot,
|
|
2576
|
+
sharedLibRoot,
|
|
2577
|
+
webmcpLibRoot,
|
|
2578
|
+
contextLibRoot,
|
|
2579
|
+
projectRoot,
|
|
2580
|
+
configDir,
|
|
2581
|
+
dirname2(nodeModulesPath),
|
|
2582
|
+
...hasStorybookDir ? [storybookDir] : [],
|
|
2583
|
+
...installedPkgRoots
|
|
2584
|
+
]
|
|
2373
2585
|
}
|
|
2374
2586
|
},
|
|
2375
2587
|
plugins: [
|
|
@@ -2377,6 +2589,8 @@ async function createDevServer(options = {}) {
|
|
|
2377
2589
|
...hasReactPlugin(projectViteConfig) ? [] : [react()],
|
|
2378
2590
|
// CJS interop for packages imported from within node_modules
|
|
2379
2591
|
cjsInteropPlugin(nodeModulesPath),
|
|
2592
|
+
// Rewrite require() → ESM import for optional peer deps (e.g., @tanstack/react-table)
|
|
2593
|
+
optionalPeerDepsPlugin(uiLibRoot),
|
|
2380
2594
|
// Fragments plugins (array including SVGR)
|
|
2381
2595
|
...fragmentsPlugin({
|
|
2382
2596
|
fragmentFiles: allFragmentFiles,
|
|
@@ -2389,6 +2603,15 @@ async function createDevServer(options = {}) {
|
|
|
2389
2603
|
css: {
|
|
2390
2604
|
modules: {
|
|
2391
2605
|
localsConvention: "camelCase"
|
|
2606
|
+
},
|
|
2607
|
+
preprocessorOptions: {
|
|
2608
|
+
scss: {
|
|
2609
|
+
api: "modern-compiler",
|
|
2610
|
+
loadPaths: [
|
|
2611
|
+
resolve2(projectRoot, "src"),
|
|
2612
|
+
resolve2(projectRoot, "src/styles")
|
|
2613
|
+
]
|
|
2614
|
+
}
|
|
2392
2615
|
}
|
|
2393
2616
|
},
|
|
2394
2617
|
optimizeDeps: {
|
|
@@ -2400,17 +2623,21 @@ async function createDevServer(options = {}) {
|
|
|
2400
2623
|
// Dedupe ensures all imports of these packages resolve to the same copy
|
|
2401
2624
|
dedupe: ["react", "react-dom"],
|
|
2402
2625
|
alias: {
|
|
2626
|
+
// Project-specific aliases (tsconfig paths, Storybook static dirs)
|
|
2627
|
+
// Listed first — Fragments-specific aliases below take precedence
|
|
2628
|
+
...tsconfigAliases,
|
|
2629
|
+
...storybookAliases,
|
|
2403
2630
|
// Resolve @fragments-sdk/ui to local source or installed package
|
|
2404
2631
|
"@fragments-sdk/ui": uiLibRoot,
|
|
2405
2632
|
// Resolve @fragments-sdk/shared to monorepo source or vendored fallback
|
|
2406
2633
|
"@fragments-sdk/shared": sharedLibRoot,
|
|
2407
2634
|
// Resolve @fragments-sdk/webmcp subpaths to monorepo source or installed package
|
|
2408
|
-
"@fragments-sdk/webmcp/react": join(webmcpLibRoot, "react/index.ts"),
|
|
2409
|
-
"@fragments-sdk/webmcp/fragments": join(webmcpLibRoot, "fragments/index.ts"),
|
|
2635
|
+
"@fragments-sdk/webmcp/react": isWebMCPSource ? join(webmcpLibRoot, "react/index.ts") : join(webmcpLibRoot, "dist/react/index.js"),
|
|
2636
|
+
"@fragments-sdk/webmcp/fragments": isWebMCPSource ? join(webmcpLibRoot, "fragments/index.ts") : join(webmcpLibRoot, "dist/fragments/index.js"),
|
|
2410
2637
|
"@fragments-sdk/webmcp": webmcpLibRoot,
|
|
2411
2638
|
// Resolve @fragments-sdk/context subpaths to monorepo source or installed package
|
|
2412
|
-
"@fragments-sdk/context/types": join(contextLibRoot, "types/index.ts"),
|
|
2413
|
-
"@fragments-sdk/context/mcp-tools": join(contextLibRoot, "mcp-tools/index.ts"),
|
|
2639
|
+
"@fragments-sdk/context/types": isContextSource ? join(contextLibRoot, "types/index.ts") : join(contextLibRoot, "dist/types/index.js"),
|
|
2640
|
+
"@fragments-sdk/context/mcp-tools": isContextSource ? join(contextLibRoot, "mcp-tools/index.ts") : join(contextLibRoot, "dist/mcp-tools/index.js"),
|
|
2414
2641
|
"@fragments-sdk/context": contextLibRoot,
|
|
2415
2642
|
// Resolve @fragments-sdk/cli/core to the CLI's own core source
|
|
2416
2643
|
"@fragments-sdk/cli/core": resolve2(cliPackageRoot, "src/core/index.ts"),
|
|
@@ -2481,4 +2708,4 @@ export {
|
|
|
2481
2708
|
createDevServer,
|
|
2482
2709
|
fragmentsPlugin
|
|
2483
2710
|
};
|
|
2484
|
-
//# sourceMappingURL=viewer-
|
|
2711
|
+
//# sourceMappingURL=viewer-RFA2KVBG.js.map
|