@yahoo/uds 3.114.0 → 3.115.0-beta.2
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/mapTextVariantFixtureToValue.cjs +12 -1
- package/dist/automated-config/dist/mapTextVariantFixtureToValue.js +12 -1
- package/dist/automated-config/dist/properties.cjs +1 -1
- package/dist/automated-config/dist/properties.js +1 -1
- package/dist/cli/commands/sync.cjs +1 -3
- package/dist/cli/commands/sync.d.cts +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +1 -3
- package/dist/cli/commands/version.cjs +0 -2
- package/dist/cli/commands/version.d.cts +1 -1
- package/dist/cli/commands/version.d.ts +1 -1
- package/dist/cli/commands/version.js +0 -2
- package/dist/cli/dist/commands/editor-rules.cjs +1 -1
- package/dist/cli/dist/commands/editor-rules.js +1 -1
- package/dist/cli/dist/lib/logger.cjs +66 -0
- package/dist/cli/dist/lib/logger.js +66 -0
- package/dist/cli/runner.cjs +9 -0
- package/dist/cli/runner.js +9 -0
- package/dist/components/client/Menu/Menu.ItemCheckbox.d.cts +1 -1
- package/dist/components/client/Menu/Menu.ItemCheckbox.d.ts +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/styles/styler.d.cts +29 -29
- package/dist/styles/styler.d.ts +29 -29
- package/dist/styles/variants.cjs +278 -278
- package/dist/styles/variants.js +278 -278
- package/dist/tailwind/dist/commands/css.cjs +79 -0
- package/dist/tailwind/dist/commands/css.helpers.cjs +32 -0
- package/dist/tailwind/dist/commands/css.helpers.js +28 -0
- package/dist/tailwind/dist/commands/css.js +79 -0
- package/dist/tailwind/dist/commands/generateComponentData.cjs +33 -31
- package/dist/tailwind/dist/commands/generateComponentData.d.ts +1 -1
- package/dist/tailwind/dist/commands/generateComponentData.js +33 -31
- package/dist/tailwind/dist/commands/purge.cjs +3 -4
- package/dist/tailwind/dist/commands/purge.js +3 -4
- package/dist/tailwind/dist/css/generate.cjs +121 -0
- package/dist/tailwind/dist/css/generate.d.cts +30 -0
- package/dist/tailwind/dist/css/generate.d.ts +31 -0
- package/dist/tailwind/dist/css/generate.helpers.cjs +112 -0
- package/dist/tailwind/dist/css/generate.helpers.js +100 -0
- package/dist/tailwind/dist/css/generate.js +116 -0
- package/dist/tailwind/dist/css/nodeUtils.cjs +156 -0
- package/dist/tailwind/dist/css/nodeUtils.js +149 -0
- package/dist/tailwind/dist/css/postcss.cjs +35 -0
- package/dist/tailwind/dist/css/postcss.helpers.cjs +27 -0
- package/dist/tailwind/dist/css/postcss.helpers.js +26 -0
- package/dist/tailwind/dist/css/postcss.js +35 -0
- package/dist/tailwind/dist/css/runner.cjs +279 -0
- package/dist/tailwind/dist/css/runner.helpers.cjs +26 -0
- package/dist/tailwind/dist/css/runner.helpers.js +23 -0
- package/dist/tailwind/dist/css/runner.js +276 -0
- package/dist/tailwind/dist/css/theme.cjs +12 -0
- package/dist/tailwind/dist/css/theme.d.cts +66 -0
- package/dist/tailwind/dist/css/theme.d.ts +66 -0
- package/dist/tailwind/dist/css/theme.js +11 -0
- package/dist/tailwind/dist/css/utils.cjs +72 -0
- package/dist/tailwind/dist/css/utils.js +69 -0
- package/dist/tailwind/dist/index.d.cts +1 -0
- package/dist/tailwind/dist/index.d.ts +2 -4
- package/dist/tailwind/dist/purger/legacy/purgeCSS.cjs +2 -1
- package/dist/tailwind/dist/purger/legacy/purgeCSS.js +2 -1
- package/dist/tailwind/dist/purger/optimized/ast/expressions.cjs +122 -125
- package/dist/tailwind/dist/purger/optimized/ast/expressions.js +122 -125
- package/dist/tailwind/dist/purger/optimized/ast/jsx.cjs +1 -8
- package/dist/tailwind/dist/purger/optimized/ast/jsx.js +1 -8
- package/dist/tailwind/dist/purger/optimized/purge.cjs +9 -8
- package/dist/tailwind/dist/purger/optimized/purge.js +9 -8
- package/dist/tailwind/dist/purger/optimized/purgeFromCode.cjs +238 -127
- package/dist/tailwind/dist/purger/optimized/purgeFromCode.js +238 -127
- package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.cjs +352 -260
- package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js +351 -260
- package/dist/tailwind/dist/purger/optimized/utils/files.cjs +4 -3
- package/dist/tailwind/dist/purger/optimized/utils/files.js +4 -3
- package/dist/tailwind/dist/purger/optimized/utils/safelist.cjs +12 -20
- package/dist/tailwind/dist/purger/optimized/utils/safelist.js +12 -20
- package/dist/tailwind/dist/tailwind/components/getResponsiveTextStyles.cjs +1 -1
- package/dist/tailwind/dist/tailwind/components/getResponsiveTextStyles.js +1 -1
- package/dist/tailwind/dist/tailwind/plugins/breakpoints.cjs +1 -1
- package/dist/tailwind/dist/tailwind/plugins/breakpoints.js +1 -1
- package/dist/tailwind/dist/tailwind/plugins/typography.cjs +41 -13
- package/dist/tailwind/dist/tailwind/plugins/typography.js +41 -13
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.cjs +4 -2
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.d.cts +10 -1
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.d.ts +10 -1
- package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.js +4 -2
- package/dist/tailwind/dist/utils/optimizeCSS.cjs +405 -0
- package/dist/tailwind/dist/utils/optimizeCSS.js +403 -0
- package/dist/tailwind/dist/utils/postcssPreserveVars.cjs +67 -0
- package/dist/tailwind/dist/utils/postcssPreserveVars.js +65 -0
- package/dist/tailwind/dist/utils/tsMorph.cjs +1 -1
- package/dist/uds/generated/componentData.cjs +1218 -1182
- package/dist/uds/generated/componentData.js +1218 -1182
- package/dist/uds/package.cjs +10 -4
- package/dist/uds/package.js +10 -4
- package/generated/componentData.json +2683 -0
- package/generated/tailwindPurge.ts +4591 -0
- package/package.json +7 -4
- package/dist/tailwind/dist/commands/generatePurgeCSSData.d.ts +0 -3
- package/dist/tailwind/dist/commands/purge.d.ts +0 -4
- package/dist/tailwind/dist/purger/legacy/purgeCSS.d.ts +0 -2
|
@@ -3,7 +3,10 @@ const require_runtime = require('../../../../../_virtual/_rolldown/runtime.cjs')
|
|
|
3
3
|
const require_index = require('../../../../../motion-tokens/dist/index.cjs');
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
node_path = require_runtime.__toESM(node_path);
|
|
6
|
+
let node_fs = require("node:fs");
|
|
6
7
|
let ts_morph = require("ts-morph");
|
|
8
|
+
let fast_glob = require("fast-glob");
|
|
9
|
+
fast_glob = require_runtime.__toESM(fast_glob);
|
|
7
10
|
|
|
8
11
|
//#region ../tailwind/dist/purger/optimized/utils/componentAnalyzer.js
|
|
9
12
|
/*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
|
|
@@ -15,27 +18,31 @@ let knownComponents = null;
|
|
|
15
18
|
* Map of component name -> file path
|
|
16
19
|
*/
|
|
17
20
|
let componentPaths = null;
|
|
21
|
+
let scannedComponentsDir = null;
|
|
22
|
+
const scanComponentFilePaths = async (componentsDir) => (0, fast_glob.default)("**/*.tsx", {
|
|
23
|
+
cwd: componentsDir,
|
|
24
|
+
absolute: true
|
|
25
|
+
});
|
|
18
26
|
/**
|
|
19
27
|
* Scan src/components to build a map of all component files
|
|
20
28
|
*/
|
|
21
|
-
async
|
|
22
|
-
if (componentPaths) return componentPaths;
|
|
29
|
+
const scanComponentFiles = async (componentsDir) => {
|
|
30
|
+
if (componentPaths && scannedComponentsDir === componentsDir) return componentPaths;
|
|
23
31
|
componentPaths = /* @__PURE__ */ new Map();
|
|
24
32
|
knownComponents = /* @__PURE__ */ new Set();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (file.includes(".test.") || file.endsWith("index.tsx")) continue;
|
|
33
|
+
scannedComponentsDir = componentsDir;
|
|
34
|
+
const nextComponentPaths = componentPaths;
|
|
35
|
+
const nextKnownComponents = knownComponents;
|
|
36
|
+
(await scanComponentFilePaths(componentsDir)).forEach((file) => {
|
|
37
|
+
if (file.includes(".test.") || file.endsWith("index.tsx")) return;
|
|
31
38
|
const fileName = node_path.default.basename(file, ".tsx");
|
|
32
39
|
if (/^[A-Z]/.test(fileName)) {
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
nextComponentPaths.set(fileName, file);
|
|
41
|
+
nextKnownComponents.add(fileName);
|
|
35
42
|
}
|
|
36
|
-
}
|
|
37
|
-
return
|
|
38
|
-
}
|
|
43
|
+
});
|
|
44
|
+
return nextComponentPaths;
|
|
45
|
+
};
|
|
39
46
|
/**
|
|
40
47
|
* Analyze an object literal for variant key mappings.
|
|
41
48
|
* Handles:
|
|
@@ -43,60 +50,64 @@ async function scanComponentFiles(componentsDir) {
|
|
|
43
50
|
* - Nullish coalescing: { fontSize: fontSize ?? variant } -> variant maps to fontSize
|
|
44
51
|
* - Conditional spreads: ...(condition ? { props } : {}) -> recursively analyze props
|
|
45
52
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (initializer && ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
|
|
52
|
-
if (initializer && ts_morph.Node.isIdentifier(initializer)) {
|
|
53
|
-
const propName = initializer.getText();
|
|
54
|
-
const existing = propToVariantKeys.get(propName) ?? [];
|
|
55
|
-
if (!existing.includes(variantKey)) {
|
|
56
|
-
existing.push(variantKey);
|
|
57
|
-
propToVariantKeys.set(propName, existing);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (initializer && ts_morph.Node.isBinaryExpression(initializer)) {
|
|
61
|
-
const operatorToken = initializer.getOperatorToken();
|
|
62
|
-
if (operatorToken.getKind() === ts_morph.SyntaxKind.QuestionQuestionToken || operatorToken.getKind() === ts_morph.SyntaxKind.BarBarToken) {
|
|
63
|
-
const rightSide = initializer.getRight();
|
|
64
|
-
if (ts_morph.Node.isIdentifier(rightSide)) {
|
|
65
|
-
const fallbackPropName = rightSide.getText();
|
|
66
|
-
const existing = propToVariantKeys.get(fallbackPropName) ?? [];
|
|
67
|
-
if (!existing.includes(variantKey)) {
|
|
68
|
-
existing.push(variantKey);
|
|
69
|
-
propToVariantKeys.set(fallbackPropName, existing);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
53
|
+
const analyzeObjectForVariantMappings = (objLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
|
|
54
|
+
objLiteral.getProperties().forEach((prop) => {
|
|
55
|
+
if (ts_morph.Node.isPropertyAssignment(prop)) {
|
|
56
|
+
analyzeVariantPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys);
|
|
57
|
+
return;
|
|
73
58
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
59
|
+
if (ts_morph.Node.isSpreadAssignment(prop)) analyzeVariantSpreadAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const addStyleProp = (styleProps, variantKey) => {
|
|
63
|
+
if (!styleProps.includes(variantKey)) styleProps.push(variantKey);
|
|
64
|
+
};
|
|
65
|
+
const addPropToVariantKeyMapping = (propToVariantKeys, propName, variantKey) => {
|
|
66
|
+
const existing = propToVariantKeys.get(propName) ?? [];
|
|
67
|
+
if (!existing.includes(variantKey)) propToVariantKeys.set(propName, [...existing, variantKey]);
|
|
68
|
+
};
|
|
69
|
+
const extractFallbackIdentifier = (initializer) => {
|
|
70
|
+
if (!ts_morph.Node.isBinaryExpression(initializer)) return null;
|
|
71
|
+
const operatorKind = initializer.getOperatorToken().getKind();
|
|
72
|
+
if (!(operatorKind === ts_morph.SyntaxKind.QuestionQuestionToken || operatorKind === ts_morph.SyntaxKind.BarBarToken) || !ts_morph.Node.isIdentifier(initializer.getRight())) return null;
|
|
73
|
+
return initializer.getRight().getText();
|
|
74
|
+
};
|
|
75
|
+
const analyzeVariantPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys) => {
|
|
76
|
+
const variantKey = prop.getName();
|
|
77
|
+
addStyleProp(styleProps, variantKey);
|
|
78
|
+
const initializer = prop.getInitializer();
|
|
79
|
+
if (!initializer) return;
|
|
80
|
+
if (ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
|
|
81
|
+
if (ts_morph.Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
|
|
82
|
+
const fallbackIdentifier = extractFallbackIdentifier(initializer);
|
|
83
|
+
if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
|
|
84
|
+
};
|
|
85
|
+
const findVariableObjectLiteral = (sourceFile, variableName) => {
|
|
86
|
+
const initializer = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((candidate) => candidate.getName() === variableName)?.getInitializer();
|
|
87
|
+
return initializer && ts_morph.Node.isObjectLiteralExpression(initializer) ? initializer : null;
|
|
88
|
+
};
|
|
89
|
+
const analyzeVariantSpreadAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
|
|
90
|
+
const spreadExpr = prop.getExpression();
|
|
91
|
+
if (ts_morph.Node.isParenthesizedExpression(spreadExpr)) {
|
|
92
|
+
const conditionalExpr = spreadExpr.getExpression();
|
|
93
|
+
if (ts_morph.Node.isConditionalExpression(conditionalExpr)) {
|
|
94
|
+
const whenTrue = conditionalExpr.getWhenTrue();
|
|
95
|
+
if (!ts_morph.Node.isObjectLiteralExpression(whenTrue)) return;
|
|
96
|
+
analyzeObjectForVariantMappings(whenTrue, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
|
-
|
|
99
|
+
if (ts_morph.Node.isIdentifier(spreadExpr)) {
|
|
100
|
+
const objectLiteral = findVariableObjectLiteral(sourceFile, spreadExpr.getText());
|
|
101
|
+
if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
93
104
|
/**
|
|
94
105
|
* Analyzes a UDS component file to extract:
|
|
95
106
|
* 1. Default prop values (e.g., display = 'flex')
|
|
96
107
|
* 2. Props passed to getStyles()
|
|
97
108
|
* 3. Internal UDS component usage
|
|
98
109
|
*/
|
|
99
|
-
|
|
110
|
+
const analyzeComponent = (project, componentPath) => {
|
|
100
111
|
const sourceFile = project.getSourceFile(componentPath);
|
|
101
112
|
if (!sourceFile) return null;
|
|
102
113
|
const componentName = node_path.default.basename(componentPath, ".tsx");
|
|
@@ -108,98 +119,10 @@ function analyzeComponent(project, componentPath) {
|
|
|
108
119
|
const internalComponents = [];
|
|
109
120
|
const internalComponentProps = /* @__PURE__ */ new Map();
|
|
110
121
|
const propToVariantKeys = /* @__PURE__ */ new Map();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
for (const fn of functions) {
|
|
116
|
-
if (ts_morph.Node.isVariableDeclaration(fn)) {
|
|
117
|
-
const init = fn.getInitializer();
|
|
118
|
-
if (!init) continue;
|
|
119
|
-
if (ts_morph.Node.isCallExpression(init)) {
|
|
120
|
-
const args = init.getArguments();
|
|
121
|
-
for (const arg of args) if (ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) {
|
|
122
|
-
extractDefaultsFromFunction(arg, defaultProps);
|
|
123
|
-
extractAllPropNames(arg, componentPropNames);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (ts_morph.Node.isArrowFunction(init)) {
|
|
127
|
-
extractDefaultsFromFunction(init, defaultProps);
|
|
128
|
-
extractAllPropNames(init, componentPropNames);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
if (ts_morph.Node.isFunctionDeclaration(fn)) {
|
|
132
|
-
extractDefaultsFromFunction(fn, defaultProps);
|
|
133
|
-
extractAllPropNames(fn, componentPropNames);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
const getStylesCalls = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles");
|
|
137
|
-
for (const call of getStylesCalls) {
|
|
138
|
-
const args = call.getArguments();
|
|
139
|
-
if (args.length > 0 && ts_morph.Node.isObjectLiteralExpression(args[0])) {
|
|
140
|
-
const objLiteral = args[0];
|
|
141
|
-
for (const prop of objLiteral.getProperties()) if (ts_morph.Node.isPropertyAssignment(prop)) {
|
|
142
|
-
const variantKey = prop.getName();
|
|
143
|
-
if (variantKey && !styleProps.includes(variantKey)) styleProps.push(variantKey);
|
|
144
|
-
const initializer = prop.getInitializer();
|
|
145
|
-
if (initializer && ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
|
|
146
|
-
if (initializer && ts_morph.Node.isIdentifier(initializer)) {
|
|
147
|
-
const propName = initializer.getText();
|
|
148
|
-
const existing = propToVariantKeys.get(propName) ?? [];
|
|
149
|
-
if (!existing.includes(variantKey)) {
|
|
150
|
-
existing.push(variantKey);
|
|
151
|
-
propToVariantKeys.set(propName, existing);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (initializer && ts_morph.Node.isBinaryExpression(initializer)) {
|
|
155
|
-
const operatorToken = initializer.getOperatorToken();
|
|
156
|
-
if (operatorToken.getKind() === ts_morph.SyntaxKind.QuestionQuestionToken || operatorToken.getKind() === ts_morph.SyntaxKind.BarBarToken) {
|
|
157
|
-
const rightSide = initializer.getRight();
|
|
158
|
-
if (ts_morph.Node.isIdentifier(rightSide)) {
|
|
159
|
-
const fallbackPropName = rightSide.getText();
|
|
160
|
-
const existing = propToVariantKeys.get(fallbackPropName) ?? [];
|
|
161
|
-
if (!existing.includes(variantKey)) {
|
|
162
|
-
existing.push(variantKey);
|
|
163
|
-
propToVariantKeys.set(fallbackPropName, existing);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (initializer && ts_morph.Node.isConditionalExpression(initializer)) {
|
|
169
|
-
const whenTrue = initializer.getWhenTrue();
|
|
170
|
-
const whenFalse = initializer.getWhenFalse();
|
|
171
|
-
const extractLiterals = (node) => {
|
|
172
|
-
const literals = [];
|
|
173
|
-
if (ts_morph.Node.isStringLiteral(node)) literals.push(node.getLiteralValue());
|
|
174
|
-
else if (ts_morph.Node.isConditionalExpression(node)) {
|
|
175
|
-
literals.push(...extractLiterals(node.getWhenTrue()));
|
|
176
|
-
literals.push(...extractLiterals(node.getWhenFalse()));
|
|
177
|
-
}
|
|
178
|
-
return literals;
|
|
179
|
-
};
|
|
180
|
-
[...extractLiterals(whenTrue), ...extractLiterals(whenFalse)].forEach((value, index) => {
|
|
181
|
-
const literalKey = index === 0 ? variantKey : `${variantKey}:${index}`;
|
|
182
|
-
getStylesLiterals.set(literalKey, value);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
} else if (ts_morph.Node.isShorthandPropertyAssignment(prop)) {
|
|
186
|
-
const propName = prop.getName();
|
|
187
|
-
if (propName && !styleProps.includes(propName)) styleProps.push(propName);
|
|
188
|
-
} else if (ts_morph.Node.isSpreadAssignment(prop)) {
|
|
189
|
-
const spreadExpr = prop.getExpression();
|
|
190
|
-
if (ts_morph.Node.isIdentifier(spreadExpr)) {
|
|
191
|
-
const varName = spreadExpr.getText();
|
|
192
|
-
const varDecl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((v) => v.getName() === varName);
|
|
193
|
-
if (varDecl) {
|
|
194
|
-
const varInit = varDecl.getInitializer();
|
|
195
|
-
if (varInit && ts_morph.Node.isObjectLiteralExpression(varInit)) analyzeObjectForVariantMappings(varInit, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
const cxCalls = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "cx");
|
|
202
|
-
for (const call of cxCalls) for (const arg of call.getArguments()) extractCxStringLiterals(arg, cxLiterals);
|
|
122
|
+
collectComponentDefaultsAndProps(sourceFile, defaultProps, componentPropNames);
|
|
123
|
+
collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys);
|
|
124
|
+
collectCxLiterals(sourceFile, cxLiterals);
|
|
125
|
+
collectIntrinsicClassNameLiterals(sourceFile, cxLiterals);
|
|
203
126
|
extractInternalComponents(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentPropNames);
|
|
204
127
|
return {
|
|
205
128
|
name: componentName,
|
|
@@ -213,96 +136,217 @@ function analyzeComponent(project, componentPath) {
|
|
|
213
136
|
propToVariantKeys,
|
|
214
137
|
motionVarPrefixes: extractMotionVarPrefixes(sourceFile)
|
|
215
138
|
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
139
|
+
};
|
|
140
|
+
const getComponentFunctionNodes = (sourceFile) => [...sourceFile.getFunctions(), ...sourceFile.getVariableDeclarations().filter((declaration) => {
|
|
141
|
+
const initializer = declaration.getInitializer();
|
|
142
|
+
return initializer && (ts_morph.Node.isArrowFunction(initializer) || ts_morph.Node.isCallExpression(initializer));
|
|
143
|
+
})];
|
|
144
|
+
const collectComponentDefaultsAndProps = (sourceFile, defaultProps, componentPropNames) => {
|
|
145
|
+
getComponentFunctionNodes(sourceFile).forEach((fn) => {
|
|
146
|
+
if (ts_morph.Node.isFunctionDeclaration(fn)) {
|
|
147
|
+
extractDefaultsFromFunction(fn, defaultProps);
|
|
148
|
+
extractAllPropNames(fn, componentPropNames);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (!ts_morph.Node.isVariableDeclaration(fn)) return;
|
|
152
|
+
const initializer = fn.getInitializer();
|
|
153
|
+
if (!initializer) return;
|
|
154
|
+
if (ts_morph.Node.isCallExpression(initializer)) initializer.getArguments().forEach((arg) => {
|
|
155
|
+
if (ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) {
|
|
156
|
+
extractDefaultsFromFunction(arg, defaultProps);
|
|
157
|
+
extractAllPropNames(arg, componentPropNames);
|
|
228
158
|
}
|
|
159
|
+
});
|
|
160
|
+
if (ts_morph.Node.isArrowFunction(initializer)) {
|
|
161
|
+
extractDefaultsFromFunction(initializer, defaultProps);
|
|
162
|
+
extractAllPropNames(initializer, componentPropNames);
|
|
229
163
|
}
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
const extractConditionalStringLiterals = (node) => {
|
|
167
|
+
if (ts_morph.Node.isStringLiteral(node)) return [node.getLiteralValue()];
|
|
168
|
+
if (ts_morph.Node.isConditionalExpression(node)) return [...extractConditionalStringLiterals(node.getWhenTrue()), ...extractConditionalStringLiterals(node.getWhenFalse())];
|
|
169
|
+
return [];
|
|
170
|
+
};
|
|
171
|
+
const storeVariantLiteralValues = (variantKey, literalValues, getStylesLiterals) => {
|
|
172
|
+
literalValues.forEach((value, index) => {
|
|
173
|
+
const literalKey = index === 0 ? variantKey : `${variantKey}:${index}`;
|
|
174
|
+
getStylesLiterals.set(literalKey, value);
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys) => {
|
|
178
|
+
const variantKey = prop.getName();
|
|
179
|
+
addStyleProp(styleProps, variantKey);
|
|
180
|
+
const initializer = prop.getInitializer();
|
|
181
|
+
if (!initializer) return;
|
|
182
|
+
if (ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
|
|
183
|
+
if (ts_morph.Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
|
|
184
|
+
const fallbackIdentifier = extractFallbackIdentifier(initializer);
|
|
185
|
+
if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
|
|
186
|
+
if (ts_morph.Node.isConditionalExpression(initializer)) storeVariantLiteralValues(variantKey, [...extractConditionalStringLiterals(initializer.getWhenTrue()), ...extractConditionalStringLiterals(initializer.getWhenFalse())], getStylesLiterals);
|
|
187
|
+
};
|
|
188
|
+
const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
|
|
189
|
+
if (ts_morph.Node.isPropertyAssignment(prop)) {
|
|
190
|
+
handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (ts_morph.Node.isShorthandPropertyAssignment(prop)) {
|
|
194
|
+
addStyleProp(styleProps, prop.getName());
|
|
195
|
+
return;
|
|
230
196
|
}
|
|
231
|
-
|
|
232
|
-
|
|
197
|
+
if (ts_morph.Node.isSpreadAssignment(prop) && ts_morph.Node.isIdentifier(prop.getExpression())) {
|
|
198
|
+
const objectLiteral = findVariableObjectLiteral(sourceFile, prop.getExpression().getText());
|
|
199
|
+
if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys) => {
|
|
203
|
+
sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles").forEach((call) => {
|
|
204
|
+
const args = call.getArguments();
|
|
205
|
+
if (args.length === 0 || !ts_morph.Node.isObjectLiteralExpression(args[0])) return;
|
|
206
|
+
args[0].getProperties().forEach((prop) => {
|
|
207
|
+
handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
};
|
|
211
|
+
const collectCxLiterals = (sourceFile, cxLiterals) => {
|
|
212
|
+
sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "cx").forEach((call) => {
|
|
213
|
+
call.getArguments().forEach((arg) => extractCxStringLiterals(arg, cxLiterals));
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
const pushUniqueClasses = (target, rawValue) => {
|
|
217
|
+
rawValue.split(/\s+/).filter(Boolean).forEach((className) => {
|
|
218
|
+
if (!target.includes(className)) target.push(className);
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
const collectIntrinsicClassNameLiterals = (sourceFile, cxLiterals) => {
|
|
222
|
+
[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
|
|
233
223
|
const tagName = element.getTagNameNode().getText();
|
|
234
|
-
if (!/^[
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
for (const attr of attrs) if (ts_morph.Node.isJsxAttribute(attr)) {
|
|
238
|
-
const propName = attr.getNameNode().getText();
|
|
224
|
+
if (!/^[a-z]/.test(tagName)) return;
|
|
225
|
+
element.getAttributes().forEach((attr) => {
|
|
226
|
+
if (!ts_morph.Node.isJsxAttribute(attr) || attr.getNameNode().getText() !== "className") return;
|
|
239
227
|
const initializer = attr.getInitializer();
|
|
240
|
-
|
|
241
|
-
if (initializer) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const expr = initializer.getExpression();
|
|
245
|
-
if (expr && ts_morph.Node.isStringLiteral(expr)) values = [expr.getLiteralValue()];
|
|
246
|
-
else if (expr && ts_morph.Node.isIdentifier(expr)) {
|
|
247
|
-
const identifierName = expr.getText();
|
|
248
|
-
if (componentProps.has(identifierName) && identifierName !== propName) {
|
|
249
|
-
const existing = propToVariantKeys.get(identifierName) ?? [];
|
|
250
|
-
if (!existing.includes(propName)) {
|
|
251
|
-
existing.push(propName);
|
|
252
|
-
propToVariantKeys.set(identifierName, existing);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
228
|
+
if (!initializer) return;
|
|
229
|
+
if (ts_morph.Node.isStringLiteral(initializer)) {
|
|
230
|
+
pushUniqueClasses(cxLiterals, initializer.getLiteralValue());
|
|
231
|
+
return;
|
|
257
232
|
}
|
|
258
|
-
if (
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
233
|
+
if (!ts_morph.Node.isJsxExpression(initializer)) return;
|
|
234
|
+
const expr = initializer.getExpression();
|
|
235
|
+
if (expr && ts_morph.Node.isStringLiteral(expr)) pushUniqueClasses(cxLiterals, expr.getLiteralValue());
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Extract UDS components used internally in the file and their prop values.
|
|
241
|
+
* Also detects prop aliasing (e.g., columnGap={gap} means gap -> columnGap).
|
|
242
|
+
*/
|
|
243
|
+
const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
|
|
244
|
+
collectImportedInternalComponents(sourceFile, internalComponents);
|
|
245
|
+
collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps);
|
|
246
|
+
};
|
|
247
|
+
const isInternalUdsModule = (moduleSpec) => {
|
|
248
|
+
return (moduleSpec.startsWith("@yahoo/uds") || moduleSpec.startsWith("../") || moduleSpec.startsWith("./")) && (moduleSpec.includes("/components/") || moduleSpec === "@yahoo/uds");
|
|
249
|
+
};
|
|
250
|
+
const pushUniqueComponentName = (components, name) => {
|
|
251
|
+
if (/^[A-Z]/.test(name) && !components.includes(name)) components.push(name);
|
|
252
|
+
};
|
|
253
|
+
const collectImportedInternalComponents = (sourceFile, internalComponents) => {
|
|
254
|
+
sourceFile.getImportDeclarations().forEach((importDecl) => {
|
|
255
|
+
if (!isInternalUdsModule(importDecl.getModuleSpecifierValue())) return;
|
|
256
|
+
importDecl.getNamedImports().forEach((namedImport) => pushUniqueComponentName(internalComponents, namedImport.getName()));
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
const getOrCreateComponentPropsMap = (internalComponentProps, componentName) => {
|
|
260
|
+
const existing = internalComponentProps.get(componentName);
|
|
261
|
+
if (existing) return existing;
|
|
262
|
+
const created = /* @__PURE__ */ new Map();
|
|
263
|
+
internalComponentProps.set(componentName, created);
|
|
264
|
+
return created;
|
|
265
|
+
};
|
|
266
|
+
const extractJsxAttributeLiteralValues = (attr, componentProps, propToVariantKeys) => {
|
|
267
|
+
if (!ts_morph.Node.isJsxAttribute(attr)) return null;
|
|
268
|
+
const propName = attr.getNameNode().getText();
|
|
269
|
+
const initializer = attr.getInitializer();
|
|
270
|
+
if (!initializer) return {
|
|
271
|
+
propName,
|
|
272
|
+
values: []
|
|
273
|
+
};
|
|
274
|
+
if (ts_morph.Node.isStringLiteral(initializer)) return {
|
|
275
|
+
propName,
|
|
276
|
+
values: [initializer.getLiteralValue()]
|
|
277
|
+
};
|
|
278
|
+
if (!ts_morph.Node.isJsxExpression(initializer)) return {
|
|
279
|
+
propName,
|
|
280
|
+
values: []
|
|
281
|
+
};
|
|
282
|
+
const expr = initializer.getExpression();
|
|
283
|
+
if (expr && ts_morph.Node.isStringLiteral(expr)) return {
|
|
284
|
+
propName,
|
|
285
|
+
values: [expr.getLiteralValue()]
|
|
286
|
+
};
|
|
287
|
+
if (expr && ts_morph.Node.isIdentifier(expr)) {
|
|
288
|
+
const identifierName = expr.getText();
|
|
289
|
+
if (componentProps.has(identifierName) && identifierName !== propName) addPropToVariantKeyMapping(propToVariantKeys, identifierName, propName);
|
|
269
290
|
}
|
|
270
|
-
|
|
291
|
+
return {
|
|
292
|
+
propName,
|
|
293
|
+
values: []
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
|
|
297
|
+
[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
|
|
298
|
+
const tagName = element.getTagNameNode().getText();
|
|
299
|
+
if (!/^[A-Z]/.test(tagName)) return;
|
|
300
|
+
pushUniqueComponentName(internalComponents, tagName);
|
|
301
|
+
element.getAttributes().forEach((attr) => {
|
|
302
|
+
const extracted = extractJsxAttributeLiteralValues(attr, componentProps, propToVariantKeys);
|
|
303
|
+
if (!extracted || extracted.values.length === 0) return;
|
|
304
|
+
const componentPropsMap = getOrCreateComponentPropsMap(internalComponentProps, tagName);
|
|
305
|
+
const existingValues = componentPropsMap.get(extracted.propName) ?? [];
|
|
306
|
+
const mergedValues = [...new Set([...existingValues, ...extracted.values])];
|
|
307
|
+
componentPropsMap.set(extracted.propName, mergedValues);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
};
|
|
271
311
|
/**
|
|
272
312
|
* Extract default prop values from a function's parameter destructuring
|
|
273
313
|
*/
|
|
274
|
-
|
|
314
|
+
const extractDefaultsFromFunction = (fn, defaults) => {
|
|
275
315
|
let params = [];
|
|
276
316
|
if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
|
|
277
317
|
else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
|
|
278
|
-
|
|
279
|
-
if (!ts_morph.Node.isParameterDeclaration(param))
|
|
318
|
+
params.forEach((param) => {
|
|
319
|
+
if (!ts_morph.Node.isParameterDeclaration(param)) return;
|
|
280
320
|
const nameNode = param.getNameNode();
|
|
281
|
-
if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode))
|
|
282
|
-
|
|
321
|
+
if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) return;
|
|
322
|
+
nameNode.getElements().forEach((element) => {
|
|
283
323
|
const propName = element.getPropertyNameNode()?.getText() || element.getName();
|
|
284
324
|
const initializer = element.getInitializer();
|
|
285
325
|
if (initializer && ts_morph.Node.isStringLiteral(initializer)) defaults.set(propName, initializer.getLiteralValue());
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
326
|
+
else if (initializer && ts_morph.Node.isIdentifier(initializer)) {
|
|
327
|
+
const resolved = resolveIdentifierToStringLiteral(initializer);
|
|
328
|
+
if (resolved) defaults.set(propName, resolved);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
};
|
|
289
333
|
/**
|
|
290
334
|
* Extract ALL prop names from a function's parameter destructuring (not just defaults)
|
|
291
335
|
*/
|
|
292
|
-
|
|
336
|
+
const extractAllPropNames = (fn, propNames) => {
|
|
293
337
|
let params = [];
|
|
294
338
|
if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
|
|
295
339
|
else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
|
|
296
|
-
|
|
297
|
-
if (!ts_morph.Node.isParameterDeclaration(param))
|
|
340
|
+
params.forEach((param) => {
|
|
341
|
+
if (!ts_morph.Node.isParameterDeclaration(param)) return;
|
|
298
342
|
const nameNode = param.getNameNode();
|
|
299
|
-
if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode))
|
|
300
|
-
|
|
343
|
+
if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) return;
|
|
344
|
+
nameNode.getElements().forEach((element) => {
|
|
301
345
|
const propName = element.getPropertyNameNode()?.getText() || element.getName();
|
|
302
346
|
propNames.add(propName);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
};
|
|
306
350
|
/**
|
|
307
351
|
* Extract string literals from cx() call arguments.
|
|
308
352
|
* Handles:
|
|
@@ -310,22 +354,25 @@ function extractAllPropNames(fn, propNames) {
|
|
|
310
354
|
* - Object keys: cx({ 'class1': condition, 'class2': true })
|
|
311
355
|
* - Nested calls and arrays
|
|
312
356
|
*/
|
|
313
|
-
|
|
314
|
-
if (ts_morph.Node.isStringLiteral(node)) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
357
|
+
const extractCxStringLiterals = (node, literals) => {
|
|
358
|
+
if (ts_morph.Node.isStringLiteral(node)) node.getLiteralValue().split(/\s+/).filter(Boolean).forEach((cls) => {
|
|
359
|
+
if (!literals.includes(cls)) literals.push(cls);
|
|
360
|
+
});
|
|
361
|
+
else if (ts_morph.Node.isObjectLiteralExpression(node)) node.getProperties().forEach((prop) => {
|
|
362
|
+
if (ts_morph.Node.isPropertyAssignment(prop)) {
|
|
319
363
|
const nameNode = prop.getNameNode();
|
|
320
|
-
if (ts_morph.Node.isStringLiteral(nameNode)) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
364
|
+
if (ts_morph.Node.isStringLiteral(nameNode)) nameNode.getLiteralValue().split(/\s+/).filter(Boolean).forEach((cls) => {
|
|
365
|
+
if (!literals.includes(cls)) literals.push(cls);
|
|
366
|
+
});
|
|
367
|
+
else if (ts_morph.Node.isIdentifier(nameNode)) {
|
|
324
368
|
const cls = nameNode.getText();
|
|
325
369
|
if (!literals.includes(cls)) literals.push(cls);
|
|
326
370
|
}
|
|
327
371
|
}
|
|
328
|
-
}
|
|
372
|
+
});
|
|
373
|
+
else if (ts_morph.Node.isArrayLiteralExpression(node)) node.getElements().forEach((element) => {
|
|
374
|
+
extractCxStringLiterals(element, literals);
|
|
375
|
+
});
|
|
329
376
|
else if (ts_morph.Node.isConditionalExpression(node)) {
|
|
330
377
|
extractCxStringLiterals(node.getWhenTrue(), literals);
|
|
331
378
|
extractCxStringLiterals(node.getWhenFalse(), literals);
|
|
@@ -333,59 +380,54 @@ function extractCxStringLiterals(node, literals) {
|
|
|
333
380
|
extractCxStringLiterals(node.getLeft(), literals);
|
|
334
381
|
extractCxStringLiterals(node.getRight(), literals);
|
|
335
382
|
}
|
|
336
|
-
}
|
|
383
|
+
};
|
|
337
384
|
/**
|
|
338
385
|
* Try to resolve an identifier to its initializer value (for const declarations)
|
|
339
386
|
*/
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
387
|
+
const resolveIdentifierToObject = (sourceFile, identifier) => {
|
|
388
|
+
const decl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((candidate) => candidate.getName() === identifier);
|
|
389
|
+
if (!decl) return null;
|
|
390
|
+
let initializer = decl.getInitializer();
|
|
391
|
+
if (!initializer) return null;
|
|
392
|
+
if (ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
|
|
393
|
+
if (!ts_morph.Node.isObjectLiteralExpression(initializer)) return null;
|
|
394
|
+
const result = {};
|
|
395
|
+
initializer.getProperties().forEach((prop) => {
|
|
396
|
+
if (!ts_morph.Node.isPropertyAssignment(prop)) return;
|
|
397
|
+
const propName = prop.getName();
|
|
398
|
+
const propInit = prop.getInitializer();
|
|
399
|
+
if (propInit && ts_morph.Node.isStringLiteral(propInit)) result[propName] = propInit.getLiteralValue();
|
|
400
|
+
});
|
|
401
|
+
return result;
|
|
402
|
+
};
|
|
359
403
|
/**
|
|
360
404
|
* Extract motion CSS variable prefixes from SpringMotionConfig usage.
|
|
361
405
|
* Returns prefixes like ['--uds-motion-bouncy-4-', '--uds-motion-smooth-3-']
|
|
362
406
|
*/
|
|
363
|
-
|
|
407
|
+
const extractMotionVarPrefixes = (sourceFile) => {
|
|
364
408
|
const prefixes = [];
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if (element.getTagNameNode().getText() !== "SpringMotionConfig") continue;
|
|
409
|
+
[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
|
|
410
|
+
if (element.getTagNameNode().getText() !== "SpringMotionConfig") return;
|
|
368
411
|
const props = {
|
|
369
412
|
layoutVariant: null,
|
|
370
413
|
layoutSpeed: null,
|
|
371
414
|
colorVariant: null,
|
|
372
415
|
colorSpeed: null
|
|
373
416
|
};
|
|
374
|
-
|
|
375
|
-
for (const attr of attrs) {
|
|
417
|
+
element.getAttributes().forEach((attr) => {
|
|
376
418
|
if (ts_morph.Node.isJsxSpreadAttribute(attr)) {
|
|
377
419
|
const expr = attr.getExpression();
|
|
378
420
|
if (ts_morph.Node.isIdentifier(expr)) {
|
|
379
421
|
const spreadObj = resolveIdentifierToObject(sourceFile, expr.getText());
|
|
380
|
-
if (spreadObj) {
|
|
381
|
-
|
|
382
|
-
}
|
|
422
|
+
if (spreadObj) Object.keys(props).forEach((key) => {
|
|
423
|
+
if (key in spreadObj) props[key] = spreadObj[key];
|
|
424
|
+
});
|
|
383
425
|
}
|
|
384
|
-
|
|
426
|
+
return;
|
|
385
427
|
}
|
|
386
|
-
if (!ts_morph.Node.isJsxAttribute(attr))
|
|
428
|
+
if (!ts_morph.Node.isJsxAttribute(attr)) return;
|
|
387
429
|
const propName = attr.getNameNode().getText();
|
|
388
|
-
if (!(propName in props))
|
|
430
|
+
if (!(propName in props)) return;
|
|
389
431
|
const initializer = attr.getInitializer();
|
|
390
432
|
if (initializer) {
|
|
391
433
|
if (ts_morph.Node.isStringLiteral(initializer)) props[propName] = initializer.getLiteralValue();
|
|
@@ -394,14 +436,64 @@ function extractMotionVarPrefixes(sourceFile) {
|
|
|
394
436
|
if (expr && ts_morph.Node.isStringLiteral(expr)) props[propName] = expr.getLiteralValue();
|
|
395
437
|
}
|
|
396
438
|
}
|
|
397
|
-
}
|
|
439
|
+
});
|
|
398
440
|
const layoutPrefix = `--uds-motion-${props.layoutVariant ?? require_index.SPRING_MOTION_DEFAULTS.layoutVariant}-${props.layoutSpeed ?? require_index.SPRING_MOTION_DEFAULTS.layoutSpeed}-`;
|
|
399
441
|
if (!prefixes.includes(layoutPrefix)) prefixes.push(layoutPrefix);
|
|
400
442
|
const colorPrefix = `--uds-motion-${props.colorVariant ?? require_index.SPRING_MOTION_DEFAULTS.colorVariant}-${props.colorSpeed ?? require_index.SPRING_MOTION_DEFAULTS.colorSpeed}-`;
|
|
401
443
|
if (!prefixes.includes(colorPrefix)) prefixes.push(colorPrefix);
|
|
402
|
-
}
|
|
444
|
+
});
|
|
403
445
|
return prefixes;
|
|
404
|
-
}
|
|
446
|
+
};
|
|
447
|
+
const resolveIdentifierToStringLiteral = (identifier) => {
|
|
448
|
+
if (!ts_morph.Node.isIdentifier(identifier)) return null;
|
|
449
|
+
const symbol = identifier.getSymbol();
|
|
450
|
+
if (!symbol) return resolveImportedIdentifier(identifier);
|
|
451
|
+
const resolvedDeclarationValue = symbol.getDeclarations().reduce((resolved, declaration) => {
|
|
452
|
+
if (resolved) return resolved;
|
|
453
|
+
if (ts_morph.Node.isVariableDeclaration(declaration)) {
|
|
454
|
+
let initializer = declaration.getInitializer();
|
|
455
|
+
if (initializer && ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
|
|
456
|
+
if (initializer && ts_morph.Node.isStringLiteral(initializer)) return initializer.getLiteralValue();
|
|
457
|
+
}
|
|
458
|
+
if (ts_morph.Node.isEnumMember(declaration)) {
|
|
459
|
+
const initializer = declaration.getInitializer();
|
|
460
|
+
if (initializer && ts_morph.Node.isStringLiteral(initializer)) return initializer.getLiteralValue();
|
|
461
|
+
}
|
|
462
|
+
}, void 0);
|
|
463
|
+
if (resolvedDeclarationValue) return resolvedDeclarationValue;
|
|
464
|
+
return resolveImportedIdentifier(identifier);
|
|
465
|
+
};
|
|
466
|
+
const resolveImportedIdentifier = (identifier) => {
|
|
467
|
+
if (!ts_morph.Node.isIdentifier(identifier)) return null;
|
|
468
|
+
const name = identifier.getText();
|
|
469
|
+
const sourceFile = identifier.getSourceFile();
|
|
470
|
+
const project = sourceFile.getProject();
|
|
471
|
+
const baseDir = node_path.default.dirname(sourceFile.getFilePath());
|
|
472
|
+
const importResolution = sourceFile.getImportDeclarations().reduce((resolvedImport, importDecl) => {
|
|
473
|
+
if (resolvedImport) return resolvedImport;
|
|
474
|
+
if (!importDecl.getNamedImports().find((n) => n.getName() === name)) return;
|
|
475
|
+
const moduleSpec = importDecl.getModuleSpecifierValue();
|
|
476
|
+
if (!moduleSpec.startsWith(".")) return;
|
|
477
|
+
const resolvedBase = node_path.default.resolve(baseDir, moduleSpec);
|
|
478
|
+
return [
|
|
479
|
+
resolvedBase,
|
|
480
|
+
`${resolvedBase}.ts`,
|
|
481
|
+
`${resolvedBase}.tsx`
|
|
482
|
+
].reduce((resolvedCandidate, candidate) => {
|
|
483
|
+
if (resolvedCandidate) return resolvedCandidate;
|
|
484
|
+
if (!(0, node_fs.existsSync)(candidate)) return;
|
|
485
|
+
const importedFile = project.addSourceFileAtPathIfExists(candidate);
|
|
486
|
+
if (!importedFile) return;
|
|
487
|
+
const varDecl = importedFile.getVariableDeclaration(name);
|
|
488
|
+
if (!varDecl) return;
|
|
489
|
+
let initializer = varDecl.getInitializer();
|
|
490
|
+
if (initializer && ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
|
|
491
|
+
return initializer && ts_morph.Node.isStringLiteral(initializer) ? initializer.getLiteralValue() : void 0;
|
|
492
|
+
}, void 0);
|
|
493
|
+
}, void 0);
|
|
494
|
+
if (importResolution) return importResolution;
|
|
495
|
+
return null;
|
|
496
|
+
};
|
|
405
497
|
|
|
406
498
|
//#endregion
|
|
407
499
|
exports.analyzeComponent = analyzeComponent;
|