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