@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.
Files changed (29) hide show
  1. package/dist/automated-config/dist/utils/getConfigVariantProperties.d.cts +2 -2
  2. package/dist/automated-config/dist/utils/getConfigVariantProperties.d.ts +2 -2
  3. package/dist/css/dist/css/purgeWorker.js +50 -0
  4. package/dist/css/dist/css/runner.cjs +3 -1
  5. package/dist/css/dist/css/runner.js +3 -1
  6. package/dist/css/dist/css/workerPool.cjs +18 -2
  7. package/dist/css/dist/css/workerPool.js +16 -1
  8. package/dist/css/dist/purger/optimized/ast/expressions.cjs +278 -278
  9. package/dist/css/dist/purger/optimized/ast/expressions.js +278 -278
  10. package/dist/css/dist/purger/optimized/ast/jsx.cjs +67 -36
  11. package/dist/css/dist/purger/optimized/ast/jsx.js +67 -35
  12. package/dist/css/dist/purger/optimized/ast/oxc.cjs +265 -0
  13. package/dist/css/dist/purger/optimized/ast/oxc.js +253 -0
  14. package/dist/css/dist/purger/optimized/ast/props.cjs +21 -15
  15. package/dist/css/dist/purger/optimized/ast/props.js +21 -14
  16. package/dist/css/dist/purger/optimized/ast/spread.cjs +19 -19
  17. package/dist/css/dist/purger/optimized/ast/spread.js +19 -18
  18. package/dist/css/dist/purger/optimized/purgeFromCode.cjs +86 -101
  19. package/dist/css/dist/purger/optimized/purgeFromCode.js +86 -100
  20. package/dist/tailwind-internal/dist/utils/getShadowStyles.d.cts +2 -2
  21. package/dist/tailwind-internal/dist/utils/getShadowStyles.d.ts +2 -2
  22. package/dist/tailwind-v3/dist/purger/legacy/purgeCSS.cjs +1 -1
  23. package/dist/tailwind-v3/dist/purger/legacy/purgeCSS.js +1 -1
  24. package/dist/uds/generated/componentData.cjs +273 -273
  25. package/dist/uds/generated/componentData.js +273 -273
  26. package/dist/uds/package.cjs +2 -0
  27. package/dist/uds/package.js +2 -0
  28. package/generated/componentData.json +419 -419
  29. package/package.json +3 -1
@@ -1,40 +1,46 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
2
- require("../../../../../_virtual/_rolldown/runtime.cjs");
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 (!ts_morph.Node.isCallExpression(node)) return false;
11
- const expression = node.getExpression();
12
- if (ts_morph.Node.isIdentifier(expression) && expression.getText() === "forwardRef") return true;
13
- if (ts_morph.Node.isPropertyAccessExpression(expression) && expression.getText() === "React.forwardRef") return true;
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
- let name;
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 (ts_morph.Node.isFunctionDeclaration(declaration)) return declaration;
31
- if (ts_morph.Node.isVariableDeclaration(declaration)) {
32
- const initializer = declaration.getInitializer();
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.getArguments();
36
- if (ts_morph.Node.isFunctionDeclaration(arg) || ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) return arg;
37
- } else if (ts_morph.Node.isFunctionDeclaration(initializer) || ts_morph.Node.isFunctionExpression(initializer) || ts_morph.Node.isArrowFunction(initializer)) return initializer;
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
- const block = reference.getParentWhile((parent) => !getReactFunctionDeclaration(parent));
47
- if (!block) return;
48
- const blockParent = block.getParent();
49
- if (!blockParent) return;
50
- const reactComponent = getReactFunctionDeclaration(blockParent);
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
- const variableDeclaration = reactComponent.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration);
54
- if (variableDeclaration) componentName = variableDeclaration.getName();
55
- else if (ts_morph.Node.isFunctionDeclaration(reactComponent)) componentName = reactComponent.getName();
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.getParameters().forEach((parameter) => {
60
- const objectBindingPattern = parameter.getChildrenOfKind(ts_morph.SyntaxKind.ObjectBindingPattern)[0];
61
- const identifier = parameter.getChildrenOfKind(ts_morph.SyntaxKind.Identifier)[0];
62
- if (objectBindingPattern) {
63
- const dotDotToken = objectBindingPattern.getFirstDescendantByKind(ts_morph.SyntaxKind.DotDotDotToken);
64
- if (dotDotToken) spreadRestIdentifier = dotDotToken.getParent()?.getFirstChildByKindOrThrow(ts_morph.SyntaxKind.Identifier).getText();
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 { Node, SyntaxKind } from "ts-morph";
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 (!Node.isCallExpression(node)) return false;
10
- const expression = node.getExpression();
11
- if (Node.isIdentifier(expression) && expression.getText() === "forwardRef") return true;
12
- if (Node.isPropertyAccessExpression(expression) && expression.getText() === "React.forwardRef") return true;
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
- let name;
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 (Node.isFunctionDeclaration(declaration)) return declaration;
30
- if (Node.isVariableDeclaration(declaration)) {
31
- const initializer = declaration.getInitializer();
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.getArguments();
35
- if (Node.isFunctionDeclaration(arg) || Node.isFunctionExpression(arg) || Node.isArrowFunction(arg)) return arg;
36
- } else if (Node.isFunctionDeclaration(initializer) || Node.isFunctionExpression(initializer) || Node.isArrowFunction(initializer)) return initializer;
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
- const block = reference.getParentWhile((parent) => !getReactFunctionDeclaration(parent));
46
- if (!block) return;
47
- const blockParent = block.getParent();
48
- if (!blockParent) return;
49
- const reactComponent = getReactFunctionDeclaration(blockParent);
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
- const variableDeclaration = reactComponent.getFirstAncestorByKind(SyntaxKind.VariableDeclaration);
53
- if (variableDeclaration) componentName = variableDeclaration.getName();
54
- else if (Node.isFunctionDeclaration(reactComponent)) componentName = reactComponent.getName();
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.getParameters().forEach((parameter) => {
59
- const objectBindingPattern = parameter.getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0];
60
- const identifier = parameter.getChildrenOfKind(SyntaxKind.Identifier)[0];
61
- if (objectBindingPattern) {
62
- const dotDotToken = objectBindingPattern.getFirstDescendantByKind(SyntaxKind.DotDotDotToken);
63
- if (dotDotToken) spreadRestIdentifier = dotDotToken.getParent()?.getFirstChildByKindOrThrow(SyntaxKind.Identifier).getText();
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;