@shrkcrft/framework-scanners 0.1.0-alpha.21 → 0.1.0-alpha.23

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.
@@ -127,11 +127,26 @@ function visitTopLevel(stmt, input, out) {
127
127
  }
128
128
  return;
129
129
  }
130
- // export default function Foo() {}
131
- if (ts.isExportAssignment(stmt) && ts.isFunctionExpression(stmt.expression)) {
132
- const name = stmt.expression.name?.text ?? 'Default';
133
- if (/^[A-Z]/.test(name) && containsJsx(stmt.expression)) {
134
- out.push({ id: makeComponentId(input.filePath, name), name, node: stmt.expression });
130
+ // export default function () { return <div />; } (anonymous declaration)
131
+ if (ts.isFunctionDeclaration(stmt) && !stmt.name && isExportDefault(stmt) && containsJsx(stmt)) {
132
+ const name = defaultComponentName(input.filePath);
133
+ out.push({ id: makeComponentId(input.filePath, name), name, node: stmt });
134
+ return;
135
+ }
136
+ // export default function Foo() {} / export default () => <div />
137
+ if (ts.isExportAssignment(stmt) && !stmt.isExportEquals) {
138
+ const expr = stmt.expression;
139
+ if (ts.isFunctionExpression(expr)) {
140
+ const name = expr.name?.text ?? defaultComponentName(input.filePath);
141
+ if (/^[A-Z]/.test(name) && containsJsx(expr)) {
142
+ out.push({ id: makeComponentId(input.filePath, name), name, node: expr });
143
+ }
144
+ return;
145
+ }
146
+ if (ts.isArrowFunction(expr) && containsJsx(expr)) {
147
+ const name = defaultComponentName(input.filePath);
148
+ out.push({ id: makeComponentId(input.filePath, name), name, node: expr });
149
+ return;
135
150
  }
136
151
  return;
137
152
  }
@@ -184,6 +199,35 @@ function isAncestor(ancestor, descendant) {
184
199
  function makeComponentId(path, name) {
185
200
  return `framework:react:component:${path}#${name}`;
186
201
  }
202
+ /** True when a function declaration carries both `export` and `default`. */
203
+ function isExportDefault(node) {
204
+ const mods = node.modifiers;
205
+ if (!mods)
206
+ return false;
207
+ let hasExport = false;
208
+ let hasDefault = false;
209
+ for (const m of mods) {
210
+ if (m.kind === ts.SyntaxKind.ExportKeyword)
211
+ hasExport = true;
212
+ else if (m.kind === ts.SyntaxKind.DefaultKeyword)
213
+ hasDefault = true;
214
+ }
215
+ return hasExport && hasDefault;
216
+ }
217
+ /**
218
+ * Deterministic PascalCase component name for a nameless default export,
219
+ * derived from the file basename (`home-page.tsx` → `HomePage`). Falls
220
+ * back to `Default` when the basename yields nothing usable.
221
+ */
222
+ function defaultComponentName(filePath) {
223
+ const base = nodePath.basename(filePath).replace(/\.[^.]+$/, '');
224
+ const pascal = base
225
+ .split(/[^A-Za-z0-9]+/)
226
+ .filter(Boolean)
227
+ .map((p) => p.charAt(0).toUpperCase() + p.slice(1))
228
+ .join('');
229
+ return /^[A-Za-z]/.test(pascal) ? pascal : 'Default';
230
+ }
187
231
  function edge(from, to, kind, data) {
188
232
  return {
189
233
  id: createHash('sha1').update(`${from}|${to}|${kind}`).digest('hex'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shrkcrft/framework-scanners",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "SharkCraft framework-aware extractors. Plugin-shaped enrichment for the code graph: NestJS controllers/modules/providers, React components/hooks, future Angular/Express/Next.",
5
5
  "license": "MIT",
6
6
  "author": "SharkCraft contributors",
@@ -45,9 +45,9 @@
45
45
  "typecheck": "tsc --noEmit -p tsconfig.json"
46
46
  },
47
47
  "dependencies": {
48
- "@shrkcrft/core": "^0.1.0-alpha.21",
49
- "@shrkcrft/graph": "^0.1.0-alpha.21",
50
- "@shrkcrft/packs": "^0.1.0-alpha.21",
48
+ "@shrkcrft/core": "^0.1.0-alpha.23",
49
+ "@shrkcrft/graph": "^0.1.0-alpha.23",
50
+ "@shrkcrft/packs": "^0.1.0-alpha.23",
51
51
  "typescript": "^5.5.0"
52
52
  },
53
53
  "publishConfig": {