@yahoo/uds 3.117.2 → 3.117.4

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.
Files changed (46) hide show
  1. package/dist/styles/styler.d.cts +35 -35
  2. package/dist/styles/styler.d.ts +35 -35
  3. package/dist/tailwind/dist/cli/dist/lib/colors.cjs +22 -0
  4. package/dist/tailwind/dist/cli/dist/lib/colors.js +17 -0
  5. package/dist/tailwind/dist/cli/dist/lib/colors.js.map +1 -0
  6. package/dist/{cli → tailwind/dist/cli}/dist/lib/logger.cjs +1 -1
  7. package/dist/{cli → tailwind/dist/cli}/dist/lib/logger.js +3 -2
  8. package/dist/tailwind/dist/cli/dist/lib/logger.js.map +1 -0
  9. package/dist/tailwind/dist/cli/dist/lib/print.cjs +13 -0
  10. package/dist/tailwind/dist/cli/dist/lib/print.js +13 -0
  11. package/dist/tailwind/dist/cli/dist/lib/print.js.map +1 -0
  12. package/dist/{cli → tailwind/dist/cli}/dist/lib/spinner.cjs +1 -1
  13. package/dist/{cli → tailwind/dist/cli}/dist/lib/spinner.js +3 -2
  14. package/dist/tailwind/dist/cli/dist/lib/spinner.js.map +1 -0
  15. package/dist/tailwind/dist/commands/css.cjs +34 -34
  16. package/dist/tailwind/dist/commands/css.js +2 -1
  17. package/dist/tailwind/dist/commands/css.js.map +1 -1
  18. package/dist/tailwind/dist/commands/generateComponentData.cjs +9 -9
  19. package/dist/tailwind/dist/commands/generateComponentData.d.ts +1 -1
  20. package/dist/tailwind/dist/commands/generateComponentData.js +1 -1
  21. package/dist/tailwind/dist/commands/generatePurgeCSSData.cjs +3 -2
  22. package/dist/tailwind/dist/commands/generatePurgeCSSData.d.ts +1 -1
  23. package/dist/tailwind/dist/commands/generatePurgeCSSData.js +2 -1
  24. package/dist/tailwind/dist/commands/generatePurgeCSSData.js.map +1 -1
  25. package/dist/tailwind/dist/commands/purge.cjs +13 -13
  26. package/dist/tailwind/dist/commands/purge.js +2 -1
  27. package/dist/tailwind/dist/commands/purge.js.map +1 -1
  28. package/dist/tailwind/dist/css/generate.cjs +8 -6
  29. package/dist/tailwind/dist/css/generate.js +3 -1
  30. package/dist/tailwind/dist/css/generate.js.map +1 -1
  31. package/dist/tailwind/dist/css/nodeUtils.cjs +10 -9
  32. package/dist/tailwind/dist/css/nodeUtils.js +2 -1
  33. package/dist/tailwind/dist/css/nodeUtils.js.map +1 -1
  34. package/dist/tailwind/dist/css/runner.cjs +25 -22
  35. package/dist/tailwind/dist/css/runner.js +4 -1
  36. package/dist/tailwind/dist/css/runner.js.map +1 -1
  37. package/dist/tailwind/dist/purger/legacy/purgeCSS.cjs +8 -7
  38. package/dist/tailwind/dist/purger/legacy/purgeCSS.js +2 -1
  39. package/dist/tailwind/dist/purger/legacy/purgeCSS.js.map +1 -1
  40. package/dist/tailwind/dist/utils/generatePurgeCSSData.cjs +4 -3
  41. package/dist/tailwind/dist/utils/generatePurgeCSSData.js +2 -1
  42. package/dist/tailwind/dist/utils/generatePurgeCSSData.js.map +1 -1
  43. package/dist/uds/generated/componentData.cjs +81 -81
  44. package/dist/uds/generated/componentData.js +81 -81
  45. package/generated/componentData.json +112 -112
  46. package/package.json +1 -1
@@ -1,12 +1,15 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ const require_colors = require('../cli/dist/lib/colors.cjs');
4
+ const require_print = require('../cli/dist/lib/print.cjs');
5
+ const require_spinner = require('../cli/dist/lib/spinner.cjs');
6
+ const require_logger = require('../cli/dist/lib/logger.cjs');
3
7
  const require_entryPoints = require('../utils/entryPoints.cjs');
4
8
  const require_nodeUtils = require('./nodeUtils.cjs');
5
9
  const require_safelist = require('../purger/optimized/utils/safelist.cjs');
6
10
  const require_utils = require('./utils.cjs');
7
11
  const require_generate = require('./generate.cjs');
8
12
  const require_runner_helpers = require('./runner.helpers.cjs');
9
- let _yahoo_uds_cli_lib = require("@yahoo/uds-cli/lib");
10
13
  let node_fs = require("node:fs");
11
14
  node_fs = require_runtime.__toESM(node_fs);
12
15
  let node_path = require("node:path");
@@ -93,7 +96,7 @@ const runCssCommand = async (options, context) => {
93
96
  const runSimpleMode = async (options, context) => {
94
97
  const entry = options.entryOption ?? require_entryPoints.DEFAULT_ENTRY;
95
98
  const configPath = typeof options.configOption === "string" ? options.configOption : void 0;
96
- if (!options.watch && !options.silent) (0, _yahoo_uds_cli_lib.spinStart)("Generating CSS...");
99
+ if (!options.watch && !options.silent) require_spinner.spinStart("Generating CSS...");
97
100
  try {
98
101
  const result = await require_generate.generateSimpleModeCSS({
99
102
  workspaceDir: options.workspaceDir,
@@ -109,7 +112,7 @@ const runSimpleMode = async (options, context) => {
109
112
  });
110
113
  if (options.watch) await runSimpleModeWatch(options, context, entry, configPath, result.packageDirs ?? []);
111
114
  } catch (error) {
112
- (0, _yahoo_uds_cli_lib.spinStop)("❌", error instanceof Error ? error.message : "CSS generation failed");
115
+ require_spinner.spinStop("❌", error instanceof Error ? error.message : "CSS generation failed");
113
116
  process.exitCode = 1;
114
117
  }
115
118
  };
@@ -121,15 +124,15 @@ const runSimpleModeWatch = async (options, context, entry, configPath, packageDi
121
124
  }));
122
125
  const watchTargets = packageDirs.length > 0 ? fallbackTargets : entryWatchTargets;
123
126
  if (!options.silent) {
124
- (0, _yahoo_uds_cli_lib.print)("");
125
- (0, _yahoo_uds_cli_lib.print)(`${(0, _yahoo_uds_cli_lib.magenta)("Watching for changes...")}`);
126
- watchTargets.forEach((target) => (0, _yahoo_uds_cli_lib.print)(` ${(0, _yahoo_uds_cli_lib.gray)("•")} ${target.watchPath}`));
127
- (0, _yahoo_uds_cli_lib.print)(`${(0, _yahoo_uds_cli_lib.gray)("Press Ctrl+C to stop")}`);
128
- (0, _yahoo_uds_cli_lib.print)("");
127
+ require_print.print("");
128
+ require_print.print(`${require_colors.magenta("Watching for changes...")}`);
129
+ watchTargets.forEach((target) => require_print.print(` ${require_colors.gray("•")} ${target.watchPath}`));
130
+ require_print.print(`${require_colors.gray("Press Ctrl+C to stop")}`);
131
+ require_print.print("");
129
132
  }
130
133
  const regenerate = createQueuedRegenerator({
131
134
  onStart: () => {
132
- if (!options.silent) (0, _yahoo_uds_cli_lib.print)(`${(0, _yahoo_uds_cli_lib.gray)(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`)} Change detected, regenerating...`);
135
+ if (!options.silent) require_print.print(`${require_colors.gray(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`)} Change detected, regenerating...`);
133
136
  },
134
137
  regenerateOnce: async () => {
135
138
  await require_generate.generateSimpleModeCSS({
@@ -147,12 +150,12 @@ const runSimpleModeWatch = async (options, context, entry, configPath, packageDi
147
150
  },
148
151
  onSuccess: () => {
149
152
  if (!options.silent) {
150
- (0, _yahoo_uds_cli_lib.print)(`${(0, _yahoo_uds_cli_lib.gray)(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`)} ${(0, _yahoo_uds_cli_lib.green)("CSS updated")}`);
151
- (0, _yahoo_uds_cli_lib.print)("");
153
+ require_print.print(`${require_colors.gray(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`)} ${require_colors.green("CSS updated")}`);
154
+ require_print.print("");
152
155
  }
153
156
  },
154
157
  onError: (message) => {
155
- (0, _yahoo_uds_cli_lib.print)(`Error: ${message}`);
158
+ require_print.print(`Error: ${message}`);
156
159
  }
157
160
  });
158
161
  watchSourceFiles(watchTargets, createDebouncedAction(() => {
@@ -186,7 +189,7 @@ const runThemeMode = async (options, context) => {
186
189
  const workspaceDir = options.workspaceDir;
187
190
  const outputPath = node_path.default.isAbsolute(options.outFile) ? options.outFile : node_path.default.join(workspaceDir, String(options.outFile));
188
191
  let effectiveSilent = options.silent;
189
- let log = (0, _yahoo_uds_cli_lib.createLogger)({ silent: effectiveSilent });
192
+ let log = require_logger.createLogger({ silent: effectiveSilent });
190
193
  log.spinStart("Loading theme configuration...");
191
194
  try {
192
195
  const setup = await loadThemeModeSetup(options);
@@ -197,14 +200,14 @@ const runThemeMode = async (options, context) => {
197
200
  }
198
201
  const { themeConfig, colorModes, entries, appConfig, appVariantDefaults } = setup;
199
202
  effectiveSilent = setup.effectiveSilent;
200
- log = (0, _yahoo_uds_cli_lib.createLogger)({ silent: effectiveSilent });
203
+ log = require_logger.createLogger({ silent: effectiveSilent });
201
204
  const entryDirs = entries.map((entry) => entry.absolutePath);
202
205
  if (!effectiveSilent) log.spinStop("✅", "Theme configuration loaded");
203
206
  if (themeConfig.config && appConfig === _yahoo_uds_config.defaultTokensConfig) log.warn(`App config not found: ${themeConfig.config}, using defaults`);
204
207
  const packageDirs = [];
205
208
  const generateThemeModeCSS = async (opts) => {
206
209
  const genStartTime = performance.now();
207
- const genLog = opts?.isWatch ? (0, _yahoo_uds_cli_lib.createLogger)({ silent: true }) : log;
210
+ const genLog = opts?.isWatch ? require_logger.createLogger({ silent: true }) : log;
208
211
  genLog.spinStart("Scanning app code...");
209
212
  const appScanResult = await require_nodeUtils.scanDirectoriesForSafelist(entryDirs, colorModes, context.variants, context.autoVariants, context.componentData, appVariantDefaults);
210
213
  genLog.spinStop("✅", `Scanned ${appScanResult.filesScanned} files`);
@@ -250,11 +253,11 @@ const runThemeMode = async (options, context) => {
250
253
  }));
251
254
  const duration = Math.round(performance.now() - genStartTime);
252
255
  genLog.newline();
253
- genLog.print((0, _yahoo_uds_cli_lib.green)("CSS generation complete!"));
256
+ genLog.print(require_colors.green("CSS generation complete!"));
254
257
  genLog.newline();
255
258
  genLog.label("Output file:", outputPath);
256
259
  genLog.newline();
257
- genLog.print(`${(0, _yahoo_uds_cli_lib.magenta)("Total time:")} ${duration}ms`);
260
+ genLog.print(`${require_colors.magenta("Total time:")} ${duration}ms`);
258
261
  return {
259
262
  duration,
260
263
  outputPath,
@@ -267,28 +270,28 @@ const runThemeMode = async (options, context) => {
267
270
  const { filteredPackageDirs } = require_runner_helpers.getWatchDirectoryGroups(getWatchDirs(entryWatchTargets.map((target) => target.watchPath)), [...entryDirs, ...packageDirs]);
268
271
  if (!effectiveSilent) {
269
272
  log.newline();
270
- log.print(`${(0, _yahoo_uds_cli_lib.magenta)("Watching for changes...")}`);
273
+ log.print(`${require_colors.magenta("Watching for changes...")}`);
271
274
  entryDirs.forEach((entryDir) => {
272
275
  log.listItem(`App: ${entryDir}`);
273
276
  });
274
277
  filteredPackageDirs.forEach((dir) => {
275
278
  log.listItem(`Package: ${dir}`);
276
279
  });
277
- log.print(`${(0, _yahoo_uds_cli_lib.gray)("Press Ctrl+C to stop")}`);
280
+ log.print(`${require_colors.gray("Press Ctrl+C to stop")}`);
278
281
  log.newline();
279
282
  }
280
283
  const regenerate = createQueuedRegenerator({
281
284
  onStart: () => {
282
285
  if (!effectiveSilent) {
283
286
  const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
284
- log.print(`${(0, _yahoo_uds_cli_lib.gray)(`[${timestamp}]`)} Change detected, regenerating...`);
287
+ log.print(`${require_colors.gray(`[${timestamp}]`)} Change detected, regenerating...`);
285
288
  }
286
289
  },
287
290
  regenerateOnce: async () => generateThemeModeCSS({ isWatch: true }),
288
291
  onSuccess: (result) => {
289
292
  if (!effectiveSilent) {
290
293
  const updatedAt = (/* @__PURE__ */ new Date()).toLocaleTimeString();
291
- log.print(`${(0, _yahoo_uds_cli_lib.gray)(`[${updatedAt}]`)} ${(0, _yahoo_uds_cli_lib.green)(`CSS updated (${result?.duration}ms)`)}`);
294
+ log.print(`${require_colors.gray(`[${updatedAt}]`)} ${require_colors.green(`CSS updated (${result?.duration}ms)`)}`);
292
295
  log.newline();
293
296
  }
294
297
  },
@@ -307,7 +310,7 @@ const runThemeMode = async (options, context) => {
307
310
  }
308
311
  } catch (error) {
309
312
  const message = error instanceof Error ? error.message : "CSS generation failed";
310
- if (effectiveSilent) (0, _yahoo_uds_cli_lib.spinStop)("❌", message);
313
+ if (effectiveSilent) require_spinner.spinStop("❌", message);
311
314
  else log.spinStop("❌", message);
312
315
  process.exitCode = 1;
313
316
  }
@@ -1,11 +1,14 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
+ import { gray, green, magenta } from "../cli/dist/lib/colors.js";
3
+ import { print } from "../cli/dist/lib/print.js";
4
+ import { spinStart, spinStop } from "../cli/dist/lib/spinner.js";
5
+ import { createLogger } from "../cli/dist/lib/logger.js";
2
6
  import { DEFAULT_ENTRY, resolveEntryPaths } from "../utils/entryPoints.js";
3
7
  import { findPackageSourceDir, loadConfigFile, scanDirectoriesForSafelist, scanDirectoryForSafelist } from "./nodeUtils.js";
4
8
  import { deduplicateSafelist, getThemeAndScaleClasses } from "../purger/optimized/utils/safelist.js";
5
9
  import { extractVariantDefaults, formatBytes, getConfigurableCssVariables, getMotionVarPrefixes } from "./utils.js";
6
10
  import { generateCSS, generateSimpleModeCSS } from "./generate.js";
7
11
  import { getMainCssSummaryMessage, getWatchDirectoryGroups } from "./runner.helpers.js";
8
- import { createLogger, gray, green, magenta, print, spinStart, spinStop } from "@yahoo/uds-cli/lib";
9
12
  import fs from "node:fs";
10
13
  import path from "node:path";
11
14
  import { defaultTokensConfig } from "@yahoo/uds-config";
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","names":[],"sources":["../../src/css/runner.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { createLogger, gray, green, magenta, print, spinStart, spinStop } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport { deduplicateSafelist, getThemeAndScaleClasses } from '../purger/optimized/utils/safelist';\nimport type { EntryValue, ResolvedEntryPath } from '../utils/entryPoints';\nimport { DEFAULT_ENTRY, resolveEntryPaths } from '../utils/entryPoints';\nimport { generateCSS, generateSimpleModeCSS } from './generate';\nimport {\n findPackageSourceDir,\n loadConfigFile,\n scanDirectoriesForSafelist,\n scanDirectoryForSafelist,\n} from './nodeUtils';\nimport { getMainCssSummaryMessage, getWatchDirectoryGroups } from './runner.helpers';\nimport type { UDSThemeConfig, UDSThemeConfigInput, UDSThemeContext } from './theme';\nimport {\n extractVariantDefaults,\n formatBytes,\n getConfigurableCssVariables,\n getMotionVarPrefixes,\n} from './utils';\n\ntype CssCommandContext = {\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n};\n\ntype CssCommandOptions = {\n workspaceDir: string;\n outFile: string;\n themeConfigPath: string;\n scope?: string;\n entryOption?: EntryValue;\n configOption?: string;\n watch: boolean;\n silent: boolean;\n};\n\ntype ThemeModeSetup = {\n themeConfig: UDSThemeConfig;\n colorModes: ('dark' | 'light')[];\n entries: ResolvedEntryPath[];\n appConfig: UniversalTokensConfig;\n appVariantDefaults: ReturnType<typeof extractVariantDefaults>;\n effectiveSilent: boolean;\n};\n\nconst SOURCE_FILE_PATTERN = /\\.(jsx?|tsx?)$/i;\n\ntype WatchTarget = {\n watchPath: string;\n recursive: boolean;\n fileNames?: string[];\n};\n\nconst getWatchDirs = (dirs: string[]): string[] => [\n ...new Set(dirs.filter((dir) => !dir.split(path.sep).includes('node_modules'))),\n];\n\nconst isCoveredByRecursiveWatch = (watchPath: string, targetPath: string): boolean =>\n targetPath === watchPath || targetPath.startsWith(`${watchPath}${path.sep}`);\n\nconst getEntryWatchTargets = (entries: ResolvedEntryPath[]): WatchTarget[] => {\n const directoryTargets = getWatchDirs(\n entries.filter((entry) => entry.kind === 'directory').map((entry) => entry.absolutePath),\n ).map((watchPath) => ({ watchPath, recursive: true }));\n\n const fileNamesByDirectory = new Map<string, Set<string>>();\n\n entries\n .filter(\n (entry): entry is ResolvedEntryPath & { kind: 'file'; fileName: string } =>\n entry.kind === 'file' && typeof entry.fileName === 'string',\n )\n .forEach((entry) => {\n if (\n directoryTargets.some((target) =>\n isCoveredByRecursiveWatch(target.watchPath, entry.absolutePath),\n )\n ) {\n return;\n }\n\n const fileNames = fileNamesByDirectory.get(entry.watchDirectory) ?? new Set<string>();\n fileNames.add(entry.fileName);\n fileNamesByDirectory.set(entry.watchDirectory, fileNames);\n });\n\n const fileTargets = [...fileNamesByDirectory.entries()].map(([watchPath, fileNames]) => ({\n watchPath,\n recursive: false,\n fileNames: [...fileNames],\n }));\n\n return [...directoryTargets, ...fileTargets];\n};\n\nconst watchSourceFiles = (targets: WatchTarget[], onFileChange: () => void): void => {\n targets.forEach((target) => {\n fs.watch(target.watchPath, { recursive: target.recursive }, (_eventType, filename) => {\n if (!filename || !SOURCE_FILE_PATTERN.test(filename)) {\n return;\n }\n\n if (target.fileNames && !target.fileNames.includes(path.basename(String(filename)))) {\n return;\n }\n\n onFileChange();\n });\n });\n};\n\nconst createDebouncedAction = (action: () => void, delayMs: number): (() => void) => {\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n return () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(action, delayMs);\n };\n};\n\nconst getPruneVarSafelist = (themeConfig: UDSThemeConfig): Array<string | RegExp> => {\n const pruneVars = themeConfig.css?.optimization?.pruneVars;\n\n if (!pruneVars || typeof pruneVars !== 'object') {\n return [];\n }\n\n return pruneVars.safelist ?? [];\n};\n\nconst createQueuedRegenerator = <T>(options: {\n onStart?: () => void;\n onSuccess?: (result: T) => void;\n onError: (message: string) => void;\n regenerateOnce: () => Promise<T>;\n}): (() => Promise<void>) => {\n let isGenerating = false;\n let pendingRegenerate = false;\n\n const regenerate = async (): Promise<void> => {\n if (isGenerating) {\n pendingRegenerate = true;\n return;\n }\n\n isGenerating = true;\n try {\n options.onStart?.();\n const result = await options.regenerateOnce();\n options.onSuccess?.(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'CSS generation failed';\n options.onError(message);\n } finally {\n isGenerating = false;\n\n if (pendingRegenerate) {\n pendingRegenerate = false;\n await regenerate();\n }\n }\n };\n\n return regenerate;\n};\n\nconst runCssCommand = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const themeConfigExists = fs.existsSync(\n path.join(options.workspaceDir, String(options.themeConfigPath)),\n );\n\n if (!themeConfigExists) {\n await runSimpleMode(options, context);\n return;\n }\n\n await runThemeMode(options, context);\n};\n\nconst runSimpleMode = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const entry = options.entryOption ?? DEFAULT_ENTRY;\n const configPath = typeof options.configOption === 'string' ? options.configOption : undefined;\n\n if (!options.watch && !options.silent) {\n spinStart('Generating CSS...');\n }\n\n try {\n const result = await generateSimpleModeCSS({\n workspaceDir: options.workspaceDir,\n entry,\n outFile: String(options.outFile),\n variants: context.variants,\n autoVariants: context.autoVariants,\n componentData: context.componentData,\n scope: options.scope,\n configPath,\n isWatch: options.watch,\n silent: options.silent,\n });\n\n if (options.watch) {\n await runSimpleModeWatch(options, context, entry, configPath, result.packageDirs ?? []);\n }\n } catch (error) {\n spinStop('❌', error instanceof Error ? error.message : 'CSS generation failed');\n process.exitCode = 1;\n }\n};\n\nconst runSimpleModeWatch = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n entry: EntryValue,\n configPath: string | undefined,\n packageDirs: string[],\n): Promise<void> => {\n const resolvedEntries = resolveEntryPaths(entry, options.workspaceDir);\n const entryWatchTargets = getEntryWatchTargets(resolvedEntries);\n const fallbackTargets = getWatchDirs(packageDirs).map((watchPath) => ({\n watchPath,\n recursive: true,\n }));\n const watchTargets = packageDirs.length > 0 ? fallbackTargets : entryWatchTargets;\n\n if (!options.silent) {\n print('');\n print(`${magenta('Watching for changes...')}`);\n watchTargets.forEach((target) => print(` ${gray('•')} ${target.watchPath}`));\n print(`${gray('Press Ctrl+C to stop')}`);\n print('');\n }\n\n const regenerate = createQueuedRegenerator({\n onStart: () => {\n if (!options.silent) {\n const timestamp = new Date().toLocaleTimeString();\n print(`${gray(`[${timestamp}]`)} Change detected, regenerating...`);\n }\n },\n regenerateOnce: async () => {\n await generateSimpleModeCSS({\n workspaceDir: options.workspaceDir,\n entry,\n outFile: String(options.outFile),\n variants: context.variants,\n autoVariants: context.autoVariants,\n componentData: context.componentData,\n scope: options.scope,\n configPath,\n isWatch: true,\n silent: true,\n });\n },\n onSuccess: () => {\n if (!options.silent) {\n const updatedAt = new Date().toLocaleTimeString();\n print(`${gray(`[${updatedAt}]`)} ${green('CSS updated')}`);\n print('');\n }\n },\n onError: (message) => {\n print(`Error: ${message}`);\n },\n });\n\n watchSourceFiles(\n watchTargets,\n createDebouncedAction(() => {\n void regenerate();\n }, 100),\n );\n\n await new Promise(() => {});\n};\n\nconst loadThemeModeSetup = async (options: CssCommandOptions): Promise<ThemeModeSetup | null> => {\n const themeConfigInput = await loadConfigFile<UDSThemeConfigInput>(\n String(options.themeConfigPath),\n );\n if (!themeConfigInput) {\n return null;\n }\n\n const themeContext: UDSThemeContext = {\n cwd: options.workspaceDir,\n watch: options.watch,\n };\n const themeConfig: UDSThemeConfig =\n typeof themeConfigInput === 'function'\n ? await themeConfigInput(themeContext)\n : themeConfigInput;\n\n let appConfig: UniversalTokensConfig = defaultTokensConfig;\n if (themeConfig.config) {\n const loadedConfig = await loadConfigFile<UniversalTokensConfig>(themeConfig.config);\n if (loadedConfig) {\n appConfig = loadedConfig;\n }\n }\n\n return {\n themeConfig,\n colorModes: themeConfig.colorModes ?? ['dark'],\n entries: resolveEntryPaths(themeConfig.entry, options.workspaceDir),\n appConfig,\n appVariantDefaults: extractVariantDefaults(appConfig),\n effectiveSilent: options.silent || themeConfig.silent === true,\n };\n};\n\nconst runThemeMode = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const workspaceDir = options.workspaceDir;\n const outputPath = path.isAbsolute(options.outFile)\n ? options.outFile\n : path.join(workspaceDir, String(options.outFile));\n let effectiveSilent = options.silent;\n let log = createLogger({ silent: effectiveSilent });\n\n log.spinStart('Loading theme configuration...');\n\n try {\n const setup = await loadThemeModeSetup(options);\n if (!setup) {\n log.spinStop('❌', `Theme config not found: ${options.themeConfigPath}`);\n process.exitCode = 1;\n return;\n }\n\n const { themeConfig, colorModes, entries, appConfig, appVariantDefaults } = setup;\n effectiveSilent = setup.effectiveSilent;\n log = createLogger({ silent: effectiveSilent });\n const entryDirs = entries.map((entry) => entry.absolutePath);\n\n if (!effectiveSilent) {\n log.spinStop('✅', 'Theme configuration loaded');\n }\n\n if (themeConfig.config && appConfig === defaultTokensConfig) {\n log.warn(`App config not found: ${themeConfig.config}, using defaults`);\n }\n const packageDirs: string[] = [];\n\n const generateThemeModeCSS = async (opts?: { isWatch?: boolean }) => {\n const genStartTime = performance.now();\n const genLog = opts?.isWatch ? createLogger({ silent: true }) : log;\n\n genLog.spinStart('Scanning app code...');\n const appScanResult = await scanDirectoriesForSafelist(\n entryDirs,\n colorModes,\n context.variants,\n context.autoVariants,\n context.componentData,\n appVariantDefaults,\n );\n genLog.spinStop('✅', `Scanned ${appScanResult.filesScanned} files`);\n\n genLog.spinStart('Generating main CSS...');\n\n const inheritedClasses: string[] = [...appScanResult.safelist];\n const inheritedComponents = new Set<string>(appScanResult.components);\n\n const processInheritedPackage = async (packageName: string) => {\n genLog.spinStart(`Processing package: ${packageName}...`);\n\n const packageDir = findPackageSourceDir(packageName);\n if (!packageDir) {\n genLog.spinStop('⚠️', `Package not found: ${packageName}`);\n return;\n }\n\n if (!packageDirs.includes(packageDir)) {\n packageDirs.push(packageDir);\n }\n\n const packageScanResult = await scanDirectoryForSafelist(\n packageDir,\n colorModes,\n context.variants,\n context.autoVariants,\n context.componentData,\n appVariantDefaults,\n true,\n );\n inheritedClasses.push(...packageScanResult.safelist);\n packageScanResult.components.forEach((comp) => inheritedComponents.add(comp));\n genLog.spinStop('✅', `${packageName}: ${packageScanResult.filesScanned} files (inherit)`);\n };\n\n await (themeConfig.inherit ?? []).reduce(async (promise, packageName) => {\n await promise;\n await processInheritedPackage(packageName);\n }, Promise.resolve());\n\n const mainSafelist = deduplicateSafelist([\n ...inheritedClasses,\n ...getThemeAndScaleClasses(colorModes),\n ]);\n\n const allMotionComponents: string[] = [...inheritedComponents];\n\n const mainCssResult = await generateCSS(\n [...(themeConfig.css?.safelist ?? []), ...mainSafelist],\n appConfig,\n {\n scope: options.scope,\n contentDir: entryDirs,\n cssOptions: themeConfig.css,\n safeVarPrefixes: [\n ...getMotionVarPrefixes(context.componentData, allMotionComponents),\n ...getConfigurableCssVariables(),\n ...getPruneVarSafelist(themeConfig),\n ],\n },\n );\n\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, mainCssResult.css);\n\n genLog.spinStop(\n '✅',\n getMainCssSummaryMessage({\n sizeGzipBytes: mainCssResult.sizeGzipBytes,\n optimizationStats: mainCssResult.optimizationStats,\n formatBytes,\n }),\n );\n\n const duration = Math.round(performance.now() - genStartTime);\n\n genLog.newline();\n genLog.print(green('CSS generation complete!'));\n genLog.newline();\n genLog.label('Output file:', outputPath);\n genLog.newline();\n genLog.print(`${magenta('Total time:')} ${duration}ms`);\n\n return { duration, outputPath, packageDirs };\n };\n\n await generateThemeModeCSS();\n\n if (options.watch) {\n const entryWatchTargets = getEntryWatchTargets(entries);\n const entryWatchDirs = getWatchDirs(entryWatchTargets.map((target) => target.watchPath));\n const { filteredPackageDirs } = getWatchDirectoryGroups(entryWatchDirs, [\n ...entryDirs,\n ...packageDirs,\n ]);\n\n if (!effectiveSilent) {\n log.newline();\n log.print(`${magenta('Watching for changes...')}`);\n entryDirs.forEach((entryDir) => {\n log.listItem(`App: ${entryDir}`);\n });\n filteredPackageDirs.forEach((dir) => {\n log.listItem(`Package: ${dir}`);\n });\n log.print(`${gray('Press Ctrl+C to stop')}`);\n log.newline();\n }\n\n const regenerate = createQueuedRegenerator({\n onStart: () => {\n if (!effectiveSilent) {\n const timestamp = new Date().toLocaleTimeString();\n log.print(`${gray(`[${timestamp}]`)} Change detected, regenerating...`);\n }\n },\n regenerateOnce: async () => generateThemeModeCSS({ isWatch: true }),\n onSuccess: (result) => {\n if (!effectiveSilent) {\n const updatedAt = new Date().toLocaleTimeString();\n log.print(`${gray(`[${updatedAt}]`)} ${green(`CSS updated (${result?.duration}ms)`)}`);\n log.newline();\n }\n },\n onError: (message) => {\n log.print(message);\n },\n });\n\n const watchDebounce = themeConfig.css?.watchDebounce ?? 100;\n\n watchSourceFiles(\n [\n ...entryWatchTargets,\n ...filteredPackageDirs\n .filter(\n (packageDir) =>\n !entryWatchTargets.some((target) =>\n isCoveredByRecursiveWatch(target.watchPath, packageDir),\n ),\n )\n .map((watchPath) => ({ watchPath, recursive: true })),\n ],\n createDebouncedAction(() => {\n void regenerate();\n }, watchDebounce),\n );\n\n await new Promise(() => {});\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'CSS generation failed';\n if (effectiveSilent) {\n spinStop('❌', message);\n } else {\n log.spinStop('❌', message);\n }\n process.exitCode = 1;\n }\n};\n\nexport { runCssCommand };\nexport type { CssCommandContext, CssCommandOptions };\n"],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","names":[],"sources":["../../src/css/runner.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { createLogger, gray, green, magenta, print, spinStart, spinStop } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\n\nimport type { SerializedComponentInfo } from '../commands/generateComponentData';\nimport { deduplicateSafelist, getThemeAndScaleClasses } from '../purger/optimized/utils/safelist';\nimport type { EntryValue, ResolvedEntryPath } from '../utils/entryPoints';\nimport { DEFAULT_ENTRY, resolveEntryPaths } from '../utils/entryPoints';\nimport { generateCSS, generateSimpleModeCSS } from './generate';\nimport {\n findPackageSourceDir,\n loadConfigFile,\n scanDirectoriesForSafelist,\n scanDirectoryForSafelist,\n} from './nodeUtils';\nimport { getMainCssSummaryMessage, getWatchDirectoryGroups } from './runner.helpers';\nimport type { UDSThemeConfig, UDSThemeConfigInput, UDSThemeContext } from './theme';\nimport {\n extractVariantDefaults,\n formatBytes,\n getConfigurableCssVariables,\n getMotionVarPrefixes,\n} from './utils';\n\ntype CssCommandContext = {\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n};\n\ntype CssCommandOptions = {\n workspaceDir: string;\n outFile: string;\n themeConfigPath: string;\n scope?: string;\n entryOption?: EntryValue;\n configOption?: string;\n watch: boolean;\n silent: boolean;\n};\n\ntype ThemeModeSetup = {\n themeConfig: UDSThemeConfig;\n colorModes: ('dark' | 'light')[];\n entries: ResolvedEntryPath[];\n appConfig: UniversalTokensConfig;\n appVariantDefaults: ReturnType<typeof extractVariantDefaults>;\n effectiveSilent: boolean;\n};\n\nconst SOURCE_FILE_PATTERN = /\\.(jsx?|tsx?)$/i;\n\ntype WatchTarget = {\n watchPath: string;\n recursive: boolean;\n fileNames?: string[];\n};\n\nconst getWatchDirs = (dirs: string[]): string[] => [\n ...new Set(dirs.filter((dir) => !dir.split(path.sep).includes('node_modules'))),\n];\n\nconst isCoveredByRecursiveWatch = (watchPath: string, targetPath: string): boolean =>\n targetPath === watchPath || targetPath.startsWith(`${watchPath}${path.sep}`);\n\nconst getEntryWatchTargets = (entries: ResolvedEntryPath[]): WatchTarget[] => {\n const directoryTargets = getWatchDirs(\n entries.filter((entry) => entry.kind === 'directory').map((entry) => entry.absolutePath),\n ).map((watchPath) => ({ watchPath, recursive: true }));\n\n const fileNamesByDirectory = new Map<string, Set<string>>();\n\n entries\n .filter(\n (entry): entry is ResolvedEntryPath & { kind: 'file'; fileName: string } =>\n entry.kind === 'file' && typeof entry.fileName === 'string',\n )\n .forEach((entry) => {\n if (\n directoryTargets.some((target) =>\n isCoveredByRecursiveWatch(target.watchPath, entry.absolutePath),\n )\n ) {\n return;\n }\n\n const fileNames = fileNamesByDirectory.get(entry.watchDirectory) ?? new Set<string>();\n fileNames.add(entry.fileName);\n fileNamesByDirectory.set(entry.watchDirectory, fileNames);\n });\n\n const fileTargets = [...fileNamesByDirectory.entries()].map(([watchPath, fileNames]) => ({\n watchPath,\n recursive: false,\n fileNames: [...fileNames],\n }));\n\n return [...directoryTargets, ...fileTargets];\n};\n\nconst watchSourceFiles = (targets: WatchTarget[], onFileChange: () => void): void => {\n targets.forEach((target) => {\n fs.watch(target.watchPath, { recursive: target.recursive }, (_eventType, filename) => {\n if (!filename || !SOURCE_FILE_PATTERN.test(filename)) {\n return;\n }\n\n if (target.fileNames && !target.fileNames.includes(path.basename(String(filename)))) {\n return;\n }\n\n onFileChange();\n });\n });\n};\n\nconst createDebouncedAction = (action: () => void, delayMs: number): (() => void) => {\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n return () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(action, delayMs);\n };\n};\n\nconst getPruneVarSafelist = (themeConfig: UDSThemeConfig): Array<string | RegExp> => {\n const pruneVars = themeConfig.css?.optimization?.pruneVars;\n\n if (!pruneVars || typeof pruneVars !== 'object') {\n return [];\n }\n\n return pruneVars.safelist ?? [];\n};\n\nconst createQueuedRegenerator = <T>(options: {\n onStart?: () => void;\n onSuccess?: (result: T) => void;\n onError: (message: string) => void;\n regenerateOnce: () => Promise<T>;\n}): (() => Promise<void>) => {\n let isGenerating = false;\n let pendingRegenerate = false;\n\n const regenerate = async (): Promise<void> => {\n if (isGenerating) {\n pendingRegenerate = true;\n return;\n }\n\n isGenerating = true;\n try {\n options.onStart?.();\n const result = await options.regenerateOnce();\n options.onSuccess?.(result);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'CSS generation failed';\n options.onError(message);\n } finally {\n isGenerating = false;\n\n if (pendingRegenerate) {\n pendingRegenerate = false;\n await regenerate();\n }\n }\n };\n\n return regenerate;\n};\n\nconst runCssCommand = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const themeConfigExists = fs.existsSync(\n path.join(options.workspaceDir, String(options.themeConfigPath)),\n );\n\n if (!themeConfigExists) {\n await runSimpleMode(options, context);\n return;\n }\n\n await runThemeMode(options, context);\n};\n\nconst runSimpleMode = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const entry = options.entryOption ?? DEFAULT_ENTRY;\n const configPath = typeof options.configOption === 'string' ? options.configOption : undefined;\n\n if (!options.watch && !options.silent) {\n spinStart('Generating CSS...');\n }\n\n try {\n const result = await generateSimpleModeCSS({\n workspaceDir: options.workspaceDir,\n entry,\n outFile: String(options.outFile),\n variants: context.variants,\n autoVariants: context.autoVariants,\n componentData: context.componentData,\n scope: options.scope,\n configPath,\n isWatch: options.watch,\n silent: options.silent,\n });\n\n if (options.watch) {\n await runSimpleModeWatch(options, context, entry, configPath, result.packageDirs ?? []);\n }\n } catch (error) {\n spinStop('❌', error instanceof Error ? error.message : 'CSS generation failed');\n process.exitCode = 1;\n }\n};\n\nconst runSimpleModeWatch = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n entry: EntryValue,\n configPath: string | undefined,\n packageDirs: string[],\n): Promise<void> => {\n const resolvedEntries = resolveEntryPaths(entry, options.workspaceDir);\n const entryWatchTargets = getEntryWatchTargets(resolvedEntries);\n const fallbackTargets = getWatchDirs(packageDirs).map((watchPath) => ({\n watchPath,\n recursive: true,\n }));\n const watchTargets = packageDirs.length > 0 ? fallbackTargets : entryWatchTargets;\n\n if (!options.silent) {\n print('');\n print(`${magenta('Watching for changes...')}`);\n watchTargets.forEach((target) => print(` ${gray('•')} ${target.watchPath}`));\n print(`${gray('Press Ctrl+C to stop')}`);\n print('');\n }\n\n const regenerate = createQueuedRegenerator({\n onStart: () => {\n if (!options.silent) {\n const timestamp = new Date().toLocaleTimeString();\n print(`${gray(`[${timestamp}]`)} Change detected, regenerating...`);\n }\n },\n regenerateOnce: async () => {\n await generateSimpleModeCSS({\n workspaceDir: options.workspaceDir,\n entry,\n outFile: String(options.outFile),\n variants: context.variants,\n autoVariants: context.autoVariants,\n componentData: context.componentData,\n scope: options.scope,\n configPath,\n isWatch: true,\n silent: true,\n });\n },\n onSuccess: () => {\n if (!options.silent) {\n const updatedAt = new Date().toLocaleTimeString();\n print(`${gray(`[${updatedAt}]`)} ${green('CSS updated')}`);\n print('');\n }\n },\n onError: (message) => {\n print(`Error: ${message}`);\n },\n });\n\n watchSourceFiles(\n watchTargets,\n createDebouncedAction(() => {\n void regenerate();\n }, 100),\n );\n\n await new Promise(() => {});\n};\n\nconst loadThemeModeSetup = async (options: CssCommandOptions): Promise<ThemeModeSetup | null> => {\n const themeConfigInput = await loadConfigFile<UDSThemeConfigInput>(\n String(options.themeConfigPath),\n );\n if (!themeConfigInput) {\n return null;\n }\n\n const themeContext: UDSThemeContext = {\n cwd: options.workspaceDir,\n watch: options.watch,\n };\n const themeConfig: UDSThemeConfig =\n typeof themeConfigInput === 'function'\n ? await themeConfigInput(themeContext)\n : themeConfigInput;\n\n let appConfig: UniversalTokensConfig = defaultTokensConfig;\n if (themeConfig.config) {\n const loadedConfig = await loadConfigFile<UniversalTokensConfig>(themeConfig.config);\n if (loadedConfig) {\n appConfig = loadedConfig;\n }\n }\n\n return {\n themeConfig,\n colorModes: themeConfig.colorModes ?? ['dark'],\n entries: resolveEntryPaths(themeConfig.entry, options.workspaceDir),\n appConfig,\n appVariantDefaults: extractVariantDefaults(appConfig),\n effectiveSilent: options.silent || themeConfig.silent === true,\n };\n};\n\nconst runThemeMode = async (\n options: CssCommandOptions,\n context: CssCommandContext,\n): Promise<void> => {\n const workspaceDir = options.workspaceDir;\n const outputPath = path.isAbsolute(options.outFile)\n ? options.outFile\n : path.join(workspaceDir, String(options.outFile));\n let effectiveSilent = options.silent;\n let log = createLogger({ silent: effectiveSilent });\n\n log.spinStart('Loading theme configuration...');\n\n try {\n const setup = await loadThemeModeSetup(options);\n if (!setup) {\n log.spinStop('❌', `Theme config not found: ${options.themeConfigPath}`);\n process.exitCode = 1;\n return;\n }\n\n const { themeConfig, colorModes, entries, appConfig, appVariantDefaults } = setup;\n effectiveSilent = setup.effectiveSilent;\n log = createLogger({ silent: effectiveSilent });\n const entryDirs = entries.map((entry) => entry.absolutePath);\n\n if (!effectiveSilent) {\n log.spinStop('✅', 'Theme configuration loaded');\n }\n\n if (themeConfig.config && appConfig === defaultTokensConfig) {\n log.warn(`App config not found: ${themeConfig.config}, using defaults`);\n }\n const packageDirs: string[] = [];\n\n const generateThemeModeCSS = async (opts?: { isWatch?: boolean }) => {\n const genStartTime = performance.now();\n const genLog = opts?.isWatch ? createLogger({ silent: true }) : log;\n\n genLog.spinStart('Scanning app code...');\n const appScanResult = await scanDirectoriesForSafelist(\n entryDirs,\n colorModes,\n context.variants,\n context.autoVariants,\n context.componentData,\n appVariantDefaults,\n );\n genLog.spinStop('✅', `Scanned ${appScanResult.filesScanned} files`);\n\n genLog.spinStart('Generating main CSS...');\n\n const inheritedClasses: string[] = [...appScanResult.safelist];\n const inheritedComponents = new Set<string>(appScanResult.components);\n\n const processInheritedPackage = async (packageName: string) => {\n genLog.spinStart(`Processing package: ${packageName}...`);\n\n const packageDir = findPackageSourceDir(packageName);\n if (!packageDir) {\n genLog.spinStop('⚠️', `Package not found: ${packageName}`);\n return;\n }\n\n if (!packageDirs.includes(packageDir)) {\n packageDirs.push(packageDir);\n }\n\n const packageScanResult = await scanDirectoryForSafelist(\n packageDir,\n colorModes,\n context.variants,\n context.autoVariants,\n context.componentData,\n appVariantDefaults,\n true,\n );\n inheritedClasses.push(...packageScanResult.safelist);\n packageScanResult.components.forEach((comp) => inheritedComponents.add(comp));\n genLog.spinStop('✅', `${packageName}: ${packageScanResult.filesScanned} files (inherit)`);\n };\n\n await (themeConfig.inherit ?? []).reduce(async (promise, packageName) => {\n await promise;\n await processInheritedPackage(packageName);\n }, Promise.resolve());\n\n const mainSafelist = deduplicateSafelist([\n ...inheritedClasses,\n ...getThemeAndScaleClasses(colorModes),\n ]);\n\n const allMotionComponents: string[] = [...inheritedComponents];\n\n const mainCssResult = await generateCSS(\n [...(themeConfig.css?.safelist ?? []), ...mainSafelist],\n appConfig,\n {\n scope: options.scope,\n contentDir: entryDirs,\n cssOptions: themeConfig.css,\n safeVarPrefixes: [\n ...getMotionVarPrefixes(context.componentData, allMotionComponents),\n ...getConfigurableCssVariables(),\n ...getPruneVarSafelist(themeConfig),\n ],\n },\n );\n\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, mainCssResult.css);\n\n genLog.spinStop(\n '✅',\n getMainCssSummaryMessage({\n sizeGzipBytes: mainCssResult.sizeGzipBytes,\n optimizationStats: mainCssResult.optimizationStats,\n formatBytes,\n }),\n );\n\n const duration = Math.round(performance.now() - genStartTime);\n\n genLog.newline();\n genLog.print(green('CSS generation complete!'));\n genLog.newline();\n genLog.label('Output file:', outputPath);\n genLog.newline();\n genLog.print(`${magenta('Total time:')} ${duration}ms`);\n\n return { duration, outputPath, packageDirs };\n };\n\n await generateThemeModeCSS();\n\n if (options.watch) {\n const entryWatchTargets = getEntryWatchTargets(entries);\n const entryWatchDirs = getWatchDirs(entryWatchTargets.map((target) => target.watchPath));\n const { filteredPackageDirs } = getWatchDirectoryGroups(entryWatchDirs, [\n ...entryDirs,\n ...packageDirs,\n ]);\n\n if (!effectiveSilent) {\n log.newline();\n log.print(`${magenta('Watching for changes...')}`);\n entryDirs.forEach((entryDir) => {\n log.listItem(`App: ${entryDir}`);\n });\n filteredPackageDirs.forEach((dir) => {\n log.listItem(`Package: ${dir}`);\n });\n log.print(`${gray('Press Ctrl+C to stop')}`);\n log.newline();\n }\n\n const regenerate = createQueuedRegenerator({\n onStart: () => {\n if (!effectiveSilent) {\n const timestamp = new Date().toLocaleTimeString();\n log.print(`${gray(`[${timestamp}]`)} Change detected, regenerating...`);\n }\n },\n regenerateOnce: async () => generateThemeModeCSS({ isWatch: true }),\n onSuccess: (result) => {\n if (!effectiveSilent) {\n const updatedAt = new Date().toLocaleTimeString();\n log.print(`${gray(`[${updatedAt}]`)} ${green(`CSS updated (${result?.duration}ms)`)}`);\n log.newline();\n }\n },\n onError: (message) => {\n log.print(message);\n },\n });\n\n const watchDebounce = themeConfig.css?.watchDebounce ?? 100;\n\n watchSourceFiles(\n [\n ...entryWatchTargets,\n ...filteredPackageDirs\n .filter(\n (packageDir) =>\n !entryWatchTargets.some((target) =>\n isCoveredByRecursiveWatch(target.watchPath, packageDir),\n ),\n )\n .map((watchPath) => ({ watchPath, recursive: true })),\n ],\n createDebouncedAction(() => {\n void regenerate();\n }, watchDebounce),\n );\n\n await new Promise(() => {});\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'CSS generation failed';\n if (effectiveSilent) {\n spinStop('❌', message);\n } else {\n log.spinStop('❌', message);\n }\n process.exitCode = 1;\n }\n};\n\nexport { runCssCommand };\nexport type { CssCommandContext, CssCommandOptions };\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
2
  const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
3
+ const require_print = require('../../cli/dist/lib/print.cjs');
4
+ const require_spinner = require('../../cli/dist/lib/spinner.cjs');
3
5
  const require_entryPoints = require('../../utils/entryPoints.cjs');
4
6
  const require_tsMorph = require('../../utils/tsMorph.cjs');
5
7
  let _yahoo_uds_css_tokens = require("@yahoo/uds-css-tokens");
6
- let _yahoo_uds_cli_lib = require("@yahoo/uds-cli/lib");
7
8
  let node_fs = require("node:fs");
8
9
  let node_path = require("node:path");
9
10
  node_path = require_runtime.__toESM(node_path);
@@ -239,18 +240,18 @@ async function purge(variants, packageJson, generatedPurgeCssData, options = {})
239
240
  } catch {
240
241
  throw new Error("Couldn't load the UDS config. Make sure you have uds.config.ts in the root of your project.");
241
242
  }
242
- (0, _yahoo_uds_cli_lib.spinStart)("Getting used UDS components...");
243
- (0, _yahoo_uds_cli_lib.print)("Loading the project...");
243
+ require_spinner.spinStart("Getting used UDS components...");
244
+ require_print.print("Loading the project...");
244
245
  const files = await getFiles(entry);
245
- (0, _yahoo_uds_cli_lib.print)("Going through the imports...");
246
+ require_print.print("Going through the imports...");
246
247
  const udsImports = parseFiles(project, files);
247
- (0, _yahoo_uds_cli_lib.print)("Finding all the components imported from UDS...");
248
+ require_print.print("Finding all the components imported from UDS...");
248
249
  const udsComponents = getComponentsToConvertToTW(udsImports, generatedPurgeCssData);
249
- (0, _yahoo_uds_cli_lib.print)("🧑‍🍳 Cooking...");
250
+ require_print.print("🧑‍🍳 Cooking...");
250
251
  const safeList = getTailwindSafelist(project, udsComponents, variants, generatedPurgeCssData, packageJson);
251
252
  const themesAndScalesClasses = getClassesForEnabledThemesAndScales();
252
253
  saveToFile(safeList.concat(themesAndScalesClasses), outputFilePath);
253
- (0, _yahoo_uds_cli_lib.spinStop)("Generated your safelist!");
254
+ require_spinner.spinStop("Generated your safelist!");
254
255
  }
255
256
 
256
257
  //#endregion
@@ -1,8 +1,9 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
+ import { print } from "../../cli/dist/lib/print.js";
3
+ import { spinStart, spinStop } from "../../cli/dist/lib/spinner.js";
2
4
  import { DEFAULT_ENTRY, resolveEntryPaths } from "../../utils/entryPoints.js";
3
5
  import { findReferencesAsJsxElements, getUsedPropsInReference } from "../../utils/tsMorph.js";
4
6
  import { DARK_COLOR_MODE_CLASSNAME, LARGE_SCALE_MODE_CLASSNAME, LIGHT_COLOR_MODE_CLASSNAME, MEDIUM_SCALE_MODE_CLASSNAME, SMALL_SCALE_MODE_CLASSNAME, XLARGE_SCALE_MODE_CLASSNAME, XSMALL_SCALE_MODE_CLASSNAME, XXLARGE_SCALE_MODE_CLASSNAME, XXXLARGE_SCALE_MODE_CLASSNAME } from "@yahoo/uds-css-tokens";
5
- import { print, spinStart, spinStop } from "@yahoo/uds-cli/lib";
6
7
  import { mkdirSync, writeFileSync } from "node:fs";
7
8
  import path from "node:path";
8
9
  import fg from "fast-glob";
@@ -1 +1 @@
1
- {"version":3,"file":"purgeCSS.js","names":[],"sources":["../../../src/purger/legacy/purgeCSS.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nimport { print, spinStart, spinStop } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n DARK_COLOR_MODE_CLASSNAME,\n LARGE_SCALE_MODE_CLASSNAME,\n LIGHT_COLOR_MODE_CLASSNAME,\n MEDIUM_SCALE_MODE_CLASSNAME,\n SMALL_SCALE_MODE_CLASSNAME,\n XLARGE_SCALE_MODE_CLASSNAME,\n XSMALL_SCALE_MODE_CLASSNAME,\n XXLARGE_SCALE_MODE_CLASSNAME,\n XXXLARGE_SCALE_MODE_CLASSNAME,\n} from '@yahoo/uds-css-tokens';\nimport type { ColorModeConfig, ScaleModeConfig } from '@yahoo/uds-types';\nimport fg from 'fast-glob';\nimport type { CallExpression, JsxOpeningElement, JsxSelfClosingElement } from 'ts-morph';\nimport { Node, Project, SyntaxKind, ts } from 'ts-morph';\n\nimport { DEFAULT_ENTRY, resolveEntryPaths } from '../../utils/entryPoints';\nimport { findReferencesAsJsxElements, getUsedPropsInReference } from '../../utils/tsMorph';\n\ntype PropToUsedOptions = [string, string[]];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\n\ninterface GeneratedPurgeCSSData {\n variantsList: VariantsList;\n componentToVariants: ComponentToVariants;\n componentToTwClasses: ComponentToTwClasses;\n componentsDependencies: ComponentDependencies;\n}\n\nconst scaleModeToClass: { [key in keyof ScaleModeConfig]: string } = {\n large: LARGE_SCALE_MODE_CLASSNAME,\n medium: MEDIUM_SCALE_MODE_CLASSNAME,\n small: SMALL_SCALE_MODE_CLASSNAME,\n xLarge: XLARGE_SCALE_MODE_CLASSNAME,\n xSmall: XSMALL_SCALE_MODE_CLASSNAME,\n xxLarge: XXLARGE_SCALE_MODE_CLASSNAME,\n xxxLarge: XXXLARGE_SCALE_MODE_CLASSNAME,\n};\n\nconst colorModeToClass: { [key in keyof ColorModeConfig]: string } = {\n dark: DARK_COLOR_MODE_CLASSNAME,\n light: LIGHT_COLOR_MODE_CLASSNAME,\n};\n\ntype SafeList = string[];\ntype ImportsList = string[];\ntype Files = string[];\n\nconst getFiles = async (entry: string | string[]): Promise<Files> => {\n try {\n const workspaceDir = process.env.PWD || process.cwd();\n\n if (!workspaceDir) {\n throw new Error('Workspace directory not found.');\n }\n\n const files = await Promise.all(\n resolveEntryPaths(entry, workspaceDir, DEFAULT_ENTRY).map((entryPath) => {\n if (entryPath.kind === 'file') {\n return [entryPath.absolutePath];\n }\n\n return fg(['**/*.jsx', '**/*.tsx'], {\n cwd: entryPath.absolutePath,\n absolute: true,\n ignore: ['**/node_modules/**'],\n });\n }),\n );\n return [...new Set(files.flat())];\n } catch (error) {\n throw error instanceof Error\n ? error\n : new Error(`Couldn't find the entry directory: ${entry}. Please make sure it exists.`);\n }\n};\n\n/**\n * Find all JSX references for a named import.\n *\n * @example\n * const references = findNamedImportReferences(project, '@yahoo/uds', 'HStack')\n */\nfunction findNamedImportReferences(\n project: Project,\n moduleSpecifierValue: string,\n namedImportName: string,\n) {\n const references: (JsxOpeningElement | JsxSelfClosingElement)[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n if (importDeclaration.getModuleSpecifierValue() === moduleSpecifierValue) {\n for (const namedImport of importDeclaration.getNamedImports()) {\n if (namedImport.getName() === namedImportName) {\n const identifier = namedImport.getFirstDescendantByKindOrThrow(\n ts.SyntaxKind.Identifier,\n );\n\n references.push(...findReferencesAsJsxElements(identifier));\n }\n }\n }\n }\n }\n\n return references;\n}\n\n/**\n * Given a file it returns the list of imports from @yahoo/uds\n */\nconst parseFiles = (project: Project, files: Files): ImportsList => {\n const importsSet = new Set();\n\n const importsPerFile: string[] = files\n .map((file: string) => {\n const sourceFile = project.getSourceFile(file);\n\n const udsImports =\n sourceFile\n ?.getImportDeclarations()\n .filter((declaration) => {\n return (\n declaration.getModuleSpecifier().getText().includes('@yahoo/uds') ||\n declaration.getModuleSpecifier().getText().includes('@yahoo/uds/experimental')\n );\n })\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat() ?? [];\n\n return udsImports;\n })\n .flat();\n\n importsPerFile.forEach((item: string) => {\n if (!importsSet.has(item)) {\n importsSet.add(item);\n }\n });\n\n return Array.from(importsSet) as string[];\n};\n\nconst getTailwindSafelist = (\n project: Project,\n componentList: string[],\n variants: Record<string, Record<string, string>>,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): SafeList => {\n const { variantsList, componentToVariants, componentToTwClasses } = generatedPurgeCssData;\n const safeList: SafeList = [];\n const validVariants = new Set<string>(variantsList);\n // we track the prop name and which values have been used\n const usedProps = new Map<string, Set<string>>();\n componentList.forEach((component: string) => {\n if (isUDSComponent(component, generatedPurgeCssData)) {\n // get the TW classes relevant for each prop\n // these classes are used internally in UDS,\n // they either have been initialized or used by other UDS components\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n componentToVariants[component].forEach(([propName, usedValues]: [string, any]) => {\n if (validVariants.has(propName)) {\n const options: Set<string> = usedProps.get(propName) ?? new Set();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n usedValues.forEach((val: any) => options.add(val));\n usedProps.set(propName, options);\n }\n });\n\n // scan the project for used props and\n // get the corresponding css for those used props\n getUsedProps(project, component, variants, packageJson).forEach(([propName, usedValues]) => {\n if (validVariants.has(propName)) {\n // This means that an expression has been used (Ex: `<Button size={getSize()} />`)\n // so we need to add all possible options for that prop\n if (usedValues.length === 0) {\n usedValues = Object.keys(variants[propName as keyof typeof variants] ?? {});\n }\n\n const options: Set<string> = usedProps.get(propName) ?? new Set();\n usedValues.forEach((val) => options.add(val));\n usedProps.set(propName, options);\n }\n });\n\n // get the inline TW classes used in each component\n safeList.push(...componentToTwClasses[component].replaceAll('\\\\', '').split(' '));\n }\n });\n\n for (const [propName, usedValues] of usedProps) {\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n usedValues.forEach((option) => {\n const variantClass = (variantGroup as Record<string, string>)[option];\n if (variantClass) {\n safeList.push(variantClass.replaceAll('\\\\', ''));\n }\n });\n }\n }\n\n for (const [variant, variantOptions] of scanGetStylesReferences(project, variants, packageJson)) {\n const variantGroup = variants[variant as keyof typeof variants];\n if (variantGroup) {\n variantOptions.forEach((option) => {\n const variantClass = (variantGroup as Record<string, string>)[option];\n if (variantClass) {\n safeList.push(variantClass.replaceAll('\\\\', ''));\n }\n });\n }\n }\n\n // Return a deduped list and strip out any empty strings\n return Array.from(new Set(safeList)).filter(Boolean);\n};\n\n/**\n * Get the used props for a given component.\n *\n * @example\n * const usedProps = getUsedProps(project, 'HStack');\n */\nconst getUsedProps = (\n project: Project,\n component: string,\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): Array<[string, string[]]> => {\n const references: (JsxOpeningElement | JsxSelfClosingElement)[] = [];\n references.push(...findNamedImportReferences(project, packageJson.name, component));\n references.push(\n ...findNamedImportReferences(project, `${packageJson.name}/experimental`, component),\n );\n\n const usedProps = references\n .map((reference) => getUsedPropsInReference(reference, variants))\n .flat();\n\n return usedProps;\n};\n\nconst isUDSComponent = (\n component: string,\n { componentToVariants }: GeneratedPurgeCSSData,\n): boolean => {\n return !!componentToVariants[component];\n};\n\nconst saveToFile = (safeList: SafeList, outputPath: string) => {\n const fileContent = `\n //! This file is generated by \\`uds purge\\` from @yahoo/uds\n //! Do not edit directly\n //! If there is issue with this file please report to #ask-uds\n export const safelist = ${JSON.stringify(safeList)};\n `;\n\n // Ensure the output directory exists\n mkdirSync(path.dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, fileContent);\n};\n\nconst getComponentsToConvertToTW = (\n udsImport: ImportsList,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n): string[] => {\n const { componentToVariants, componentsDependencies } = generatedPurgeCssData;\n // filter out just the components\n const components = udsImport.filter((importedItem) => !!componentToVariants[importedItem]);\n const set = new Set();\n components.forEach((component) => {\n if (!set.has(component)) {\n set.add(component);\n }\n if (componentsDependencies[component]) {\n componentsDependencies[component].forEach((dependent: string) => {\n if (!set.has(dependent)) {\n set.add(dependent);\n }\n });\n }\n });\n return Array.from(set) as string[];\n};\n\n/**\n * Get the classes that corresponds to the used modes\n */\nconst getClassesForEnabledThemesAndScales = (): string[] => {\n const classes: string[] = [];\n\n // TODO: Remove this once the config supports toggling colorModes and scaleModes\n if (process.env.ENABLED_SCALE_AND_COLOR_MODES) {\n process.env.ENABLED_SCALE_AND_COLOR_MODES.split(',').map((mode) => {\n mode = mode.trim();\n if (colorModeToClass[mode as keyof ColorModeConfig]) {\n classes.push(colorModeToClass[mode as keyof ColorModeConfig]);\n } else if (scaleModeToClass[mode as keyof ScaleModeConfig]) {\n classes.push(scaleModeToClass[mode as keyof ScaleModeConfig]);\n }\n });\n } else {\n // Default: Light, Dark and Large\n classes.push(colorModeToClass.dark);\n classes.push(colorModeToClass.light);\n classes.push(scaleModeToClass.large);\n }\n\n return classes;\n};\n\n/**\n * Scan the source code for all `getStyles` references\n *\n * Note: This currently only works if we are passing a literal object to getStyles.\n *\n * Explanation: They we are able to enfer what css to include is by looking at the properties of the object passed.\n * If something other than an object is passed, we can fallback on the Type, but that would require handling\n * a lot of edge cases (function return type, spread operator, ternary, ...) and each one of these cases will\n * most likely have a sub case. Falling back to the Type will complicate the code a lot is error prone as there\n * is only so much info we can get out of the types as the Users are free to use `any` on their project which will\n * provide no value for us. Hence why having a literal object passed is the best and probably the only sane way\n * to go about this.\n */\nconst scanGetStylesReferences = (\n project: Project,\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): Map<string, Set<string>> => {\n // Find all the references for `getStyles`\n const references: CallExpression[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n if (importDeclaration.getModuleSpecifierValue() === packageJson.name) {\n for (const namedImport of importDeclaration.getNamedImports()) {\n if (namedImport.getName() === 'getStyles') {\n const identifier = namedImport.getFirstDescendantByKindOrThrow(\n ts.SyntaxKind.Identifier,\n );\n\n for (const reference of identifier.findReferencesAsNodes()) {\n const node = reference.getFirstAncestor((node) => {\n return Node.isCallExpression(node);\n });\n\n if (node) {\n references.push(node as CallExpression);\n }\n }\n }\n }\n }\n }\n }\n\n const usedProps = new Map<string, Set<string>>();\n for (const reference of references) {\n // TODO: handle the throw, tell users to not use something other than an object when calling `getStyles`\n const objectLiteralExpression = reference.getFirstChildByKindOrThrow(\n SyntaxKind.ObjectLiteralExpression,\n );\n const propertyAssignments = objectLiteralExpression.getDescendantsOfKind(\n SyntaxKind.PropertyAssignment,\n ); // PropertyAssignment is { property: 'test' }\n const shorthandPropertyAssignments = objectLiteralExpression.getDescendantsOfKind(\n SyntaxKind.ShorthandPropertyAssignment,\n ); // ShorthandPropertyAssignment is { property }\n // TODO: handle spread assignment\n propertyAssignments.forEach((propertyAssigment) => {\n const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();\n // check if we are assigning a string\n const stringLiteral = propertyAssigment\n .getFirstChildByKind(SyntaxKind.StringLiteral)\n ?.getLiteralText();\n if (identifier && !stringLiteral) {\n // this means an expression has been used\n // so we add all the possibilites\n const isvalidVariant = !!variants[identifier as keyof typeof variants];\n const fallback = isvalidVariant\n ? Object.keys(variants[identifier as keyof typeof variants])\n : [];\n usedProps.set(identifier, new Set(fallback));\n }\n if (identifier && stringLiteral) {\n let options: Set<string>;\n if (usedProps.has(identifier)) {\n options = usedProps.get(identifier)!;\n } else {\n options = new Set();\n }\n options.add(stringLiteral);\n usedProps.set(identifier, options);\n }\n });\n shorthandPropertyAssignments.forEach((propertyAssigment) => {\n const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();\n if (identifier) {\n usedProps.set(identifier, new Set());\n }\n });\n }\n\n return usedProps;\n};\n\ntype PurgeOptions = {\n config?: string;\n output?: string;\n entry?: string | string[];\n optimized?: string | boolean;\n};\n\nconst applyPurgeDefaults = (\n options: PurgeOptions = {},\n): Required<Pick<PurgeOptions, 'config' | 'output' | 'entry'>> => ({\n config: options.config ?? process.env.UDS_OUT_FILE ?? './uds.config.ts',\n output: options.output ?? 'dist/safelist.ts',\n entry: options.entry ?? DEFAULT_ENTRY,\n});\n\nasync function purge(\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n options: PurgeOptions = {},\n) {\n const { config: configPath, output, entry } = applyPurgeDefaults(options);\n const workspaceDir = process.env.PWD || process.cwd();\n if (!workspaceDir) {\n throw new Error('Workspace directory not found.');\n }\n const srcDir = path.join(workspaceDir, '/tsconfig.json');\n const project = new Project({\n tsConfigFilePath: srcDir,\n });\n const outputFilePath = path.join(workspaceDir, output);\n\n // // we need to load the UDS config\n const configAbsolutePath = path.join(workspaceDir, configPath);\n // The config is currently unused because we haven't implemented the feature to toggle the color and scale modes\n // in the configurator. This is a placeholder for when we do, so we can purge the unused classes.\n let config: { config: UniversalTokensConfig } | undefined;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n config = await import(configAbsolutePath);\n } catch {\n throw new Error(\n \"Couldn't load the UDS config. Make sure you have uds.config.ts in the root of your project.\",\n );\n }\n spinStart('Getting used UDS components...');\n // 1. Get all files from the current dir\n print('Loading the project...');\n const files = await getFiles(entry);\n // 2. For each file get the imports;\n print('Going through the imports...');\n const udsImports = parseFiles(project, files);\n // 3. Now that we have the imported components\n print('Finding all the components imported from UDS...');\n const udsComponents = getComponentsToConvertToTW(udsImports, generatedPurgeCssData);\n // 4. Generate the CSS we need\n print('🧑‍🍳 Cooking...');\n const safeList = getTailwindSafelist(\n project,\n udsComponents,\n variants,\n generatedPurgeCssData,\n packageJson,\n );\n const themesAndScalesClasses = getClassesForEnabledThemesAndScales();\n // 5. Write the allowlist to a file\n saveToFile(safeList.concat(themesAndScalesClasses), outputFilePath);\n spinStop('Generated your safelist!');\n}\n\nexport {\n applyPurgeDefaults,\n findNamedImportReferences,\n type GeneratedPurgeCSSData,\n getClassesForEnabledThemesAndScales,\n getComponentsToConvertToTW,\n getTailwindSafelist,\n getUsedProps,\n isUDSComponent,\n parseFiles,\n purge,\n type PurgeOptions,\n scanGetStylesReferences,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"purgeCSS.js","names":[],"sources":["../../../src/purger/legacy/purgeCSS.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nimport { print, spinStart, spinStop } from '@yahoo/uds-cli/lib';\nimport type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n DARK_COLOR_MODE_CLASSNAME,\n LARGE_SCALE_MODE_CLASSNAME,\n LIGHT_COLOR_MODE_CLASSNAME,\n MEDIUM_SCALE_MODE_CLASSNAME,\n SMALL_SCALE_MODE_CLASSNAME,\n XLARGE_SCALE_MODE_CLASSNAME,\n XSMALL_SCALE_MODE_CLASSNAME,\n XXLARGE_SCALE_MODE_CLASSNAME,\n XXXLARGE_SCALE_MODE_CLASSNAME,\n} from '@yahoo/uds-css-tokens';\nimport type { ColorModeConfig, ScaleModeConfig } from '@yahoo/uds-types';\nimport fg from 'fast-glob';\nimport type { CallExpression, JsxOpeningElement, JsxSelfClosingElement } from 'ts-morph';\nimport { Node, Project, SyntaxKind, ts } from 'ts-morph';\n\nimport { DEFAULT_ENTRY, resolveEntryPaths } from '../../utils/entryPoints';\nimport { findReferencesAsJsxElements, getUsedPropsInReference } from '../../utils/tsMorph';\n\ntype PropToUsedOptions = [string, string[]];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\n\ninterface GeneratedPurgeCSSData {\n variantsList: VariantsList;\n componentToVariants: ComponentToVariants;\n componentToTwClasses: ComponentToTwClasses;\n componentsDependencies: ComponentDependencies;\n}\n\nconst scaleModeToClass: { [key in keyof ScaleModeConfig]: string } = {\n large: LARGE_SCALE_MODE_CLASSNAME,\n medium: MEDIUM_SCALE_MODE_CLASSNAME,\n small: SMALL_SCALE_MODE_CLASSNAME,\n xLarge: XLARGE_SCALE_MODE_CLASSNAME,\n xSmall: XSMALL_SCALE_MODE_CLASSNAME,\n xxLarge: XXLARGE_SCALE_MODE_CLASSNAME,\n xxxLarge: XXXLARGE_SCALE_MODE_CLASSNAME,\n};\n\nconst colorModeToClass: { [key in keyof ColorModeConfig]: string } = {\n dark: DARK_COLOR_MODE_CLASSNAME,\n light: LIGHT_COLOR_MODE_CLASSNAME,\n};\n\ntype SafeList = string[];\ntype ImportsList = string[];\ntype Files = string[];\n\nconst getFiles = async (entry: string | string[]): Promise<Files> => {\n try {\n const workspaceDir = process.env.PWD || process.cwd();\n\n if (!workspaceDir) {\n throw new Error('Workspace directory not found.');\n }\n\n const files = await Promise.all(\n resolveEntryPaths(entry, workspaceDir, DEFAULT_ENTRY).map((entryPath) => {\n if (entryPath.kind === 'file') {\n return [entryPath.absolutePath];\n }\n\n return fg(['**/*.jsx', '**/*.tsx'], {\n cwd: entryPath.absolutePath,\n absolute: true,\n ignore: ['**/node_modules/**'],\n });\n }),\n );\n return [...new Set(files.flat())];\n } catch (error) {\n throw error instanceof Error\n ? error\n : new Error(`Couldn't find the entry directory: ${entry}. Please make sure it exists.`);\n }\n};\n\n/**\n * Find all JSX references for a named import.\n *\n * @example\n * const references = findNamedImportReferences(project, '@yahoo/uds', 'HStack')\n */\nfunction findNamedImportReferences(\n project: Project,\n moduleSpecifierValue: string,\n namedImportName: string,\n) {\n const references: (JsxOpeningElement | JsxSelfClosingElement)[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n if (importDeclaration.getModuleSpecifierValue() === moduleSpecifierValue) {\n for (const namedImport of importDeclaration.getNamedImports()) {\n if (namedImport.getName() === namedImportName) {\n const identifier = namedImport.getFirstDescendantByKindOrThrow(\n ts.SyntaxKind.Identifier,\n );\n\n references.push(...findReferencesAsJsxElements(identifier));\n }\n }\n }\n }\n }\n\n return references;\n}\n\n/**\n * Given a file it returns the list of imports from @yahoo/uds\n */\nconst parseFiles = (project: Project, files: Files): ImportsList => {\n const importsSet = new Set();\n\n const importsPerFile: string[] = files\n .map((file: string) => {\n const sourceFile = project.getSourceFile(file);\n\n const udsImports =\n sourceFile\n ?.getImportDeclarations()\n .filter((declaration) => {\n return (\n declaration.getModuleSpecifier().getText().includes('@yahoo/uds') ||\n declaration.getModuleSpecifier().getText().includes('@yahoo/uds/experimental')\n );\n })\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat() ?? [];\n\n return udsImports;\n })\n .flat();\n\n importsPerFile.forEach((item: string) => {\n if (!importsSet.has(item)) {\n importsSet.add(item);\n }\n });\n\n return Array.from(importsSet) as string[];\n};\n\nconst getTailwindSafelist = (\n project: Project,\n componentList: string[],\n variants: Record<string, Record<string, string>>,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): SafeList => {\n const { variantsList, componentToVariants, componentToTwClasses } = generatedPurgeCssData;\n const safeList: SafeList = [];\n const validVariants = new Set<string>(variantsList);\n // we track the prop name and which values have been used\n const usedProps = new Map<string, Set<string>>();\n componentList.forEach((component: string) => {\n if (isUDSComponent(component, generatedPurgeCssData)) {\n // get the TW classes relevant for each prop\n // these classes are used internally in UDS,\n // they either have been initialized or used by other UDS components\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n componentToVariants[component].forEach(([propName, usedValues]: [string, any]) => {\n if (validVariants.has(propName)) {\n const options: Set<string> = usedProps.get(propName) ?? new Set();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n usedValues.forEach((val: any) => options.add(val));\n usedProps.set(propName, options);\n }\n });\n\n // scan the project for used props and\n // get the corresponding css for those used props\n getUsedProps(project, component, variants, packageJson).forEach(([propName, usedValues]) => {\n if (validVariants.has(propName)) {\n // This means that an expression has been used (Ex: `<Button size={getSize()} />`)\n // so we need to add all possible options for that prop\n if (usedValues.length === 0) {\n usedValues = Object.keys(variants[propName as keyof typeof variants] ?? {});\n }\n\n const options: Set<string> = usedProps.get(propName) ?? new Set();\n usedValues.forEach((val) => options.add(val));\n usedProps.set(propName, options);\n }\n });\n\n // get the inline TW classes used in each component\n safeList.push(...componentToTwClasses[component].replaceAll('\\\\', '').split(' '));\n }\n });\n\n for (const [propName, usedValues] of usedProps) {\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n usedValues.forEach((option) => {\n const variantClass = (variantGroup as Record<string, string>)[option];\n if (variantClass) {\n safeList.push(variantClass.replaceAll('\\\\', ''));\n }\n });\n }\n }\n\n for (const [variant, variantOptions] of scanGetStylesReferences(project, variants, packageJson)) {\n const variantGroup = variants[variant as keyof typeof variants];\n if (variantGroup) {\n variantOptions.forEach((option) => {\n const variantClass = (variantGroup as Record<string, string>)[option];\n if (variantClass) {\n safeList.push(variantClass.replaceAll('\\\\', ''));\n }\n });\n }\n }\n\n // Return a deduped list and strip out any empty strings\n return Array.from(new Set(safeList)).filter(Boolean);\n};\n\n/**\n * Get the used props for a given component.\n *\n * @example\n * const usedProps = getUsedProps(project, 'HStack');\n */\nconst getUsedProps = (\n project: Project,\n component: string,\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): Array<[string, string[]]> => {\n const references: (JsxOpeningElement | JsxSelfClosingElement)[] = [];\n references.push(...findNamedImportReferences(project, packageJson.name, component));\n references.push(\n ...findNamedImportReferences(project, `${packageJson.name}/experimental`, component),\n );\n\n const usedProps = references\n .map((reference) => getUsedPropsInReference(reference, variants))\n .flat();\n\n return usedProps;\n};\n\nconst isUDSComponent = (\n component: string,\n { componentToVariants }: GeneratedPurgeCSSData,\n): boolean => {\n return !!componentToVariants[component];\n};\n\nconst saveToFile = (safeList: SafeList, outputPath: string) => {\n const fileContent = `\n //! This file is generated by \\`uds purge\\` from @yahoo/uds\n //! Do not edit directly\n //! If there is issue with this file please report to #ask-uds\n export const safelist = ${JSON.stringify(safeList)};\n `;\n\n // Ensure the output directory exists\n mkdirSync(path.dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, fileContent);\n};\n\nconst getComponentsToConvertToTW = (\n udsImport: ImportsList,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n): string[] => {\n const { componentToVariants, componentsDependencies } = generatedPurgeCssData;\n // filter out just the components\n const components = udsImport.filter((importedItem) => !!componentToVariants[importedItem]);\n const set = new Set();\n components.forEach((component) => {\n if (!set.has(component)) {\n set.add(component);\n }\n if (componentsDependencies[component]) {\n componentsDependencies[component].forEach((dependent: string) => {\n if (!set.has(dependent)) {\n set.add(dependent);\n }\n });\n }\n });\n return Array.from(set) as string[];\n};\n\n/**\n * Get the classes that corresponds to the used modes\n */\nconst getClassesForEnabledThemesAndScales = (): string[] => {\n const classes: string[] = [];\n\n // TODO: Remove this once the config supports toggling colorModes and scaleModes\n if (process.env.ENABLED_SCALE_AND_COLOR_MODES) {\n process.env.ENABLED_SCALE_AND_COLOR_MODES.split(',').map((mode) => {\n mode = mode.trim();\n if (colorModeToClass[mode as keyof ColorModeConfig]) {\n classes.push(colorModeToClass[mode as keyof ColorModeConfig]);\n } else if (scaleModeToClass[mode as keyof ScaleModeConfig]) {\n classes.push(scaleModeToClass[mode as keyof ScaleModeConfig]);\n }\n });\n } else {\n // Default: Light, Dark and Large\n classes.push(colorModeToClass.dark);\n classes.push(colorModeToClass.light);\n classes.push(scaleModeToClass.large);\n }\n\n return classes;\n};\n\n/**\n * Scan the source code for all `getStyles` references\n *\n * Note: This currently only works if we are passing a literal object to getStyles.\n *\n * Explanation: They we are able to enfer what css to include is by looking at the properties of the object passed.\n * If something other than an object is passed, we can fallback on the Type, but that would require handling\n * a lot of edge cases (function return type, spread operator, ternary, ...) and each one of these cases will\n * most likely have a sub case. Falling back to the Type will complicate the code a lot is error prone as there\n * is only so much info we can get out of the types as the Users are free to use `any` on their project which will\n * provide no value for us. Hence why having a literal object passed is the best and probably the only sane way\n * to go about this.\n */\nconst scanGetStylesReferences = (\n project: Project,\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n): Map<string, Set<string>> => {\n // Find all the references for `getStyles`\n const references: CallExpression[] = [];\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n if (importDeclaration.getModuleSpecifierValue() === packageJson.name) {\n for (const namedImport of importDeclaration.getNamedImports()) {\n if (namedImport.getName() === 'getStyles') {\n const identifier = namedImport.getFirstDescendantByKindOrThrow(\n ts.SyntaxKind.Identifier,\n );\n\n for (const reference of identifier.findReferencesAsNodes()) {\n const node = reference.getFirstAncestor((node) => {\n return Node.isCallExpression(node);\n });\n\n if (node) {\n references.push(node as CallExpression);\n }\n }\n }\n }\n }\n }\n }\n\n const usedProps = new Map<string, Set<string>>();\n for (const reference of references) {\n // TODO: handle the throw, tell users to not use something other than an object when calling `getStyles`\n const objectLiteralExpression = reference.getFirstChildByKindOrThrow(\n SyntaxKind.ObjectLiteralExpression,\n );\n const propertyAssignments = objectLiteralExpression.getDescendantsOfKind(\n SyntaxKind.PropertyAssignment,\n ); // PropertyAssignment is { property: 'test' }\n const shorthandPropertyAssignments = objectLiteralExpression.getDescendantsOfKind(\n SyntaxKind.ShorthandPropertyAssignment,\n ); // ShorthandPropertyAssignment is { property }\n // TODO: handle spread assignment\n propertyAssignments.forEach((propertyAssigment) => {\n const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();\n // check if we are assigning a string\n const stringLiteral = propertyAssigment\n .getFirstChildByKind(SyntaxKind.StringLiteral)\n ?.getLiteralText();\n if (identifier && !stringLiteral) {\n // this means an expression has been used\n // so we add all the possibilites\n const isvalidVariant = !!variants[identifier as keyof typeof variants];\n const fallback = isvalidVariant\n ? Object.keys(variants[identifier as keyof typeof variants])\n : [];\n usedProps.set(identifier, new Set(fallback));\n }\n if (identifier && stringLiteral) {\n let options: Set<string>;\n if (usedProps.has(identifier)) {\n options = usedProps.get(identifier)!;\n } else {\n options = new Set();\n }\n options.add(stringLiteral);\n usedProps.set(identifier, options);\n }\n });\n shorthandPropertyAssignments.forEach((propertyAssigment) => {\n const identifier = propertyAssigment.getFirstChildByKind(SyntaxKind.Identifier)?.getText();\n if (identifier) {\n usedProps.set(identifier, new Set());\n }\n });\n }\n\n return usedProps;\n};\n\ntype PurgeOptions = {\n config?: string;\n output?: string;\n entry?: string | string[];\n optimized?: string | boolean;\n};\n\nconst applyPurgeDefaults = (\n options: PurgeOptions = {},\n): Required<Pick<PurgeOptions, 'config' | 'output' | 'entry'>> => ({\n config: options.config ?? process.env.UDS_OUT_FILE ?? './uds.config.ts',\n output: options.output ?? 'dist/safelist.ts',\n entry: options.entry ?? DEFAULT_ENTRY,\n});\n\nasync function purge(\n variants: Record<string, Record<string, string>>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n packageJson: Record<string, any>,\n generatedPurgeCssData: GeneratedPurgeCSSData,\n options: PurgeOptions = {},\n) {\n const { config: configPath, output, entry } = applyPurgeDefaults(options);\n const workspaceDir = process.env.PWD || process.cwd();\n if (!workspaceDir) {\n throw new Error('Workspace directory not found.');\n }\n const srcDir = path.join(workspaceDir, '/tsconfig.json');\n const project = new Project({\n tsConfigFilePath: srcDir,\n });\n const outputFilePath = path.join(workspaceDir, output);\n\n // // we need to load the UDS config\n const configAbsolutePath = path.join(workspaceDir, configPath);\n // The config is currently unused because we haven't implemented the feature to toggle the color and scale modes\n // in the configurator. This is a placeholder for when we do, so we can purge the unused classes.\n let config: { config: UniversalTokensConfig } | undefined;\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n config = await import(configAbsolutePath);\n } catch {\n throw new Error(\n \"Couldn't load the UDS config. Make sure you have uds.config.ts in the root of your project.\",\n );\n }\n spinStart('Getting used UDS components...');\n // 1. Get all files from the current dir\n print('Loading the project...');\n const files = await getFiles(entry);\n // 2. For each file get the imports;\n print('Going through the imports...');\n const udsImports = parseFiles(project, files);\n // 3. Now that we have the imported components\n print('Finding all the components imported from UDS...');\n const udsComponents = getComponentsToConvertToTW(udsImports, generatedPurgeCssData);\n // 4. Generate the CSS we need\n print('🧑‍🍳 Cooking...');\n const safeList = getTailwindSafelist(\n project,\n udsComponents,\n variants,\n generatedPurgeCssData,\n packageJson,\n );\n const themesAndScalesClasses = getClassesForEnabledThemesAndScales();\n // 5. Write the allowlist to a file\n saveToFile(safeList.concat(themesAndScalesClasses), outputFilePath);\n spinStop('Generated your safelist!');\n}\n\nexport {\n applyPurgeDefaults,\n findNamedImportReferences,\n type GeneratedPurgeCSSData,\n getClassesForEnabledThemesAndScales,\n getComponentsToConvertToTW,\n getTailwindSafelist,\n getUsedProps,\n isUDSComponent,\n parseFiles,\n purge,\n type PurgeOptions,\n scanGetStylesReferences,\n};\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ const require_colors = require('../cli/dist/lib/colors.cjs');
4
+ const require_print = require('../cli/dist/lib/print.cjs');
3
5
  const require_plugin = require('../plugin.cjs');
4
6
  const require_tsMorph = require('./tsMorph.cjs');
5
- let _yahoo_uds_cli_lib = require("@yahoo/uds-cli/lib");
6
7
  let ts_morph = require("ts-morph");
7
8
  let _yahoo_uds_config = require("@yahoo/uds-config");
8
9
  let postcss = require("postcss");
@@ -71,10 +72,10 @@ const getInitializedAndReferencedProps = (project, componentName, variants, vari
71
72
  const variableDeclarations = sourceFile.getVariableDeclarations();
72
73
  const node = [...functionDeclarations, ...variableDeclarations].filter((declaration) => declaration.getName() === componentName)[0];
73
74
  const functionDeclaration = require_tsMorph.getReactFunctionDeclaration(node);
74
- if (!functionDeclaration) (0, _yahoo_uds_cli_lib.print)((0, _yahoo_uds_cli_lib.red)(`No function declaration found for ${componentName}`));
75
+ if (!functionDeclaration) require_print.print(require_colors.red(`No function declaration found for ${componentName}`));
75
76
  const parameterDeclaration = functionDeclaration?.getParameters();
76
77
  if (!parameterDeclaration || parameterDeclaration.length === 0) {
77
- (0, _yahoo_uds_cli_lib.print)((0, _yahoo_uds_cli_lib.red)(`No parameter declaration found for ${componentName}`));
78
+ require_print.print(require_colors.red(`No parameter declaration found for ${componentName}`));
78
79
  return [];
79
80
  }
80
81
  if (!parameterDeclaration[0].getChildrenOfKind(ts_morph.SyntaxKind.ObjectBindingPattern)[0]) return [];
@@ -1,7 +1,8 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
+ import { red } from "../cli/dist/lib/colors.js";
3
+ import { print } from "../cli/dist/lib/print.js";
2
4
  import { tailwindPlugin } from "../plugin.js";
3
5
  import { findReferencesAsJsxElements, getReactFunctionDeclaration, getUsedPropsInReference } from "./tsMorph.js";
4
- import { print, red } from "@yahoo/uds-cli/lib";
5
6
  import { SyntaxKind } from "ts-morph";
6
7
  import { defaultTokensConfig } from "@yahoo/uds-config";
7
8
  import postcss from "postcss";
@@ -1 +1 @@
1
- {"version":3,"file":"generatePurgeCSSData.js","names":[],"sources":["../../src/utils/generatePurgeCSSData.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { autoVariants } from '@yahoo/uds-automated-config/autoVariants';\nimport { print, red } from '@yahoo/uds-cli/lib';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport type { AcceptedPlugin } from 'postcss';\nimport postcss from 'postcss';\nimport tailwindcss from 'tailwindcss';\nimport type { Project } from 'ts-morph';\nimport { SyntaxKind } from 'ts-morph';\n\nimport { tailwindPlugin } from '../tailwind/tailwindPlugin';\nimport {\n findReferencesAsJsxElements,\n getReactFunctionDeclaration,\n getUsedPropsInReference,\n} from './tsMorph';\n\ntype ComponentsList = string[];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\ntype ExportToFilePath = { [key: string]: string };\ntype AllProps = Array<[string, string[]]>;\ntype PropToUsedOptions = [string, string[]];\n\nconst NO_FILE: string = 'noFile';\n\n/**\n * Returns a list of exported Components from UDS\n * both stable and experimental\n */\nconst getExportedComponents = (\n UDS: Record<string, any>,\n UDS_EXPERIMENTAL: Record<string, any>,\n): ComponentsList => {\n const udsStableExports = Object.keys(UDS);\n const udsExperimentalExports = Object.keys(UDS_EXPERIMENTAL);\n const allExports = udsStableExports.concat(udsExperimentalExports);\n const keys = allExports.filter((key) => {\n const regexStartsWithCapitalLetter = new RegExp('^[A-Z].[^_]');\n const hasUnderscore = key.includes('_');\n const startsWithCapitalLetter = regexStartsWithCapitalLetter.test(key);\n return !hasUnderscore && startsWithCapitalLetter;\n });\n return keys;\n};\n\n/**\n * Some UDS components are built using other UDS components,\n * we need to know those dependencies so generate the correct\n */\nconst getComponentsDependencies = (\n project: Project,\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentDependencies => {\n const componentsListSet = new Set(componentsList);\n // the components a component from UDS depends on\n const componentUDSDependencies: { [k: string]: string[] } = {};\n componentsList.forEach((component) => {\n componentUDSDependencies[component] = getComponentUdsDependencies(\n project,\n componentsListSet,\n component,\n exportsToFilePath,\n );\n });\n return componentUDSDependencies;\n};\n\n/**\n * We need to make sure that components from UDS that use other components\n * from UDS also gets included\n */\nconst getComponentUdsDependencies = (\n project: Project,\n componentsList: Set<string>,\n componentName: string,\n exportsToFilePath: ExportToFilePath,\n): string[] => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName]);\n\n const deps = sourceFile\n .getImportDeclarations()\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat()\n .filter((namedImport) => componentsList.has(namedImport));\n\n return deps;\n};\n\nconst getComponentsProps = (\n project: Project,\n list: ComponentsList,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentToVariants => {\n const map: ComponentToVariants = {};\n\n list.forEach((componentName) => {\n const list = getInitializedAndReferencedProps(\n project,\n componentName,\n variants,\n variantsList,\n exportsToFilePath,\n );\n map[componentName] = list;\n });\n\n return map;\n};\n\n/**\n * Converts the variants object used in CVA to\n */\nconst convertVariantsIntoTailwindClass = (\n variants: Record<string, Record<string, string>>,\n): VariantsList => {\n const variantsList = Object.keys(variants) as Array<keyof typeof variants>;\n\n return variantsList;\n};\n\n/**\n * Get the params with default values,\n * required and the ones used in references\n */\nconst getInitializedAndReferencedProps = (\n project: Project,\n componentName: string,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): AllProps => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName] ?? NO_FILE);\n\n const functionDeclarations = sourceFile.getFunctions();\n const variableDeclarations = sourceFile.getVariableDeclarations();\n const node = [...functionDeclarations, ...variableDeclarations].filter(\n (declaration) => declaration.getName() === componentName,\n )[0];\n\n const functionDeclaration = getReactFunctionDeclaration(node);\n\n if (!functionDeclaration) {\n print(red(`No function declaration found for ${componentName}`));\n }\n\n const parameterDeclaration = functionDeclaration?.getParameters();\n\n if (!parameterDeclaration || parameterDeclaration.length === 0) {\n print(red(`No parameter declaration found for ${componentName}`));\n return [];\n }\n\n // the first parameter in all react components is the props\n if (!parameterDeclaration[0].getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]) {\n return [];\n }\n\n const componentIdentifier = node.getFirstDescendantByKindOrThrow(SyntaxKind.Identifier);\n const references = findReferencesAsJsxElements(componentIdentifier);\n\n const propsWithDefaultValues = parameterDeclaration[0]\n .getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]\n .getElements()\n .filter((el) => !!el.getInitializer())\n .map((el) => {\n const stringLiteral = el.getDescendantsOfKind(SyntaxKind.StringLiteral)[0];\n const propName = el.getName();\n const values: string[] = [];\n if (stringLiteral) {\n values.push(stringLiteral.getLiteralText());\n }\n\n return [propName, values] as [string, string[]];\n })\n .filter(([propName]) => variantsList.includes(propName));\n\n const propsUsedInReferences = references\n .map((r) => getUsedPropsInReference(r, variants))\n .flat()\n .filter(([propName]) => variantsList.includes(propName));\n\n const mapPropToUsedOptions = new Map<string, Set<string>>();\n\n propsWithDefaultValues.concat(propsUsedInReferences).forEach(([propName, propValues]) => {\n // This means that an expression has been used\n // so we need to add all possible options for that prop\n if (propValues.length === 0) {\n propValues = Object.keys(variants[propName as keyof typeof variants]);\n }\n\n const options: Set<string> = mapPropToUsedOptions.get(propName) ?? new Set();\n propValues.forEach((val) => options.add(val));\n mapPropToUsedOptions.set(propName, options);\n });\n\n const res: Array<[string, string[]]> = Array.from(mapPropToUsedOptions).map(\n ([propName, options]) => [propName, Array.from(options)],\n );\n\n return res;\n};\n\n/**\n * Gets the Tailwind CSS classes used in a component\n */\nconst getTwClassesInComponent = async (\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): Promise<ComponentToTwClasses> => {\n const CSS_DATA = `\n @tailwind components;\n @tailwind utilities;\n `;\n\n const res: ComponentToTwClasses = {};\n\n const promises = componentsList.map((component) => {\n const plugin = tailwindcss({\n content: [exportsToFilePath[component]],\n plugins: [tailwindPlugin({ config: defaultTokensConfig })],\n });\n return postcss([plugin as AcceptedPlugin]).process(CSS_DATA, {\n from: 'app.css',\n to: './dist/app.css',\n });\n });\n\n const resolvedPromises = await Promise.all(promises);\n\n resolvedPromises.forEach((result, i) => {\n const currentComponent = componentsList[i];\n const classes = result.root.nodes\n .map((node) => {\n if ((node as any).selector) {\n return (node as any).selector.replace('.', '');\n }\n\n return [];\n })\n .join(' ')\n // replace multiple spaces with one space\n .replace(/\\s+/g, ' ');\n res[currentComponent] = classes;\n });\n\n return res;\n};\n\n/**\n * Goes through the list of all exports from UDS (stable and experimental)\n * and return a map of each exports and the source file path where its declared\n */\nconst getExportsToFilePath = (project: Project): ExportToFilePath => {\n const stableComponentsMainFile = project.getSourceFileOrThrow('./src/components/index.ts');\n const experimentalComponentsMainFile = project.getSourceFileOrThrow(\n './src/components/experimental/index.ts',\n );\n const exportToFilePath: ExportToFilePath = {};\n for (const [name, declarations] of stableComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n for (const [name, declarations] of experimentalComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n\n return exportToFilePath;\n};\n\n/**\n * Adds auto-generated variants to the Tailwind CSS classes of components.\n *\n * This function extracts component names from auto variants keys, groups class names by component,\n * updates component classes using auto-generated variant classes, and propagates base classes to subcomponents.\n *\n * @param componentToTwClasses - A map of component names to their current Tailwind CSS classes.\n * @returns Updated map with auto variants added to the component classes.\n */\nconst addAutoVariantsToComponentClasses = (\n componentToTwClasses: ComponentToTwClasses,\n): ComponentToTwClasses => {\n // Extract component names from auto variants keys\n // Example: \"checkboxSizeRoot\" -> \"Checkbox\"\n const componentNameRegex = /^([a-z]+)[A-Z]/;\n const componentNameMap: Record<string, string[]> = {};\n\n // Create a case-insensitive lookup map from component names in componentToTwClasses\n const componentNameLookup = new Map<string, string>();\n Object.keys(componentToTwClasses).forEach((actualName) => {\n componentNameLookup.set(actualName.toLowerCase(), actualName);\n });\n\n // Group class names by component\n Object.keys(autoVariants).forEach((key) => {\n const match = key.match(componentNameRegex);\n if (match && match[1]) {\n const extractedName = match[1].charAt(0).toUpperCase() + match[1].slice(1);\n // Use case-insensitive lookup to find the actual component name\n const actualComponentName =\n componentNameLookup.get(extractedName.toLowerCase()) || extractedName;\n\n if (!componentNameMap[actualComponentName]) {\n componentNameMap[actualComponentName] = [];\n }\n\n // Get all class names for this variant\n Object.values(autoVariants[key as keyof typeof autoVariants]).forEach((className) => {\n componentNameMap[actualComponentName].push(className);\n });\n }\n });\n\n // Add or update component classes\n Object.entries(componentNameMap).forEach(([componentName, classes]) => {\n const existingClasses = componentToTwClasses[componentName] || '';\n componentToTwClasses[componentName] = `${existingClasses} ${classes.join(' ')}`.trim();\n });\n\n // add a step to also add the classes to sub components (example, AvatarText, AvatarIcon, ...)\n const components = Object.keys(componentNameMap);\n Object.keys(componentToTwClasses).forEach((key) => {\n components.forEach((comp) => {\n const compName = comp.charAt(0).toUpperCase() + comp.slice(1);\n if (key.startsWith(compName) && key !== compName) {\n const baseClasses = componentToTwClasses[compName] || '';\n if (baseClasses) {\n componentToTwClasses[key] = `${componentToTwClasses[key]} ${baseClasses}`.trim();\n }\n }\n });\n });\n return componentToTwClasses;\n};\n\nexport {\n addAutoVariantsToComponentClasses,\n convertVariantsIntoTailwindClass,\n getComponentsDependencies,\n getComponentsProps,\n getComponentUdsDependencies,\n getExportedComponents,\n getExportsToFilePath,\n getInitializedAndReferencedProps,\n getTwClassesInComponent,\n NO_FILE,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"generatePurgeCSSData.js","names":[],"sources":["../../src/utils/generatePurgeCSSData.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { autoVariants } from '@yahoo/uds-automated-config/autoVariants';\nimport { print, red } from '@yahoo/uds-cli/lib';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport type { AcceptedPlugin } from 'postcss';\nimport postcss from 'postcss';\nimport tailwindcss from 'tailwindcss';\nimport type { Project } from 'ts-morph';\nimport { SyntaxKind } from 'ts-morph';\n\nimport { tailwindPlugin } from '../tailwind/tailwindPlugin';\nimport {\n findReferencesAsJsxElements,\n getReactFunctionDeclaration,\n getUsedPropsInReference,\n} from './tsMorph';\n\ntype ComponentsList = string[];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\ntype ExportToFilePath = { [key: string]: string };\ntype AllProps = Array<[string, string[]]>;\ntype PropToUsedOptions = [string, string[]];\n\nconst NO_FILE: string = 'noFile';\n\n/**\n * Returns a list of exported Components from UDS\n * both stable and experimental\n */\nconst getExportedComponents = (\n UDS: Record<string, any>,\n UDS_EXPERIMENTAL: Record<string, any>,\n): ComponentsList => {\n const udsStableExports = Object.keys(UDS);\n const udsExperimentalExports = Object.keys(UDS_EXPERIMENTAL);\n const allExports = udsStableExports.concat(udsExperimentalExports);\n const keys = allExports.filter((key) => {\n const regexStartsWithCapitalLetter = new RegExp('^[A-Z].[^_]');\n const hasUnderscore = key.includes('_');\n const startsWithCapitalLetter = regexStartsWithCapitalLetter.test(key);\n return !hasUnderscore && startsWithCapitalLetter;\n });\n return keys;\n};\n\n/**\n * Some UDS components are built using other UDS components,\n * we need to know those dependencies so generate the correct\n */\nconst getComponentsDependencies = (\n project: Project,\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentDependencies => {\n const componentsListSet = new Set(componentsList);\n // the components a component from UDS depends on\n const componentUDSDependencies: { [k: string]: string[] } = {};\n componentsList.forEach((component) => {\n componentUDSDependencies[component] = getComponentUdsDependencies(\n project,\n componentsListSet,\n component,\n exportsToFilePath,\n );\n });\n return componentUDSDependencies;\n};\n\n/**\n * We need to make sure that components from UDS that use other components\n * from UDS also gets included\n */\nconst getComponentUdsDependencies = (\n project: Project,\n componentsList: Set<string>,\n componentName: string,\n exportsToFilePath: ExportToFilePath,\n): string[] => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName]);\n\n const deps = sourceFile\n .getImportDeclarations()\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat()\n .filter((namedImport) => componentsList.has(namedImport));\n\n return deps;\n};\n\nconst getComponentsProps = (\n project: Project,\n list: ComponentsList,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentToVariants => {\n const map: ComponentToVariants = {};\n\n list.forEach((componentName) => {\n const list = getInitializedAndReferencedProps(\n project,\n componentName,\n variants,\n variantsList,\n exportsToFilePath,\n );\n map[componentName] = list;\n });\n\n return map;\n};\n\n/**\n * Converts the variants object used in CVA to\n */\nconst convertVariantsIntoTailwindClass = (\n variants: Record<string, Record<string, string>>,\n): VariantsList => {\n const variantsList = Object.keys(variants) as Array<keyof typeof variants>;\n\n return variantsList;\n};\n\n/**\n * Get the params with default values,\n * required and the ones used in references\n */\nconst getInitializedAndReferencedProps = (\n project: Project,\n componentName: string,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): AllProps => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName] ?? NO_FILE);\n\n const functionDeclarations = sourceFile.getFunctions();\n const variableDeclarations = sourceFile.getVariableDeclarations();\n const node = [...functionDeclarations, ...variableDeclarations].filter(\n (declaration) => declaration.getName() === componentName,\n )[0];\n\n const functionDeclaration = getReactFunctionDeclaration(node);\n\n if (!functionDeclaration) {\n print(red(`No function declaration found for ${componentName}`));\n }\n\n const parameterDeclaration = functionDeclaration?.getParameters();\n\n if (!parameterDeclaration || parameterDeclaration.length === 0) {\n print(red(`No parameter declaration found for ${componentName}`));\n return [];\n }\n\n // the first parameter in all react components is the props\n if (!parameterDeclaration[0].getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]) {\n return [];\n }\n\n const componentIdentifier = node.getFirstDescendantByKindOrThrow(SyntaxKind.Identifier);\n const references = findReferencesAsJsxElements(componentIdentifier);\n\n const propsWithDefaultValues = parameterDeclaration[0]\n .getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]\n .getElements()\n .filter((el) => !!el.getInitializer())\n .map((el) => {\n const stringLiteral = el.getDescendantsOfKind(SyntaxKind.StringLiteral)[0];\n const propName = el.getName();\n const values: string[] = [];\n if (stringLiteral) {\n values.push(stringLiteral.getLiteralText());\n }\n\n return [propName, values] as [string, string[]];\n })\n .filter(([propName]) => variantsList.includes(propName));\n\n const propsUsedInReferences = references\n .map((r) => getUsedPropsInReference(r, variants))\n .flat()\n .filter(([propName]) => variantsList.includes(propName));\n\n const mapPropToUsedOptions = new Map<string, Set<string>>();\n\n propsWithDefaultValues.concat(propsUsedInReferences).forEach(([propName, propValues]) => {\n // This means that an expression has been used\n // so we need to add all possible options for that prop\n if (propValues.length === 0) {\n propValues = Object.keys(variants[propName as keyof typeof variants]);\n }\n\n const options: Set<string> = mapPropToUsedOptions.get(propName) ?? new Set();\n propValues.forEach((val) => options.add(val));\n mapPropToUsedOptions.set(propName, options);\n });\n\n const res: Array<[string, string[]]> = Array.from(mapPropToUsedOptions).map(\n ([propName, options]) => [propName, Array.from(options)],\n );\n\n return res;\n};\n\n/**\n * Gets the Tailwind CSS classes used in a component\n */\nconst getTwClassesInComponent = async (\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): Promise<ComponentToTwClasses> => {\n const CSS_DATA = `\n @tailwind components;\n @tailwind utilities;\n `;\n\n const res: ComponentToTwClasses = {};\n\n const promises = componentsList.map((component) => {\n const plugin = tailwindcss({\n content: [exportsToFilePath[component]],\n plugins: [tailwindPlugin({ config: defaultTokensConfig })],\n });\n return postcss([plugin as AcceptedPlugin]).process(CSS_DATA, {\n from: 'app.css',\n to: './dist/app.css',\n });\n });\n\n const resolvedPromises = await Promise.all(promises);\n\n resolvedPromises.forEach((result, i) => {\n const currentComponent = componentsList[i];\n const classes = result.root.nodes\n .map((node) => {\n if ((node as any).selector) {\n return (node as any).selector.replace('.', '');\n }\n\n return [];\n })\n .join(' ')\n // replace multiple spaces with one space\n .replace(/\\s+/g, ' ');\n res[currentComponent] = classes;\n });\n\n return res;\n};\n\n/**\n * Goes through the list of all exports from UDS (stable and experimental)\n * and return a map of each exports and the source file path where its declared\n */\nconst getExportsToFilePath = (project: Project): ExportToFilePath => {\n const stableComponentsMainFile = project.getSourceFileOrThrow('./src/components/index.ts');\n const experimentalComponentsMainFile = project.getSourceFileOrThrow(\n './src/components/experimental/index.ts',\n );\n const exportToFilePath: ExportToFilePath = {};\n for (const [name, declarations] of stableComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n for (const [name, declarations] of experimentalComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n\n return exportToFilePath;\n};\n\n/**\n * Adds auto-generated variants to the Tailwind CSS classes of components.\n *\n * This function extracts component names from auto variants keys, groups class names by component,\n * updates component classes using auto-generated variant classes, and propagates base classes to subcomponents.\n *\n * @param componentToTwClasses - A map of component names to their current Tailwind CSS classes.\n * @returns Updated map with auto variants added to the component classes.\n */\nconst addAutoVariantsToComponentClasses = (\n componentToTwClasses: ComponentToTwClasses,\n): ComponentToTwClasses => {\n // Extract component names from auto variants keys\n // Example: \"checkboxSizeRoot\" -> \"Checkbox\"\n const componentNameRegex = /^([a-z]+)[A-Z]/;\n const componentNameMap: Record<string, string[]> = {};\n\n // Create a case-insensitive lookup map from component names in componentToTwClasses\n const componentNameLookup = new Map<string, string>();\n Object.keys(componentToTwClasses).forEach((actualName) => {\n componentNameLookup.set(actualName.toLowerCase(), actualName);\n });\n\n // Group class names by component\n Object.keys(autoVariants).forEach((key) => {\n const match = key.match(componentNameRegex);\n if (match && match[1]) {\n const extractedName = match[1].charAt(0).toUpperCase() + match[1].slice(1);\n // Use case-insensitive lookup to find the actual component name\n const actualComponentName =\n componentNameLookup.get(extractedName.toLowerCase()) || extractedName;\n\n if (!componentNameMap[actualComponentName]) {\n componentNameMap[actualComponentName] = [];\n }\n\n // Get all class names for this variant\n Object.values(autoVariants[key as keyof typeof autoVariants]).forEach((className) => {\n componentNameMap[actualComponentName].push(className);\n });\n }\n });\n\n // Add or update component classes\n Object.entries(componentNameMap).forEach(([componentName, classes]) => {\n const existingClasses = componentToTwClasses[componentName] || '';\n componentToTwClasses[componentName] = `${existingClasses} ${classes.join(' ')}`.trim();\n });\n\n // add a step to also add the classes to sub components (example, AvatarText, AvatarIcon, ...)\n const components = Object.keys(componentNameMap);\n Object.keys(componentToTwClasses).forEach((key) => {\n components.forEach((comp) => {\n const compName = comp.charAt(0).toUpperCase() + comp.slice(1);\n if (key.startsWith(compName) && key !== compName) {\n const baseClasses = componentToTwClasses[compName] || '';\n if (baseClasses) {\n componentToTwClasses[key] = `${componentToTwClasses[key]} ${baseClasses}`.trim();\n }\n }\n });\n });\n return componentToTwClasses;\n};\n\nexport {\n addAutoVariantsToComponentClasses,\n convertVariantsIntoTailwindClass,\n getComponentsDependencies,\n getComponentsProps,\n getComponentUdsDependencies,\n getExportedComponents,\n getExportsToFilePath,\n getInitializedAndReferencedProps,\n getTwClassesInComponent,\n NO_FILE,\n};\n"],"mappings":"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"}