@yahoo/uds 3.122.2 → 3.123.0-beta.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/components/experimental/client/SegmentedControl.d.cts +2 -1
- package/dist/styles/styler.d.cts +12 -12
- package/dist/styles/styler.d.ts +12 -12
- package/dist/tailwind/dist/commands/css.cjs +17 -3
- package/dist/tailwind/dist/commands/css.d.cts.map +1 -1
- package/dist/tailwind/dist/commands/css.d.ts.map +1 -1
- package/dist/tailwind/dist/commands/css.helpers.cjs +2 -1
- package/dist/tailwind/dist/commands/css.helpers.js +2 -1
- package/dist/tailwind/dist/commands/css.helpers.js.map +1 -1
- package/dist/tailwind/dist/commands/css.js +17 -3
- package/dist/tailwind/dist/commands/css.js.map +1 -1
- package/dist/tailwind/dist/css/generate.cjs +3 -0
- package/dist/tailwind/dist/css/generate.helpers.cjs +14 -6
- package/dist/tailwind/dist/css/generate.helpers.js +15 -7
- package/dist/tailwind/dist/css/generate.helpers.js.map +1 -1
- package/dist/tailwind/dist/css/generate.js +3 -0
- package/dist/tailwind/dist/css/generate.js.map +1 -1
- package/dist/tailwind/dist/css/nodeUtils.cjs +91 -20
- package/dist/tailwind/dist/css/nodeUtils.js +90 -21
- package/dist/tailwind/dist/css/nodeUtils.js.map +1 -1
- package/dist/tailwind/dist/css/postcss.cjs +22 -1
- package/dist/tailwind/dist/css/postcss.helpers.cjs +12 -1
- package/dist/tailwind/dist/css/postcss.helpers.js +11 -1
- package/dist/tailwind/dist/css/postcss.helpers.js.map +1 -1
- package/dist/tailwind/dist/css/postcss.js +22 -2
- package/dist/tailwind/dist/css/postcss.js.map +1 -1
- package/dist/tailwind/dist/css/runner.cjs +171 -20
- package/dist/tailwind/dist/css/runner.helpers.cjs +58 -6
- package/dist/tailwind/dist/css/runner.helpers.js +54 -7
- package/dist/tailwind/dist/css/runner.helpers.js.map +1 -1
- package/dist/tailwind/dist/css/runner.js +172 -20
- package/dist/tailwind/dist/css/runner.js.map +1 -1
- package/dist/tailwind/dist/css/theme.d.cts +11 -0
- package/dist/tailwind/dist/css/theme.d.cts.map +1 -1
- package/dist/tailwind/dist/css/theme.d.ts +11 -0
- package/dist/tailwind/dist/css/theme.d.ts.map +1 -1
- package/dist/tailwind/dist/css/theme.js.map +1 -1
- package/dist/tailwind/dist/purger/optimized/ast/expressions.cjs +26 -3
- package/dist/tailwind/dist/purger/optimized/ast/expressions.js +26 -3
- package/dist/tailwind/dist/purger/optimized/ast/expressions.js.map +1 -1
- package/dist/uds/dist/automated-config/dist/generated/universalTokensConfigAuto.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/properties.d.cts +5 -0
- package/dist/uds/dist/automated-config/dist/types/ComponentConfig.d.cts +3 -0
- package/dist/uds/dist/automated-config/dist/types/ComponentStyles.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/types/ConfigSchema.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/utils/buildConfigSchema.d.cts +7 -0
- package/dist/uds/dist/automated-config/dist/utils/coalesceConfigVariant.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/utils/defaults.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/utils/getConfigVariantComponentStatesMatrix.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/utils/getConfigVariantProperties.d.cts +3 -0
- package/dist/uds/dist/automated-config/dist/utils/getConfigVariantPseudoStates.d.cts +3 -0
- package/dist/uds/dist/automated-config/dist/utils/getConfigVariants.d.cts +2 -0
- package/dist/uds/dist/automated-config/dist/utils/index.d.cts +12 -0
- package/dist/uds/dist/automated-config/dist/utils/subcomponents.d.cts +2 -0
- package/dist/uds/dist/components/Box.d.cts +4 -0
- package/dist/uds/dist/components/Divider/Divider.d.cts +3 -0
- package/dist/uds/dist/components/Divider/DividerCore.d.cts +5 -0
- package/dist/uds/dist/components/Divider/DividerInternal.d.cts +5 -0
- package/dist/uds/dist/components/Divider/index.d.cts +2 -0
- package/dist/uds/dist/components/FormLabel.d.cts +4 -0
- package/dist/uds/dist/components/HStack.d.cts +5 -0
- package/dist/uds/dist/components/Icon.d.cts +4 -0
- package/dist/uds/dist/components/Image.d.cts +3 -0
- package/dist/uds/dist/components/Link.d.cts +4 -0
- package/dist/uds/dist/components/Scrim.d.cts +3 -0
- package/dist/uds/dist/components/Text.d.cts +4 -0
- package/dist/uds/dist/components/VStack.d.cts +5 -0
- package/dist/uds/dist/components/client/Avatar/Avatar.d.cts +2 -0
- package/dist/uds/dist/components/client/Avatar/AvatarIcon.d.cts +4 -0
- package/dist/uds/dist/components/client/Avatar/AvatarImage.d.cts +6 -0
- package/dist/uds/dist/components/client/Avatar/AvatarText.d.cts +4 -0
- package/dist/uds/dist/components/client/Avatar/index.d.cts +5 -0
- package/dist/uds/dist/components/client/Badge.d.cts +4 -0
- package/dist/uds/dist/components/client/BottomSheet/BottomSheet.d.cts +5 -0
- package/dist/uds/dist/components/client/BottomSheet/BottomSheetContent.d.cts +2 -0
- package/dist/uds/dist/components/client/BottomSheet/BottomSheetHeader.d.cts +2 -0
- package/dist/uds/dist/components/client/BottomSheet/BottomSheetProvider.d.cts +3 -0
- package/dist/uds/dist/components/client/BottomSheet/UDSBottomSheetConfigProvider.d.cts +3 -0
- package/dist/uds/dist/components/client/BottomSheet/index.d.cts +7 -0
- package/dist/uds/dist/components/client/BottomSheet/useBottomSheetStore.d.cts +2 -0
- package/dist/uds/dist/components/client/Button.d.cts +5 -0
- package/dist/uds/dist/components/client/Checkbox.d.cts +4 -0
- package/dist/uds/dist/components/client/Chip/Chip.d.cts +5 -0
- package/dist/uds/dist/components/client/Chip/ChipBase.d.cts +6 -0
- package/dist/uds/dist/components/client/Chip/ChipButton.d.cts +5 -0
- package/dist/uds/dist/components/client/Chip/ChipDismissible.d.cts +5 -0
- package/dist/uds/dist/components/client/Chip/ChipLink.d.cts +5 -0
- package/dist/uds/dist/components/client/Chip/ChipToggle.d.cts +5 -0
- package/dist/uds/dist/components/client/Chip/index.d.cts +6 -0
- package/dist/uds/dist/components/client/IconButton.d.cts +5 -0
- package/dist/uds/dist/components/client/Input/Input.d.cts +7 -0
- package/dist/uds/dist/components/client/Input/InputHelpText.d.cts +2 -0
- package/dist/uds/dist/components/client/Input/InputHelpTextInternal.d.cts +6 -0
- package/dist/uds/dist/components/client/Input/index.d.cts +3 -0
- package/dist/uds/dist/components/client/Menu/Menu.Content.d.cts +6 -0
- package/dist/uds/dist/components/client/Menu/Menu.Divider.d.cts +3 -0
- package/dist/uds/dist/components/client/Menu/Menu.Item.d.cts +6 -0
- package/dist/uds/dist/components/client/Menu/Menu.ItemCheckbox.d.cts +6 -0
- package/dist/uds/dist/components/client/Menu/Menu.Provider.d.cts +3 -0
- package/dist/uds/dist/components/client/Menu/Menu.Trigger.d.cts +5 -0
- package/dist/uds/dist/components/client/Menu/Menu.d.cts +2 -0
- package/dist/uds/dist/components/client/Menu/Menu.index.d.cts +9 -0
- package/dist/uds/dist/components/client/Menu/index.d.cts +9 -0
- package/dist/uds/dist/components/client/Popover/Popover.d.cts +2 -0
- package/dist/uds/dist/components/client/Popover/PopoverContent.d.cts +5 -0
- package/dist/uds/dist/components/client/Popover/PopoverTrigger.d.cts +2 -0
- package/dist/uds/dist/components/client/Popover/UDSPopoverConfigProvider.d.cts +4 -0
- package/dist/uds/dist/components/client/Popover/index.d.cts +6 -0
- package/dist/uds/dist/components/client/Pressable.d.cts +4 -0
- package/dist/uds/dist/components/client/Radio/Radio.d.cts +4 -0
- package/dist/uds/dist/components/client/Radio/RadioGroupProvider.d.cts +4 -0
- package/dist/uds/dist/components/client/Radio/index.d.cts +3 -0
- package/dist/uds/dist/components/client/SpringMotionConfig.d.cts +5 -0
- package/dist/uds/dist/components/client/Switch.d.cts +4 -0
- package/dist/uds/dist/components/client/Toast/Toast.d.cts +8 -0
- package/dist/uds/dist/components/client/Toast/ToastContainer.d.cts +6 -0
- package/dist/uds/dist/components/client/Toast/ToastPortal.d.cts +3 -0
- package/dist/uds/dist/components/client/Toast/UDSToastConfigProvider.d.cts +5 -0
- package/dist/uds/dist/components/client/Toast/createToast.d.cts +6 -0
- package/dist/uds/dist/components/client/Toast/index.d.cts +6 -0
- package/dist/uds/dist/components/client/Tooltip/Tooltip.d.cts +2 -0
- package/dist/uds/dist/components/client/Tooltip/TooltipContent.d.cts +3 -0
- package/dist/uds/dist/components/client/Tooltip/TooltipTrigger.d.cts +2 -0
- package/dist/uds/dist/components/client/Tooltip/UDSTooltipConfigProvider.d.cts +5 -0
- package/dist/uds/dist/components/client/Tooltip/index.d.cts +6 -0
- package/dist/uds/dist/components/client/index.d.cts +59 -0
- package/dist/uds/dist/components/client/providers/UDSBreakpointsConfigProvider.d.cts +4 -0
- package/dist/uds/dist/components/client/providers/UDSConfigProvider.d.cts +3 -0
- package/dist/uds/dist/components/index.d.cts +61 -0
- package/dist/uds/dist/config/dist/index.d.cts +4 -0
- package/dist/uds/dist/css-tokens/dist/index.d.cts +2 -0
- package/dist/uds/dist/fixtures/dist/index.d.cts +2 -0
- package/dist/uds/dist/fonts/dist/index.d.cts +2 -0
- package/dist/uds/dist/index.d.cts +93 -0
- package/dist/uds/dist/modes/dist/index.d.cts +2 -0
- package/dist/uds/dist/runtime/bottomSheetConfig.d.cts +3 -0
- package/dist/uds/dist/runtime/breakpointsConfig.d.cts +4 -0
- package/dist/uds/dist/runtime/index.d.cts +7 -0
- package/dist/uds/dist/runtime/popoverConfig.d.cts +5 -0
- package/dist/uds/dist/runtime/toastConfig.d.cts +4 -0
- package/dist/uds/dist/runtime/tooltipConfig.d.cts +5 -0
- package/dist/uds/dist/runtime/udsConfig.d.cts +8 -0
- package/dist/uds/dist/styles/styler.d.cts +2 -0
- package/dist/uds/dist/styles/stylerTypes.d.cts +3 -0
- package/dist/uds/dist/tailwind/dist/config/dist/index.d.cts +2 -0
- package/dist/uds/dist/tailwind/dist/index.d.cts +3 -0
- package/dist/uds/dist/tailwind/dist/tailwind/components/getResponsiveTextStyles.d.cts +2 -0
- package/dist/uds/dist/tailwind/dist/utils/parseTokens.d.cts +2 -0
- package/dist/uds/dist/tokens/automation/index.d.cts +10 -0
- package/dist/uds/dist/tokens/configs/shadow.d.cts +3 -0
- package/dist/uds/dist/tokens/consts/cssTokens.d.cts +2 -0
- package/dist/uds/dist/tokens/consts/defaultModes.d.cts +2 -0
- package/dist/uds/dist/tokens/consts/fontDeclarationsMap.d.cts +2 -0
- package/dist/uds/dist/tokens/index.d.cts +28 -0
- package/dist/uds/dist/tokens/parseButtonVariants.d.cts +3 -0
- package/dist/uds/dist/tokens/types.d.cts +9 -0
- package/dist/uds/dist/tokens/utils/getFontUrls.d.cts +4 -0
- package/dist/uds/dist/tokens/utils/spectrum.d.cts +3 -0
- package/dist/uds/dist/types/dist/index.d.cts +11 -0
- package/dist/uds/dist/types.d.cts +2 -0
- package/dist/uds/generated/componentData.cjs +131 -131
- package/dist/uds/generated/componentData.js +131 -131
- package/generated/componentData.json +183 -183
- package/package.json +1 -1
|
@@ -105,13 +105,16 @@ const generateSimpleModeCSS = async (options) => {
|
|
|
105
105
|
fs.writeFileSync(outputPath, cssResult.css);
|
|
106
106
|
const duration = Math.round(performance.now() - startTime);
|
|
107
107
|
if (shouldLogStats) printSimpleModeStats({
|
|
108
|
+
cwd: options.workspaceDir,
|
|
108
109
|
outputPath,
|
|
109
110
|
totalFilesScanned,
|
|
111
|
+
scannedFilePaths: scanResult.filePaths,
|
|
110
112
|
classCount: cssResult.classCount,
|
|
111
113
|
sizeBytes: cssResult.sizeBytes,
|
|
112
114
|
sizeGzipBytes: cssResult.sizeGzipBytes,
|
|
113
115
|
duration,
|
|
114
116
|
scope: options.scope,
|
|
117
|
+
verbose: options.verbose,
|
|
115
118
|
optimizationStats: cssResult.optimizationStats,
|
|
116
119
|
print,
|
|
117
120
|
magenta,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","names":[],"sources":["../../src/css/generate.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { gzipSync } from 'node:zlib';\n\nimport { cyan, magenta, print, spinStop, yellow } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport postcss from 'postcss';\nimport type { SafelistConfig } from 'tailwindcss/types/config';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport {\n deduplicateSafelist,\n getInternalSafelistClasses,\n getThemeAndScaleClasses,\n} from '../purger/optimized';\nimport type { EntryValue } from '../utils/entryPoints';\nimport { resolveEntryPaths } from '../utils/entryPoints';\nimport {\n applyScopedColorModeFix,\n buildPostcssPlugins,\n createTailwindPlugin,\n getCssFeatureFlags,\n getInternalIconModeCss,\n optimizeGeneratedCss,\n printSimpleModeStats,\n} from './generate.helpers';\nimport { loadConfigFile, scanDirectoriesForSafelist } from './nodeUtils';\nimport type { UDSCSSOptimizationOptions, UDSCSSVarSafelistPattern } from './theme';\nimport {\n extractRuntimeConfigValues,\n extractVariantDefaults,\n getConfigurableCssVariables,\n getMotionVarPrefixes,\n} from './utils';\n\n/**\n * Result from generating CSS\n */\ninterface CSSResult {\n css: string;\n sizeBytes: number;\n sizeGzipBytes: number;\n classCount: number;\n optimizationStats?: {\n originalSize: number;\n originalSizeGzip: number;\n fontFacesRemoved: number;\n emptyRulesRemoved: number;\n validationErrors: string[];\n };\n}\n\n/**\n * CSS generation options for uds.theme.ts\n */\ninterface UDSCSSOptions {\n /** CSS scope wrapper class (optional) */\n scope?: string;\n /** Safelist of CSS classes to always include */\n safelist?: SafelistConfig[];\n /** CSS optimization settings */\n optimization?: UDSCSSOptimizationOptions;\n /** Include Tailwind preflight/reset styles (default: true) */\n preflight?: boolean;\n /** Include @font-face declarations (default: true) */\n fontFaceDeclarations?: boolean;\n /** Debounce delay (ms) for watch mode regenerations */\n watchDebounce?: number;\n}\n\n/**\n * Options for generateCSS function\n */\ninterface GenerateCSSOptions {\n /** CSS scope wrapper class */\n scope?: string;\n /** Directory to scan for arbitrary Tailwind classes (className props) */\n contentDir?: string | string[];\n /** CSS generation options from theme config */\n cssOptions?: UDSCSSOptions;\n /** Reference CSS to deduplicate font-faces against (for scoped CSS) */\n referenceCss?: string;\n /** CSS variable prefixes or patterns to preserve during pruning */\n safeVarPrefixes?: UDSCSSVarSafelistPattern[];\n}\n\nconst normalizeScope = (scope?: string): string | undefined => {\n const trimmedScope = scope?.trim();\n return trimmedScope ? trimmedScope : undefined;\n};\n\nconst getArbitrarySafelistRawContent = (safelist: SafelistConfig[]): string[] => {\n const arbitraryClasses = safelist.filter(\n (entry): entry is string => typeof entry === 'string' && entry.includes('['),\n );\n\n if (arbitraryClasses.length === 0) {\n return [];\n }\n\n return [`<div class=\"${arbitraryClasses.join(' ')}\"></div>`];\n};\n\n/**\n * Generate CSS from a safelist using Tailwind + PostCSS\n * @param safelist - UDS component classes to include\n * @param config - Token configuration\n * @param options - Additional options\n */\nconst generateCSS = async (\n safelist: SafelistConfig[],\n config: UniversalTokensConfig,\n options?: GenerateCSSOptions,\n): Promise<CSSResult> => {\n // Do we need base?\n const sourceCSS = '@tailwind base; @tailwind components; @tailwind utilities';\n\n const contentDir = options?.contentDir ?? path.join(process.cwd(), 'src');\n const cssFlags = getCssFeatureFlags(options?.cssOptions);\n const optimizationConfig = options?.cssOptions?.optimization;\n const scopeClass = normalizeScope(options?.scope) ?? normalizeScope(options?.cssOptions?.scope);\n const twPlugin = createTailwindPlugin({\n contentDir,\n rawContents: getArbitrarySafelistRawContent(safelist),\n safelist,\n config,\n enablePreflight: cssFlags.enablePreflight,\n enableFontFaceDeclarations: cssFlags.enableFontFaceDeclarations,\n });\n const plugins = buildPostcssPlugins({\n tailwindPlugin: twPlugin,\n shouldPruneVars: cssFlags.shouldPruneVars,\n safeVarPrefixes: options?.safeVarPrefixes ?? [],\n scopeClass,\n });\n\n const result = await postcss(plugins).process(sourceCSS, { from: undefined });\n let css = await applyScopedColorModeFix(result.css, scopeClass);\n if (!css.includes('uds-light-mode-icon') || !css.includes('uds-dark-mode-icon')) {\n css = `${css} ${getInternalIconModeCss(scopeClass)}`.trim();\n }\n const optimizedCss = await optimizeGeneratedCss({\n css,\n shouldOptimize: cssFlags.shouldOptimize,\n optimizationConfig,\n referenceCss: options?.referenceCss,\n scopeClass,\n });\n css = optimizedCss.css;\n\n const sizeBytes = Buffer.byteLength(css, 'utf8');\n const sizeGzipBytes = gzipSync(css).length;\n\n return {\n css,\n sizeBytes,\n sizeGzipBytes,\n classCount: safelist.length,\n optimizationStats: optimizedCss.optimizationStats,\n };\n};\n\n/**\n * Generate CSS in simple mode (no uds.theme.ts)\n */\nconst generateSimpleModeCSS = async (options: {\n workspaceDir: string;\n entry: EntryValue;\n outFile: string;\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n scope?: string;\n configPath?: string;\n isWatch?: boolean;\n silent?: boolean;\n}): Promise<{ success: boolean; outputPath: string; packageDirs?: string[] }> => {\n const isWatch = options.isWatch === true;\n const isSilent = options.silent === true;\n const shouldLogStats = !isSilent && !isWatch;\n const startTime = performance.now();\n const colorModes: ('dark' | 'light')[] = ['dark']; // Light mode is already in :root\n\n // Load config if provided, otherwise use default\n let tokensConfig: UniversalTokensConfig = defaultTokensConfig;\n if (options.configPath) {\n const loadedConfig = await loadConfigFile<UniversalTokensConfig>(options.configPath);\n if (loadedConfig) {\n tokensConfig = loadedConfig;\n } else if (shouldLogStats) {\n spinStop('⚠️', `Config file not found: ${options.configPath}, using defaults`);\n }\n }\n\n // Extract variant defaults from config for auto-variant class generation\n const variantDefaults = extractVariantDefaults(tokensConfig);\n const runtimeConfigValues = extractRuntimeConfigValues(tokensConfig);\n\n const resolvedEntries = resolveEntryPaths(options.entry, options.workspaceDir);\n const entryDirs = resolvedEntries.map((entry) => entry.absolutePath);\n const scanResult = await scanDirectoriesForSafelist(\n entryDirs,\n colorModes,\n options.variants,\n options.autoVariants,\n options.componentData,\n variantDefaults,\n runtimeConfigValues,\n );\n\n const totalFilesScanned = scanResult.filesScanned;\n const allClasses: string[] = [...scanResult.safelist];\n const allComponents = new Set<string>(scanResult.components);\n const packageDirs: string[] = [\n ...new Set(\n resolvedEntries.map((entry) =>\n entry.kind === 'directory' ? entry.absolutePath : entry.watchDirectory,\n ),\n ),\n ];\n\n // Add color mode classes\n const fullSafelist = [\n ...allClasses,\n ...getThemeAndScaleClasses(colorModes),\n ...getInternalSafelistClasses(),\n ];\n const finalSafelist = deduplicateSafelist(fullSafelist);\n\n // Generate CSS (Tailwind will scan entry dir for arbitrary classes on className props)\n const cssResult = await generateCSS(finalSafelist, tokensConfig, {\n scope: options.scope,\n contentDir: entryDirs,\n safeVarPrefixes: [\n ...getMotionVarPrefixes(options.componentData, [...allComponents]),\n ...getConfigurableCssVariables(),\n ],\n });\n\n // Write output\n const outputPath = path.isAbsolute(options.outFile)\n ? options.outFile\n : path.join(options.workspaceDir, options.outFile);\n const outputDir = path.dirname(outputPath);\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, cssResult.css);\n\n const duration = Math.round(performance.now() - startTime);\n\n if (shouldLogStats) {\n printSimpleModeStats({\n outputPath,\n totalFilesScanned,\n classCount: cssResult.classCount,\n sizeBytes: cssResult.sizeBytes,\n sizeGzipBytes: cssResult.sizeGzipBytes,\n duration,\n scope: options.scope,\n optimizationStats: cssResult.optimizationStats,\n print,\n magenta,\n cyan,\n yellow,\n });\n }\n\n return { success: true, outputPath, packageDirs };\n};\n\nexport { generateCSS, generateSimpleModeCSS };\nexport type { UDSCSSOptions };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","names":[],"sources":["../../src/css/generate.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { gzipSync } from 'node:zlib';\n\nimport { cyan, magenta, print, spinStop, yellow } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport postcss from 'postcss';\nimport type { SafelistConfig } from 'tailwindcss/types/config';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport {\n deduplicateSafelist,\n getInternalSafelistClasses,\n getThemeAndScaleClasses,\n} from '../purger/optimized';\nimport type { EntryValue } from '../utils/entryPoints';\nimport { resolveEntryPaths } from '../utils/entryPoints';\nimport {\n applyScopedColorModeFix,\n buildPostcssPlugins,\n createTailwindPlugin,\n getCssFeatureFlags,\n getInternalIconModeCss,\n optimizeGeneratedCss,\n printSimpleModeStats,\n} from './generate.helpers';\nimport { loadConfigFile, scanDirectoriesForSafelist } from './nodeUtils';\nimport type { UDSCSSOptimizationOptions, UDSCSSVarSafelistPattern } from './theme';\nimport {\n extractRuntimeConfigValues,\n extractVariantDefaults,\n getConfigurableCssVariables,\n getMotionVarPrefixes,\n} from './utils';\n\n/**\n * Result from generating CSS\n */\ninterface CSSResult {\n css: string;\n sizeBytes: number;\n sizeGzipBytes: number;\n classCount: number;\n optimizationStats?: {\n originalSize: number;\n originalSizeGzip: number;\n fontFacesRemoved: number;\n emptyRulesRemoved: number;\n validationErrors: string[];\n };\n}\n\n/**\n * CSS generation options for uds.theme.ts\n */\ninterface UDSCSSOptions {\n /** CSS scope wrapper class (optional) */\n scope?: string;\n /** Safelist of CSS classes to always include */\n safelist?: SafelistConfig[];\n /** CSS optimization settings */\n optimization?: UDSCSSOptimizationOptions;\n /** Include Tailwind preflight/reset styles (default: true) */\n preflight?: boolean;\n /** Include @font-face declarations (default: true) */\n fontFaceDeclarations?: boolean;\n /** Debounce delay (ms) for watch mode regenerations */\n watchDebounce?: number;\n}\n\n/**\n * Options for generateCSS function\n */\ninterface GenerateCSSOptions {\n /** CSS scope wrapper class */\n scope?: string;\n /** Directory to scan for arbitrary Tailwind classes (className props) */\n contentDir?: string | string[];\n /** CSS generation options from theme config */\n cssOptions?: UDSCSSOptions;\n /** Reference CSS to deduplicate font-faces against (for scoped CSS) */\n referenceCss?: string;\n /** CSS variable prefixes or patterns to preserve during pruning */\n safeVarPrefixes?: UDSCSSVarSafelistPattern[];\n}\n\nconst normalizeScope = (scope?: string): string | undefined => {\n const trimmedScope = scope?.trim();\n return trimmedScope ? trimmedScope : undefined;\n};\n\nconst getArbitrarySafelistRawContent = (safelist: SafelistConfig[]): string[] => {\n const arbitraryClasses = safelist.filter(\n (entry): entry is string => typeof entry === 'string' && entry.includes('['),\n );\n\n if (arbitraryClasses.length === 0) {\n return [];\n }\n\n return [`<div class=\"${arbitraryClasses.join(' ')}\"></div>`];\n};\n\n/**\n * Generate CSS from a safelist using Tailwind + PostCSS\n * @param safelist - UDS component classes to include\n * @param config - Token configuration\n * @param options - Additional options\n */\nconst generateCSS = async (\n safelist: SafelistConfig[],\n config: UniversalTokensConfig,\n options?: GenerateCSSOptions,\n): Promise<CSSResult> => {\n // Do we need base?\n const sourceCSS = '@tailwind base; @tailwind components; @tailwind utilities';\n\n const contentDir = options?.contentDir ?? path.join(process.cwd(), 'src');\n const cssFlags = getCssFeatureFlags(options?.cssOptions);\n const optimizationConfig = options?.cssOptions?.optimization;\n const scopeClass = normalizeScope(options?.scope) ?? normalizeScope(options?.cssOptions?.scope);\n const twPlugin = createTailwindPlugin({\n contentDir,\n rawContents: getArbitrarySafelistRawContent(safelist),\n safelist,\n config,\n enablePreflight: cssFlags.enablePreflight,\n enableFontFaceDeclarations: cssFlags.enableFontFaceDeclarations,\n });\n const plugins = buildPostcssPlugins({\n tailwindPlugin: twPlugin,\n shouldPruneVars: cssFlags.shouldPruneVars,\n safeVarPrefixes: options?.safeVarPrefixes ?? [],\n scopeClass,\n });\n\n const result = await postcss(plugins).process(sourceCSS, { from: undefined });\n let css = await applyScopedColorModeFix(result.css, scopeClass);\n if (!css.includes('uds-light-mode-icon') || !css.includes('uds-dark-mode-icon')) {\n css = `${css} ${getInternalIconModeCss(scopeClass)}`.trim();\n }\n const optimizedCss = await optimizeGeneratedCss({\n css,\n shouldOptimize: cssFlags.shouldOptimize,\n optimizationConfig,\n referenceCss: options?.referenceCss,\n scopeClass,\n });\n css = optimizedCss.css;\n\n const sizeBytes = Buffer.byteLength(css, 'utf8');\n const sizeGzipBytes = gzipSync(css).length;\n\n return {\n css,\n sizeBytes,\n sizeGzipBytes,\n classCount: safelist.length,\n optimizationStats: optimizedCss.optimizationStats,\n };\n};\n\n/**\n * Generate CSS in simple mode (no uds.theme.ts)\n */\nconst generateSimpleModeCSS = async (options: {\n workspaceDir: string;\n entry: EntryValue;\n outFile: string;\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n scope?: string;\n configPath?: string;\n isWatch?: boolean;\n silent?: boolean;\n verbose?: boolean;\n}): Promise<{ success: boolean; outputPath: string; packageDirs?: string[] }> => {\n const isWatch = options.isWatch === true;\n const isSilent = options.silent === true;\n const shouldLogStats = !isSilent && !isWatch;\n const startTime = performance.now();\n const colorModes: ('dark' | 'light')[] = ['dark']; // Light mode is already in :root\n\n // Load config if provided, otherwise use default\n let tokensConfig: UniversalTokensConfig = defaultTokensConfig;\n if (options.configPath) {\n const loadedConfig = await loadConfigFile<UniversalTokensConfig>(options.configPath);\n if (loadedConfig) {\n tokensConfig = loadedConfig;\n } else if (shouldLogStats) {\n spinStop('⚠️', `Config file not found: ${options.configPath}, using defaults`);\n }\n }\n\n // Extract variant defaults from config for auto-variant class generation\n const variantDefaults = extractVariantDefaults(tokensConfig);\n const runtimeConfigValues = extractRuntimeConfigValues(tokensConfig);\n\n const resolvedEntries = resolveEntryPaths(options.entry, options.workspaceDir);\n const entryDirs = resolvedEntries.map((entry) => entry.absolutePath);\n const scanResult = await scanDirectoriesForSafelist(\n entryDirs,\n colorModes,\n options.variants,\n options.autoVariants,\n options.componentData,\n variantDefaults,\n runtimeConfigValues,\n );\n\n const totalFilesScanned = scanResult.filesScanned;\n const allClasses: string[] = [...scanResult.safelist];\n const allComponents = new Set<string>(scanResult.components);\n const packageDirs: string[] = [\n ...new Set(\n resolvedEntries.map((entry) =>\n entry.kind === 'directory' ? entry.absolutePath : entry.watchDirectory,\n ),\n ),\n ];\n\n // Add color mode classes\n const fullSafelist = [\n ...allClasses,\n ...getThemeAndScaleClasses(colorModes),\n ...getInternalSafelistClasses(),\n ];\n const finalSafelist = deduplicateSafelist(fullSafelist);\n\n // Generate CSS (Tailwind will scan entry dir for arbitrary classes on className props)\n const cssResult = await generateCSS(finalSafelist, tokensConfig, {\n scope: options.scope,\n contentDir: entryDirs,\n safeVarPrefixes: [\n ...getMotionVarPrefixes(options.componentData, [...allComponents]),\n ...getConfigurableCssVariables(),\n ],\n });\n\n // Write output\n const outputPath = path.isAbsolute(options.outFile)\n ? options.outFile\n : path.join(options.workspaceDir, options.outFile);\n const outputDir = path.dirname(outputPath);\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, cssResult.css);\n\n const duration = Math.round(performance.now() - startTime);\n\n if (shouldLogStats) {\n printSimpleModeStats({\n cwd: options.workspaceDir,\n outputPath,\n totalFilesScanned,\n scannedFilePaths: scanResult.filePaths,\n classCount: cssResult.classCount,\n sizeBytes: cssResult.sizeBytes,\n sizeGzipBytes: cssResult.sizeGzipBytes,\n duration,\n scope: options.scope,\n verbose: options.verbose,\n optimizationStats: cssResult.optimizationStats,\n print,\n magenta,\n cyan,\n yellow,\n });\n }\n\n return { success: true, outputPath, packageDirs };\n};\n\nexport { generateCSS, generateSimpleModeCSS };\nexport type { UDSCSSOptions };\n"],"mappings":"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"}
|
|
@@ -24,11 +24,11 @@ const loadConfigFile = async (configPath) => {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
const scanDirectoryForSafelist = async (dir, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
27
|
-
const files = await (0, fast_glob.default)("**/*.{js,jsx,ts,tsx}", {
|
|
27
|
+
const files = (await (0, fast_glob.default)("**/*.{js,jsx,mjs,cjs,ts,tsx}", {
|
|
28
28
|
cwd: dir,
|
|
29
29
|
absolute: true,
|
|
30
30
|
ignore: ["**/node_modules/**"]
|
|
31
|
-
});
|
|
31
|
+
})).sort((left, right) => left.localeCompare(right));
|
|
32
32
|
const results = await Promise.all(files.map(async (filePath) => {
|
|
33
33
|
return require_purgeFromCode.purgeFromCodeOptimized(node_fs.default.readFileSync(filePath, "utf-8"), {
|
|
34
34
|
colorModes,
|
|
@@ -41,10 +41,15 @@ const scanDirectoryForSafelist = async (dir, colorModes, variants, autoVariants,
|
|
|
41
41
|
filePath
|
|
42
42
|
});
|
|
43
43
|
}));
|
|
44
|
+
const allClasses = results.flatMap((result) => result.safelist);
|
|
45
|
+
const allComponents = new Set(results.flatMap((result) => result.components));
|
|
46
|
+
const filesWithComponents = results.filter((result) => result.components.length > 0).length;
|
|
44
47
|
return {
|
|
45
|
-
safelist:
|
|
46
|
-
components: [...
|
|
47
|
-
filesScanned: files.length
|
|
48
|
+
safelist: allClasses,
|
|
49
|
+
components: [...allComponents],
|
|
50
|
+
filesScanned: files.length,
|
|
51
|
+
filesWithComponents,
|
|
52
|
+
filePaths: files
|
|
48
53
|
};
|
|
49
54
|
};
|
|
50
55
|
const scanFileForSafelist = async (filePath, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
@@ -60,7 +65,9 @@ const scanFileForSafelist = async (filePath, colorModes, variants, autoVariants,
|
|
|
60
65
|
return {
|
|
61
66
|
safelist: result.safelist,
|
|
62
67
|
components: result.components,
|
|
63
|
-
filesScanned: 1
|
|
68
|
+
filesScanned: 1,
|
|
69
|
+
filesWithComponents: result.components.length > 0 ? 1 : 0,
|
|
70
|
+
filePaths: [filePath]
|
|
64
71
|
};
|
|
65
72
|
};
|
|
66
73
|
const scanDirectoriesForSafelist = async (dirs, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
@@ -71,7 +78,9 @@ const scanDirectoriesForSafelist = async (dirs, colorModes, variants, autoVarian
|
|
|
71
78
|
return {
|
|
72
79
|
safelist: results.flatMap((result) => result.safelist),
|
|
73
80
|
components: [...new Set(results.flatMap((result) => result.components))],
|
|
74
|
-
filesScanned: results.reduce((total, result) => total + result.filesScanned, 0)
|
|
81
|
+
filesScanned: results.reduce((total, result) => total + result.filesScanned, 0),
|
|
82
|
+
filesWithComponents: results.reduce((total, result) => total + result.filesWithComponents, 0),
|
|
83
|
+
filePaths: results.flatMap((result) => result.filePaths).sort((left, right) => left.localeCompare(right))
|
|
75
84
|
};
|
|
76
85
|
};
|
|
77
86
|
const findMonorepoRoot = (startDir) => {
|
|
@@ -82,13 +91,45 @@ const findMonorepoRoot = (startDir) => {
|
|
|
82
91
|
};
|
|
83
92
|
return findUp(startDir);
|
|
84
93
|
};
|
|
94
|
+
const readPackageName = (packageJsonPath) => {
|
|
95
|
+
try {
|
|
96
|
+
const pkgJson = JSON.parse(node_fs.default.readFileSync(packageJsonPath, "utf8"));
|
|
97
|
+
return typeof pkgJson.name === "string" ? pkgJson.name : null;
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const findPackageRootFromResolvedEntry = (resolvedEntryPath, packageName) => {
|
|
103
|
+
let currentPath = node_fs.default.statSync(resolvedEntryPath).isDirectory() ? resolvedEntryPath : node_path.default.dirname(resolvedEntryPath);
|
|
104
|
+
while (true) {
|
|
105
|
+
const packageJsonPath = node_path.default.join(currentPath, "package.json");
|
|
106
|
+
if (node_fs.default.existsSync(packageJsonPath) && readPackageName(packageJsonPath) === packageName) return currentPath;
|
|
107
|
+
const parentPath = node_path.default.dirname(currentPath);
|
|
108
|
+
if (parentPath === currentPath) return null;
|
|
109
|
+
currentPath = parentPath;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const findPackageRootInNodeModules = (startDir, packageName) => {
|
|
113
|
+
let currentDir = startDir;
|
|
114
|
+
while (true) {
|
|
115
|
+
const packageJsonPath = node_path.default.join(currentDir, "node_modules", packageName, "package.json");
|
|
116
|
+
if (node_fs.default.existsSync(packageJsonPath)) return node_path.default.dirname(packageJsonPath);
|
|
117
|
+
const parentDir = node_path.default.dirname(currentDir);
|
|
118
|
+
if (parentDir === currentDir) return null;
|
|
119
|
+
currentDir = parentDir;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
85
122
|
const resolvePackageRoot = (workspaceDir, packageName) => {
|
|
86
|
-
const
|
|
123
|
+
const requireFromWorkspace = (0, node_module.createRequire)(node_path.default.join(workspaceDir, "package.json"));
|
|
87
124
|
try {
|
|
88
|
-
const resolvedPackageJson =
|
|
125
|
+
const resolvedPackageJson = requireFromWorkspace.resolve(node_path.default.join(packageName, "package.json"));
|
|
89
126
|
return node_path.default.dirname(resolvedPackageJson);
|
|
90
127
|
} catch {
|
|
91
|
-
|
|
128
|
+
try {
|
|
129
|
+
const packageRoot = findPackageRootFromResolvedEntry(requireFromWorkspace.resolve(packageName), packageName);
|
|
130
|
+
if (packageRoot) return packageRoot;
|
|
131
|
+
} catch {}
|
|
132
|
+
return findPackageRootInNodeModules(workspaceDir, packageName);
|
|
92
133
|
}
|
|
93
134
|
};
|
|
94
135
|
const findPackageRootInMonorepo = (monorepoRoot, packageName) => {
|
|
@@ -97,14 +138,17 @@ const findPackageRootInMonorepo = (monorepoRoot, packageName) => {
|
|
|
97
138
|
absolute: true,
|
|
98
139
|
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
99
140
|
}).find((pkgJsonPath) => {
|
|
100
|
-
|
|
101
|
-
return JSON.parse(node_fs.default.readFileSync(pkgJsonPath, "utf8")).name === packageName;
|
|
102
|
-
} catch {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
141
|
+
return readPackageName(pkgJsonPath) === packageName;
|
|
105
142
|
});
|
|
106
143
|
return matchingPath ? node_path.default.dirname(matchingPath) : null;
|
|
107
144
|
};
|
|
145
|
+
const findPackageRoot = (packageName) => {
|
|
146
|
+
const workspaceDir = process.cwd();
|
|
147
|
+
const monorepoRoot = findMonorepoRoot(workspaceDir);
|
|
148
|
+
let packageRoot = resolvePackageRoot(workspaceDir, packageName);
|
|
149
|
+
if (!packageRoot && monorepoRoot) packageRoot = findPackageRootInMonorepo(monorepoRoot, packageName);
|
|
150
|
+
return packageRoot;
|
|
151
|
+
};
|
|
108
152
|
const buildPackageSourceCandidates = (workspaceDir, packageName, packageRoot) => {
|
|
109
153
|
return [
|
|
110
154
|
packageRoot ? node_path.default.join(packageRoot, "src") : null,
|
|
@@ -119,11 +163,19 @@ const buildPackageSourceCandidates = (workspaceDir, packageName, packageRoot) =>
|
|
|
119
163
|
};
|
|
120
164
|
const getFirstExistingPath = (candidates) => candidates.find((candidate) => node_fs.default.existsSync(candidate)) ?? null;
|
|
121
165
|
const findPackageSourceDir = (packageName) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
166
|
+
return getFirstExistingPath(buildPackageSourceCandidates(process.cwd(), packageName, findPackageRoot(packageName)));
|
|
167
|
+
};
|
|
168
|
+
const getPackageUdsScope = (packageName) => {
|
|
169
|
+
const packageRoot = findPackageRoot(packageName);
|
|
170
|
+
if (!packageRoot) return null;
|
|
171
|
+
const packageJsonPath = node_path.default.join(packageRoot, "package.json");
|
|
172
|
+
if (!node_fs.default.existsSync(packageJsonPath)) return null;
|
|
173
|
+
try {
|
|
174
|
+
const scope = JSON.parse(node_fs.default.readFileSync(packageJsonPath, "utf8")).uds?.scope;
|
|
175
|
+
return typeof scope === "string" && scope.trim().length > 0 ? scope.trim() : null;
|
|
176
|
+
} catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
127
179
|
};
|
|
128
180
|
const scaffoldThemeConfig = async (options) => {
|
|
129
181
|
const workspaceDir = process.cwd();
|
|
@@ -155,6 +207,23 @@ export default defineTheme({
|
|
|
155
207
|
// Packages that inherit your app's theme (merged into main uds.css)
|
|
156
208
|
// inherit: ['@your-org/shared-ui'],
|
|
157
209
|
|
|
210
|
+
// Packages that generate separate scoped CSS outputs.
|
|
211
|
+
// Scope class is discovered from each package.json uds.scope.
|
|
212
|
+
// When entry is omitted, the package is scanned the same way as inherit.
|
|
213
|
+
// scoped: {
|
|
214
|
+
// '@your-org/shared-ui': './packages/shared-ui/uds.config.ts'
|
|
215
|
+
// }
|
|
216
|
+
//
|
|
217
|
+
// Or use the expanded form for custom output paths:
|
|
218
|
+
// scoped: {
|
|
219
|
+
// '@your-org/shared-ui': {
|
|
220
|
+
// config: './packages/shared-ui/uds.config.ts',
|
|
221
|
+
// entry: './src',
|
|
222
|
+
// // outFile defaults to dist/shared-ui.css
|
|
223
|
+
// outFile: 'dist/shared-ui.css'
|
|
224
|
+
// },
|
|
225
|
+
// },
|
|
226
|
+
|
|
158
227
|
// CSS generation options (all optional)
|
|
159
228
|
// css: {
|
|
160
229
|
// safelist: [],
|
|
@@ -179,7 +248,9 @@ export default defineTheme({
|
|
|
179
248
|
};
|
|
180
249
|
|
|
181
250
|
//#endregion
|
|
251
|
+
exports.findPackageRoot = findPackageRoot;
|
|
182
252
|
exports.findPackageSourceDir = findPackageSourceDir;
|
|
253
|
+
exports.getPackageUdsScope = getPackageUdsScope;
|
|
183
254
|
exports.loadConfigFile = loadConfigFile;
|
|
184
255
|
exports.scaffoldThemeConfig = scaffoldThemeConfig;
|
|
185
256
|
exports.scanDirectoriesForSafelist = scanDirectoriesForSafelist;
|
|
@@ -20,11 +20,11 @@ const loadConfigFile = async (configPath) => {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
const scanDirectoryForSafelist = async (dir, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
23
|
-
const files = await fg("**/*.{js,jsx,ts,tsx}", {
|
|
23
|
+
const files = (await fg("**/*.{js,jsx,mjs,cjs,ts,tsx}", {
|
|
24
24
|
cwd: dir,
|
|
25
25
|
absolute: true,
|
|
26
26
|
ignore: ["**/node_modules/**"]
|
|
27
|
-
});
|
|
27
|
+
})).sort((left, right) => left.localeCompare(right));
|
|
28
28
|
const results = await Promise.all(files.map(async (filePath) => {
|
|
29
29
|
return purgeFromCodeOptimized(fs.readFileSync(filePath, "utf-8"), {
|
|
30
30
|
colorModes,
|
|
@@ -37,10 +37,15 @@ const scanDirectoryForSafelist = async (dir, colorModes, variants, autoVariants,
|
|
|
37
37
|
filePath
|
|
38
38
|
});
|
|
39
39
|
}));
|
|
40
|
+
const allClasses = results.flatMap((result) => result.safelist);
|
|
41
|
+
const allComponents = new Set(results.flatMap((result) => result.components));
|
|
42
|
+
const filesWithComponents = results.filter((result) => result.components.length > 0).length;
|
|
40
43
|
return {
|
|
41
|
-
safelist:
|
|
42
|
-
components: [...
|
|
43
|
-
filesScanned: files.length
|
|
44
|
+
safelist: allClasses,
|
|
45
|
+
components: [...allComponents],
|
|
46
|
+
filesScanned: files.length,
|
|
47
|
+
filesWithComponents,
|
|
48
|
+
filePaths: files
|
|
44
49
|
};
|
|
45
50
|
};
|
|
46
51
|
const scanFileForSafelist = async (filePath, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
@@ -56,7 +61,9 @@ const scanFileForSafelist = async (filePath, colorModes, variants, autoVariants,
|
|
|
56
61
|
return {
|
|
57
62
|
safelist: result.safelist,
|
|
58
63
|
components: result.components,
|
|
59
|
-
filesScanned: 1
|
|
64
|
+
filesScanned: 1,
|
|
65
|
+
filesWithComponents: result.components.length > 0 ? 1 : 0,
|
|
66
|
+
filePaths: [filePath]
|
|
60
67
|
};
|
|
61
68
|
};
|
|
62
69
|
const scanDirectoriesForSafelist = async (dirs, colorModes, variants, autoVariants, componentData, variantDefaults, runtimeConfigValues, includeAllClassNamePrimitives = false) => {
|
|
@@ -67,7 +74,9 @@ const scanDirectoriesForSafelist = async (dirs, colorModes, variants, autoVarian
|
|
|
67
74
|
return {
|
|
68
75
|
safelist: results.flatMap((result) => result.safelist),
|
|
69
76
|
components: [...new Set(results.flatMap((result) => result.components))],
|
|
70
|
-
filesScanned: results.reduce((total, result) => total + result.filesScanned, 0)
|
|
77
|
+
filesScanned: results.reduce((total, result) => total + result.filesScanned, 0),
|
|
78
|
+
filesWithComponents: results.reduce((total, result) => total + result.filesWithComponents, 0),
|
|
79
|
+
filePaths: results.flatMap((result) => result.filePaths).sort((left, right) => left.localeCompare(right))
|
|
71
80
|
};
|
|
72
81
|
};
|
|
73
82
|
const findMonorepoRoot = (startDir) => {
|
|
@@ -78,13 +87,45 @@ const findMonorepoRoot = (startDir) => {
|
|
|
78
87
|
};
|
|
79
88
|
return findUp(startDir);
|
|
80
89
|
};
|
|
90
|
+
const readPackageName = (packageJsonPath) => {
|
|
91
|
+
try {
|
|
92
|
+
const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
93
|
+
return typeof pkgJson.name === "string" ? pkgJson.name : null;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const findPackageRootFromResolvedEntry = (resolvedEntryPath, packageName) => {
|
|
99
|
+
let currentPath = fs.statSync(resolvedEntryPath).isDirectory() ? resolvedEntryPath : path.dirname(resolvedEntryPath);
|
|
100
|
+
while (true) {
|
|
101
|
+
const packageJsonPath = path.join(currentPath, "package.json");
|
|
102
|
+
if (fs.existsSync(packageJsonPath) && readPackageName(packageJsonPath) === packageName) return currentPath;
|
|
103
|
+
const parentPath = path.dirname(currentPath);
|
|
104
|
+
if (parentPath === currentPath) return null;
|
|
105
|
+
currentPath = parentPath;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const findPackageRootInNodeModules = (startDir, packageName) => {
|
|
109
|
+
let currentDir = startDir;
|
|
110
|
+
while (true) {
|
|
111
|
+
const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
|
|
112
|
+
if (fs.existsSync(packageJsonPath)) return path.dirname(packageJsonPath);
|
|
113
|
+
const parentDir = path.dirname(currentDir);
|
|
114
|
+
if (parentDir === currentDir) return null;
|
|
115
|
+
currentDir = parentDir;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
81
118
|
const resolvePackageRoot = (workspaceDir, packageName) => {
|
|
82
|
-
const
|
|
119
|
+
const requireFromWorkspace = createRequire(path.join(workspaceDir, "package.json"));
|
|
83
120
|
try {
|
|
84
|
-
const resolvedPackageJson =
|
|
121
|
+
const resolvedPackageJson = requireFromWorkspace.resolve(path.join(packageName, "package.json"));
|
|
85
122
|
return path.dirname(resolvedPackageJson);
|
|
86
123
|
} catch {
|
|
87
|
-
|
|
124
|
+
try {
|
|
125
|
+
const packageRoot = findPackageRootFromResolvedEntry(requireFromWorkspace.resolve(packageName), packageName);
|
|
126
|
+
if (packageRoot) return packageRoot;
|
|
127
|
+
} catch {}
|
|
128
|
+
return findPackageRootInNodeModules(workspaceDir, packageName);
|
|
88
129
|
}
|
|
89
130
|
};
|
|
90
131
|
const findPackageRootInMonorepo = (monorepoRoot, packageName) => {
|
|
@@ -93,14 +134,17 @@ const findPackageRootInMonorepo = (monorepoRoot, packageName) => {
|
|
|
93
134
|
absolute: true,
|
|
94
135
|
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
95
136
|
}).find((pkgJsonPath) => {
|
|
96
|
-
|
|
97
|
-
return JSON.parse(fs.readFileSync(pkgJsonPath, "utf8")).name === packageName;
|
|
98
|
-
} catch {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
137
|
+
return readPackageName(pkgJsonPath) === packageName;
|
|
101
138
|
});
|
|
102
139
|
return matchingPath ? path.dirname(matchingPath) : null;
|
|
103
140
|
};
|
|
141
|
+
const findPackageRoot = (packageName) => {
|
|
142
|
+
const workspaceDir = process.cwd();
|
|
143
|
+
const monorepoRoot = findMonorepoRoot(workspaceDir);
|
|
144
|
+
let packageRoot = resolvePackageRoot(workspaceDir, packageName);
|
|
145
|
+
if (!packageRoot && monorepoRoot) packageRoot = findPackageRootInMonorepo(monorepoRoot, packageName);
|
|
146
|
+
return packageRoot;
|
|
147
|
+
};
|
|
104
148
|
const buildPackageSourceCandidates = (workspaceDir, packageName, packageRoot) => {
|
|
105
149
|
return [
|
|
106
150
|
packageRoot ? path.join(packageRoot, "src") : null,
|
|
@@ -115,11 +159,19 @@ const buildPackageSourceCandidates = (workspaceDir, packageName, packageRoot) =>
|
|
|
115
159
|
};
|
|
116
160
|
const getFirstExistingPath = (candidates) => candidates.find((candidate) => fs.existsSync(candidate)) ?? null;
|
|
117
161
|
const findPackageSourceDir = (packageName) => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
162
|
+
return getFirstExistingPath(buildPackageSourceCandidates(process.cwd(), packageName, findPackageRoot(packageName)));
|
|
163
|
+
};
|
|
164
|
+
const getPackageUdsScope = (packageName) => {
|
|
165
|
+
const packageRoot = findPackageRoot(packageName);
|
|
166
|
+
if (!packageRoot) return null;
|
|
167
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
168
|
+
if (!fs.existsSync(packageJsonPath)) return null;
|
|
169
|
+
try {
|
|
170
|
+
const scope = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).uds?.scope;
|
|
171
|
+
return typeof scope === "string" && scope.trim().length > 0 ? scope.trim() : null;
|
|
172
|
+
} catch {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
123
175
|
};
|
|
124
176
|
const scaffoldThemeConfig = async (options) => {
|
|
125
177
|
const workspaceDir = process.cwd();
|
|
@@ -151,6 +203,23 @@ export default defineTheme({
|
|
|
151
203
|
// Packages that inherit your app's theme (merged into main uds.css)
|
|
152
204
|
// inherit: ['@your-org/shared-ui'],
|
|
153
205
|
|
|
206
|
+
// Packages that generate separate scoped CSS outputs.
|
|
207
|
+
// Scope class is discovered from each package.json uds.scope.
|
|
208
|
+
// When entry is omitted, the package is scanned the same way as inherit.
|
|
209
|
+
// scoped: {
|
|
210
|
+
// '@your-org/shared-ui': './packages/shared-ui/uds.config.ts'
|
|
211
|
+
// }
|
|
212
|
+
//
|
|
213
|
+
// Or use the expanded form for custom output paths:
|
|
214
|
+
// scoped: {
|
|
215
|
+
// '@your-org/shared-ui': {
|
|
216
|
+
// config: './packages/shared-ui/uds.config.ts',
|
|
217
|
+
// entry: './src',
|
|
218
|
+
// // outFile defaults to dist/shared-ui.css
|
|
219
|
+
// outFile: 'dist/shared-ui.css'
|
|
220
|
+
// },
|
|
221
|
+
// },
|
|
222
|
+
|
|
154
223
|
// CSS generation options (all optional)
|
|
155
224
|
// css: {
|
|
156
225
|
// safelist: [],
|
|
@@ -175,5 +244,5 @@ export default defineTheme({
|
|
|
175
244
|
};
|
|
176
245
|
|
|
177
246
|
//#endregion
|
|
178
|
-
export { findPackageSourceDir, loadConfigFile, scaffoldThemeConfig, scanDirectoriesForSafelist, scanDirectoryForSafelist };
|
|
247
|
+
export { findPackageRoot, findPackageSourceDir, getPackageUdsScope, loadConfigFile, scaffoldThemeConfig, scanDirectoriesForSafelist, scanDirectoryForSafelist };
|
|
179
248
|
//# sourceMappingURL=nodeUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeUtils.js","names":[],"sources":["../../src/css/nodeUtils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { cyan, green, magenta, print, red } from '@yahoo/uds-cli/lib';\nimport fg from 'fast-glob';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport type { RuntimeConfigValues, VariantDefaults } from '../purger/optimized/purgeFromCode';\nimport { purgeFromCodeOptimized } from '../purger/optimized/purgeFromCode';\nimport type { EntryValue } from '../utils/entryPoints';\nimport { formatEntryValue } from '../utils/entryPoints';\n\nconst loadConfigFile = async <T>(configPath: string): Promise<T | null> => {\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.join(process.cwd(), configPath);\n\n if (!fs.existsSync(absolutePath)) {\n return null;\n }\n\n try {\n const module = await import(absolutePath);\n return module.default ?? module.config ?? module;\n } catch (error) {\n throw new Error(\n `Failed to load config file: ${absolutePath}\\n${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n};\n\nconst scanDirectoryForSafelist = async (\n dir: string,\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<{ safelist: string[]; components: string[]; filesScanned: number }> => {\n const files = await fg('**/*.{js,jsx,ts,tsx}', {\n cwd: dir,\n absolute: true,\n ignore: ['**/node_modules/**'],\n });\n\n const results = await Promise.all(\n files.map(async (filePath) => {\n const code = fs.readFileSync(filePath, 'utf-8');\n return purgeFromCodeOptimized(code, {\n colorModes,\n variantDefaults,\n runtimeConfigValues,\n variants,\n autoVariants,\n componentData,\n includeAllClassNamePrimitives,\n filePath,\n });\n }),\n );\n\n const allClasses = results.flatMap((result) => result.safelist);\n const allComponents = new Set(results.flatMap((result) => result.components));\n\n return {\n safelist: allClasses,\n components: [...allComponents],\n filesScanned: files.length,\n };\n};\n\nconst scanFileForSafelist = async (\n filePath: string,\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<{ safelist: string[]; components: string[]; filesScanned: number }> => {\n const code = fs.readFileSync(filePath, 'utf-8');\n const result = await purgeFromCodeOptimized(code, {\n colorModes,\n variantDefaults,\n runtimeConfigValues,\n variants,\n autoVariants,\n componentData,\n includeAllClassNamePrimitives,\n });\n\n return {\n safelist: result.safelist,\n components: result.components,\n filesScanned: 1,\n };\n};\n\nconst scanDirectoriesForSafelist = async (\n dirs: string[],\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<{ safelist: string[]; components: string[]; filesScanned: number }> => {\n const results = await Promise.all(\n dirs.map((dir) => {\n if (fs.existsSync(dir) && fs.statSync(dir).isFile()) {\n return scanFileForSafelist(\n dir,\n colorModes,\n variants,\n autoVariants,\n componentData,\n variantDefaults,\n runtimeConfigValues,\n includeAllClassNamePrimitives,\n );\n }\n\n return scanDirectoryForSafelist(\n dir,\n colorModes,\n variants,\n autoVariants,\n componentData,\n variantDefaults,\n runtimeConfigValues,\n includeAllClassNamePrimitives,\n );\n }),\n );\n\n return {\n safelist: results.flatMap((result) => result.safelist),\n components: [...new Set(results.flatMap((result) => result.components))],\n filesScanned: results.reduce((total, result) => total + result.filesScanned, 0),\n };\n};\n\nconst findMonorepoRoot = (startDir: string): string | null => {\n const findUp = (currentDir: string): string | null => {\n if (fs.existsSync(path.join(currentDir, 'packages'))) {\n return currentDir;\n }\n\n const parentDir = path.dirname(currentDir);\n return parentDir === currentDir ? null : findUp(parentDir);\n };\n\n return findUp(startDir);\n};\n\nconst resolvePackageRoot = (workspaceDir: string, packageName: string): string | null => {\n const require = createRequire(import.meta.url);\n\n try {\n const resolvedPackageJson = require.resolve(path.join(packageName, 'package.json'), {\n paths: [workspaceDir],\n });\n return path.dirname(resolvedPackageJson);\n } catch {\n return null;\n }\n};\n\nconst findPackageRootInMonorepo = (monorepoRoot: string, packageName: string): string | null => {\n const packageJsonPaths = fg.sync('packages/**/package.json', {\n cwd: monorepoRoot,\n absolute: true,\n ignore: ['**/node_modules/**', '**/dist/**'],\n });\n\n const matchingPath = packageJsonPaths.find((pkgJsonPath) => {\n try {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')) as { name?: string };\n return pkgJson.name === packageName;\n } catch {\n return false;\n }\n });\n\n return matchingPath ? path.dirname(matchingPath) : null;\n};\n\nconst buildPackageSourceCandidates = (\n workspaceDir: string,\n packageName: string,\n packageRoot: string | null,\n): string[] => {\n return [\n packageRoot ? path.join(packageRoot, 'src') : null,\n packageRoot ? path.join(packageRoot, 'lib') : null,\n packageRoot ? path.join(packageRoot, 'dist') : null,\n packageRoot,\n path.join(workspaceDir, 'node_modules', packageName, 'src'),\n path.join(workspaceDir, 'node_modules', packageName, 'lib'),\n path.join(workspaceDir, 'node_modules', packageName, 'dist'),\n path.join(workspaceDir, 'node_modules', packageName),\n ].filter(Boolean) as string[];\n};\n\nconst getFirstExistingPath = (candidates: string[]): string | null =>\n candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n\nconst findPackageSourceDir = (packageName: string): string | null => {\n const workspaceDir = process.cwd();\n const monorepoRoot = findMonorepoRoot(workspaceDir);\n\n let packageRoot = resolvePackageRoot(workspaceDir, packageName);\n if (!packageRoot && monorepoRoot) {\n packageRoot = findPackageRootInMonorepo(monorepoRoot, packageName);\n }\n\n return getFirstExistingPath(buildPackageSourceCandidates(workspaceDir, packageName, packageRoot));\n};\n\nconst scaffoldThemeConfig = async (options: {\n outputPath?: string;\n configPath?: string;\n entry?: EntryValue;\n force?: boolean;\n}): Promise<void> => {\n const workspaceDir = process.cwd();\n const outputPath = options.outputPath ?? 'uds.theme.ts';\n const absoluteOutputPath = path.isAbsolute(outputPath)\n ? outputPath\n : path.join(workspaceDir, outputPath);\n\n if (fs.existsSync(absoluteOutputPath) && !options.force) {\n print(red(`Error: ${outputPath} already exists. Use --force to overwrite.`));\n process.exitCode = 1;\n return;\n }\n\n const configPath = options.configPath ?? './uds.config.ts';\n const entry = options.entry ?? './src';\n const serializedEntry = formatEntryValue(entry);\n\n const template = `import { defineTheme } from '@yahoo/uds';\n\n/**\n * UDS Theme Configuration\n * \n * This file configures CSS generation for your app and shared packages.\n * Run \\`uds css\\` to generate optimized CSS.\n */\nexport default defineTheme({\n // Path to your uds.config.ts file\n config: '${configPath}',\n\n // Entry directory or .tsx file path for scanning your app code\n entry: ${serializedEntry},\n\n // Color modes to include (light mode is always in :root)\n colorModes: ['dark'],\n\n // Packages that inherit your app's theme (merged into main uds.css)\n // inherit: ['@your-org/shared-ui'],\n\n // CSS generation options (all optional)\n // css: {\n // safelist: [],\n // preflight: true,\n // fontFaceDeclarations: true,\n // optimization: {\n // removeUnusedFonts: false,\n // removeEmptyRules: true,\n // deduplicateScopedCss: true\n // }\n // }\n});\n`;\n\n fs.writeFileSync(absoluteOutputPath, template);\n\n print('');\n print(green('✅ Created uds.theme.ts'));\n print('');\n print(`${magenta('Next steps:')}`);\n print(` 1. Review and customize ${cyan(outputPath)}`);\n print(` 2. Run ${cyan('uds css')} to generate CSS`);\n print('');\n};\n\nexport {\n findPackageSourceDir,\n loadConfigFile,\n scaffoldThemeConfig,\n scanDirectoriesForSafelist,\n scanDirectoryForSafelist,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nodeUtils.js","names":[],"sources":["../../src/css/nodeUtils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { cyan, green, magenta, print, red } from '@yahoo/uds-cli/lib';\nimport fg from 'fast-glob';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport type { RuntimeConfigValues, VariantDefaults } from '../purger/optimized/purgeFromCode';\nimport { purgeFromCodeOptimized } from '../purger/optimized/purgeFromCode';\nimport type { EntryValue } from '../utils/entryPoints';\nimport { formatEntryValue } from '../utils/entryPoints';\n\ntype SafelistScanResult = {\n safelist: string[];\n components: string[];\n filesScanned: number;\n filesWithComponents: number;\n filePaths: string[];\n};\n\nconst loadConfigFile = async <T>(configPath: string): Promise<T | null> => {\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.join(process.cwd(), configPath);\n\n if (!fs.existsSync(absolutePath)) {\n return null;\n }\n\n try {\n const module = await import(absolutePath);\n return module.default ?? module.config ?? module;\n } catch (error) {\n throw new Error(\n `Failed to load config file: ${absolutePath}\\n${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n }\n};\n\nconst scanDirectoryForSafelist = async (\n dir: string,\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<SafelistScanResult> => {\n const files = (\n await fg('**/*.{js,jsx,mjs,cjs,ts,tsx}', {\n cwd: dir,\n absolute: true,\n ignore: ['**/node_modules/**'],\n })\n ).sort((left, right) => left.localeCompare(right));\n\n const results = await Promise.all(\n files.map(async (filePath) => {\n const code = fs.readFileSync(filePath, 'utf-8');\n return purgeFromCodeOptimized(code, {\n colorModes,\n variantDefaults,\n runtimeConfigValues,\n variants,\n autoVariants,\n componentData,\n includeAllClassNamePrimitives,\n filePath,\n });\n }),\n );\n\n const allClasses = results.flatMap((result) => result.safelist);\n const allComponents = new Set(results.flatMap((result) => result.components));\n const filesWithComponents = results.filter((result) => result.components.length > 0).length;\n\n return {\n safelist: allClasses,\n components: [...allComponents],\n filesScanned: files.length,\n filesWithComponents,\n filePaths: files,\n };\n};\n\nconst scanFileForSafelist = async (\n filePath: string,\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<SafelistScanResult> => {\n const code = fs.readFileSync(filePath, 'utf-8');\n const result = await purgeFromCodeOptimized(code, {\n colorModes,\n variantDefaults,\n runtimeConfigValues,\n variants,\n autoVariants,\n componentData,\n includeAllClassNamePrimitives,\n });\n\n return {\n safelist: result.safelist,\n components: result.components,\n filesScanned: 1,\n filesWithComponents: result.components.length > 0 ? 1 : 0,\n filePaths: [filePath],\n };\n};\n\nconst scanDirectoriesForSafelist = async (\n dirs: string[],\n colorModes: ('dark' | 'light')[],\n variants: Record<string, Record<string, string>>,\n autoVariants: Record<string, Record<string, string>>,\n componentData: Record<string, SerializedComponentInfo>,\n variantDefaults?: VariantDefaults,\n runtimeConfigValues?: RuntimeConfigValues,\n includeAllClassNamePrimitives = false,\n): Promise<SafelistScanResult> => {\n const results = await Promise.all(\n dirs.map((dir) => {\n if (fs.existsSync(dir) && fs.statSync(dir).isFile()) {\n return scanFileForSafelist(\n dir,\n colorModes,\n variants,\n autoVariants,\n componentData,\n variantDefaults,\n runtimeConfigValues,\n includeAllClassNamePrimitives,\n );\n }\n\n return scanDirectoryForSafelist(\n dir,\n colorModes,\n variants,\n autoVariants,\n componentData,\n variantDefaults,\n runtimeConfigValues,\n includeAllClassNamePrimitives,\n );\n }),\n );\n\n return {\n safelist: results.flatMap((result) => result.safelist),\n components: [...new Set(results.flatMap((result) => result.components))],\n filesScanned: results.reduce((total, result) => total + result.filesScanned, 0),\n filesWithComponents: results.reduce((total, result) => total + result.filesWithComponents, 0),\n filePaths: results\n .flatMap((result) => result.filePaths)\n .sort((left, right) => left.localeCompare(right)),\n };\n};\n\nconst findMonorepoRoot = (startDir: string): string | null => {\n const findUp = (currentDir: string): string | null => {\n if (fs.existsSync(path.join(currentDir, 'packages'))) {\n return currentDir;\n }\n\n const parentDir = path.dirname(currentDir);\n return parentDir === currentDir ? null : findUp(parentDir);\n };\n\n return findUp(startDir);\n};\n\nconst readPackageName = (packageJsonPath: string): string | null => {\n try {\n const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { name?: string };\n return typeof pkgJson.name === 'string' ? pkgJson.name : null;\n } catch {\n return null;\n }\n};\n\nconst findPackageRootFromResolvedEntry = (\n resolvedEntryPath: string,\n packageName: string,\n): string | null => {\n let currentPath = fs.statSync(resolvedEntryPath).isDirectory()\n ? resolvedEntryPath\n : path.dirname(resolvedEntryPath);\n\n while (true) {\n const packageJsonPath = path.join(currentPath, 'package.json');\n if (fs.existsSync(packageJsonPath) && readPackageName(packageJsonPath) === packageName) {\n return currentPath;\n }\n\n const parentPath = path.dirname(currentPath);\n if (parentPath === currentPath) {\n return null;\n }\n\n currentPath = parentPath;\n }\n};\n\nconst findPackageRootInNodeModules = (startDir: string, packageName: string): string | null => {\n let currentDir = startDir;\n\n while (true) {\n const packageJsonPath = path.join(currentDir, 'node_modules', packageName, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n return path.dirname(packageJsonPath);\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n};\n\nconst resolvePackageRoot = (workspaceDir: string, packageName: string): string | null => {\n const requireFromWorkspace = createRequire(path.join(workspaceDir, 'package.json'));\n\n try {\n const resolvedPackageJson = requireFromWorkspace.resolve(\n path.join(packageName, 'package.json'),\n );\n return path.dirname(resolvedPackageJson);\n } catch {\n try {\n const resolvedPackageEntry = requireFromWorkspace.resolve(packageName);\n const packageRoot = findPackageRootFromResolvedEntry(resolvedPackageEntry, packageName);\n if (packageRoot) {\n return packageRoot;\n }\n } catch {\n // Fall through to explicit node_modules lookup below.\n }\n\n return findPackageRootInNodeModules(workspaceDir, packageName);\n }\n};\n\ntype PackageJsonShape = {\n uds?: {\n scope?: string;\n };\n};\n\nconst findPackageRootInMonorepo = (monorepoRoot: string, packageName: string): string | null => {\n const packageJsonPaths = fg.sync('packages/**/package.json', {\n cwd: monorepoRoot,\n absolute: true,\n ignore: ['**/node_modules/**', '**/dist/**'],\n });\n\n const matchingPath = packageJsonPaths.find((pkgJsonPath) => {\n return readPackageName(pkgJsonPath) === packageName;\n });\n\n return matchingPath ? path.dirname(matchingPath) : null;\n};\n\nconst findPackageRoot = (packageName: string): string | null => {\n const workspaceDir = process.cwd();\n const monorepoRoot = findMonorepoRoot(workspaceDir);\n\n let packageRoot = resolvePackageRoot(workspaceDir, packageName);\n if (!packageRoot && monorepoRoot) {\n packageRoot = findPackageRootInMonorepo(monorepoRoot, packageName);\n }\n\n return packageRoot;\n};\n\nconst buildPackageSourceCandidates = (\n workspaceDir: string,\n packageName: string,\n packageRoot: string | null,\n): string[] => {\n return [\n packageRoot ? path.join(packageRoot, 'src') : null,\n packageRoot ? path.join(packageRoot, 'lib') : null,\n packageRoot ? path.join(packageRoot, 'dist') : null,\n packageRoot,\n path.join(workspaceDir, 'node_modules', packageName, 'src'),\n path.join(workspaceDir, 'node_modules', packageName, 'lib'),\n path.join(workspaceDir, 'node_modules', packageName, 'dist'),\n path.join(workspaceDir, 'node_modules', packageName),\n ].filter(Boolean) as string[];\n};\n\nconst getFirstExistingPath = (candidates: string[]): string | null =>\n candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n\nconst findPackageSourceDir = (packageName: string): string | null => {\n const workspaceDir = process.cwd();\n const packageRoot = findPackageRoot(packageName);\n\n return getFirstExistingPath(buildPackageSourceCandidates(workspaceDir, packageName, packageRoot));\n};\n\nconst getPackageUdsScope = (packageName: string): string | null => {\n const packageRoot = findPackageRoot(packageName);\n if (!packageRoot) {\n return null;\n }\n\n const packageJsonPath = path.join(packageRoot, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as PackageJsonShape;\n const scope = packageJson.uds?.scope;\n return typeof scope === 'string' && scope.trim().length > 0 ? scope.trim() : null;\n } catch {\n return null;\n }\n};\n\nconst scaffoldThemeConfig = async (options: {\n outputPath?: string;\n configPath?: string;\n entry?: EntryValue;\n force?: boolean;\n}): Promise<void> => {\n const workspaceDir = process.cwd();\n const outputPath = options.outputPath ?? 'uds.theme.ts';\n const absoluteOutputPath = path.isAbsolute(outputPath)\n ? outputPath\n : path.join(workspaceDir, outputPath);\n\n if (fs.existsSync(absoluteOutputPath) && !options.force) {\n print(red(`Error: ${outputPath} already exists. Use --force to overwrite.`));\n process.exitCode = 1;\n return;\n }\n\n const configPath = options.configPath ?? './uds.config.ts';\n const entry = options.entry ?? './src';\n const serializedEntry = formatEntryValue(entry);\n\n const template = `import { defineTheme } from '@yahoo/uds';\n\n/**\n * UDS Theme Configuration\n * \n * This file configures CSS generation for your app and shared packages.\n * Run \\`uds css\\` to generate optimized CSS.\n */\nexport default defineTheme({\n // Path to your uds.config.ts file\n config: '${configPath}',\n\n // Entry directory or .tsx file path for scanning your app code\n entry: ${serializedEntry},\n\n // Color modes to include (light mode is always in :root)\n colorModes: ['dark'],\n\n // Packages that inherit your app's theme (merged into main uds.css)\n // inherit: ['@your-org/shared-ui'],\n\n // Packages that generate separate scoped CSS outputs.\n // Scope class is discovered from each package.json uds.scope.\n // When entry is omitted, the package is scanned the same way as inherit.\n // scoped: {\n // '@your-org/shared-ui': './packages/shared-ui/uds.config.ts'\n // }\n //\n // Or use the expanded form for custom output paths:\n // scoped: {\n // '@your-org/shared-ui': {\n // config: './packages/shared-ui/uds.config.ts',\n // entry: './src',\n // // outFile defaults to dist/shared-ui.css\n // outFile: 'dist/shared-ui.css'\n // },\n // },\n\n // CSS generation options (all optional)\n // css: {\n // safelist: [],\n // preflight: true,\n // fontFaceDeclarations: true,\n // optimization: {\n // removeUnusedFonts: false,\n // removeEmptyRules: true,\n // deduplicateScopedCss: true\n // }\n // }\n});\n`;\n\n fs.writeFileSync(absoluteOutputPath, template);\n\n print('');\n print(green('✅ Created uds.theme.ts'));\n print('');\n print(`${magenta('Next steps:')}`);\n print(` 1. Review and customize ${cyan(outputPath)}`);\n print(` 2. Run ${cyan('uds css')} to generate CSS`);\n print('');\n};\n\nexport {\n findPackageRoot,\n findPackageSourceDir,\n getPackageUdsScope,\n loadConfigFile,\n scaffoldThemeConfig,\n scanDirectoriesForSafelist,\n scanDirectoryForSafelist,\n};\nexport type { SafelistScanResult };\n"],"mappings":"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"}
|
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
const require_postcss_helpers = require('./postcss.helpers.cjs');
|
|
3
3
|
|
|
4
4
|
//#region src/css/postcss.ts
|
|
5
|
+
const fixScopedSelfOrParentSelectorsPlugin = (scopeClass) => {
|
|
6
|
+
return {
|
|
7
|
+
postcssPlugin: "fix-scoped-self-or-parent-selectors",
|
|
8
|
+
Once(root) {
|
|
9
|
+
root.walkRules((rule) => {
|
|
10
|
+
if (!rule.selector.includes(scopeClass)) return;
|
|
11
|
+
const nextSelectors = rule.selectors.reduce((acc, selector) => {
|
|
12
|
+
const sameElementSelector = require_postcss_helpers.getScopedSelfOrParentAlternativeSelector(selector, scopeClass);
|
|
13
|
+
if (sameElementSelector && !rule.selectors.includes(sameElementSelector)) return [
|
|
14
|
+
...acc,
|
|
15
|
+
selector,
|
|
16
|
+
sameElementSelector
|
|
17
|
+
];
|
|
18
|
+
return [...acc, selector];
|
|
19
|
+
}, []);
|
|
20
|
+
if (nextSelectors.length !== rule.selectors.length) rule.selectors = nextSelectors;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
};
|
|
5
25
|
/**
|
|
6
26
|
* PostCSS plugin to fix color mode selectors for scoped CSS.
|
|
7
27
|
*
|
|
@@ -31,4 +51,5 @@ const fixScopedColorModeSelectorsPlugin = (scopeClass) => {
|
|
|
31
51
|
};
|
|
32
52
|
|
|
33
53
|
//#endregion
|
|
34
|
-
exports.fixScopedColorModeSelectorsPlugin = fixScopedColorModeSelectorsPlugin;
|
|
54
|
+
exports.fixScopedColorModeSelectorsPlugin = fixScopedColorModeSelectorsPlugin;
|
|
55
|
+
exports.fixScopedSelfOrParentSelectorsPlugin = fixScopedSelfOrParentSelectorsPlugin;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
//#region src/css/postcss.helpers.ts
|
|
4
4
|
const COLOR_MODE_RE = /^(\.(uds-color-mode-(?:dark|light)))(\s+.+)?$/;
|
|
5
5
|
const escapeForRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
+
const SCOPED_SELF_OR_PARENT_RE = /^(\.[^\s>+~]+)(.*)$/;
|
|
6
7
|
const getScopedColorModeAlternativeSelector = (selector, scopeClass, variant = "descendant") => {
|
|
7
8
|
const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\s+(.+)$`));
|
|
8
9
|
if (!scopeMatch) return null;
|
|
@@ -23,6 +24,16 @@ const buildScopedColorModeSelectorList = (ruleSelector, scopeClass) => {
|
|
|
23
24
|
];
|
|
24
25
|
}, []).join(", ");
|
|
25
26
|
};
|
|
27
|
+
const getScopedSelfOrParentAlternativeSelector = (selector, scopeClass) => {
|
|
28
|
+
const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\s+(.+)$`));
|
|
29
|
+
if (!scopeMatch) return null;
|
|
30
|
+
const targetMatch = scopeMatch[2].match(SCOPED_SELF_OR_PARENT_RE);
|
|
31
|
+
if (!targetMatch) return null;
|
|
32
|
+
const scopedTarget = targetMatch[1];
|
|
33
|
+
if (/^\.uds-color-mode-(?:dark|light)(?:$|[.#[:])/.test(scopedTarget)) return null;
|
|
34
|
+
return `${scopeClass}${scopedTarget}${targetMatch[2]}`;
|
|
35
|
+
};
|
|
26
36
|
|
|
27
37
|
//#endregion
|
|
28
|
-
exports.buildScopedColorModeSelectorList = buildScopedColorModeSelectorList;
|
|
38
|
+
exports.buildScopedColorModeSelectorList = buildScopedColorModeSelectorList;
|
|
39
|
+
exports.getScopedSelfOrParentAlternativeSelector = getScopedSelfOrParentAlternativeSelector;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
//#region src/css/postcss.helpers.ts
|
|
3
3
|
const COLOR_MODE_RE = /^(\.(uds-color-mode-(?:dark|light)))(\s+.+)?$/;
|
|
4
4
|
const escapeForRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5
|
+
const SCOPED_SELF_OR_PARENT_RE = /^(\.[^\s>+~]+)(.*)$/;
|
|
5
6
|
const getScopedColorModeAlternativeSelector = (selector, scopeClass, variant = "descendant") => {
|
|
6
7
|
const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\s+(.+)$`));
|
|
7
8
|
if (!scopeMatch) return null;
|
|
@@ -22,7 +23,16 @@ const buildScopedColorModeSelectorList = (ruleSelector, scopeClass) => {
|
|
|
22
23
|
];
|
|
23
24
|
}, []).join(", ");
|
|
24
25
|
};
|
|
26
|
+
const getScopedSelfOrParentAlternativeSelector = (selector, scopeClass) => {
|
|
27
|
+
const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\s+(.+)$`));
|
|
28
|
+
if (!scopeMatch) return null;
|
|
29
|
+
const targetMatch = scopeMatch[2].match(SCOPED_SELF_OR_PARENT_RE);
|
|
30
|
+
if (!targetMatch) return null;
|
|
31
|
+
const scopedTarget = targetMatch[1];
|
|
32
|
+
if (/^\.uds-color-mode-(?:dark|light)(?:$|[.#[:])/.test(scopedTarget)) return null;
|
|
33
|
+
return `${scopeClass}${scopedTarget}${targetMatch[2]}`;
|
|
34
|
+
};
|
|
25
35
|
|
|
26
36
|
//#endregion
|
|
27
|
-
export { buildScopedColorModeSelectorList };
|
|
37
|
+
export { buildScopedColorModeSelectorList, getScopedSelfOrParentAlternativeSelector };
|
|
28
38
|
//# sourceMappingURL=postcss.helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postcss.helpers.js","names":[],"sources":["../../src/css/postcss.helpers.ts"],"sourcesContent":["const COLOR_MODE_RE = /^(\\.(uds-color-mode-(?:dark|light)))(\\s+.+)?$/;\n\nconst escapeForRegExp = (value: string): string => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\ntype ScopedColorModeSelectorVariant = 'descendant' | 'same-element';\n\nconst getScopedColorModeAlternativeSelector = (\n selector: string,\n scopeClass: string,\n variant: ScopedColorModeSelectorVariant = 'descendant',\n): string | null => {\n const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\\\s+(.+)$`));\n\n if (!scopeMatch) {\n return null;\n }\n\n const afterScope = scopeMatch[2];\n const colorModeMatch = afterScope.match(COLOR_MODE_RE);\n if (!colorModeMatch) {\n return null;\n }\n\n const colorModeClass = colorModeMatch[1];\n const rest = colorModeMatch[3] ?? '';\n return variant === 'same-element'\n ? `${colorModeClass}${scopeClass}${rest}`\n : `${colorModeClass} ${scopeClass}${rest}`;\n};\n\nconst buildScopedColorModeSelectorList = (ruleSelector: string, scopeClass: string): string => {\n const selectors = ruleSelector.split(',').map((value) => value.trim());\n const nextSelectors = selectors.reduce<string[]>((acc, selector) => {\n const altSelectors = [\n getScopedColorModeAlternativeSelector(selector, scopeClass),\n getScopedColorModeAlternativeSelector(selector, scopeClass, 'same-element'),\n ].filter((value): value is string => Boolean(value));\n const nextAltSelectors = altSelectors.filter(\n (altSelector) => !selectors.includes(altSelector) && !acc.includes(altSelector),\n );\n\n return [...acc, selector, ...nextAltSelectors];\n }, []);\n\n return nextSelectors.join(', ');\n};\n\
|
|
1
|
+
{"version":3,"file":"postcss.helpers.js","names":[],"sources":["../../src/css/postcss.helpers.ts"],"sourcesContent":["const COLOR_MODE_RE = /^(\\.(uds-color-mode-(?:dark|light)))(\\s+.+)?$/;\n\nconst escapeForRegExp = (value: string): string => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\ntype ScopedColorModeSelectorVariant = 'descendant' | 'same-element';\n\nconst SCOPED_SELF_OR_PARENT_RE = /^(\\.[^\\s>+~]+)(.*)$/;\n\nconst getScopedColorModeAlternativeSelector = (\n selector: string,\n scopeClass: string,\n variant: ScopedColorModeSelectorVariant = 'descendant',\n): string | null => {\n const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\\\s+(.+)$`));\n\n if (!scopeMatch) {\n return null;\n }\n\n const afterScope = scopeMatch[2];\n const colorModeMatch = afterScope.match(COLOR_MODE_RE);\n if (!colorModeMatch) {\n return null;\n }\n\n const colorModeClass = colorModeMatch[1];\n const rest = colorModeMatch[3] ?? '';\n return variant === 'same-element'\n ? `${colorModeClass}${scopeClass}${rest}`\n : `${colorModeClass} ${scopeClass}${rest}`;\n};\n\nconst buildScopedColorModeSelectorList = (ruleSelector: string, scopeClass: string): string => {\n const selectors = ruleSelector.split(',').map((value) => value.trim());\n const nextSelectors = selectors.reduce<string[]>((acc, selector) => {\n const altSelectors = [\n getScopedColorModeAlternativeSelector(selector, scopeClass),\n getScopedColorModeAlternativeSelector(selector, scopeClass, 'same-element'),\n ].filter((value): value is string => Boolean(value));\n const nextAltSelectors = altSelectors.filter(\n (altSelector) => !selectors.includes(altSelector) && !acc.includes(altSelector),\n );\n\n return [...acc, selector, ...nextAltSelectors];\n }, []);\n\n return nextSelectors.join(', ');\n};\n\nconst getScopedSelfOrParentAlternativeSelector = (\n selector: string,\n scopeClass: string,\n): string | null => {\n const scopeMatch = selector.match(new RegExp(`^(${escapeForRegExp(scopeClass)})\\\\s+(.+)$`));\n\n if (!scopeMatch) {\n return null;\n }\n\n const afterScope = scopeMatch[2];\n const targetMatch = afterScope.match(SCOPED_SELF_OR_PARENT_RE);\n if (!targetMatch) {\n return null;\n }\n\n const scopedTarget = targetMatch[1];\n if (/^\\.uds-color-mode-(?:dark|light)(?:$|[.#[:])/.test(scopedTarget)) {\n return null;\n }\n\n return `${scopeClass}${scopedTarget}${targetMatch[2]}`;\n};\n\nconst buildScopedSelfOrParentSelectorList = (ruleSelector: string, scopeClass: string): string => {\n const selectors = ruleSelector.split(',').map((value) => value.trim());\n const nextSelectors = selectors.reduce<string[]>((acc, selector) => {\n const sameElementSelector = getScopedSelfOrParentAlternativeSelector(selector, scopeClass);\n const nextAltSelectors: string[] = [];\n\n if (\n sameElementSelector &&\n !selectors.includes(sameElementSelector) &&\n !acc.includes(sameElementSelector)\n ) {\n nextAltSelectors.push(sameElementSelector);\n }\n\n return [...acc, selector, ...nextAltSelectors];\n }, []);\n\n return nextSelectors.join(', ');\n};\n\nexport {\n buildScopedColorModeSelectorList,\n buildScopedSelfOrParentSelectorList,\n getScopedColorModeAlternativeSelector,\n getScopedSelfOrParentAlternativeSelector,\n};\n"],"mappings":";;AAAA,MAAM,gBAAgB;AAEtB,MAAM,mBAAmB,UAA0B,MAAM,QAAQ,uBAAuB,OAAO;AAI/F,MAAM,2BAA2B;AAEjC,MAAM,yCACJ,UACA,YACA,UAA0C,iBACxB;CAClB,MAAM,aAAa,SAAS,MAAM,IAAI,OAAO,KAAK,gBAAgB,WAAW,CAAC,YAAY,CAAC;AAE3F,KAAI,CAAC,WACH,QAAO;CAIT,MAAM,iBADa,WAAW,GACI,MAAM,cAAc;AACtD,KAAI,CAAC,eACH,QAAO;CAGT,MAAM,iBAAiB,eAAe;CACtC,MAAM,OAAO,eAAe,MAAM;AAClC,QAAO,YAAY,iBACf,GAAG,iBAAiB,aAAa,SACjC,GAAG,eAAe,GAAG,aAAa;;AAGxC,MAAM,oCAAoC,cAAsB,eAA+B;CAC7F,MAAM,YAAY,aAAa,MAAM,IAAI,CAAC,KAAK,UAAU,MAAM,MAAM,CAAC;AAatE,QAZsB,UAAU,QAAkB,KAAK,aAAa;EAKlE,MAAM,mBAJe,CACnB,sCAAsC,UAAU,WAAW,EAC3D,sCAAsC,UAAU,YAAY,eAAe,CAC5E,CAAC,QAAQ,UAA2B,QAAQ,MAAM,CAAC,CACd,QACnC,gBAAgB,CAAC,UAAU,SAAS,YAAY,IAAI,CAAC,IAAI,SAAS,YAAY,CAChF;AAED,SAAO;GAAC,GAAG;GAAK;GAAU,GAAG;GAAiB;IAC7C,EAAE,CAAC,CAEe,KAAK,KAAK;;AAGjC,MAAM,4CACJ,UACA,eACkB;CAClB,MAAM,aAAa,SAAS,MAAM,IAAI,OAAO,KAAK,gBAAgB,WAAW,CAAC,YAAY,CAAC;AAE3F,KAAI,CAAC,WACH,QAAO;CAIT,MAAM,cADa,WAAW,GACC,MAAM,yBAAyB;AAC9D,KAAI,CAAC,YACH,QAAO;CAGT,MAAM,eAAe,YAAY;AACjC,KAAI,+CAA+C,KAAK,aAAa,CACnE,QAAO;AAGT,QAAO,GAAG,aAAa,eAAe,YAAY"}
|