@fragments-sdk/cli 0.9.0 → 0.10.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/bin.d.ts +1 -0
- package/dist/bin.js +502 -84
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-CJEGT3WD.js → chunk-566BNPQZ.js} +21 -6
- package/dist/chunk-566BNPQZ.js.map +1 -0
- package/dist/{chunk-WI6SLMSO.js → chunk-CAMXG5HJ.js} +5 -5
- package/dist/chunk-D2CDBRNU.js +2 -0
- package/dist/{chunk-YMPGYEWK.js → chunk-D5PYOXEI.js} +2 -2
- package/dist/{chunk-NGIMCIK2.js → chunk-OQO55NKV.js} +405 -34
- package/dist/chunk-OQO55NKV.js.map +1 -0
- package/dist/{chunk-TOIE7VXF.js → chunk-PW7QTQA6.js} +2 -2
- package/dist/{chunk-AWYCDRPG.js → chunk-WXSR2II7.js} +2 -2
- package/dist/chunk-WXSR2II7.js.map +1 -0
- package/dist/{chunk-2JIKCJX3.js → chunk-ZDA3PLQ6.js} +17 -14
- package/dist/chunk-ZDA3PLQ6.js.map +1 -0
- package/dist/core/index.d.ts +1 -2092
- package/dist/core/index.js +26 -21
- package/dist/{discovery-Z4RDDFVR.js → discovery-NEOY4MPN.js} +3 -3
- package/dist/generate-BGKTKO6E.js +459 -0
- package/dist/generate-BGKTKO6E.js.map +1 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{init-KSAAS7X3.js → init-Q53R5Q2T.js} +66 -76
- package/dist/init-Q53R5Q2T.js.map +1 -0
- package/dist/mcp-bin.js +5 -7
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-OQU7M4GH.js +14 -0
- package/dist/scan-generate-T5QNUG7N.js +691 -0
- package/dist/scan-generate-T5QNUG7N.js.map +1 -0
- package/dist/{service-A5GIGGGK.js → service-TQYWY65E.js} +4 -5
- package/dist/{static-viewer-NSODM5VX.js → static-viewer-NUBFPKWH.js} +4 -5
- package/dist/static-viewer-NUBFPKWH.js.map +1 -0
- package/dist/{test-RPWZAYSJ.js → test-2CSOSS3B.js} +4 -5
- package/dist/{test-RPWZAYSJ.js.map → test-2CSOSS3B.js.map} +1 -1
- package/dist/{tokens-NIXSZRX7.js → tokens-DXEGYTOJ.js} +6 -7
- package/dist/{tokens-NIXSZRX7.js.map → tokens-DXEGYTOJ.js.map} +1 -1
- package/dist/{viewer-SBTJDMP7.js → viewer-DBEPYM3G.js} +245 -23
- package/dist/viewer-DBEPYM3G.js.map +1 -0
- package/package.json +2 -1
- package/src/bin.ts +33 -1
- package/src/build.ts +13 -3
- package/src/commands/__tests__/scan-generate.test.ts +308 -0
- package/src/commands/build.ts +16 -2
- package/src/commands/generate.ts +383 -68
- package/src/commands/init.ts +81 -56
- package/src/commands/perf.ts +1 -1
- package/src/commands/scan-generate.ts +1013 -0
- package/src/commands/setup.ts +499 -0
- package/src/core/auto-props.ts +1 -1
- package/src/core/bundle-measurer.ts +2 -2
- package/src/core/config.ts +16 -4
- package/src/core/discovery.ts +2 -2
- package/src/core/generators/context.ts +1 -1
- package/src/core/generators/registry.ts +3 -3
- package/src/core/generators/typescript-extractor.ts +11 -1
- package/src/core/graph-extractor.ts +1 -1
- package/src/core/index.ts +3 -190
- package/src/core/loader.ts +2 -2
- package/src/core/parser.ts +1 -1
- package/src/core/previewLoader.ts +1 -1
- package/src/index.ts +2 -2
- package/src/migrate/converter.ts +9 -1
- package/src/migrate/parser.ts +2 -0
- package/src/migrate/types.ts +2 -0
- package/src/service/snippet-validation.test.ts +1 -1
- package/src/service/snippet-validation.ts +2 -2
- package/src/setup.ts +69 -24
- package/src/viewer/__tests__/viewer-integration.test.ts +4 -10
- 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 +169 -2
- 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/DocsHeaderBar.tsx +6 -18
- package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
- package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +5 -16
- 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 +114 -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/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-AWYCDRPG.js.map +0 -1
- package/dist/chunk-CJEGT3WD.js.map +0 -1
- package/dist/chunk-EKLMXTWU.js +0 -80
- package/dist/chunk-EKLMXTWU.js.map +0 -1
- package/dist/chunk-GOVI6COW.js +0 -195
- package/dist/chunk-GOVI6COW.js.map +0 -1
- package/dist/chunk-NGIMCIK2.js.map +0 -1
- package/dist/defineFragment-D0UTve-I.d.ts +0 -665
- package/dist/generate-35OIMW4Y.js +0 -252
- package/dist/generate-35OIMW4Y.js.map +0 -1
- package/dist/init-KSAAS7X3.js.map +0 -1
- package/dist/scan-65RH3QMM.js +0 -15
- package/dist/viewer-SBTJDMP7.js.map +0 -1
- package/src/core/__tests__/preview-runtime.test.tsx +0 -111
- package/src/core/composition.test.ts +0 -262
- package/src/core/composition.ts +0 -318
- package/src/core/constants.ts +0 -114
- package/src/core/context.ts +0 -2
- package/src/core/defineFragment.ts +0 -141
- package/src/core/figma.ts +0 -263
- package/src/core/fragment-types.ts +0 -214
- package/src/core/performance-presets.ts +0 -142
- package/src/core/preview-runtime.tsx +0 -144
- package/src/core/schema.ts +0 -221
- package/src/core/storyAdapter.test.ts +0 -571
- package/src/core/storyAdapter.ts +0 -761
- package/src/core/storybook-csf.ts +0 -11
- package/src/core/token-parser.ts +0 -321
- package/src/core/token-types.ts +0 -287
- package/src/core/types.ts +0 -762
- /package/dist/{chunk-WI6SLMSO.js.map → chunk-CAMXG5HJ.js.map} +0 -0
- /package/dist/{discovery-Z4RDDFVR.js.map → chunk-D2CDBRNU.js.map} +0 -0
- /package/dist/{chunk-YMPGYEWK.js.map → chunk-D5PYOXEI.js.map} +0 -0
- /package/dist/{chunk-TOIE7VXF.js.map → chunk-PW7QTQA6.js.map} +0 -0
- /package/dist/{scan-65RH3QMM.js.map → discovery-NEOY4MPN.js.map} +0 -0
- /package/dist/{service-A5GIGGGK.js.map → scan-OQU7M4GH.js.map} +0 -0
- /package/dist/{static-viewer-NSODM5VX.js.map → service-TQYWY65E.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,18 +5,16 @@ import {
|
|
|
5
5
|
generatePreviewModule,
|
|
6
6
|
loadConfig,
|
|
7
7
|
parseFragmentFile
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-566BNPQZ.js";
|
|
9
9
|
import {
|
|
10
10
|
discoverFragmentFiles,
|
|
11
11
|
discoverInstalledFragments
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WXSR2II7.js";
|
|
13
|
+
import "./chunk-D2CDBRNU.js";
|
|
13
14
|
import {
|
|
15
|
+
BRAND,
|
|
14
16
|
generateContext
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-GOVI6COW.js";
|
|
17
|
-
import {
|
|
18
|
-
BRAND
|
|
19
|
-
} from "./chunk-EKLMXTWU.js";
|
|
17
|
+
} from "./chunk-OQO55NKV.js";
|
|
20
18
|
import "./chunk-Z7EY4VHE.js";
|
|
21
19
|
|
|
22
20
|
// src/viewer/server.ts
|
|
@@ -28,6 +26,7 @@ import {
|
|
|
28
26
|
import react from "@vitejs/plugin-react";
|
|
29
27
|
import { resolve as resolve2, dirname as dirname2, join } from "path";
|
|
30
28
|
import { existsSync, realpathSync } from "fs";
|
|
29
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
31
30
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
32
31
|
|
|
33
32
|
// src/viewer/vite-plugin.ts
|
|
@@ -361,7 +360,7 @@ var sharedRenderPool = null;
|
|
|
361
360
|
var browserPoolModule = null;
|
|
362
361
|
async function getSharedRenderPool() {
|
|
363
362
|
if (!browserPoolModule) {
|
|
364
|
-
browserPoolModule = await import("./service-
|
|
363
|
+
browserPoolModule = await import("./service-TQYWY65E.js");
|
|
365
364
|
}
|
|
366
365
|
if (!sharedRenderPool) {
|
|
367
366
|
sharedRenderPool = new browserPoolModule.BrowserPool({
|
|
@@ -604,7 +603,7 @@ function fragmentsPlugin(options) {
|
|
|
604
603
|
const address = _server.httpServer?.address();
|
|
605
604
|
const port = typeof address === "object" && address ? address.port : 6006;
|
|
606
605
|
const renderViewport = viewport || { width: 800, height: 600 };
|
|
607
|
-
const { FigmaClient, bufferToBase64Url } = await import("./service-
|
|
606
|
+
const { FigmaClient, bufferToBase64Url } = await import("./service-TQYWY65E.js");
|
|
608
607
|
const figmaClient = new FigmaClient({
|
|
609
608
|
accessToken: figmaToken
|
|
610
609
|
});
|
|
@@ -695,7 +694,7 @@ function fragmentsPlugin(options) {
|
|
|
695
694
|
);
|
|
696
695
|
return;
|
|
697
696
|
}
|
|
698
|
-
const { FigmaClient } = await import("./service-
|
|
697
|
+
const { FigmaClient } = await import("./service-TQYWY65E.js");
|
|
699
698
|
const figmaClient = new FigmaClient({ accessToken: figmaToken });
|
|
700
699
|
const { fileKey, nodeId } = figmaClient.parseUrl(figmaUrl);
|
|
701
700
|
const figmaDesignProps = await figmaClient.getNodeProperties(
|
|
@@ -736,7 +735,7 @@ function fragmentsPlugin(options) {
|
|
|
736
735
|
}));
|
|
737
736
|
return;
|
|
738
737
|
}
|
|
739
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
738
|
+
const { getSharedTokenRegistry } = await import("./service-TQYWY65E.js");
|
|
740
739
|
const registry = getSharedTokenRegistry();
|
|
741
740
|
if (!registry.isInitialized()) {
|
|
742
741
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -796,7 +795,7 @@ function fragmentsPlugin(options) {
|
|
|
796
795
|
}));
|
|
797
796
|
return;
|
|
798
797
|
}
|
|
799
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
798
|
+
const { getSharedTokenRegistry } = await import("./service-TQYWY65E.js");
|
|
800
799
|
const registry = getSharedTokenRegistry();
|
|
801
800
|
if (!registry.isInitialized()) {
|
|
802
801
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -858,7 +857,7 @@ function fragmentsPlugin(options) {
|
|
|
858
857
|
res.end(JSON.stringify({ error: "Could not resolve fragment file path" }));
|
|
859
858
|
return;
|
|
860
859
|
}
|
|
861
|
-
const { getSharedTokenRegistry } = await import("./service-
|
|
860
|
+
const { getSharedTokenRegistry } = await import("./service-TQYWY65E.js");
|
|
862
861
|
const registry = getSharedTokenRegistry();
|
|
863
862
|
if (!registry.isInitialized()) {
|
|
864
863
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -1036,7 +1035,7 @@ function fragmentsPlugin(options) {
|
|
|
1036
1035
|
}
|
|
1037
1036
|
if (!config.tokens || !config.tokens.include || config.tokens.include.length === 0) {
|
|
1038
1037
|
try {
|
|
1039
|
-
const { discoverTokenFiles } = await import("./discovery-
|
|
1038
|
+
const { discoverTokenFiles } = await import("./discovery-NEOY4MPN.js");
|
|
1040
1039
|
const discovered = await discoverTokenFiles(projectRoot);
|
|
1041
1040
|
if (discovered.length > 0) {
|
|
1042
1041
|
config.tokens = {
|
|
@@ -1073,7 +1072,7 @@ function fragmentsPlugin(options) {
|
|
|
1073
1072
|
const {
|
|
1074
1073
|
getSharedTokenRegistry,
|
|
1075
1074
|
generateTokenPatches
|
|
1076
|
-
} = await import("./service-
|
|
1075
|
+
} = await import("./service-TQYWY65E.js");
|
|
1077
1076
|
const registry = getSharedTokenRegistry();
|
|
1078
1077
|
if (!registry.isInitialized()) {
|
|
1079
1078
|
await registry.initialize(config.tokens, projectRoot);
|
|
@@ -1370,7 +1369,7 @@ function fragmentsPlugin(options) {
|
|
|
1370
1369
|
// Load virtual modules
|
|
1371
1370
|
load(id) {
|
|
1372
1371
|
if (id === VIRTUAL_FRAGMENTS_RESOLVED) {
|
|
1373
|
-
return generateFragmentsModule(fragmentFiles, config, previewConfigPath);
|
|
1372
|
+
return generateFragmentsModule(fragmentFiles, config, previewConfigPath, projectRoot);
|
|
1374
1373
|
}
|
|
1375
1374
|
if (id === VIRTUAL_VIEWER_ENTRY_RESOLVED) {
|
|
1376
1375
|
return generateViewerEntry();
|
|
@@ -1455,6 +1454,14 @@ function extractComponentName(filePath) {
|
|
|
1455
1454
|
const match = filePath.match(/([^/\\]+)\.(fragment|stories)\.(tsx?|jsx?)$/);
|
|
1456
1455
|
return match ? match[1] : filePath.split("/").pop() || filePath;
|
|
1457
1456
|
}
|
|
1457
|
+
async function readProjectPackageName(root) {
|
|
1458
|
+
try {
|
|
1459
|
+
const pkgJson = JSON.parse(await readFile(resolve(root, "package.json"), "utf-8"));
|
|
1460
|
+
return pkgJson.name || null;
|
|
1461
|
+
} catch {
|
|
1462
|
+
return null;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1458
1465
|
async function extractDependenciesFromSource(absolutePath) {
|
|
1459
1466
|
try {
|
|
1460
1467
|
const source = await readFile(absolutePath, "utf-8");
|
|
@@ -1471,7 +1478,7 @@ async function extractDependenciesFromSource(absolutePath) {
|
|
|
1471
1478
|
return [];
|
|
1472
1479
|
}
|
|
1473
1480
|
}
|
|
1474
|
-
async function generateFragmentsModule(fragmentFiles, config, previewConfigPath) {
|
|
1481
|
+
async function generateFragmentsModule(fragmentFiles, config, previewConfigPath, projectRoot) {
|
|
1475
1482
|
const authoredVariantCodeCache = /* @__PURE__ */ new Map();
|
|
1476
1483
|
async function loadAuthoredVariantCode(fragmentFilePath) {
|
|
1477
1484
|
if (authoredVariantCodeCache.has(fragmentFilePath)) {
|
|
@@ -1494,6 +1501,9 @@ async function generateFragmentsModule(fragmentFiles, config, previewConfigPath)
|
|
|
1494
1501
|
return {};
|
|
1495
1502
|
}
|
|
1496
1503
|
}
|
|
1504
|
+
const storyOnlyFiles = fragmentFiles.filter((f) => isStoryFile(f.relativePath));
|
|
1505
|
+
const { detectSubComponentPaths: _detectSubs } = await import("./core/index.js");
|
|
1506
|
+
const subComponentMap = _detectSubs(storyOnlyFiles);
|
|
1497
1507
|
const filesByBasePath = /* @__PURE__ */ new Map();
|
|
1498
1508
|
for (const file of fragmentFiles) {
|
|
1499
1509
|
const basePath = getBaseComponentPath(file.relativePath);
|
|
@@ -1517,11 +1527,14 @@ async function generateFragmentsModule(fragmentFiles, config, previewConfigPath)
|
|
|
1517
1527
|
const componentName = extractComponentName(primaryFile.relativePath);
|
|
1518
1528
|
const fragmentSource = files.fragmentFile || primaryFile;
|
|
1519
1529
|
const dependencies = await extractDependenciesFromSource(fragmentSource.absolutePath);
|
|
1530
|
+
const parentComponent = isStory ? subComponentMap.get(primaryFile.relativePath) : void 0;
|
|
1520
1531
|
return ` {
|
|
1521
1532
|
path: "${primaryFile.relativePath}",
|
|
1522
1533
|
isStory: ${isStory},
|
|
1523
1534
|
componentName: ${JSON.stringify(componentName)},
|
|
1524
1535
|
dependencies: ${JSON.stringify(dependencies)},
|
|
1536
|
+
isSubComponent: ${!!parentComponent},
|
|
1537
|
+
parentComponent: ${parentComponent ? JSON.stringify(parentComponent) : "null"},
|
|
1525
1538
|
loader: () => import("${primaryFile.absolutePath}"),
|
|
1526
1539
|
metadataLoader: ${metadataPath ? `() => import("${metadataPath}")` : "null"},
|
|
1527
1540
|
authoredVariantCode: ${JSON.stringify(authoredVariantCode)}
|
|
@@ -1541,10 +1554,14 @@ setPreviewConfig({
|
|
|
1541
1554
|
loaders: previewConfig.loaders,
|
|
1542
1555
|
});
|
|
1543
1556
|
` : "";
|
|
1557
|
+
const storybookFilterConfig = JSON.stringify(config.storybook ?? {});
|
|
1544
1558
|
return `
|
|
1545
|
-
import { storyModuleToFragment, setPreviewConfig } from "@fragments-sdk/cli/core";
|
|
1559
|
+
import { storyModuleToFragment, setPreviewConfig, checkStoryExclusion, isForceIncluded, isConfigExcluded } from "@fragments-sdk/cli/core";
|
|
1546
1560
|
${previewImport}
|
|
1547
1561
|
${previewSetup}
|
|
1562
|
+
// Storybook filter config (deep-merged with defaults at build time)
|
|
1563
|
+
const storybookFilterConfig = ${storybookFilterConfig};
|
|
1564
|
+
|
|
1548
1565
|
// Lazy fragment loaders (supports both .fragment.tsx and .stories.tsx)
|
|
1549
1566
|
const fragmentLoaders = [
|
|
1550
1567
|
${loaders}
|
|
@@ -1607,8 +1624,24 @@ function mergeAuthoredVariantCode(fragment, authoredVariantCode) {
|
|
|
1607
1624
|
return fragment;
|
|
1608
1625
|
}
|
|
1609
1626
|
|
|
1627
|
+
// Diagnostics: track exclusions for FRAGMENTS_DEBUG
|
|
1628
|
+
const exclusionLog = [];
|
|
1629
|
+
|
|
1630
|
+
/**
|
|
1631
|
+
* Try to load a paired .fragment.tsx file as fallback when a story is excluded.
|
|
1632
|
+
* Returns the fragment if available, null otherwise.
|
|
1633
|
+
*/
|
|
1634
|
+
async function tryFallbackFragment(loader) {
|
|
1635
|
+
if (!loader.metadataLoader) return null;
|
|
1636
|
+
try {
|
|
1637
|
+
const mod = await loader.metadataLoader();
|
|
1638
|
+
return mod?.default ? { path: loader.path, fragment: mod.default } : null;
|
|
1639
|
+
} catch { return null; }
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1610
1642
|
// Load all fragments (for initial render)
|
|
1611
1643
|
// Gracefully handles individual failures - one bad story won't break all fragments
|
|
1644
|
+
// Applies smart filtering for Storybook stories (SVG icons, deprecated, test stories, sub-components)
|
|
1612
1645
|
export async function loadAllFragments() {
|
|
1613
1646
|
const results = await Promise.all(
|
|
1614
1647
|
fragmentLoaders.map(async (loader) => {
|
|
@@ -1618,6 +1651,30 @@ export async function loadAllFragments() {
|
|
|
1618
1651
|
return cached ? { path: loader.path, fragment: cached } : null;
|
|
1619
1652
|
}
|
|
1620
1653
|
|
|
1654
|
+
// --- Pre-load filtering (config-level and sub-component checks) ---
|
|
1655
|
+
if (loader.isStory) {
|
|
1656
|
+
// Force-include bypasses all filters
|
|
1657
|
+
if (!isForceIncluded(loader.componentName, storybookFilterConfig)) {
|
|
1658
|
+
// Config explicit exclude
|
|
1659
|
+
if (isConfigExcluded(loader.componentName, storybookFilterConfig)) {
|
|
1660
|
+
exclusionLog.push({ component: loader.componentName, reason: 'config-excluded', detail: 'Matches storybook.exclude pattern', path: loader.path });
|
|
1661
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1662
|
+
if (fallback) return fallback;
|
|
1663
|
+
loadedFragments.set(loader.path, null);
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
// Sub-component check (directory-based, computed at build time)
|
|
1668
|
+
if (loader.isSubComponent && storybookFilterConfig.excludeSubComponents !== false) {
|
|
1669
|
+
exclusionLog.push({ component: loader.componentName, reason: 'sub-component', detail: 'Sub-component of ' + loader.parentComponent, path: loader.path });
|
|
1670
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1671
|
+
if (fallback) return fallback;
|
|
1672
|
+
loadedFragments.set(loader.path, null);
|
|
1673
|
+
return null;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1621
1678
|
const module = await loader.loader();
|
|
1622
1679
|
|
|
1623
1680
|
// Convert story modules to fragments at runtime
|
|
@@ -1629,6 +1686,29 @@ export async function loadAllFragments() {
|
|
|
1629
1686
|
loadedFragments.set(loader.path, null);
|
|
1630
1687
|
return null;
|
|
1631
1688
|
}
|
|
1689
|
+
|
|
1690
|
+
// --- Post-load filtering (needs loaded module data) ---
|
|
1691
|
+
if (!isForceIncluded(loader.componentName, storybookFilterConfig)) {
|
|
1692
|
+
const meta = module.default || {};
|
|
1693
|
+
const exclusion = checkStoryExclusion({
|
|
1694
|
+
storybookTitle: meta.title,
|
|
1695
|
+
componentName: fragment.meta?.name || loader.componentName,
|
|
1696
|
+
componentDisplayName: meta.component?.displayName,
|
|
1697
|
+
componentFunctionName: meta.component?.name,
|
|
1698
|
+
tags: meta.tags,
|
|
1699
|
+
variantCount: fragment.variants?.length || 0,
|
|
1700
|
+
filePath: loader.path,
|
|
1701
|
+
config: storybookFilterConfig,
|
|
1702
|
+
});
|
|
1703
|
+
|
|
1704
|
+
if (exclusion.excluded) {
|
|
1705
|
+
exclusionLog.push({ component: fragment.meta?.name || loader.componentName, reason: exclusion.reason, detail: exclusion.detail, path: loader.path });
|
|
1706
|
+
const fallback = await tryFallbackFragment(loader);
|
|
1707
|
+
if (fallback) return fallback;
|
|
1708
|
+
loadedFragments.set(loader.path, null);
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1632
1712
|
} else {
|
|
1633
1713
|
fragment = module.default;
|
|
1634
1714
|
}
|
|
@@ -1670,6 +1750,15 @@ export async function loadAllFragments() {
|
|
|
1670
1750
|
}
|
|
1671
1751
|
})
|
|
1672
1752
|
);
|
|
1753
|
+
|
|
1754
|
+
// Log exclusions in debug mode
|
|
1755
|
+
if (exclusionLog.length > 0) {
|
|
1756
|
+
console.log("[Fragments] Filtered " + exclusionLog.length + " component(s)");
|
|
1757
|
+
if (typeof process !== 'undefined' && process.env?.FRAGMENTS_DEBUG) {
|
|
1758
|
+
console.table(exclusionLog);
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1673
1762
|
// Filter out nulls (fragments that had no component)
|
|
1674
1763
|
return results.filter(r => r !== null);
|
|
1675
1764
|
}
|
|
@@ -1718,9 +1807,12 @@ export async function loadFragment(path) {
|
|
|
1718
1807
|
let fragments = [];
|
|
1719
1808
|
const fragmentsPromise = loadAllFragments().then(s => { fragments = s; return s; });
|
|
1720
1809
|
|
|
1721
|
-
export { fragments, fragmentsPromise };
|
|
1810
|
+
export { fragments, fragmentsPromise, exclusionLog };
|
|
1722
1811
|
export const config = ${JSON.stringify(config)};
|
|
1723
1812
|
|
|
1813
|
+
// Auto-detect consumer package name from package.json
|
|
1814
|
+
export const projectPackageName = ${JSON.stringify(await readProjectPackageName(projectRoot))};
|
|
1815
|
+
|
|
1724
1816
|
// HMR support
|
|
1725
1817
|
if (import.meta.hot) {
|
|
1726
1818
|
import.meta.hot.accept();
|
|
@@ -2088,7 +2180,7 @@ async function loadFullFragmentForCompare(_server, _fragmentFiles, componentName
|
|
|
2088
2180
|
}
|
|
2089
2181
|
}
|
|
2090
2182
|
async function compareImages(image1Base64, image2Base64, threshold) {
|
|
2091
|
-
const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-
|
|
2183
|
+
const { DiffEngine, base64UrlToBuffer, bufferToBase64Url } = await import("./service-TQYWY65E.js");
|
|
2092
2184
|
const { PNG } = await import("pngjs");
|
|
2093
2185
|
const buffer1 = base64UrlToBuffer(image1Base64);
|
|
2094
2186
|
const buffer2 = base64UrlToBuffer(image2Base64);
|
|
@@ -2308,6 +2400,100 @@ export function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServ
|
|
|
2308
2400
|
}
|
|
2309
2401
|
};
|
|
2310
2402
|
}
|
|
2403
|
+
function optionalPeerDepsPlugin(uiLibRoot) {
|
|
2404
|
+
const optionalDeps = [
|
|
2405
|
+
"@tanstack/react-table",
|
|
2406
|
+
"shiki",
|
|
2407
|
+
"recharts",
|
|
2408
|
+
"react-day-picker",
|
|
2409
|
+
"date-fns",
|
|
2410
|
+
"react-colorful",
|
|
2411
|
+
"react-markdown",
|
|
2412
|
+
"remark-gfm",
|
|
2413
|
+
"@tiptap/react",
|
|
2414
|
+
"@tiptap/starter-kit",
|
|
2415
|
+
"@tiptap/extension-link"
|
|
2416
|
+
];
|
|
2417
|
+
let resolvedUiRoot;
|
|
2418
|
+
try {
|
|
2419
|
+
resolvedUiRoot = realpathSync(uiLibRoot);
|
|
2420
|
+
} catch {
|
|
2421
|
+
resolvedUiRoot = uiLibRoot;
|
|
2422
|
+
}
|
|
2423
|
+
const availableDeps = /* @__PURE__ */ new Set();
|
|
2424
|
+
for (const dep of optionalDeps) {
|
|
2425
|
+
const depPath = join(uiLibRoot, "..", "node_modules", ...dep.split("/"));
|
|
2426
|
+
if (existsSync(depPath)) availableDeps.add(dep);
|
|
2427
|
+
}
|
|
2428
|
+
return {
|
|
2429
|
+
name: "fragments:optional-peer-deps",
|
|
2430
|
+
enforce: "pre",
|
|
2431
|
+
transform(code, id) {
|
|
2432
|
+
let resolvedId;
|
|
2433
|
+
try {
|
|
2434
|
+
resolvedId = realpathSync(id);
|
|
2435
|
+
} catch {
|
|
2436
|
+
resolvedId = id;
|
|
2437
|
+
}
|
|
2438
|
+
if (!resolvedId.startsWith(resolvedUiRoot)) return;
|
|
2439
|
+
if (!id.endsWith(".tsx") && !id.endsWith(".ts")) return;
|
|
2440
|
+
if (!code.includes("require(")) return;
|
|
2441
|
+
let transformed = code;
|
|
2442
|
+
const imports = [];
|
|
2443
|
+
let counter = 0;
|
|
2444
|
+
for (const dep of availableDeps) {
|
|
2445
|
+
const escapedDep = dep.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2446
|
+
const regex = new RegExp(`require\\(['"]${escapedDep}['"]\\)`, "g");
|
|
2447
|
+
if (regex.test(code)) {
|
|
2448
|
+
const varName = `__fui_dep_${counter++}`;
|
|
2449
|
+
imports.push(`import * as ${varName} from '${dep}';`);
|
|
2450
|
+
regex.lastIndex = 0;
|
|
2451
|
+
transformed = transformed.replace(regex, varName);
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
if (imports.length > 0) {
|
|
2455
|
+
transformed = imports.join("\n") + "\n" + transformed;
|
|
2456
|
+
return { code: transformed, map: null };
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
async function detectTsconfigPaths(projectRoot) {
|
|
2462
|
+
const aliases = {};
|
|
2463
|
+
const tsconfigPath = join(projectRoot, "tsconfig.json");
|
|
2464
|
+
if (!existsSync(tsconfigPath)) return aliases;
|
|
2465
|
+
try {
|
|
2466
|
+
const content = await readFile2(tsconfigPath, "utf-8");
|
|
2467
|
+
const cleaned = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
2468
|
+
const tsconfig = JSON.parse(cleaned);
|
|
2469
|
+
const paths = tsconfig?.compilerOptions?.paths;
|
|
2470
|
+
const baseUrl = tsconfig?.compilerOptions?.baseUrl || ".";
|
|
2471
|
+
if (paths) {
|
|
2472
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
2473
|
+
const target = targets[0];
|
|
2474
|
+
if (target) {
|
|
2475
|
+
const cleanAlias = alias.replace("/*", "");
|
|
2476
|
+
const cleanTarget = target.replace("/*", "");
|
|
2477
|
+
aliases[cleanAlias] = resolve2(projectRoot, baseUrl, cleanTarget);
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
} catch {
|
|
2482
|
+
}
|
|
2483
|
+
return aliases;
|
|
2484
|
+
}
|
|
2485
|
+
async function detectStorybookAliases(projectRoot) {
|
|
2486
|
+
const aliases = {};
|
|
2487
|
+
const assetsDir = resolve2(projectRoot, "assets");
|
|
2488
|
+
const fontsDir = resolve2(projectRoot, "assets/fonts");
|
|
2489
|
+
if (existsSync(fontsDir)) {
|
|
2490
|
+
aliases["/fonts"] = fontsDir;
|
|
2491
|
+
}
|
|
2492
|
+
if (existsSync(assetsDir)) {
|
|
2493
|
+
aliases["/assets"] = assetsDir;
|
|
2494
|
+
}
|
|
2495
|
+
return aliases;
|
|
2496
|
+
}
|
|
2311
2497
|
async function createDevServer(options = {}) {
|
|
2312
2498
|
const startTime = performance.now();
|
|
2313
2499
|
const {
|
|
@@ -2349,6 +2535,16 @@ async function createDevServer(options = {}) {
|
|
|
2349
2535
|
const isWebMCPSource = existsSync(join(webmcpLibRoot, "react/index.ts"));
|
|
2350
2536
|
const isContextSource = existsSync(join(contextLibRoot, "types/index.ts"));
|
|
2351
2537
|
console.log(`\u{1F4C1} Using node_modules: ${nodeModulesPath}`);
|
|
2538
|
+
const tsconfigAliases = await detectTsconfigPaths(projectRoot);
|
|
2539
|
+
const storybookAliases = await detectStorybookAliases(projectRoot);
|
|
2540
|
+
const storybookDir = resolve2(projectRoot, ".storybook");
|
|
2541
|
+
const hasStorybookDir = existsSync(storybookDir);
|
|
2542
|
+
if (Object.keys(tsconfigAliases).length > 0) {
|
|
2543
|
+
console.log(`\u{1F4CE} Detected ${Object.keys(tsconfigAliases).length} tsconfig path alias(es)`);
|
|
2544
|
+
}
|
|
2545
|
+
if (hasStorybookDir) {
|
|
2546
|
+
console.log(`\u{1F4D8} Detected .storybook directory`);
|
|
2547
|
+
}
|
|
2352
2548
|
const installedPkgRoots = [...new Set(
|
|
2353
2549
|
installedFiles.map((f) => {
|
|
2354
2550
|
const idx = f.absolutePath.indexOf("/node_modules/");
|
|
@@ -2370,8 +2566,19 @@ async function createDevServer(options = {}) {
|
|
|
2370
2566
|
port,
|
|
2371
2567
|
open: open ? "/fragments/" : false,
|
|
2372
2568
|
fs: {
|
|
2373
|
-
// Allow serving files from viewer package, project, shared libs,
|
|
2374
|
-
allow: [
|
|
2569
|
+
// Allow serving files from viewer package, project, shared libs, node_modules root, and .storybook
|
|
2570
|
+
allow: [
|
|
2571
|
+
viewerRoot,
|
|
2572
|
+
uiLibRoot,
|
|
2573
|
+
sharedLibRoot,
|
|
2574
|
+
webmcpLibRoot,
|
|
2575
|
+
contextLibRoot,
|
|
2576
|
+
projectRoot,
|
|
2577
|
+
configDir,
|
|
2578
|
+
dirname2(nodeModulesPath),
|
|
2579
|
+
...hasStorybookDir ? [storybookDir] : [],
|
|
2580
|
+
...installedPkgRoots
|
|
2581
|
+
]
|
|
2375
2582
|
}
|
|
2376
2583
|
},
|
|
2377
2584
|
plugins: [
|
|
@@ -2379,6 +2586,8 @@ async function createDevServer(options = {}) {
|
|
|
2379
2586
|
...hasReactPlugin(projectViteConfig) ? [] : [react()],
|
|
2380
2587
|
// CJS interop for packages imported from within node_modules
|
|
2381
2588
|
cjsInteropPlugin(nodeModulesPath),
|
|
2589
|
+
// Rewrite require() → ESM import for optional peer deps (e.g., @tanstack/react-table)
|
|
2590
|
+
optionalPeerDepsPlugin(uiLibRoot),
|
|
2382
2591
|
// Fragments plugins (array including SVGR)
|
|
2383
2592
|
...fragmentsPlugin({
|
|
2384
2593
|
fragmentFiles: allFragmentFiles,
|
|
@@ -2391,6 +2600,15 @@ async function createDevServer(options = {}) {
|
|
|
2391
2600
|
css: {
|
|
2392
2601
|
modules: {
|
|
2393
2602
|
localsConvention: "camelCase"
|
|
2603
|
+
},
|
|
2604
|
+
preprocessorOptions: {
|
|
2605
|
+
scss: {
|
|
2606
|
+
api: "modern-compiler",
|
|
2607
|
+
loadPaths: [
|
|
2608
|
+
resolve2(projectRoot, "src"),
|
|
2609
|
+
resolve2(projectRoot, "src/styles")
|
|
2610
|
+
]
|
|
2611
|
+
}
|
|
2394
2612
|
}
|
|
2395
2613
|
},
|
|
2396
2614
|
optimizeDeps: {
|
|
@@ -2402,6 +2620,10 @@ async function createDevServer(options = {}) {
|
|
|
2402
2620
|
// Dedupe ensures all imports of these packages resolve to the same copy
|
|
2403
2621
|
dedupe: ["react", "react-dom"],
|
|
2404
2622
|
alias: {
|
|
2623
|
+
// Project-specific aliases (tsconfig paths, Storybook static dirs)
|
|
2624
|
+
// Listed first — Fragments-specific aliases below take precedence
|
|
2625
|
+
...tsconfigAliases,
|
|
2626
|
+
...storybookAliases,
|
|
2405
2627
|
// Resolve @fragments-sdk/ui to local source or installed package
|
|
2406
2628
|
"@fragments-sdk/ui": uiLibRoot,
|
|
2407
2629
|
// Resolve @fragments-sdk/shared to monorepo source or vendored fallback
|
|
@@ -2483,4 +2705,4 @@ export {
|
|
|
2483
2705
|
createDevServer,
|
|
2484
2706
|
fragmentsPlugin
|
|
2485
2707
|
};
|
|
2486
|
-
//# sourceMappingURL=viewer-
|
|
2708
|
+
//# sourceMappingURL=viewer-DBEPYM3G.js.map
|