@component-compass/ast-utils 0.0.3 → 0.1.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.
@@ -1,3 +1,4 @@
1
+ import type { ResolveImport } from "@component-compass/plugin-core";
1
2
  export type ImportOrigin = {
2
3
  type: "external";
3
4
  package: string;
@@ -8,9 +9,25 @@ export type ImportOrigin = {
8
9
  type: "unresolved";
9
10
  };
10
11
  export type ClassifyOptions = {
11
- /** Absolute path to the repo root. Used to compute repo-relative filePath. */
12
12
  repoRoot: string;
13
- /** Absolute path of the source file containing the import. */
14
13
  fromFile: string;
14
+ /**
15
+ * The shared `ResolveImport` from `cli/walker/resolve-import.ts`. Handles
16
+ * config aliases, tsconfig `paths`, and Node resolution in one layered
17
+ * pass. Required — there is no internal fallback.
18
+ */
19
+ resolveImport: ResolveImport;
20
+ /**
21
+ * Names of packages known to belong to the scan's repo — workspace
22
+ * siblings (`workspaceGraph.packages[*].name`) plus declared deps from the
23
+ * root and workspace `package.json` files. When the resolver returns null,
24
+ * the specifier's package portion is matched against this set; a hit
25
+ * recovers external-package identity instead of marking the import
26
+ * unresolved. Necessary for yarn/pnpm workspaces where siblings live under
27
+ * `packages/*` but aren't symlinked into the root `node_modules`. Specs
28
+ * that don't parse to a known package name (e.g. `~/foo`, `@/x`) stay
29
+ * unresolved.
30
+ */
31
+ knownPackageNames?: ReadonlySet<string>;
15
32
  };
16
33
  export declare function classifyImportOrigin(specifier: string, opts: ClassifyOptions): ImportOrigin;
@@ -1,11 +1,15 @@
1
- import { createRequire } from "node:module";
2
- import { dirname, isAbsolute, relative, sep } from "node:path";
1
+ import { isAbsolute, relative, sep, dirname } from "node:path";
3
2
  import { readFileSync, existsSync, realpathSync } from "node:fs";
4
3
  import { posixPath } from "./posix.js";
5
4
  export function classifyImportOrigin(specifier, opts) {
6
- const resolved = tryResolve(specifier, opts.fromFile);
7
- if (!resolved)
5
+ const resolved = opts.resolveImport(opts.fromFile, specifier);
6
+ if (!resolved) {
7
+ const pkg = packageNameFromSpecifier(specifier);
8
+ if (pkg && opts.knownPackageNames?.has(pkg)) {
9
+ return { type: "external", package: pkg };
10
+ }
8
11
  return { type: "unresolved" };
12
+ }
9
13
  const nodeModulesIdx = resolved.lastIndexOf(`${sep}node_modules${sep}`);
10
14
  if (nodeModulesIdx >= 0) {
11
15
  const pkg = packageOf(resolved);
@@ -15,8 +19,6 @@ export function classifyImportOrigin(specifier, opts) {
15
19
  }
16
20
  if (!isAbsolute(resolved))
17
21
  return { type: "unresolved" };
18
- // Normalise both sides to real paths so that symlinks (e.g. /var → /private/var
19
- // on macOS) don't cause false "outside repo" negatives.
20
22
  let repoRoot;
21
23
  try {
22
24
  repoRoot = realpathSync(opts.repoRoot);
@@ -37,26 +39,29 @@ export function classifyImportOrigin(specifier, opts) {
37
39
  }
38
40
  return { type: "local", filePath: posixPath(rel) };
39
41
  }
40
- const SOURCE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mjs", ".cjs"];
41
- function tryResolve(specifier, fromFile) {
42
- const require = createRequire(fromFile);
43
- // First attempt: plain resolution (works for node_modules and files with known extensions).
44
- try {
45
- return require.resolve(specifier);
46
- }
47
- catch {
48
- // Fall through to extension-probing for extensionless relative imports.
42
+ /**
43
+ * Parse a module specifier into its package-name portion. Returns null for
44
+ * specifiers that aren't shaped like a package import (relative paths,
45
+ * tsconfig/alias prefixes like `~/x`, `@/x`, `#x`, absolute paths).
46
+ * - `@scope/name` → `@scope/name`
47
+ * - `@scope/name/sub/path` → `@scope/name`
48
+ * - `lodash` → `lodash`
49
+ * - `lodash/fp/flow` → `lodash`
50
+ * - `./x`, `../x`, `/x` → null
51
+ * - `~/x`, `@/x`, `#alias` → null (scoped form requires `@scope/name`)
52
+ */
53
+ function packageNameFromSpecifier(specifier) {
54
+ if (specifier.startsWith("@")) {
55
+ const slash1 = specifier.indexOf("/");
56
+ if (slash1 < 0)
57
+ return null;
58
+ const slash2 = specifier.indexOf("/", slash1 + 1);
59
+ return slash2 < 0 ? specifier : specifier.slice(0, slash2);
49
60
  }
50
- // Second attempt: probe TypeScript/JSX extensions that Node's require doesn't try by default.
51
- for (const ext of SOURCE_EXTENSIONS) {
52
- try {
53
- return require.resolve(`${specifier}${ext}`);
54
- }
55
- catch {
56
- // continue
57
- }
58
- }
59
- return null;
61
+ if (!/^[a-zA-Z]/.test(specifier))
62
+ return null;
63
+ const slash = specifier.indexOf("/");
64
+ return slash < 0 ? specifier : specifier.slice(0, slash);
60
65
  }
61
66
  function packageOf(absolute) {
62
67
  let cursor = dirname(absolute);
@@ -1 +1 @@
1
- {"version":3,"file":"classify-import.js","sourceRoot":"","sources":["../src/classify-import.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classify-import.js","sourceRoot":"","sources":["../src/classify-import.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Walk a Babel NodePath upward to find the nearest enclosing component
3
- * binding. A "component binding" is a function or class declaration / variable
2
+ * Walk an oxc/ESTree program from `program` down to `target`, returning the
3
+ * nearest enclosing component binding.
4
+ *
5
+ * A "component binding" is a function or class declaration / variable
4
6
  * declarator whose binding name is PascalCase, OR an anonymous `export default`.
5
7
  *
6
8
  * HOC wrappers (`memo`, `forwardRef`, `observer`, `React.memo`, `React.forwardRef`)
@@ -9,14 +11,27 @@
9
11
  *
10
12
  * Returns `null` when no enclosing tracked component is found before reaching
11
13
  * module scope (e.g. JSX at module top-level).
14
+ *
15
+ * Algorithm: walk top-down through `program`, maintaining two parallel stacks
16
+ * of currently-entered nodes: `pathStack` (every node) and `frameStack` (just
17
+ * the candidate owners — Function/Arrow/Class declarations or expressions).
18
+ * When the `target` node is entered, scan `frameStack` from innermost outward
19
+ * and return the first frame whose contextual binding satisfies the rules:
20
+ * PascalCase id, predicate (if any), default-export special case, HOC
21
+ * unwrapping. Pop both stacks in `leave`.
22
+ *
23
+ * `loc` is always returned as `null` — oxc-parser only emits byte offsets,
24
+ * and the sole current consumer (parser-react/walk-jsx.ts) reads only
25
+ * `binding.name`. If a future caller needs a line/column, thread the source
26
+ * string through and call `positionAt` from `./oxc-helpers.ts`.
12
27
  */
13
- import type { NodePath } from "@babel/traverse";
28
+ import type { Node as OxcNode, Program } from "@oxc-project/types";
14
29
  export type EnclosingComponentBinding = {
15
30
  /** Binding name; `"default"` for anonymous default exports. */
16
31
  name: string;
17
32
  /** True for `export default ...` cases. */
18
33
  isDefault: boolean;
19
- /** Declaration site (line/column from the node's source position). */
34
+ /** Declaration site — always null (oxc-parser emits byte offsets only). */
20
35
  loc: {
21
36
  line: number;
22
37
  column: number;
@@ -26,7 +41,12 @@ export type EnclosingComponentBinding = {
26
41
  * Optional predicate supplied by the caller. When provided, a candidate
27
42
  * binding is only returned if `isKnownComponent(name)` returns true; otherwise
28
43
  * the walk continues upward. When omitted, any PascalCase binding (or
29
- * anonymous `export default`) is accepted — preserving backward compatibility.
44
+ * anonymous `export default`) is accepted.
30
45
  */
31
46
  export type IsKnownComponent = (name: string) => boolean;
32
- export declare function findEnclosingComponentBinding(path: NodePath, isKnownComponent?: IsKnownComponent): EnclosingComponentBinding | null;
47
+ /**
48
+ * Walk an oxc/ESTree program from `program` down to `target`, returning the
49
+ * nearest enclosing component binding. The `target` must be a node within
50
+ * `program`. Reference equality is used to detect arrival.
51
+ */
52
+ export declare function findEnclosingComponentBinding(target: OxcNode, program: Program, isKnownComponent?: IsKnownComponent): EnclosingComponentBinding | null;
@@ -1,89 +1,145 @@
1
+ import { walk } from "oxc-walker";
1
2
  const HOC_NAMES = new Set(["memo", "forwardRef", "observer"]);
2
- export function findEnclosingComponentBinding(path, isKnownComponent) {
3
- let current = path.parentPath;
4
- while (current) {
5
- if (current.isClassDeclaration() || current.isClassExpression()) {
6
- const node = current.node;
7
- const id = node.id;
8
- if (id && isPascalCase(id.name)) {
9
- if (!isKnownComponent || isKnownComponent(id.name)) {
10
- return { name: id.name, isDefault: false, loc: nodeLoc(node) };
11
- }
3
+ /**
4
+ * Walk an oxc/ESTree program from `program` down to `target`, returning the
5
+ * nearest enclosing component binding. The `target` must be a node within
6
+ * `program`. Reference equality is used to detect arrival.
7
+ */
8
+ export function findEnclosingComponentBinding(target, program, isKnownComponent) {
9
+ const pathStack = [];
10
+ // Frames hold the candidate node plus the pathStack depth at which it was
11
+ // pushed, so binding-evaluation can look up parents/grandparents at scan
12
+ // time without re-discovering them.
13
+ const frameStack = [];
14
+ let result = null;
15
+ let done = false;
16
+ walk(program, {
17
+ enter(node) {
18
+ if (done) {
19
+ this.skip?.();
20
+ return;
12
21
  }
13
- const parent = current.parentPath;
14
- if (parent?.isExportDefaultDeclaration()) {
15
- if (!isKnownComponent || isKnownComponent("default")) {
16
- return { name: "default", isDefault: true, loc: nodeLoc(node) };
17
- }
22
+ pathStack.push(node);
23
+ // Arrival check — must happen BEFORE pushing the target's own frame, so
24
+ // a candidate-shaped target (e.g. an ArrowFunctionExpression passed in
25
+ // by a caller) is not considered its own owner.
26
+ if (node === target) {
27
+ result = scanFrameStack(frameStack, pathStack, isKnownComponent);
28
+ done = true;
29
+ this.skip?.();
30
+ return;
31
+ }
32
+ if (isOwnerCandidateNode(node)) {
33
+ frameStack.push({ node, depth: pathStack.length - 1 });
34
+ }
35
+ },
36
+ leave(node) {
37
+ // Pop frameStack first (it is a subset of pathStack frames).
38
+ const top = frameStack[frameStack.length - 1];
39
+ if (top && top.node === node)
40
+ frameStack.pop();
41
+ pathStack.pop();
42
+ },
43
+ });
44
+ return result;
45
+ }
46
+ function isOwnerCandidateNode(node) {
47
+ return (node.type === "FunctionDeclaration" ||
48
+ node.type === "FunctionExpression" ||
49
+ node.type === "ArrowFunctionExpression" ||
50
+ node.type === "ClassDeclaration" ||
51
+ node.type === "ClassExpression");
52
+ }
53
+ function scanFrameStack(frameStack, pathStack, isKnownComponent) {
54
+ for (let i = frameStack.length - 1; i >= 0; i--) {
55
+ const frame = frameStack[i];
56
+ if (!frame)
57
+ continue;
58
+ const parent = pathStack[frame.depth - 1] ?? null;
59
+ const grand = pathStack[frame.depth - 2] ?? null;
60
+ const binding = bindingForOxcFrame(frame.node, parent, grand, isKnownComponent);
61
+ if (binding)
62
+ return binding;
63
+ }
64
+ return null;
65
+ }
66
+ function bindingForOxcFrame(node, parent, grand, isKnownComponent) {
67
+ // class Name { … } / class Name extends Base { … }
68
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
69
+ const cls = node;
70
+ const id = cls.id;
71
+ if (id && isPascalCase(id.name)) {
72
+ if (!isKnownComponent || isKnownComponent(id.name)) {
73
+ return { name: id.name, isDefault: false, loc: null };
18
74
  }
19
75
  }
20
- if (current.isFunctionDeclaration()) {
21
- const node = current.node;
22
- const id = node.id;
23
- const parent = current.parentPath;
24
- if (parent?.isExportDefaultDeclaration()) {
25
- const name = id && isPascalCase(id.name) ? id.name : "default";
26
- if (!isKnownComponent || isKnownComponent(name)) {
27
- return {
28
- name,
29
- isDefault: true,
30
- loc: nodeLoc(node),
31
- };
32
- }
76
+ if (parent?.type === "ExportDefaultDeclaration") {
77
+ if (!isKnownComponent || isKnownComponent("default")) {
78
+ return { name: "default", isDefault: true, loc: null };
33
79
  }
34
- if (id && isPascalCase(id.name)) {
35
- if (!isKnownComponent || isKnownComponent(id.name)) {
36
- return { name: id.name, isDefault: false, loc: nodeLoc(node) };
37
- }
80
+ }
81
+ return null;
82
+ }
83
+ // function Name() { … }
84
+ if (node.type === "FunctionDeclaration") {
85
+ const fn = node;
86
+ const id = fn.id;
87
+ if (parent?.type === "ExportDefaultDeclaration") {
88
+ const name = id && isPascalCase(id.name) ? id.name : "default";
89
+ if (!isKnownComponent || isKnownComponent(name)) {
90
+ return { name, isDefault: true, loc: null };
38
91
  }
39
92
  }
40
- if (current.isArrowFunctionExpression() || current.isFunctionExpression()) {
41
- const binding = ownerFromFunctionExprAncestor(current, isKnownComponent);
42
- if (binding)
43
- return binding;
93
+ if (id && isPascalCase(id.name)) {
94
+ if (!isKnownComponent || isKnownComponent(id.name)) {
95
+ return { name: id.name, isDefault: false, loc: null };
96
+ }
44
97
  }
45
- current = current.parentPath;
98
+ return null;
99
+ }
100
+ // (...) => … / function () { … } (anonymous), examined by its context.
101
+ if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") {
102
+ return bindingFromAnonymousFunctionParent(parent, grand, isKnownComponent);
46
103
  }
47
104
  return null;
48
105
  }
49
- function ownerFromFunctionExprAncestor(path, isKnownComponent) {
50
- const parent = path.parentPath;
106
+ function bindingFromAnonymousFunctionParent(parent, grand, isKnownComponent) {
51
107
  if (!parent)
52
108
  return null;
53
- if (parent.isVariableDeclarator()) {
54
- return bindingFromVariableDeclarator(parent.node, path.node, isKnownComponent);
109
+ if (parent.type === "VariableDeclarator" && parent.id.type === "Identifier") {
110
+ return bindingFromVariableId(parent.id.name, isKnownComponent);
55
111
  }
56
- if (parent.isCallExpression() && isHocCall(parent.node)) {
57
- const grand = parent.parentPath;
112
+ if (parent.type === "CallExpression" && isHocCall(parent)) {
58
113
  if (!grand)
59
114
  return null;
60
- if (grand.isVariableDeclarator()) {
61
- return bindingFromVariableDeclarator(grand.node, path.node, isKnownComponent);
115
+ if (grand.type === "VariableDeclarator" && grand.id.type === "Identifier") {
116
+ return bindingFromVariableId(grand.id.name, isKnownComponent);
62
117
  }
63
- if (grand.isExportDefaultDeclaration()) {
118
+ if (grand.type === "ExportDefaultDeclaration") {
64
119
  if (!isKnownComponent || isKnownComponent("default")) {
65
- return { name: "default", isDefault: true, loc: nodeLoc(path.node) };
120
+ return { name: "default", isDefault: true, loc: null };
66
121
  }
67
122
  }
123
+ return null;
68
124
  }
69
- if (parent.isExportDefaultDeclaration()) {
125
+ if (parent.type === "ExportDefaultDeclaration") {
70
126
  if (!isKnownComponent || isKnownComponent("default")) {
71
- return { name: "default", isDefault: true, loc: nodeLoc(path.node) };
127
+ return { name: "default", isDefault: true, loc: null };
72
128
  }
73
129
  }
74
130
  return null;
75
131
  }
76
- function bindingFromVariableDeclarator(decl, fnNode, isKnownComponent) {
77
- if (decl.id.type !== "Identifier")
78
- return null;
79
- if (!isPascalCase(decl.id.name))
132
+ function bindingFromVariableId(name, isKnownComponent) {
133
+ if (!isPascalCase(name))
80
134
  return null;
81
- if (isKnownComponent && !isKnownComponent(decl.id.name))
135
+ if (isKnownComponent && !isKnownComponent(name))
82
136
  return null;
83
- return { name: decl.id.name, isDefault: false, loc: nodeLoc(decl) ?? nodeLoc(fnNode) };
137
+ return { name, isDefault: false, loc: null };
84
138
  }
85
- function isHocCall(node) {
86
- const callee = node.callee;
139
+ function isHocCall(call) {
140
+ if (call.type !== "CallExpression")
141
+ return false;
142
+ const callee = call.callee;
87
143
  if (callee.type === "Identifier")
88
144
  return HOC_NAMES.has(callee.name);
89
145
  if (callee.type === "MemberExpression" &&
@@ -97,10 +153,4 @@ function isHocCall(node) {
97
153
  function isPascalCase(name) {
98
154
  return /^[A-Z]/.test(name);
99
155
  }
100
- function nodeLoc(node) {
101
- if (!node)
102
- return null;
103
- const s = node.loc?.start;
104
- return s ? { line: s.line, column: s.column } : null;
105
- }
106
156
  //# sourceMappingURL=find-owner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"find-owner.js","sourceRoot":"","sources":["../src/find-owner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"find-owner.js","sourceRoot":"","sources":["../src/find-owner.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export { isElement, hasChildren } from "./parse5-guards.js";
2
- export { traverse } from "./babel-interop.js";
3
2
  export { posixPath } from "./posix.js";
4
3
  export { errorMessage, errorStack } from "./errors.js";
5
4
  export { classifyImportOrigin } from "./classify-import.js";
6
5
  export type { ImportOrigin, ClassifyOptions } from "./classify-import.js";
7
6
  export { findEnclosingComponentBinding } from "./find-owner.js";
8
7
  export type { EnclosingComponentBinding } from "./find-owner.js";
8
+ export { positionAt, getJSXName, isJSXElement, isJSXFragment, isJSXAttribute, isJSXSpreadAttribute, isCallExpression, isImportDeclaration, } from "./oxc-helpers.js";
9
+ export type { Position } from "./oxc-helpers.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { isElement, hasChildren } from "./parse5-guards.js";
2
- export { traverse } from "./babel-interop.js";
3
2
  export { posixPath } from "./posix.js";
4
3
  export { errorMessage, errorStack } from "./errors.js";
5
4
  export { classifyImportOrigin } from "./classify-import.js";
6
5
  export { findEnclosingComponentBinding } from "./find-owner.js";
6
+ export { positionAt, getJSXName, isJSXElement, isJSXFragment, isJSXAttribute, isJSXSpreadAttribute, isCallExpression, isImportDeclaration, } from "./oxc-helpers.js";
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Helpers for working with oxc-parser's ESTree-shaped AST. Used by every
3
+ * default-path plugin/detector.
4
+ *
5
+ * - `positionAt` — UTF-16 offset → { line, column } conversion (as emitted by oxc-parser)
6
+ * - `getJSXName` — JSXIdentifier | JSXMemberExpression | JSXNamespacedName → string
7
+ * - `is*` predicates — type-narrow ESTree nodes by `type` field
8
+ *
9
+ * Keep this module dependency-free except for @oxc-project/types (type-only
10
+ * at runtime). All helpers work against plain ESTree-shape objects.
11
+ */
12
+ import type { CallExpression, ImportDeclaration, JSXElement, JSXFragment, JSXIdentifier, JSXMemberExpression, JSXNamespacedName, JSXAttribute, JSXSpreadAttribute } from "@oxc-project/types";
13
+ export type Position = {
14
+ line: number;
15
+ column: number;
16
+ };
17
+ /**
18
+ * Convert a UTF-16 code unit offset (as emitted by oxc-parser) into a
19
+ * 1-indexed line + 0-indexed column position. O(offset) — fine for emit-time
20
+ * use (called once per occurrence), avoid in tight walk loops. Cache by source
21
+ * if profile shows it matters.
22
+ */
23
+ export declare function positionAt(source: string, offset: number): Position;
24
+ export declare function isJSXElement(node: unknown): node is JSXElement;
25
+ export declare function isJSXFragment(node: unknown): node is JSXFragment;
26
+ export declare function isJSXAttribute(node: unknown): node is JSXAttribute;
27
+ export declare function isJSXSpreadAttribute(node: unknown): node is JSXSpreadAttribute;
28
+ export declare function isCallExpression(node: unknown): node is CallExpression;
29
+ export declare function isImportDeclaration(node: unknown): node is ImportDeclaration;
30
+ type JSXName = JSXIdentifier | JSXMemberExpression | JSXNamespacedName;
31
+ /**
32
+ * Stringify a JSX element/attribute name node:
33
+ * <Foo /> → "Foo" (JSXIdentifier)
34
+ * <Foo.Bar /> → "Foo.Bar" (JSXMemberExpression)
35
+ * <svg:rect /> → "svg:rect" (JSXNamespacedName)
36
+ * <a.b.c /> → "a.b.c" (nested JSXMemberExpression)
37
+ */
38
+ export declare function getJSXName(el: JSXElement | {
39
+ openingElement: JSXElement["openingElement"];
40
+ } | JSXName): string;
41
+ export {};
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Helpers for working with oxc-parser's ESTree-shaped AST. Used by every
3
+ * default-path plugin/detector.
4
+ *
5
+ * - `positionAt` — UTF-16 offset → { line, column } conversion (as emitted by oxc-parser)
6
+ * - `getJSXName` — JSXIdentifier | JSXMemberExpression | JSXNamespacedName → string
7
+ * - `is*` predicates — type-narrow ESTree nodes by `type` field
8
+ *
9
+ * Keep this module dependency-free except for @oxc-project/types (type-only
10
+ * at runtime). All helpers work against plain ESTree-shape objects.
11
+ */
12
+ /**
13
+ * Convert a UTF-16 code unit offset (as emitted by oxc-parser) into a
14
+ * 1-indexed line + 0-indexed column position. O(offset) — fine for emit-time
15
+ * use (called once per occurrence), avoid in tight walk loops. Cache by source
16
+ * if profile shows it matters.
17
+ */
18
+ export function positionAt(source, offset) {
19
+ let line = 1;
20
+ let column = 0;
21
+ for (let i = 0; i < offset && i < source.length; i++) {
22
+ if (source[i] === "\n") {
23
+ line++;
24
+ column = 0;
25
+ }
26
+ else if (source[i] === "\r") {
27
+ // \r\n counted via the next \n; lone \r increments line.
28
+ if (source[i + 1] !== "\n") {
29
+ line++;
30
+ column = 0;
31
+ }
32
+ }
33
+ else {
34
+ column++;
35
+ }
36
+ }
37
+ return { line, column };
38
+ }
39
+ export function isJSXElement(node) {
40
+ return node?.type === "JSXElement";
41
+ }
42
+ export function isJSXFragment(node) {
43
+ return node?.type === "JSXFragment";
44
+ }
45
+ export function isJSXAttribute(node) {
46
+ return node?.type === "JSXAttribute";
47
+ }
48
+ export function isJSXSpreadAttribute(node) {
49
+ return node?.type === "JSXSpreadAttribute";
50
+ }
51
+ export function isCallExpression(node) {
52
+ return node?.type === "CallExpression";
53
+ }
54
+ export function isImportDeclaration(node) {
55
+ return node?.type === "ImportDeclaration";
56
+ }
57
+ /**
58
+ * Stringify a JSX element/attribute name node:
59
+ * <Foo /> → "Foo" (JSXIdentifier)
60
+ * <Foo.Bar /> → "Foo.Bar" (JSXMemberExpression)
61
+ * <svg:rect /> → "svg:rect" (JSXNamespacedName)
62
+ * <a.b.c /> → "a.b.c" (nested JSXMemberExpression)
63
+ */
64
+ export function getJSXName(el) {
65
+ const name = "openingElement" in el ? el.openingElement.name : el;
66
+ return stringifyJSXName(name);
67
+ }
68
+ function stringifyJSXName(name) {
69
+ if (name.type === "JSXIdentifier")
70
+ return name.name;
71
+ if (name.type === "JSXNamespacedName") {
72
+ return `${name.namespace.name}:${name.name.name}`;
73
+ }
74
+ // JSXMemberExpression — may be nested
75
+ return `${stringifyJSXName(name.object)}.${name.property.name}`;
76
+ }
77
+ //# sourceMappingURL=oxc-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oxc-helpers.js","sourceRoot":"","sources":["../src/oxc-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,MAAc;IACvD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrD,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvB,IAAI,EAAE,CAAC;YACP,MAAM,GAAG,CAAC,CAAC;QACb,CAAC;aAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC9B,yDAAyD;YACzD,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC3B,IAAI,EAAE,CAAC;gBACP,MAAM,GAAG,CAAC,CAAC;YACb,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,OAAQ,IAAa,EAAE,IAAI,KAAK,YAAY,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,OAAQ,IAAa,EAAE,IAAI,KAAK,aAAa,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAQ,IAAa,EAAE,IAAI,KAAK,cAAc,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAa;IAChD,OAAQ,IAAa,EAAE,IAAI,KAAK,oBAAoB,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAQ,IAAa,EAAE,IAAI,KAAK,gBAAgB,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,OAAQ,IAAa,EAAE,IAAI,KAAK,mBAAmB,CAAC;AACtD,CAAC;AAID;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,EAA2E;IAE3E,MAAM,IAAI,GAAG,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAE,EAAc,CAAC;IAC/E,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAa;IACrC,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IACpD,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACtC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,sCAAsC;IACtC,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@component-compass/ast-utils",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "Shared AST utilities for component-compass parsers and manifest plugins. Internal infrastructure.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -24,14 +24,16 @@
24
24
  "clean": "rm -rf dist .turbo"
25
25
  },
26
26
  "dependencies": {
27
- "@babel/traverse": "^7.29.0",
28
- "parse5": "^8.0.0"
27
+ "@component-compass/plugin-core": "0.1.0",
28
+ "@oxc-project/types": "0.130.0",
29
+ "oxc-walker": "1.0.0",
30
+ "parse5": "8.0.1"
29
31
  },
30
32
  "devDependencies": {
31
- "@types/babel__traverse": "^7.28.0",
32
- "@types/node": "^24.0.0",
33
- "typescript": "^5.9.0",
34
- "vitest": "^4.0.0"
33
+ "@types/node": "24.12.2",
34
+ "oxc-parser": "0.130.0",
35
+ "typescript": "5.9.3",
36
+ "vitest": "4.1.5"
35
37
  },
36
38
  "engines": {
37
39
  "node": ">=24"
@@ -1,2 +0,0 @@
1
- import type traverseType from "@babel/traverse";
2
- export declare const traverse: typeof traverseType.default;
@@ -1,15 +0,0 @@
1
- import { createRequire } from "node:module";
2
- /**
3
- * @babel/traverse is a CJS-only package ("type": "commonjs"). Under our
4
- * module: NodeNext setup, Node's CJS-from-ESM default-import interop puts
5
- * module.exports itself on the default binding (not module.exports.default),
6
- * so the bare `import traverse from "@babel/traverse"` shape used in the
7
- * Babel docs fails at call time. Babel docs assume bundler/esModuleInterop
8
- * context, which auto-unwraps default — Node-native ESM does not.
9
- *
10
- * createRequire is Node's official escape hatch for loading CJS from ESM.
11
- * Vitest also implements it. No runtime branching needed.
12
- */
13
- const require = createRequire(import.meta.url);
14
- export const traverse = require("@babel/traverse").default;
15
- //# sourceMappingURL=babel-interop.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"babel-interop.js","sourceRoot":"","sources":["../src/babel-interop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,QAAQ,GAAgC,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC"}