@yahoo/uds 3.114.0-beta.2 → 3.114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/automated-config/dist/generated/autoVariants.cjs +3 -0
- package/dist/automated-config/dist/generated/autoVariants.d.cts +3 -0
- package/dist/automated-config/dist/generated/autoVariants.d.ts +3 -0
- package/dist/automated-config/dist/generated/autoVariants.js +3 -0
- package/dist/automated-config/dist/generated/generatedConfigs.cjs +1883 -0
- package/dist/automated-config/dist/generated/generatedConfigs.d.cts +175 -1
- package/dist/automated-config/dist/generated/generatedConfigs.d.ts +175 -1
- package/dist/automated-config/dist/generated/generatedConfigs.js +1882 -1
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.cjs +84 -0
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.d.cts +3 -1
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.d.ts +3 -1
- package/dist/automated-config/dist/generated/universalTokensConfigAuto.js +84 -0
- package/dist/automated-config/dist/mapTextVariantFixtureToValue.cjs +1 -12
- package/dist/automated-config/dist/mapTextVariantFixtureToValue.js +1 -12
- package/dist/automated-config/dist/properties.cjs +58 -12
- package/dist/automated-config/dist/properties.d.cts +8 -0
- package/dist/automated-config/dist/properties.d.ts +8 -0
- package/dist/automated-config/dist/properties.js +58 -12
- package/dist/automated-config/dist/utils/getConfigVariantProperties.d.cts +2 -2
- package/dist/automated-config/dist/utils/getConfigVariantProperties.d.ts +2 -2
- package/dist/cli/commands/sync.cjs +7 -1
- package/dist/cli/commands/sync.d.cts +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +7 -1
- package/dist/cli/commands/version.cjs +2 -0
- package/dist/cli/commands/version.d.cts +1 -1
- package/dist/cli/commands/version.d.ts +1 -1
- package/dist/cli/commands/version.js +2 -0
- package/dist/cli/dist/cli.cjs +1 -1
- package/dist/cli/dist/cli.js +1 -1
- package/dist/cli/dist/commands/editor-rules.cjs +2 -2
- package/dist/cli/dist/commands/editor-rules.js +2 -2
- package/dist/cli/dist/utils/rules/config.cjs +1 -1
- package/dist/cli/dist/utils/rules/config.js +1 -1
- package/dist/cli/runner.cjs +2 -11
- package/dist/cli/runner.js +2 -11
- package/dist/components/Scrim.cjs +28 -0
- package/dist/components/Scrim.d.cts +14 -0
- package/dist/components/Scrim.d.ts +14 -0
- package/dist/components/Scrim.js +26 -0
- package/dist/components/client/BottomSheet/BottomSheet.cjs +209 -0
- package/dist/components/client/BottomSheet/BottomSheet.d.cts +77 -0
- package/dist/components/client/BottomSheet/BottomSheet.d.ts +77 -0
- package/dist/components/client/BottomSheet/BottomSheet.js +207 -0
- package/dist/components/client/BottomSheet/BottomSheetContent.cjs +26 -0
- package/dist/components/client/BottomSheet/BottomSheetContent.d.cts +15 -0
- package/dist/components/client/BottomSheet/BottomSheetContent.d.ts +15 -0
- package/dist/components/client/BottomSheet/BottomSheetContent.js +24 -0
- package/dist/components/client/BottomSheet/BottomSheetDismiss.cjs +15 -0
- package/dist/components/client/BottomSheet/BottomSheetDismiss.d.cts +12 -0
- package/dist/components/client/BottomSheet/BottomSheetDismiss.d.ts +12 -0
- package/dist/components/client/BottomSheet/BottomSheetDismiss.js +13 -0
- package/dist/components/client/BottomSheet/BottomSheetHandle.cjs +30 -0
- package/dist/components/client/BottomSheet/BottomSheetHandle.d.cts +19 -0
- package/dist/components/client/BottomSheet/BottomSheetHandle.d.ts +19 -0
- package/dist/components/client/BottomSheet/BottomSheetHandle.js +28 -0
- package/dist/components/client/BottomSheet/BottomSheetHeader.cjs +42 -0
- package/dist/components/client/BottomSheet/BottomSheetHeader.d.cts +18 -0
- package/dist/components/client/BottomSheet/BottomSheetHeader.d.ts +18 -0
- package/dist/components/client/BottomSheet/BottomSheetHeader.js +40 -0
- package/dist/components/client/BottomSheet/BottomSheetProvider.cjs +21 -0
- package/dist/components/client/BottomSheet/BottomSheetProvider.d.cts +19 -0
- package/dist/components/client/BottomSheet/BottomSheetProvider.d.ts +19 -0
- package/dist/components/client/BottomSheet/BottomSheetProvider.js +19 -0
- package/dist/components/client/BottomSheet/BottomSheetTrigger.cjs +15 -0
- package/dist/components/client/BottomSheet/BottomSheetTrigger.d.cts +12 -0
- package/dist/components/client/BottomSheet/BottomSheetTrigger.d.ts +12 -0
- package/dist/components/client/BottomSheet/BottomSheetTrigger.js +13 -0
- package/dist/components/client/BottomSheet/UDSBottomSheetConfigProvider.cjs +32 -0
- package/dist/components/client/BottomSheet/UDSBottomSheetConfigProvider.d.cts +22 -0
- package/dist/components/client/BottomSheet/UDSBottomSheetConfigProvider.d.ts +22 -0
- package/dist/components/client/BottomSheet/UDSBottomSheetConfigProvider.js +29 -0
- package/dist/components/client/BottomSheet/index.cjs +22 -0
- package/dist/components/client/BottomSheet/index.d.cts +10 -0
- package/dist/components/client/BottomSheet/index.d.ts +10 -0
- package/dist/components/client/BottomSheet/index.js +12 -0
- package/dist/components/client/BottomSheet/useBottomSheetDrag.cjs +188 -0
- package/dist/components/client/BottomSheet/useBottomSheetDrag.d.cts +44 -0
- package/dist/components/client/BottomSheet/useBottomSheetDrag.d.ts +44 -0
- package/dist/components/client/BottomSheet/useBottomSheetDrag.js +185 -0
- package/dist/components/client/BottomSheet/useBottomSheetSnapModel.cjs +138 -0
- package/dist/components/client/BottomSheet/useBottomSheetSnapModel.d.cts +46 -0
- package/dist/components/client/BottomSheet/useBottomSheetSnapModel.d.ts +46 -0
- package/dist/components/client/BottomSheet/useBottomSheetSnapModel.js +135 -0
- package/dist/components/client/BottomSheet/useBottomSheetStore.cjs +34 -0
- package/dist/components/client/BottomSheet/useBottomSheetStore.d.cts +38 -0
- package/dist/components/client/BottomSheet/useBottomSheetStore.d.ts +38 -0
- package/dist/components/client/BottomSheet/useBottomSheetStore.js +31 -0
- package/dist/components/client/BottomSheet/useBottomSheetStoreInternal.cjs +17 -0
- package/dist/components/client/BottomSheet/useBottomSheetStoreInternal.d.cts +13 -0
- package/dist/components/client/BottomSheet/useBottomSheetStoreInternal.d.ts +13 -0
- package/dist/components/client/BottomSheet/useBottomSheetStoreInternal.js +15 -0
- package/dist/components/client/BottomSheet/useExpansionMargins.cjs +89 -0
- package/dist/components/client/BottomSheet/useExpansionMargins.d.cts +34 -0
- package/dist/components/client/BottomSheet/useExpansionMargins.d.ts +34 -0
- package/dist/components/client/BottomSheet/useExpansionMargins.js +87 -0
- package/dist/components/client/BottomSheet/useViewportHeight.cjs +32 -0
- package/dist/components/client/BottomSheet/useViewportHeight.d.cts +9 -0
- package/dist/components/client/BottomSheet/useViewportHeight.d.ts +9 -0
- package/dist/components/client/BottomSheet/useViewportHeight.js +30 -0
- package/dist/components/client/BottomSheet/useVirtualKeyboard.cjs +48 -0
- package/dist/components/client/BottomSheet/useVirtualKeyboard.d.cts +10 -0
- package/dist/components/client/BottomSheet/useVirtualKeyboard.d.ts +10 -0
- package/dist/components/client/BottomSheet/useVirtualKeyboard.js +46 -0
- package/dist/components/client/BottomSheet/utils.cjs +128 -0
- package/dist/components/client/BottomSheet/utils.d.cts +61 -0
- package/dist/components/client/BottomSheet/utils.d.ts +61 -0
- package/dist/components/client/BottomSheet/utils.js +118 -0
- package/dist/components/client/Menu/Menu.Content.cjs +1 -1
- package/dist/components/client/Menu/Menu.Content.js +1 -1
- package/dist/components/client/Menu/Menu.ItemCheckbox.d.cts +1 -1
- package/dist/components/client/Menu/Menu.ItemCheckbox.d.ts +1 -1
- package/dist/components/client/Menu/Menu.index.d.cts +1 -1
- package/dist/components/client/index.cjs +16 -0
- package/dist/components/client/index.d.cts +10 -1
- package/dist/components/client/index.d.ts +10 -1
- package/dist/components/client/index.js +9 -1
- package/dist/components/client/providers/UDSConfigProvider.cjs +10 -6
- package/dist/components/client/providers/UDSConfigProvider.d.cts +1 -0
- package/dist/components/client/providers/UDSConfigProvider.d.ts +1 -0
- package/dist/components/client/providers/UDSConfigProvider.js +10 -6
- package/dist/components/index.cjs +24 -0
- package/dist/components/index.d.cts +9 -1
- package/dist/components/index.d.ts +9 -1
- package/dist/components/index.js +17 -1
- package/dist/config/dist/index.cjs +110 -2
- package/dist/config/dist/index.js +110 -2
- package/dist/fixtures/dist/index.cjs +103 -0
- package/dist/fixtures/dist/index.d.cts +3 -2
- package/dist/fixtures/dist/index.d.ts +3 -2
- package/dist/fixtures/dist/index.js +103 -1
- package/dist/fixtures/index.cjs +1 -0
- package/dist/fixtures/index.d.cts +2 -2
- package/dist/fixtures/index.d.ts +2 -2
- package/dist/fixtures/index.js +2 -2
- package/dist/index.cjs +20 -2
- package/dist/index.d.cts +12 -5
- package/dist/index.d.ts +12 -5
- package/dist/index.js +11 -3
- package/dist/runtime/bottomSheetConfig.cjs +11 -0
- package/dist/runtime/bottomSheetConfig.d.cts +15 -0
- package/dist/runtime/bottomSheetConfig.d.ts +15 -0
- package/dist/runtime/bottomSheetConfig.js +9 -0
- package/dist/runtime/index.cjs +2 -0
- package/dist/runtime/index.d.cts +2 -1
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +2 -1
- package/dist/runtime/udsConfig.cjs +2 -0
- package/dist/runtime/udsConfig.d.cts +2 -0
- package/dist/runtime/udsConfig.d.ts +2 -0
- package/dist/runtime/udsConfig.js +2 -0
- package/dist/styles/styler.d.cts +33 -30
- package/dist/styles/styler.d.ts +33 -30
- package/dist/styles/variants.cjs +278 -278
- package/dist/styles/variants.d.cts +9 -0
- package/dist/styles/variants.d.ts +9 -0
- package/dist/styles/variants.js +278 -278
- package/dist/tailwind/dist/commands/generateComponentData.cjs +31 -33
- package/dist/tailwind/dist/commands/generateComponentData.d.ts +1 -1
- package/dist/tailwind/dist/commands/generateComponentData.js +31 -33
- package/dist/tailwind/dist/commands/generatePurgeCSSData.d.ts +1 -1
- package/dist/tailwind/dist/commands/purge.cjs +4 -3
- package/dist/tailwind/dist/commands/purge.d.ts +1 -1
- package/dist/tailwind/dist/commands/purge.js +4 -3
- package/dist/tailwind/dist/index.d.cts +0 -1
- package/dist/tailwind/dist/index.d.ts +3 -5
- package/dist/tailwind/dist/purger/legacy/purgeCSS.cjs +3 -4
- package/dist/tailwind/dist/purger/legacy/purgeCSS.js +3 -4
- package/dist/tailwind/dist/purger/optimized/ast/expressions.cjs +125 -122
- package/dist/tailwind/dist/purger/optimized/ast/expressions.js +125 -122
- package/dist/tailwind/dist/purger/optimized/ast/jsx.cjs +8 -1
- package/dist/tailwind/dist/purger/optimized/ast/jsx.js +8 -1
- package/dist/tailwind/dist/purger/optimized/purge.cjs +10 -11
- package/dist/tailwind/dist/purger/optimized/purge.js +9 -10
- package/dist/tailwind/dist/purger/optimized/purgeFromCode.cjs +127 -232
- package/dist/tailwind/dist/purger/optimized/purgeFromCode.js +127 -232
- package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.cjs +262 -330
- package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js +262 -329
- package/dist/tailwind/dist/purger/optimized/utils/files.cjs +3 -4
- package/dist/tailwind/dist/purger/optimized/utils/files.js +3 -4
- package/dist/tailwind/dist/purger/optimized/utils/safelist.cjs +21 -13
- package/dist/tailwind/dist/purger/optimized/utils/safelist.js +21 -13
- package/dist/tailwind/dist/tailwind/plugins/components.cjs +2 -0
- package/dist/tailwind/dist/tailwind/plugins/components.js +3 -1
- package/dist/tailwind/dist/tailwind/plugins/typography.cjs +13 -41
- package/dist/tailwind/dist/tailwind/plugins/typography.js +13 -41
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.cjs +2 -4
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.d.cts +1 -10
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.d.ts +1 -10
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.js +2 -4
- package/dist/tailwind/dist/utils/tsMorph.cjs +1 -1
- package/dist/tokens/automation/configs/index.cjs +2 -0
- package/dist/tokens/automation/configs/index.d.cts +2 -2
- package/dist/tokens/automation/configs/index.d.ts +2 -2
- package/dist/tokens/automation/configs/index.js +2 -2
- package/dist/tokens/automation/index.cjs +2 -0
- package/dist/tokens/automation/index.d.cts +2 -2
- package/dist/tokens/automation/index.d.ts +2 -2
- package/dist/tokens/automation/index.js +2 -2
- package/dist/tokens/index.cjs +2 -0
- package/dist/tokens/index.d.cts +3 -3
- package/dist/tokens/index.d.ts +3 -3
- package/dist/tokens/index.js +2 -2
- package/dist/tokens/types.d.cts +2 -2
- package/dist/tokens/types.d.ts +2 -2
- package/dist/types/dist/index.d.cts +76 -1
- package/dist/types/dist/index.d.ts +76 -1
- package/dist/uds/generated/componentData.cjs +1187 -961
- package/dist/uds/generated/componentData.js +1111 -939
- package/dist/uds/generated/tailwindPurge.cjs +57 -29
- package/dist/uds/generated/tailwindPurge.js +57 -29
- package/dist/uds/package.cjs +4 -10
- package/dist/uds/package.js +4 -10
- package/package.json +4 -7
- package/dist/cli/dist/lib/logger.cjs +0 -66
- package/dist/cli/dist/lib/logger.js +0 -66
- package/dist/tailwind/dist/commands/css.cjs +0 -79
- package/dist/tailwind/dist/commands/css.d.ts +0 -3
- package/dist/tailwind/dist/commands/css.helpers.cjs +0 -32
- package/dist/tailwind/dist/commands/css.helpers.js +0 -28
- package/dist/tailwind/dist/commands/css.js +0 -79
- package/dist/tailwind/dist/css/generate.cjs +0 -120
- package/dist/tailwind/dist/css/generate.d.cts +0 -30
- package/dist/tailwind/dist/css/generate.d.ts +0 -31
- package/dist/tailwind/dist/css/generate.helpers.cjs +0 -112
- package/dist/tailwind/dist/css/generate.helpers.js +0 -100
- package/dist/tailwind/dist/css/generate.js +0 -115
- package/dist/tailwind/dist/css/postcss.cjs +0 -35
- package/dist/tailwind/dist/css/postcss.helpers.cjs +0 -27
- package/dist/tailwind/dist/css/postcss.helpers.js +0 -26
- package/dist/tailwind/dist/css/postcss.js +0 -35
- package/dist/tailwind/dist/css/runner.cjs +0 -278
- package/dist/tailwind/dist/css/runner.helpers.cjs +0 -26
- package/dist/tailwind/dist/css/runner.helpers.js +0 -23
- package/dist/tailwind/dist/css/runner.js +0 -275
- package/dist/tailwind/dist/css/theme.cjs +0 -12
- package/dist/tailwind/dist/css/theme.d.cts +0 -66
- package/dist/tailwind/dist/css/theme.d.ts +0 -66
- package/dist/tailwind/dist/css/theme.js +0 -11
- package/dist/tailwind/dist/css/utils.cjs +0 -234
- package/dist/tailwind/dist/css/utils.js +0 -223
- package/dist/tailwind/dist/utils/optimizeCSS.cjs +0 -405
- package/dist/tailwind/dist/utils/optimizeCSS.js +0 -403
- package/dist/tailwind/dist/utils/postcssPreserveVars.cjs +0 -67
- package/dist/tailwind/dist/utils/postcssPreserveVars.js +0 -65
- package/generated/componentData.json +0 -2397
- package/generated/tailwindPurge.ts +0 -4560
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
-
import { configurableProperties } from "../../../automated-config/dist/properties.js";
|
|
3
|
-
import { purgeFromCodeOptimized } from "../purger/optimized/purgeFromCode.js";
|
|
4
|
-
import { cyan, green, magenta, red } from "../../../cli/dist/lib/colors.js";
|
|
5
|
-
import { print } from "../../../cli/dist/lib/print.js";
|
|
6
|
-
import fs from "node:fs";
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import fg from "fast-glob";
|
|
9
|
-
import { createRequire } from "node:module";
|
|
10
|
-
|
|
11
|
-
//#region ../tailwind/dist/css/utils.js
|
|
12
|
-
/*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
|
|
13
|
-
/**
|
|
14
|
-
* Load a TypeScript/JavaScript config file dynamically
|
|
15
|
-
*/
|
|
16
|
-
const loadConfigFile = async (configPath) => {
|
|
17
|
-
const absolutePath = path.isAbsolute(configPath) ? configPath : path.join(process.cwd(), configPath);
|
|
18
|
-
if (!fs.existsSync(absolutePath)) return null;
|
|
19
|
-
try {
|
|
20
|
-
const module = await import(absolutePath);
|
|
21
|
-
return module.default ?? module.config ?? module;
|
|
22
|
-
} catch (error) {
|
|
23
|
-
throw new Error(`Failed to load config file: ${absolutePath}\n${error instanceof Error ? error.message : "Unknown error"}`);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Extract variant defaults from a UniversalTokensConfig.
|
|
28
|
-
* Converts from config structure to a simpler lookup format.
|
|
29
|
-
* e.g., { button: { defaults: { size: 'md' } } } -> { Button: { size: 'md' } }
|
|
30
|
-
*/
|
|
31
|
-
const extractVariantDefaults = (config) => {
|
|
32
|
-
const componentNameMap = {
|
|
33
|
-
avatar: "Avatar",
|
|
34
|
-
badge: "Badge",
|
|
35
|
-
button: "Button",
|
|
36
|
-
checkbox: "Checkbox",
|
|
37
|
-
chip: "Chip",
|
|
38
|
-
divider: "Divider",
|
|
39
|
-
iconButton: "IconButton",
|
|
40
|
-
input: "Input",
|
|
41
|
-
link: "Link",
|
|
42
|
-
menu: "Menu",
|
|
43
|
-
radio: "Radio",
|
|
44
|
-
switch: "Switch"
|
|
45
|
-
};
|
|
46
|
-
return Object.entries(config).reduce((acc, [configKey, componentConfig]) => {
|
|
47
|
-
const pascalName = componentNameMap[configKey];
|
|
48
|
-
if (!pascalName || !componentConfig || typeof componentConfig !== "object") return acc;
|
|
49
|
-
const configWithDefaults = componentConfig;
|
|
50
|
-
return configWithDefaults.defaults ? {
|
|
51
|
-
...acc,
|
|
52
|
-
[pascalName]: configWithDefaults.defaults
|
|
53
|
-
} : acc;
|
|
54
|
-
}, {});
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* Scan directory for JSX/TSX files and extract safelist
|
|
58
|
-
*/
|
|
59
|
-
const scanDirectoryForSafelist = async (dir, colorModes, variants, autoVariants, componentData, variantDefaults, includeAllClassNamePrimitives = false) => {
|
|
60
|
-
const files = await fg("**/*.{js,jsx,ts,tsx}", {
|
|
61
|
-
cwd: dir,
|
|
62
|
-
absolute: true,
|
|
63
|
-
ignore: ["**/node_modules/**"]
|
|
64
|
-
});
|
|
65
|
-
const results = await Promise.all(files.map(async (filePath) => {
|
|
66
|
-
return purgeFromCodeOptimized(fs.readFileSync(filePath, "utf-8"), {
|
|
67
|
-
colorModes,
|
|
68
|
-
variantDefaults,
|
|
69
|
-
variants,
|
|
70
|
-
autoVariants,
|
|
71
|
-
componentData,
|
|
72
|
-
includeAllClassNamePrimitives
|
|
73
|
-
});
|
|
74
|
-
}));
|
|
75
|
-
return {
|
|
76
|
-
safelist: results.flatMap((result) => result.safelist),
|
|
77
|
-
components: [...new Set(results.flatMap((result) => result.components))],
|
|
78
|
-
filesScanned: files.length
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
/**
|
|
82
|
-
* Find a package's source directory in node_modules
|
|
83
|
-
*/
|
|
84
|
-
const findMonorepoRoot = (startDir) => {
|
|
85
|
-
const findUp = (currentDir) => {
|
|
86
|
-
if (fs.existsSync(path.join(currentDir, "packages"))) return currentDir;
|
|
87
|
-
const parentDir = path.dirname(currentDir);
|
|
88
|
-
return parentDir === currentDir ? null : findUp(parentDir);
|
|
89
|
-
};
|
|
90
|
-
return findUp(startDir);
|
|
91
|
-
};
|
|
92
|
-
const resolvePackageRoot = (workspaceDir, packageName) => {
|
|
93
|
-
const require = createRequire(import.meta.url);
|
|
94
|
-
try {
|
|
95
|
-
const resolvedPackageJson = require.resolve(path.join(packageName, "package.json"), { paths: [workspaceDir] });
|
|
96
|
-
return path.dirname(resolvedPackageJson);
|
|
97
|
-
} catch {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
const findPackageRootInMonorepo = (monorepoRoot, packageName) => {
|
|
102
|
-
const matchingPath = fg.sync("packages/**/package.json", {
|
|
103
|
-
cwd: monorepoRoot,
|
|
104
|
-
absolute: true,
|
|
105
|
-
ignore: ["**/node_modules/**", "**/dist/**"]
|
|
106
|
-
}).find((pkgJsonPath) => {
|
|
107
|
-
try {
|
|
108
|
-
return JSON.parse(fs.readFileSync(pkgJsonPath, "utf8")).name === packageName;
|
|
109
|
-
} catch {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
return matchingPath ? path.dirname(matchingPath) : null;
|
|
114
|
-
};
|
|
115
|
-
const buildPackageSourceCandidates = (workspaceDir, packageName, packageRoot) => {
|
|
116
|
-
return [
|
|
117
|
-
packageRoot ? path.join(packageRoot, "src") : null,
|
|
118
|
-
packageRoot ? path.join(packageRoot, "lib") : null,
|
|
119
|
-
packageRoot ? path.join(packageRoot, "dist") : null,
|
|
120
|
-
packageRoot,
|
|
121
|
-
path.join(workspaceDir, "node_modules", packageName, "src"),
|
|
122
|
-
path.join(workspaceDir, "node_modules", packageName, "lib"),
|
|
123
|
-
path.join(workspaceDir, "node_modules", packageName, "dist"),
|
|
124
|
-
path.join(workspaceDir, "node_modules", packageName)
|
|
125
|
-
].filter(Boolean);
|
|
126
|
-
};
|
|
127
|
-
const getFirstExistingPath = (candidates) => candidates.find((candidate) => fs.existsSync(candidate)) ?? null;
|
|
128
|
-
const findPackageSourceDir = (packageName) => {
|
|
129
|
-
const workspaceDir = process.cwd();
|
|
130
|
-
const monorepoRoot = findMonorepoRoot(workspaceDir);
|
|
131
|
-
let packageRoot = resolvePackageRoot(workspaceDir, packageName);
|
|
132
|
-
if (!packageRoot && monorepoRoot) packageRoot = findPackageRootInMonorepo(monorepoRoot, packageName);
|
|
133
|
-
return getFirstExistingPath(buildPackageSourceCandidates(workspaceDir, packageName, packageRoot));
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Format bytes to human readable string
|
|
137
|
-
*/
|
|
138
|
-
const formatBytes = (bytes) => {
|
|
139
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
140
|
-
const kb = bytes / 1024;
|
|
141
|
-
if (kb < 1024) return `${kb.toFixed(1)} KB`;
|
|
142
|
-
return `${(kb / 1024).toFixed(2)} MB`;
|
|
143
|
-
};
|
|
144
|
-
/**
|
|
145
|
-
* Generate a uds.theme.ts scaffold file
|
|
146
|
-
*/
|
|
147
|
-
const scaffoldThemeConfig = async (options) => {
|
|
148
|
-
const workspaceDir = process.cwd();
|
|
149
|
-
const outputPath = options.outputPath ?? "uds.theme.ts";
|
|
150
|
-
const absoluteOutputPath = path.isAbsolute(outputPath) ? outputPath : path.join(workspaceDir, outputPath);
|
|
151
|
-
if (fs.existsSync(absoluteOutputPath) && !options.force) {
|
|
152
|
-
print(red(`Error: ${outputPath} already exists. Use --force to overwrite.`));
|
|
153
|
-
process.exitCode = 1;
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
const template = `import { defineTheme } from '@yahoo/uds';
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* UDS Theme Configuration
|
|
160
|
-
*
|
|
161
|
-
* This file configures CSS generation for your app and shared packages.
|
|
162
|
-
* Run \`uds css\` to generate optimized CSS.
|
|
163
|
-
*/
|
|
164
|
-
export default defineTheme({
|
|
165
|
-
// Path to your uds.config.ts file
|
|
166
|
-
config: '${options.configPath ?? "./uds.config.ts"}',
|
|
167
|
-
|
|
168
|
-
// Entry directory for scanning your app code
|
|
169
|
-
entry: '${options.entry ?? "./src"}',
|
|
170
|
-
|
|
171
|
-
// Color modes to include (light mode is always in :root)
|
|
172
|
-
colorModes: ['dark'],
|
|
173
|
-
|
|
174
|
-
// Packages that inherit your app's theme (merged into main uds.css)
|
|
175
|
-
// inherit: ['@your-org/shared-ui'],
|
|
176
|
-
|
|
177
|
-
// CSS generation options (all optional)
|
|
178
|
-
// css: {
|
|
179
|
-
// safelist: [],
|
|
180
|
-
// preflight: true,
|
|
181
|
-
// fontFaceDeclarations: true,
|
|
182
|
-
// optimization: {
|
|
183
|
-
// removeUnusedFonts: false,
|
|
184
|
-
// removeEmptyRules: true,
|
|
185
|
-
// deduplicateScopedCss: true
|
|
186
|
-
// }
|
|
187
|
-
// }
|
|
188
|
-
});
|
|
189
|
-
`;
|
|
190
|
-
fs.writeFileSync(absoluteOutputPath, template);
|
|
191
|
-
print("");
|
|
192
|
-
print(green("✅ Created uds.theme.ts"));
|
|
193
|
-
print("");
|
|
194
|
-
print(`${magenta("Next steps:")}`);
|
|
195
|
-
print(` 1. Review and customize ${cyan(outputPath)}`);
|
|
196
|
-
print(` 2. Run ${cyan("uds css")} to generate CSS`);
|
|
197
|
-
print("");
|
|
198
|
-
};
|
|
199
|
-
/**
|
|
200
|
-
* Get motion CSS variable prefixes needed by a set of components.
|
|
201
|
-
* Looks up motionVarPrefixes from componentData.json for each component.
|
|
202
|
-
*/
|
|
203
|
-
const getMotionVarPrefixes = (componentData, components) => {
|
|
204
|
-
const prefixes = components.flatMap((componentName) => {
|
|
205
|
-
return componentData[componentName]?.motionVarPrefixes ?? [];
|
|
206
|
-
});
|
|
207
|
-
return [...new Set(prefixes)];
|
|
208
|
-
};
|
|
209
|
-
/**
|
|
210
|
-
* Collect css variable names exposed by configurable properties.
|
|
211
|
-
*/
|
|
212
|
-
const getConfigurableCssVariables = () => {
|
|
213
|
-
const udsVarPrefix = "--uds";
|
|
214
|
-
const cssVars = Object.values(configurableProperties).flatMap(({ cssProperties }) => {
|
|
215
|
-
if (typeof cssProperties === "string") return cssProperties.startsWith(udsVarPrefix) ? [cssProperties] : [];
|
|
216
|
-
if (Array.isArray(cssProperties)) return cssProperties.filter((cssProperty) => typeof cssProperty === "string" && cssProperty.startsWith(udsVarPrefix));
|
|
217
|
-
return [];
|
|
218
|
-
});
|
|
219
|
-
return [...new Set(["--uds-button-gap", ...cssVars])];
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
//#endregion
|
|
223
|
-
export { extractVariantDefaults, findPackageSourceDir, formatBytes, getConfigurableCssVariables, getMotionVarPrefixes, loadConfigFile, scaffoldThemeConfig, scanDirectoryForSafelist };
|
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
-
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
let node_zlib = require("node:zlib");
|
|
4
|
-
let postcss = require("postcss");
|
|
5
|
-
postcss = require_runtime.__toESM(postcss);
|
|
6
|
-
|
|
7
|
-
//#region ../tailwind/dist/utils/optimizeCSS.js
|
|
8
|
-
/*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
|
|
9
|
-
/**
|
|
10
|
-
* Check if a selector is a "meaningful" selector (class, ID, attribute, or pseudo-class)
|
|
11
|
-
* as opposed to just element/type selectors (like `code, kbd, pre` in preflight).
|
|
12
|
-
* Meaningful selectors indicate the font is actually used by components, not just base reset.
|
|
13
|
-
*/
|
|
14
|
-
function isMeaningfulSelector(selector) {
|
|
15
|
-
const parts = selector.split(",").map((s) => s.trim());
|
|
16
|
-
for (const part of parts) if (part.includes(".") || part.includes("#") || part.includes("[") || part.includes(":not(") || part.includes(":where(") || part.includes(":is(") || part.includes(":has(")) return true;
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* PostCSS plugin to remove @font-face declarations for font families that are not used
|
|
21
|
-
* anywhere in the CSS (excluding preflight/reset styles that only use element selectors).
|
|
22
|
-
*/
|
|
23
|
-
function removeUnusedFontFaces() {
|
|
24
|
-
return {
|
|
25
|
-
postcssPlugin: "remove-unused-font-faces",
|
|
26
|
-
Once(root) {
|
|
27
|
-
const fontVarUsage = /* @__PURE__ */ new Map();
|
|
28
|
-
const usedFontFamilies = /* @__PURE__ */ new Set();
|
|
29
|
-
root.walkDecls("font-family", (decl) => {
|
|
30
|
-
if (decl.parent?.type === "atrule" && decl.parent.name === "font-face") return;
|
|
31
|
-
const meaningful = isMeaningfulSelector(decl.parent?.selector || "");
|
|
32
|
-
const value = decl.value;
|
|
33
|
-
const varMatches = value.matchAll(/var\(--uds-font-([^),]+)\)/g);
|
|
34
|
-
for (const match of varMatches) {
|
|
35
|
-
const varName = match[1];
|
|
36
|
-
const existing = fontVarUsage.get(varName) || {
|
|
37
|
-
used: false,
|
|
38
|
-
meaningful: false
|
|
39
|
-
};
|
|
40
|
-
fontVarUsage.set(varName, {
|
|
41
|
-
used: true,
|
|
42
|
-
meaningful: existing.meaningful || meaningful
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
if (meaningful) value.split(",").map((font) => font.trim()).map((font) => {
|
|
46
|
-
if (font.startsWith("\"") && font.endsWith("\"") || font.startsWith("'") && font.endsWith("'")) return font.slice(1, -1);
|
|
47
|
-
if (font.startsWith("var(") || [
|
|
48
|
-
"serif",
|
|
49
|
-
"sans-serif",
|
|
50
|
-
"monospace",
|
|
51
|
-
"cursive",
|
|
52
|
-
"fantasy",
|
|
53
|
-
"system-ui",
|
|
54
|
-
"ui-monospace",
|
|
55
|
-
"ui-serif",
|
|
56
|
-
"ui-sans-serif",
|
|
57
|
-
"ui-rounded"
|
|
58
|
-
].includes(font.toLowerCase())) return null;
|
|
59
|
-
return font;
|
|
60
|
-
}).filter(Boolean).forEach((name) => usedFontFamilies.add(name));
|
|
61
|
-
});
|
|
62
|
-
const fontVarDefinitions = /* @__PURE__ */ new Map();
|
|
63
|
-
root.walkDecls((decl) => {
|
|
64
|
-
if (decl.prop.startsWith("--uds-font-") && !decl.prop.includes("size") && !decl.prop.includes("weight") && !decl.prop.includes("slant") && !decl.prop.includes("width")) {
|
|
65
|
-
const varName = decl.prop.replace("--uds-font-", "");
|
|
66
|
-
fontVarDefinitions.set(varName, decl.value);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
const resolveToFontNames = (value, visited = /* @__PURE__ */ new Set()) => {
|
|
70
|
-
const fontNames = [];
|
|
71
|
-
const varMatch = value.match(/var\(--uds-font-([^),]+)\)/);
|
|
72
|
-
if (varMatch) {
|
|
73
|
-
const nestedVarName = varMatch[1];
|
|
74
|
-
if (!visited.has(nestedVarName)) {
|
|
75
|
-
visited.add(nestedVarName);
|
|
76
|
-
const nestedValue = fontVarDefinitions.get(nestedVarName);
|
|
77
|
-
if (nestedValue) {
|
|
78
|
-
const nestedUsage = fontVarUsage.get(nestedVarName);
|
|
79
|
-
if (nestedUsage) {
|
|
80
|
-
if (fontVarUsage.get(value.replace(/var\(--uds-font-([^),]+)\).*/, "$1"))?.meaningful) nestedUsage.meaningful = true;
|
|
81
|
-
}
|
|
82
|
-
fontNames.push(...resolveToFontNames(nestedValue, visited));
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
value.split(",").map((font) => font.trim()).forEach((font) => {
|
|
87
|
-
if (font.startsWith("var(")) return;
|
|
88
|
-
if (font.startsWith("\"") && font.endsWith("\"") || font.startsWith("'") && font.endsWith("'")) font = font.slice(1, -1);
|
|
89
|
-
if ([
|
|
90
|
-
"serif",
|
|
91
|
-
"sans-serif",
|
|
92
|
-
"monospace",
|
|
93
|
-
"cursive",
|
|
94
|
-
"fantasy",
|
|
95
|
-
"system-ui",
|
|
96
|
-
"ui-monospace",
|
|
97
|
-
"ui-serif",
|
|
98
|
-
"ui-sans-serif",
|
|
99
|
-
"ui-rounded"
|
|
100
|
-
].includes(font.toLowerCase())) return;
|
|
101
|
-
if (font) fontNames.push(font);
|
|
102
|
-
});
|
|
103
|
-
return fontNames;
|
|
104
|
-
};
|
|
105
|
-
for (const [varName, value] of fontVarDefinitions) {
|
|
106
|
-
const usage = fontVarUsage.get(varName);
|
|
107
|
-
if (usage?.used && usage?.meaningful) resolveToFontNames(value).forEach((name) => usedFontFamilies.add(name));
|
|
108
|
-
}
|
|
109
|
-
const keptFonts = /* @__PURE__ */ new Set();
|
|
110
|
-
root.walkAtRules("font-face", (atRule) => {
|
|
111
|
-
let fontFamily = null;
|
|
112
|
-
atRule.walkDecls("font-family", (decl) => {
|
|
113
|
-
fontFamily = decl.value.replace(/["']/g, "").trim();
|
|
114
|
-
});
|
|
115
|
-
if (fontFamily && !usedFontFamilies.has(fontFamily)) atRule.remove();
|
|
116
|
-
else if (fontFamily) keptFonts.add(fontFamily);
|
|
117
|
-
});
|
|
118
|
-
root.walkDecls((decl) => {
|
|
119
|
-
if (decl.prop.startsWith("--uds-font-") && !decl.prop.includes("size") && !decl.prop.includes("weight") && !decl.prop.includes("slant") && !decl.prop.includes("width")) {
|
|
120
|
-
const fonts = decl.value.split(",").map((f) => f.trim());
|
|
121
|
-
const filteredFonts = fonts.filter((font) => {
|
|
122
|
-
if (font.startsWith("var(")) return true;
|
|
123
|
-
let fontName = font;
|
|
124
|
-
if (font.startsWith("\"") && font.endsWith("\"") || font.startsWith("'") && font.endsWith("'")) fontName = font.slice(1, -1);
|
|
125
|
-
if ([
|
|
126
|
-
"serif",
|
|
127
|
-
"sans-serif",
|
|
128
|
-
"monospace",
|
|
129
|
-
"cursive",
|
|
130
|
-
"fantasy",
|
|
131
|
-
"system-ui",
|
|
132
|
-
"ui-monospace",
|
|
133
|
-
"ui-serif",
|
|
134
|
-
"ui-sans-serif",
|
|
135
|
-
"ui-rounded"
|
|
136
|
-
].includes(fontName.toLowerCase())) return true;
|
|
137
|
-
return keptFonts.has(fontName);
|
|
138
|
-
});
|
|
139
|
-
if (filteredFonts.length < fonts.length && filteredFonts.length > 0) decl.value = filteredFonts.join(", ");
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
removeUnusedFontFaces.postcss = true;
|
|
146
|
-
/**
|
|
147
|
-
* PostCSS plugin to remove redundant .uds-color-mode-light rules.
|
|
148
|
-
* Light mode is the default (set on :root), so the explicit class is unnecessary.
|
|
149
|
-
*/
|
|
150
|
-
function removeRedundantLightModePlugin() {
|
|
151
|
-
return {
|
|
152
|
-
postcssPlugin: "remove-redundant-light-mode",
|
|
153
|
-
Once(root) {
|
|
154
|
-
root.walkRules((rule) => {
|
|
155
|
-
const selectors = rule.selector.split(",").map((s) => s.trim());
|
|
156
|
-
const filteredSelectors = selectors.filter((s) => {
|
|
157
|
-
const normalized = s.replace(/\s+/g, " ").trim();
|
|
158
|
-
return normalized !== ".uds-color-mode-light" && normalized !== ":root .uds-color-mode-light" && normalized !== ":where(.uds-color-mode-light)" && normalized !== ":is(.uds-color-mode-light)";
|
|
159
|
-
});
|
|
160
|
-
if (filteredSelectors.length === 0) rule.remove();
|
|
161
|
-
else if (filteredSelectors.length < selectors.length) rule.selector = filteredSelectors.join(", ");
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
removeRedundantLightModePlugin.postcss = true;
|
|
167
|
-
/**
|
|
168
|
-
* PostCSS plugin to remove empty CSS rules (rules with no declarations).
|
|
169
|
-
* Also aggregates duplicate selectors.
|
|
170
|
-
*/
|
|
171
|
-
function removeEmptyRulesPlugin() {
|
|
172
|
-
return {
|
|
173
|
-
postcssPlugin: "remove-empty-rules",
|
|
174
|
-
Once(root) {
|
|
175
|
-
root.walkRules((rule) => {
|
|
176
|
-
if (!rule.nodes?.some((node) => node.type === "decl" || node.type === "rule" && node.nodes?.length > 0)) rule.remove();
|
|
177
|
-
});
|
|
178
|
-
root.walkAtRules((atRule) => {
|
|
179
|
-
if (atRule.name !== "font-face" && atRule.name !== "keyframes") {
|
|
180
|
-
if (!atRule.nodes?.some((node) => {
|
|
181
|
-
if (node.type === "rule") return node.nodes?.some((n) => n.type === "decl");
|
|
182
|
-
if (node.type === "decl") return true;
|
|
183
|
-
return false;
|
|
184
|
-
}) && atRule.nodes?.length === 0) atRule.remove();
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
removeEmptyRulesPlugin.postcss = true;
|
|
191
|
-
/**
|
|
192
|
-
* PostCSS plugin to aggregate rules with identical selectors.
|
|
193
|
-
*/
|
|
194
|
-
function aggregateDuplicateSelectorsPlugin() {
|
|
195
|
-
return {
|
|
196
|
-
postcssPlugin: "aggregate-duplicate-selectors",
|
|
197
|
-
Once(root) {
|
|
198
|
-
const selectorMap = /* @__PURE__ */ new Map();
|
|
199
|
-
const rulesToProcess = [];
|
|
200
|
-
root.walkRules((rule) => {
|
|
201
|
-
if (rule.parent?.type === "root" || rule.parent?.type === "atrule") rulesToProcess.push(rule);
|
|
202
|
-
});
|
|
203
|
-
for (const rule of rulesToProcess) {
|
|
204
|
-
const selector = rule.selector;
|
|
205
|
-
const parent = rule.parent;
|
|
206
|
-
const key = `${parent?.type === "atrule" ? `@${parent.name}:${parent.params}` : "root"}|${selector}`;
|
|
207
|
-
if (selectorMap.has(key)) {
|
|
208
|
-
const existingRule = selectorMap.get(key);
|
|
209
|
-
rule.walkDecls((decl) => {
|
|
210
|
-
const existingDecl = existingRule.nodes?.find((node) => node.type === "decl" && node.prop === decl.prop);
|
|
211
|
-
if (existingDecl) existingDecl.value = decl.value;
|
|
212
|
-
else existingRule.append(decl.clone());
|
|
213
|
-
});
|
|
214
|
-
rule.remove();
|
|
215
|
-
} else selectorMap.set(key, rule);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
aggregateDuplicateSelectorsPlugin.postcss = true;
|
|
221
|
-
/**
|
|
222
|
-
* Validates CSS syntax and returns any errors found.
|
|
223
|
-
*/
|
|
224
|
-
function validateCSS(css) {
|
|
225
|
-
const errors = [];
|
|
226
|
-
try {
|
|
227
|
-
const result = postcss.default.parse(css);
|
|
228
|
-
result.walkRules((rule) => {
|
|
229
|
-
if (!rule.selector.trim()) errors.push(`Empty selector found at line ${rule.source?.start?.line}`);
|
|
230
|
-
try {
|
|
231
|
-
if (rule.selector.includes("{{") || rule.selector.includes("}}")) errors.push(`Malformed selector "${rule.selector}" at line ${rule.source?.start?.line}`);
|
|
232
|
-
} catch {
|
|
233
|
-
errors.push(`Invalid selector "${rule.selector}" at line ${rule.source?.start?.line}`);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
result.walkDecls((decl) => {
|
|
237
|
-
if (!decl.value.trim()) errors.push(`Empty value for property "${decl.prop}" at line ${decl.source?.start?.line}`);
|
|
238
|
-
});
|
|
239
|
-
return {
|
|
240
|
-
valid: errors.length === 0,
|
|
241
|
-
errors
|
|
242
|
-
};
|
|
243
|
-
} catch (error) {
|
|
244
|
-
if (error instanceof Error) errors.push(`CSS Parse Error: ${error.message}`);
|
|
245
|
-
else errors.push("Unknown CSS parse error");
|
|
246
|
-
return {
|
|
247
|
-
valid: false,
|
|
248
|
-
errors
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Create a fingerprint for a @font-face rule
|
|
254
|
-
*/
|
|
255
|
-
function getFontFaceFingerprint(atRule) {
|
|
256
|
-
let fontFamily = "";
|
|
257
|
-
let src = "";
|
|
258
|
-
let fontWeight = "normal";
|
|
259
|
-
let fontStyle = "normal";
|
|
260
|
-
atRule.walkDecls((decl) => {
|
|
261
|
-
if (decl.prop === "font-family") fontFamily = decl.value.replace(/["']/g, "").trim();
|
|
262
|
-
else if (decl.prop === "src") src = decl.value;
|
|
263
|
-
else if (decl.prop === "font-weight") fontWeight = decl.value;
|
|
264
|
-
else if (decl.prop === "font-style") fontStyle = decl.value;
|
|
265
|
-
});
|
|
266
|
-
return JSON.stringify({
|
|
267
|
-
fontFamily,
|
|
268
|
-
src,
|
|
269
|
-
fontWeight,
|
|
270
|
-
fontStyle
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Create a fingerprint for a @keyframes rule
|
|
275
|
-
*/
|
|
276
|
-
function getKeyframesFingerprint(atRule) {
|
|
277
|
-
const name = atRule.params;
|
|
278
|
-
const content = atRule.toString().replace(/\s+/g, " ").trim();
|
|
279
|
-
return JSON.stringify({
|
|
280
|
-
name,
|
|
281
|
-
content
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Normalize a selector by removing scope prefix and whitespace
|
|
286
|
-
*/
|
|
287
|
-
function normalizeSelector(selector, scopeClass) {
|
|
288
|
-
let normalized = selector.trim();
|
|
289
|
-
if (scopeClass) {
|
|
290
|
-
const escapedScope = scopeClass.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
291
|
-
normalized = normalized.replace(new RegExp(`${escapedScope}\\s+`, "g"), "").replace(new RegExp(`${escapedScope}\\.`, "g"), ".").replace(new RegExp(`${escapedScope}`, "g"), "");
|
|
292
|
-
}
|
|
293
|
-
return normalized.replace(/\s+/g, " ").trim();
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Create a fingerprint for a CSS rule (selector + declarations)
|
|
297
|
-
*/
|
|
298
|
-
function getRuleFingerprint(rule, scopeClass) {
|
|
299
|
-
const selector = normalizeSelector(rule.selector, scopeClass);
|
|
300
|
-
const declarations = [];
|
|
301
|
-
rule.walkDecls((decl) => {
|
|
302
|
-
declarations.push(`${decl.prop}:${decl.value}`);
|
|
303
|
-
});
|
|
304
|
-
declarations.sort();
|
|
305
|
-
return JSON.stringify({
|
|
306
|
-
selector,
|
|
307
|
-
declarations
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Extract reference data from CSS for deduplication
|
|
312
|
-
*/
|
|
313
|
-
function extractCSSReferenceData(css, scopeClass) {
|
|
314
|
-
const data = {
|
|
315
|
-
fontFaces: /* @__PURE__ */ new Set(),
|
|
316
|
-
keyframes: /* @__PURE__ */ new Set(),
|
|
317
|
-
rules: /* @__PURE__ */ new Set()
|
|
318
|
-
};
|
|
319
|
-
try {
|
|
320
|
-
const root = postcss.default.parse(css);
|
|
321
|
-
root.walkAtRules((atRule) => {
|
|
322
|
-
if (atRule.name === "font-face") data.fontFaces.add(getFontFaceFingerprint(atRule));
|
|
323
|
-
else if (atRule.name === "keyframes" || atRule.name === "-webkit-keyframes") data.keyframes.add(getKeyframesFingerprint(atRule));
|
|
324
|
-
});
|
|
325
|
-
root.walkRules((rule) => {
|
|
326
|
-
if (rule.parent?.type === "atrule") {
|
|
327
|
-
const parentName = rule.parent.name;
|
|
328
|
-
if (parentName === "font-face" || parentName === "keyframes" || parentName === "-webkit-keyframes") return;
|
|
329
|
-
}
|
|
330
|
-
data.rules.add(getRuleFingerprint(rule, scopeClass));
|
|
331
|
-
});
|
|
332
|
-
} catch {}
|
|
333
|
-
return data;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* PostCSS plugin to remove CSS that exists in reference CSS
|
|
337
|
-
* Handles @font-face, @keyframes, and regular rule deduplication
|
|
338
|
-
*/
|
|
339
|
-
function removeDuplicateCss(referenceData, scopeClass) {
|
|
340
|
-
return {
|
|
341
|
-
postcssPlugin: "remove-duplicate-css",
|
|
342
|
-
Once(root) {
|
|
343
|
-
const toRemove = [];
|
|
344
|
-
root.walkAtRules((atRule) => {
|
|
345
|
-
if (atRule.name === "font-face") {
|
|
346
|
-
const fingerprint = getFontFaceFingerprint(atRule);
|
|
347
|
-
if (referenceData.fontFaces.has(fingerprint)) toRemove.push(atRule);
|
|
348
|
-
} else if (atRule.name === "keyframes" || atRule.name === "-webkit-keyframes") {
|
|
349
|
-
const fingerprint = getKeyframesFingerprint(atRule);
|
|
350
|
-
if (referenceData.keyframes.has(fingerprint)) toRemove.push(atRule);
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
root.walkRules((rule) => {
|
|
354
|
-
if (rule.parent?.type === "atrule") {
|
|
355
|
-
const parentName = rule.parent.name;
|
|
356
|
-
if (parentName === "font-face" || parentName === "keyframes" || parentName === "-webkit-keyframes") return;
|
|
357
|
-
}
|
|
358
|
-
const fingerprint = getRuleFingerprint(rule, scopeClass);
|
|
359
|
-
if (referenceData.rules.has(fingerprint)) toRemove.push(rule);
|
|
360
|
-
});
|
|
361
|
-
for (const node of toRemove) node.remove();
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Optimizes CSS by:
|
|
367
|
-
* 1. Removing unused @font-face declarations
|
|
368
|
-
* 2. Removing empty rules
|
|
369
|
-
* 3. Aggregating duplicate selectors
|
|
370
|
-
*
|
|
371
|
-
* Returns the optimized CSS and validation results.
|
|
372
|
-
*/
|
|
373
|
-
async function optimizeCSS(css, options) {
|
|
374
|
-
const originalSize = Buffer.byteLength(css, "utf8");
|
|
375
|
-
const originalSizeGzip = (0, node_zlib.gzipSync)(css).length;
|
|
376
|
-
const fontFacesBefore = (css.match(/@font-face/g) || []).length;
|
|
377
|
-
const rulesBefore = (css.match(/\{[^}]*\}/g) || []).length;
|
|
378
|
-
const plugins = [];
|
|
379
|
-
if (options?.removeUnusedFonts !== false) plugins.push(removeUnusedFontFaces());
|
|
380
|
-
plugins.push(removeRedundantLightModePlugin());
|
|
381
|
-
if (options?.referenceCss) {
|
|
382
|
-
const referenceData = extractCSSReferenceData(options.referenceCss);
|
|
383
|
-
if (referenceData.fontFaces.size > 0 || referenceData.keyframes.size > 0 || referenceData.rules.size > 0) plugins.push(removeDuplicateCss(referenceData, options.scopeClass));
|
|
384
|
-
}
|
|
385
|
-
if (options?.removeEmptyRules !== false) plugins.push(removeEmptyRulesPlugin());
|
|
386
|
-
if (options?.aggregateDuplicateSelectors !== false) plugins.push(aggregateDuplicateSelectorsPlugin());
|
|
387
|
-
const optimizedCSS = (plugins.length > 0 ? await (0, postcss.default)(plugins).process(css, { from: void 0 }) : { css }).css;
|
|
388
|
-
const optimizedSize = Buffer.byteLength(optimizedCSS, "utf8");
|
|
389
|
-
const fontFacesAfter = (optimizedCSS.match(/@font-face/g) || []).length;
|
|
390
|
-
const rulesAfter = (optimizedCSS.match(/\{[^}]*\}/g) || []).length;
|
|
391
|
-
return {
|
|
392
|
-
css: optimizedCSS,
|
|
393
|
-
validation: validateCSS(optimizedCSS),
|
|
394
|
-
stats: {
|
|
395
|
-
originalSize,
|
|
396
|
-
originalSizeGzip,
|
|
397
|
-
optimizedSize,
|
|
398
|
-
fontFacesRemoved: fontFacesBefore - fontFacesAfter,
|
|
399
|
-
emptyRulesRemoved: Math.max(0, rulesBefore - rulesAfter)
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
//#endregion
|
|
405
|
-
exports.optimizeCSS = optimizeCSS;
|