@yahoo/uds 3.171.0 → 3.172.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/utils/getConfigVariantProperties.d.cts +2 -2
- package/dist/automated-config/dist/utils/getConfigVariantProperties.d.ts +2 -2
- package/dist/css/dist/css/purgeWorker.js +50 -0
- package/dist/css/dist/css/runner.cjs +3 -1
- package/dist/css/dist/css/runner.js +3 -1
- package/dist/css/dist/css/workerPool.cjs +18 -2
- package/dist/css/dist/css/workerPool.js +16 -1
- package/dist/css/dist/purger/optimized/ast/expressions.cjs +278 -278
- package/dist/css/dist/purger/optimized/ast/expressions.js +278 -278
- package/dist/css/dist/purger/optimized/ast/jsx.cjs +67 -36
- package/dist/css/dist/purger/optimized/ast/jsx.js +67 -35
- package/dist/css/dist/purger/optimized/ast/oxc.cjs +265 -0
- package/dist/css/dist/purger/optimized/ast/oxc.js +253 -0
- package/dist/css/dist/purger/optimized/ast/props.cjs +21 -15
- package/dist/css/dist/purger/optimized/ast/props.js +21 -14
- package/dist/css/dist/purger/optimized/ast/spread.cjs +19 -19
- package/dist/css/dist/purger/optimized/ast/spread.js +19 -18
- package/dist/css/dist/purger/optimized/purgeFromCode.cjs +86 -101
- package/dist/css/dist/purger/optimized/purgeFromCode.js +86 -100
- package/dist/tailwind-internal/dist/utils/getShadowStyles.d.cts +2 -2
- package/dist/tailwind-internal/dist/utils/getShadowStyles.d.ts +2 -2
- package/dist/tailwind-v3/dist/purger/legacy/purgeCSS.cjs +1 -1
- package/dist/tailwind-v3/dist/purger/legacy/purgeCSS.js +1 -1
- package/dist/uds/generated/componentData.cjs +273 -273
- package/dist/uds/generated/componentData.js +273 -273
- package/dist/uds/package.cjs +2 -0
- package/dist/uds/package.js +2 -0
- package/generated/componentData.json +419 -419
- package/package.json +3 -1
|
@@ -1,40 +1,46 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
-
require("
|
|
3
|
-
let ts_morph = require("ts-morph");
|
|
2
|
+
const require_oxc = require("./oxc.cjs");
|
|
4
3
|
//#region ../css/dist/purger/optimized/ast/jsx.mjs
|
|
5
4
|
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
6
5
|
/**
|
|
7
6
|
* Check if an expression is using React.forwardRef
|
|
8
7
|
*/
|
|
9
|
-
const isForwardRefExpression = (node) => {
|
|
10
|
-
if (
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
13
|
-
if (
|
|
8
|
+
const isForwardRefExpression = (node, source) => {
|
|
9
|
+
if (node.type !== "CallExpression") return false;
|
|
10
|
+
const callee = node.callee;
|
|
11
|
+
if (callee.type === "Identifier" && callee.name === "forwardRef") return true;
|
|
12
|
+
if (callee.type === "MemberExpression" && !callee.computed && require_oxc.getText(source, callee) === "React.forwardRef") return true;
|
|
14
13
|
return false;
|
|
15
14
|
};
|
|
15
|
+
const getDeclarationName = (node, source) => {
|
|
16
|
+
if (node.type === "VariableDeclarator") return node.id.type === "Identifier" ? node.id.name : void 0;
|
|
17
|
+
if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") return node.id?.name;
|
|
18
|
+
if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
|
|
19
|
+
let current = require_oxc.getParent(source, node);
|
|
20
|
+
while (current && current.type !== "VariableDeclarator") current = require_oxc.getParent(source, current);
|
|
21
|
+
return current && current.id.type === "Identifier" ? current.id.name : void 0;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
16
24
|
/**
|
|
17
25
|
* Check if a node is a JSX component (PascalCase name)
|
|
18
26
|
*/
|
|
19
|
-
const isJsxComponent = (node) => {
|
|
20
|
-
|
|
21
|
-
if (ts_morph.Node.isVariableDeclaration(node) || ts_morph.Node.isFunctionDeclaration(node) || ts_morph.Node.isClassDeclaration(node)) name = node.getName();
|
|
22
|
-
else if (ts_morph.Node.isFunctionExpression(node) || ts_morph.Node.isArrowFunction(node)) name = node.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration)?.getName();
|
|
27
|
+
const isJsxComponent = (node, source) => {
|
|
28
|
+
const name = getDeclarationName(node, source);
|
|
23
29
|
return name ? /^[A-Z]/.test(name) : false;
|
|
24
30
|
};
|
|
25
31
|
/**
|
|
26
32
|
* Get the function declaration from a component, unwrapping forwardRef if needed
|
|
27
33
|
*/
|
|
28
|
-
const getReactFunctionDeclaration = (declaration) => {
|
|
29
|
-
if (!isJsxComponent(declaration)) return null;
|
|
30
|
-
if (
|
|
31
|
-
if (
|
|
32
|
-
const initializer = declaration.
|
|
34
|
+
const getReactFunctionDeclaration = (declaration, source) => {
|
|
35
|
+
if (!isJsxComponent(declaration, source)) return null;
|
|
36
|
+
if (declaration.type === "FunctionDeclaration") return declaration;
|
|
37
|
+
if (declaration.type === "VariableDeclarator") {
|
|
38
|
+
const initializer = declaration.init;
|
|
33
39
|
if (!initializer) return null;
|
|
34
|
-
if (isForwardRefExpression(initializer)) {
|
|
35
|
-
const [arg] = initializer.
|
|
36
|
-
if (
|
|
37
|
-
} else if (
|
|
40
|
+
if (initializer.type === "CallExpression" && isForwardRefExpression(initializer, source)) {
|
|
41
|
+
const [arg] = initializer.arguments;
|
|
42
|
+
if (arg && (arg.type === "FunctionExpression" || arg.type === "ArrowFunctionExpression")) return arg;
|
|
43
|
+
} else if (initializer.type === "FunctionExpression" || initializer.type === "ArrowFunctionExpression") return initializer;
|
|
38
44
|
}
|
|
39
45
|
return null;
|
|
40
46
|
};
|
|
@@ -42,27 +48,30 @@ const getReactFunctionDeclaration = (declaration) => {
|
|
|
42
48
|
* Get the parent component that contains a JSX reference.
|
|
43
49
|
* Returns information about the component including spread rest identifier.
|
|
44
50
|
*/
|
|
45
|
-
const getParentComponentInfo = (reference) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
const getParentComponentInfo = (reference, source) => {
|
|
52
|
+
let block = reference;
|
|
53
|
+
let parent = require_oxc.getParent(source, block);
|
|
54
|
+
while (parent && !getReactFunctionDeclaration(parent, source)) {
|
|
55
|
+
block = parent;
|
|
56
|
+
parent = require_oxc.getParent(source, block);
|
|
57
|
+
}
|
|
58
|
+
if (!parent) return;
|
|
59
|
+
const reactComponent = getReactFunctionDeclaration(parent, source);
|
|
51
60
|
if (!reactComponent) return;
|
|
52
61
|
let componentName;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
let ancestor = require_oxc.getParent(source, reactComponent);
|
|
63
|
+
while (ancestor && ancestor.type !== "VariableDeclarator") ancestor = require_oxc.getParent(source, ancestor);
|
|
64
|
+
if (ancestor && ancestor.id.type === "Identifier") componentName = ancestor.id.name;
|
|
65
|
+
else if (reactComponent.type === "FunctionDeclaration") componentName = reactComponent.id?.name;
|
|
56
66
|
if (!componentName) return;
|
|
57
67
|
let spreadRestIdentifier;
|
|
58
68
|
let paramIdentifier;
|
|
59
|
-
reactComponent.
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
} else if (identifier) paramIdentifier = identifier.getText();
|
|
69
|
+
reactComponent.params.forEach((parameter) => {
|
|
70
|
+
const pattern = parameter.type === "AssignmentPattern" ? parameter.left : parameter;
|
|
71
|
+
if (pattern.type === "ObjectPattern") {
|
|
72
|
+
const restIdentifier = findFirstRestIdentifier(pattern);
|
|
73
|
+
if (restIdentifier) spreadRestIdentifier = restIdentifier;
|
|
74
|
+
} else if (pattern.type === "Identifier") paramIdentifier = pattern.name;
|
|
66
75
|
});
|
|
67
76
|
return {
|
|
68
77
|
componentName,
|
|
@@ -70,5 +79,27 @@ const getParentComponentInfo = (reference) => {
|
|
|
70
79
|
paramIdentifier
|
|
71
80
|
};
|
|
72
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* Find the first rest element identifier in a binding pattern, in document
|
|
84
|
+
* order (mirrors ts-morph's first `DotDotDotToken` descendant lookup).
|
|
85
|
+
*/
|
|
86
|
+
const findFirstRestIdentifier = (pattern) => {
|
|
87
|
+
if (pattern.type === "ObjectPattern") {
|
|
88
|
+
for (const property of pattern.properties) {
|
|
89
|
+
if (property.type === "RestElement") return property.argument.type === "Identifier" ? property.argument.name : void 0;
|
|
90
|
+
if (property.type === "Property") {
|
|
91
|
+
const nested = findFirstRestIdentifier(property.value.type === "AssignmentPattern" ? property.value.left : property.value);
|
|
92
|
+
if (nested) return nested;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (pattern.type === "ArrayPattern") for (const element of pattern.elements) {
|
|
98
|
+
if (!element) continue;
|
|
99
|
+
if (element.type === "RestElement") return element.argument.type === "Identifier" ? element.argument.name : void 0;
|
|
100
|
+
const nested = findFirstRestIdentifier(element.type === "AssignmentPattern" ? element.left : element);
|
|
101
|
+
if (nested) return nested;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
73
104
|
//#endregion
|
|
74
105
|
exports.getParentComponentInfo = getParentComponentInfo;
|
|
@@ -1,39 +1,46 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
-
import {
|
|
2
|
+
import { getParent, getText } from "./oxc.js";
|
|
3
3
|
//#region ../css/dist/purger/optimized/ast/jsx.mjs
|
|
4
4
|
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
5
5
|
/**
|
|
6
6
|
* Check if an expression is using React.forwardRef
|
|
7
7
|
*/
|
|
8
|
-
const isForwardRefExpression = (node) => {
|
|
9
|
-
if (
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
if (
|
|
8
|
+
const isForwardRefExpression = (node, source) => {
|
|
9
|
+
if (node.type !== "CallExpression") return false;
|
|
10
|
+
const callee = node.callee;
|
|
11
|
+
if (callee.type === "Identifier" && callee.name === "forwardRef") return true;
|
|
12
|
+
if (callee.type === "MemberExpression" && !callee.computed && getText(source, callee) === "React.forwardRef") return true;
|
|
13
13
|
return false;
|
|
14
14
|
};
|
|
15
|
+
const getDeclarationName = (node, source) => {
|
|
16
|
+
if (node.type === "VariableDeclarator") return node.id.type === "Identifier" ? node.id.name : void 0;
|
|
17
|
+
if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") return node.id?.name;
|
|
18
|
+
if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
|
|
19
|
+
let current = getParent(source, node);
|
|
20
|
+
while (current && current.type !== "VariableDeclarator") current = getParent(source, current);
|
|
21
|
+
return current && current.id.type === "Identifier" ? current.id.name : void 0;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
15
24
|
/**
|
|
16
25
|
* Check if a node is a JSX component (PascalCase name)
|
|
17
26
|
*/
|
|
18
|
-
const isJsxComponent = (node) => {
|
|
19
|
-
|
|
20
|
-
if (Node.isVariableDeclaration(node) || Node.isFunctionDeclaration(node) || Node.isClassDeclaration(node)) name = node.getName();
|
|
21
|
-
else if (Node.isFunctionExpression(node) || Node.isArrowFunction(node)) name = node.getFirstAncestorByKind(SyntaxKind.VariableDeclaration)?.getName();
|
|
27
|
+
const isJsxComponent = (node, source) => {
|
|
28
|
+
const name = getDeclarationName(node, source);
|
|
22
29
|
return name ? /^[A-Z]/.test(name) : false;
|
|
23
30
|
};
|
|
24
31
|
/**
|
|
25
32
|
* Get the function declaration from a component, unwrapping forwardRef if needed
|
|
26
33
|
*/
|
|
27
|
-
const getReactFunctionDeclaration = (declaration) => {
|
|
28
|
-
if (!isJsxComponent(declaration)) return null;
|
|
29
|
-
if (
|
|
30
|
-
if (
|
|
31
|
-
const initializer = declaration.
|
|
34
|
+
const getReactFunctionDeclaration = (declaration, source) => {
|
|
35
|
+
if (!isJsxComponent(declaration, source)) return null;
|
|
36
|
+
if (declaration.type === "FunctionDeclaration") return declaration;
|
|
37
|
+
if (declaration.type === "VariableDeclarator") {
|
|
38
|
+
const initializer = declaration.init;
|
|
32
39
|
if (!initializer) return null;
|
|
33
|
-
if (isForwardRefExpression(initializer)) {
|
|
34
|
-
const [arg] = initializer.
|
|
35
|
-
if (
|
|
36
|
-
} else if (
|
|
40
|
+
if (initializer.type === "CallExpression" && isForwardRefExpression(initializer, source)) {
|
|
41
|
+
const [arg] = initializer.arguments;
|
|
42
|
+
if (arg && (arg.type === "FunctionExpression" || arg.type === "ArrowFunctionExpression")) return arg;
|
|
43
|
+
} else if (initializer.type === "FunctionExpression" || initializer.type === "ArrowFunctionExpression") return initializer;
|
|
37
44
|
}
|
|
38
45
|
return null;
|
|
39
46
|
};
|
|
@@ -41,27 +48,30 @@ const getReactFunctionDeclaration = (declaration) => {
|
|
|
41
48
|
* Get the parent component that contains a JSX reference.
|
|
42
49
|
* Returns information about the component including spread rest identifier.
|
|
43
50
|
*/
|
|
44
|
-
const getParentComponentInfo = (reference) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
const getParentComponentInfo = (reference, source) => {
|
|
52
|
+
let block = reference;
|
|
53
|
+
let parent = getParent(source, block);
|
|
54
|
+
while (parent && !getReactFunctionDeclaration(parent, source)) {
|
|
55
|
+
block = parent;
|
|
56
|
+
parent = getParent(source, block);
|
|
57
|
+
}
|
|
58
|
+
if (!parent) return;
|
|
59
|
+
const reactComponent = getReactFunctionDeclaration(parent, source);
|
|
50
60
|
if (!reactComponent) return;
|
|
51
61
|
let componentName;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
let ancestor = getParent(source, reactComponent);
|
|
63
|
+
while (ancestor && ancestor.type !== "VariableDeclarator") ancestor = getParent(source, ancestor);
|
|
64
|
+
if (ancestor && ancestor.id.type === "Identifier") componentName = ancestor.id.name;
|
|
65
|
+
else if (reactComponent.type === "FunctionDeclaration") componentName = reactComponent.id?.name;
|
|
55
66
|
if (!componentName) return;
|
|
56
67
|
let spreadRestIdentifier;
|
|
57
68
|
let paramIdentifier;
|
|
58
|
-
reactComponent.
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} else if (identifier) paramIdentifier = identifier.getText();
|
|
69
|
+
reactComponent.params.forEach((parameter) => {
|
|
70
|
+
const pattern = parameter.type === "AssignmentPattern" ? parameter.left : parameter;
|
|
71
|
+
if (pattern.type === "ObjectPattern") {
|
|
72
|
+
const restIdentifier = findFirstRestIdentifier(pattern);
|
|
73
|
+
if (restIdentifier) spreadRestIdentifier = restIdentifier;
|
|
74
|
+
} else if (pattern.type === "Identifier") paramIdentifier = pattern.name;
|
|
65
75
|
});
|
|
66
76
|
return {
|
|
67
77
|
componentName,
|
|
@@ -69,5 +79,27 @@ const getParentComponentInfo = (reference) => {
|
|
|
69
79
|
paramIdentifier
|
|
70
80
|
};
|
|
71
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* Find the first rest element identifier in a binding pattern, in document
|
|
84
|
+
* order (mirrors ts-morph's first `DotDotDotToken` descendant lookup).
|
|
85
|
+
*/
|
|
86
|
+
const findFirstRestIdentifier = (pattern) => {
|
|
87
|
+
if (pattern.type === "ObjectPattern") {
|
|
88
|
+
for (const property of pattern.properties) {
|
|
89
|
+
if (property.type === "RestElement") return property.argument.type === "Identifier" ? property.argument.name : void 0;
|
|
90
|
+
if (property.type === "Property") {
|
|
91
|
+
const nested = findFirstRestIdentifier(property.value.type === "AssignmentPattern" ? property.value.left : property.value);
|
|
92
|
+
if (nested) return nested;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (pattern.type === "ArrayPattern") for (const element of pattern.elements) {
|
|
98
|
+
if (!element) continue;
|
|
99
|
+
if (element.type === "RestElement") return element.argument.type === "Identifier" ? element.argument.name : void 0;
|
|
100
|
+
const nested = findFirstRestIdentifier(element.type === "AssignmentPattern" ? element.left : element);
|
|
101
|
+
if (nested) return nested;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
72
104
|
//#endregion
|
|
73
105
|
export { getParentComponentInfo };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
require("../../../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let oxc_parser = require("oxc-parser");
|
|
4
|
+
//#region ../css/dist/purger/optimized/ast/oxc.mjs
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
6
|
+
const RAW_TRANSFER_AVAILABLE = (0, oxc_parser.rawTransferSupported)();
|
|
7
|
+
const getLangForFile = (filePath) => {
|
|
8
|
+
const lowered = filePath.toLowerCase();
|
|
9
|
+
if (lowered.endsWith(".tsx")) return "tsx";
|
|
10
|
+
if (lowered.endsWith(".ts") || lowered.endsWith(".mts") || lowered.endsWith(".cts")) return "ts";
|
|
11
|
+
return "jsx";
|
|
12
|
+
};
|
|
13
|
+
const isNodeLike = (value) => typeof value === "object" && value !== null && typeof value.type === "string";
|
|
14
|
+
/**
|
|
15
|
+
* Visit `node` and all descendants in document order (self included).
|
|
16
|
+
*/
|
|
17
|
+
const visitNodeAndDescendants = (node, parent, visit) => {
|
|
18
|
+
visit(node, parent);
|
|
19
|
+
const keys = oxc_parser.visitorKeys[node.type] ?? [];
|
|
20
|
+
for (const key of keys) {
|
|
21
|
+
const value = node[key];
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
for (const child of value) if (isNodeLike(child)) visitNodeAndDescendants(child, node, visit);
|
|
24
|
+
} else if (isNodeLike(value)) visitNodeAndDescendants(value, node, visit);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Visit all descendants of `node` (self excluded), mirroring
|
|
29
|
+
* ts-morph `getDescendants()` / `getDescendantsOfKind()` scoped scans.
|
|
30
|
+
*/
|
|
31
|
+
const forEachDescendant = (node, visit) => {
|
|
32
|
+
visitNodeAndDescendants(node, null, (descendant) => {
|
|
33
|
+
if (descendant !== node) visit(descendant);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
const getPatternIdentifier = (pattern) => {
|
|
37
|
+
if (pattern.type === "Identifier") return pattern;
|
|
38
|
+
if (pattern.type === "AssignmentPattern" && pattern.left.type === "Identifier") return pattern.left;
|
|
39
|
+
if (pattern.type === "RestElement" && pattern.argument.type === "Identifier") return pattern.argument;
|
|
40
|
+
return null;
|
|
41
|
+
};
|
|
42
|
+
const getPatternDefault = (pattern) => pattern.type === "AssignmentPattern" ? pattern.right : null;
|
|
43
|
+
const getPatternTypeNode = (pattern) => {
|
|
44
|
+
return (pattern.type === "AssignmentPattern" ? pattern.left : pattern).typeAnnotation?.typeAnnotation ?? null;
|
|
45
|
+
};
|
|
46
|
+
const addDefinition = (source, definition) => {
|
|
47
|
+
const existing = source.definitions.get(definition.name);
|
|
48
|
+
if (existing) existing.push(definition);
|
|
49
|
+
else source.definitions.set(definition.name, [definition]);
|
|
50
|
+
};
|
|
51
|
+
const collectParameterDefinitions = (source, fn) => {
|
|
52
|
+
fn.params.forEach((param, index) => {
|
|
53
|
+
const identifier = getPatternIdentifier(param);
|
|
54
|
+
if (!identifier) return;
|
|
55
|
+
addDefinition(source, {
|
|
56
|
+
kind: "parameter",
|
|
57
|
+
name: identifier.name,
|
|
58
|
+
start: param.start,
|
|
59
|
+
node: param,
|
|
60
|
+
init: getPatternDefault(param),
|
|
61
|
+
typeNode: getPatternTypeNode(param),
|
|
62
|
+
paramFunction: fn,
|
|
63
|
+
paramIndex: index
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const collectBindingDefinition = (source, element, pattern) => {
|
|
68
|
+
if (element.type === "Property") {
|
|
69
|
+
const identifier = getPatternIdentifier(element.value);
|
|
70
|
+
if (!identifier) return;
|
|
71
|
+
const key = element.key;
|
|
72
|
+
const bindingPropertyName = key.type === "Identifier" ? key.name : source.code.slice(key.start, key.end);
|
|
73
|
+
addDefinition(source, {
|
|
74
|
+
kind: "binding",
|
|
75
|
+
name: identifier.name,
|
|
76
|
+
start: element.start,
|
|
77
|
+
node: element,
|
|
78
|
+
init: getPatternDefault(element.value),
|
|
79
|
+
typeNode: null,
|
|
80
|
+
bindingPropertyName,
|
|
81
|
+
bindingPattern: pattern
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const identifier = getPatternIdentifier(element);
|
|
86
|
+
if (!identifier) return;
|
|
87
|
+
addDefinition(source, {
|
|
88
|
+
kind: "binding",
|
|
89
|
+
name: identifier.name,
|
|
90
|
+
start: element.start,
|
|
91
|
+
node: element,
|
|
92
|
+
init: getPatternDefault(element),
|
|
93
|
+
typeNode: null,
|
|
94
|
+
bindingPropertyName: identifier.name,
|
|
95
|
+
bindingPattern: pattern
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const isTopLevel = (parent, source) => {
|
|
99
|
+
if (!parent) return false;
|
|
100
|
+
if (parent.type === "Program") return true;
|
|
101
|
+
if (parent.type === "ExportNamedDeclaration" || parent.type === "ExportDefaultDeclaration") return source.parents.get(parent)?.type === "Program";
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
const indexNode = (source, node, parent) => {
|
|
105
|
+
if (parent) source.parents.set(node, parent);
|
|
106
|
+
switch (node.type) {
|
|
107
|
+
case "JSXOpeningElement":
|
|
108
|
+
source.jsxElements.push(node);
|
|
109
|
+
break;
|
|
110
|
+
case "CallExpression":
|
|
111
|
+
source.callExpressions.push(node);
|
|
112
|
+
break;
|
|
113
|
+
case "JSXAttribute":
|
|
114
|
+
source.jsxAttributes.push(node);
|
|
115
|
+
break;
|
|
116
|
+
case "Property":
|
|
117
|
+
if (parent?.type === "ObjectExpression") source.objectProperties.push(node);
|
|
118
|
+
else if (parent?.type === "ObjectPattern") collectBindingDefinition(source, node, parent);
|
|
119
|
+
break;
|
|
120
|
+
case "RestElement":
|
|
121
|
+
if (parent?.type === "ObjectPattern" || parent?.type === "ArrayPattern") collectBindingDefinition(source, node, parent);
|
|
122
|
+
break;
|
|
123
|
+
case "Identifier":
|
|
124
|
+
case "AssignmentPattern":
|
|
125
|
+
if (parent?.type === "ArrayPattern") collectBindingDefinition(source, node, parent);
|
|
126
|
+
break;
|
|
127
|
+
case "VariableDeclarator":
|
|
128
|
+
source.variableDeclarators.push(node);
|
|
129
|
+
if (node.id.type === "Identifier") {
|
|
130
|
+
const name = node.id.name;
|
|
131
|
+
addDefinition(source, {
|
|
132
|
+
kind: "variable",
|
|
133
|
+
name,
|
|
134
|
+
start: node.start,
|
|
135
|
+
node,
|
|
136
|
+
init: node.init ?? null,
|
|
137
|
+
typeNode: getPatternTypeNode(node.id)
|
|
138
|
+
});
|
|
139
|
+
const declaration = source.parents.get(node);
|
|
140
|
+
if (declaration && isTopLevel(source.parents.get(declaration) ?? null, source)) {
|
|
141
|
+
if (!source.topLevelVariables.has(name)) source.topLevelVariables.set(name, node);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
case "FunctionDeclaration": {
|
|
146
|
+
const fn = node;
|
|
147
|
+
collectParameterDefinitions(source, fn);
|
|
148
|
+
if (fn.id && isTopLevel(parent, source)) {
|
|
149
|
+
const name = fn.id.name;
|
|
150
|
+
addDefinition(source, {
|
|
151
|
+
kind: "function",
|
|
152
|
+
name,
|
|
153
|
+
start: parent && parent.type !== "Program" && "start" in parent ? parent.start : fn.start,
|
|
154
|
+
node: fn,
|
|
155
|
+
init: null,
|
|
156
|
+
typeNode: null
|
|
157
|
+
});
|
|
158
|
+
if (!source.topLevelFunctions.has(name)) source.topLevelFunctions.set(name, fn);
|
|
159
|
+
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
case "FunctionExpression":
|
|
163
|
+
case "ArrowFunctionExpression":
|
|
164
|
+
collectParameterDefinitions(source, node);
|
|
165
|
+
break;
|
|
166
|
+
case "TSEnumDeclaration":
|
|
167
|
+
if (isTopLevel(parent, source) && !source.topLevelEnums.has(node.id.name)) source.topLevelEnums.set(node.id.name, node);
|
|
168
|
+
break;
|
|
169
|
+
default: break;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Parse a source file and build the purger's node indexes in a single walk.
|
|
174
|
+
*/
|
|
175
|
+
const parseSource = (filePath, code) => {
|
|
176
|
+
const parserOptions = { lang: getLangForFile(filePath) };
|
|
177
|
+
if (RAW_TRANSFER_AVAILABLE) parserOptions.experimentalRawTransfer = true;
|
|
178
|
+
const result = (0, oxc_parser.parseSync)(filePath, code, parserOptions);
|
|
179
|
+
const source = {
|
|
180
|
+
filePath,
|
|
181
|
+
code,
|
|
182
|
+
program: result.program,
|
|
183
|
+
staticImports: result.module.staticImports,
|
|
184
|
+
parents: /* @__PURE__ */ new WeakMap(),
|
|
185
|
+
jsxElements: [],
|
|
186
|
+
callExpressions: [],
|
|
187
|
+
jsxAttributes: [],
|
|
188
|
+
objectProperties: [],
|
|
189
|
+
variableDeclarators: [],
|
|
190
|
+
topLevelVariables: /* @__PURE__ */ new Map(),
|
|
191
|
+
topLevelFunctions: /* @__PURE__ */ new Map(),
|
|
192
|
+
topLevelEnums: /* @__PURE__ */ new Map(),
|
|
193
|
+
definitions: /* @__PURE__ */ new Map(),
|
|
194
|
+
lineStarts: null
|
|
195
|
+
};
|
|
196
|
+
visitNodeAndDescendants(source.program, null, (node, parent) => indexNode(source, node, parent));
|
|
197
|
+
return source;
|
|
198
|
+
};
|
|
199
|
+
/** ts-morph `node.getText()` analog */
|
|
200
|
+
const getText = (source, node) => source.code.slice(node.start, node.end);
|
|
201
|
+
const getParent = (source, node) => source.parents.get(node);
|
|
202
|
+
/** ts-morph `node.getStartLineNumber()` analog (1-based) */
|
|
203
|
+
const getLineNumber = (source, offset) => {
|
|
204
|
+
if (!source.lineStarts) {
|
|
205
|
+
const lineStarts = [0];
|
|
206
|
+
for (let i = 0; i < source.code.length; i++) if (source.code[i] === "\n") lineStarts.push(i + 1);
|
|
207
|
+
source.lineStarts = lineStarts;
|
|
208
|
+
}
|
|
209
|
+
const lineStarts = source.lineStarts;
|
|
210
|
+
let low = 0;
|
|
211
|
+
let high = lineStarts.length - 1;
|
|
212
|
+
while (low < high) {
|
|
213
|
+
const mid = Math.ceil((low + high) / 2);
|
|
214
|
+
if (lineStarts[mid] <= offset) low = mid;
|
|
215
|
+
else high = mid - 1;
|
|
216
|
+
}
|
|
217
|
+
return low + 1;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Position-aware local definition lookup, mirroring ts-morph's
|
|
221
|
+
* `getLocalDefinitionNodes`: latest definition at or before the identifier.
|
|
222
|
+
*/
|
|
223
|
+
const findLocalDefinitions = (source, identifier) => {
|
|
224
|
+
if (identifier.type !== "Identifier") return [];
|
|
225
|
+
const candidates = source.definitions.get(identifier.name);
|
|
226
|
+
if (!candidates) return [];
|
|
227
|
+
const matches = candidates.filter((definition) => definition.start <= identifier.start);
|
|
228
|
+
if (matches.length === 0) return [];
|
|
229
|
+
return [...matches].sort((left, right) => right.start - left.start).slice(0, 1);
|
|
230
|
+
};
|
|
231
|
+
/** True for a string `Literal` node */
|
|
232
|
+
const isStringLiteral = (node) => node.type === "Literal" && typeof node.value === "string";
|
|
233
|
+
const getStringLiteralValue = (node) => node.value;
|
|
234
|
+
/** True for a `TemplateLiteral` with no substitutions (ts NoSubstitutionTemplateLiteral) */
|
|
235
|
+
const isNoSubstitutionTemplate = (node) => node.type === "TemplateLiteral" && node.expressions.length === 0;
|
|
236
|
+
/** ts-morph `element.getTagNameNode().getText()` analog */
|
|
237
|
+
const getJsxTagName = (source, element) => {
|
|
238
|
+
const name = element.name;
|
|
239
|
+
return name.type === "JSXIdentifier" ? name.name : source.code.slice(name.start, name.end);
|
|
240
|
+
};
|
|
241
|
+
/** ts-morph `attr.getNameNode().getText()` analog */
|
|
242
|
+
const getJsxAttributeName = (source, attribute) => {
|
|
243
|
+
const name = attribute.name;
|
|
244
|
+
return name.type === "JSXIdentifier" ? name.name : source.code.slice(name.start, name.end);
|
|
245
|
+
};
|
|
246
|
+
/** ts-morph `prop.getName()` analog for object-literal properties */
|
|
247
|
+
const getPropertyName = (source, property) => {
|
|
248
|
+
const key = property.key;
|
|
249
|
+
if (key.type === "Identifier") return key.name;
|
|
250
|
+
if (isStringLiteral(key)) return getStringLiteralValue(key);
|
|
251
|
+
return source.code.slice(key.start, key.end);
|
|
252
|
+
};
|
|
253
|
+
//#endregion
|
|
254
|
+
exports.findLocalDefinitions = findLocalDefinitions;
|
|
255
|
+
exports.forEachDescendant = forEachDescendant;
|
|
256
|
+
exports.getJsxAttributeName = getJsxAttributeName;
|
|
257
|
+
exports.getJsxTagName = getJsxTagName;
|
|
258
|
+
exports.getLineNumber = getLineNumber;
|
|
259
|
+
exports.getParent = getParent;
|
|
260
|
+
exports.getPropertyName = getPropertyName;
|
|
261
|
+
exports.getStringLiteralValue = getStringLiteralValue;
|
|
262
|
+
exports.getText = getText;
|
|
263
|
+
exports.isNoSubstitutionTemplate = isNoSubstitutionTemplate;
|
|
264
|
+
exports.isStringLiteral = isStringLiteral;
|
|
265
|
+
exports.parseSource = parseSource;
|