@vibexdotnew/inspector 0.0.11 → 0.0.13

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,461 +1,371 @@
1
-
2
1
  "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.default = componentTagger;
5
- const parser_1 = require("@babel/parser");
6
- const magic_string_1 = require("magic-string");
7
- const estree_walker_1 = require("estree-walker");
2
+
3
+ /**
4
+ * FlexApp Element Tagger - Turbopack/Webpack Loader
5
+ *
6
+ * Transforms JSX to inject location attributes for visual editing.
7
+ * Injects: data-flex-loc="filepath:line:col" data-flex-name="tagName"
8
+ *
9
+ * SAFE: Never throws errors - returns original source on any failure
10
+ */
11
+
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ // Safe imports with fallbacks
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+
16
+ let parse, MagicString, walk;
17
+
18
+ try {
19
+ parse = require("@babel/parser").parse;
20
+ } catch {
21
+ parse = null;
22
+ }
23
+
24
+ try {
25
+ MagicString = require("magic-string");
26
+ } catch {
27
+ MagicString = null;
28
+ }
29
+
30
+ // estree-walker v3 is ESM-only, try multiple import strategies
31
+ try {
32
+ walk = require("estree-walker").walk;
33
+ } catch {
34
+ try {
35
+ // Try the sync version
36
+ const mod = require("estree-walker/src/sync.js");
37
+ walk = mod.walk || mod.default?.walk;
38
+ } catch {
39
+ walk = null;
40
+ }
41
+ }
42
+
8
43
  const path = require("path");
9
- /* ───────────────────────────────────────────── Blacklists */
10
- const threeFiberElems = [
11
- "object3D",
12
- "audioListener",
13
- "positionalAudio",
14
- "mesh",
15
- "batchedMesh",
16
- "instancedMesh",
17
- "scene",
18
- "sprite",
19
- "lOD",
20
- "skinnedMesh",
21
- "skeleton",
22
- "bone",
23
- "lineSegments",
24
- "lineLoop",
25
- "points",
26
- "group",
27
- "camera",
28
- "perspectiveCamera",
29
- "orthographicCamera",
30
- "cubeCamera",
31
- "arrayCamera",
32
- "instancedBufferGeometry",
33
- "bufferGeometry",
34
- "boxBufferGeometry",
35
- "circleBufferGeometry",
36
- "coneBufferGeometry",
37
- "cylinderBufferGeometry",
38
- "dodecahedronBufferGeometry",
39
- "extrudeBufferGeometry",
40
- "icosahedronBufferGeometry",
41
- "latheBufferGeometry",
42
- "octahedronBufferGeometry",
43
- "planeBufferGeometry",
44
- "polyhedronBufferGeometry",
45
- "ringBufferGeometry",
46
- "shapeBufferGeometry",
47
- "sphereBufferGeometry",
48
- "tetrahedronBufferGeometry",
49
- "torusBufferGeometry",
50
- "torusKnotBufferGeometry",
51
- "tubeBufferGeometry",
52
- "wireframeGeometry",
53
- "tetrahedronGeometry",
54
- "octahedronGeometry",
55
- "icosahedronGeometry",
56
- "dodecahedronGeometry",
57
- "polyhedronGeometry",
58
- "tubeGeometry",
59
- "torusKnotGeometry",
60
- "torusGeometry",
61
- "sphereGeometry",
62
- "ringGeometry",
63
- "planeGeometry",
64
- "latheGeometry",
65
- "shapeGeometry",
66
- "extrudeGeometry",
67
- "edgesGeometry",
68
- "coneGeometry",
69
- "cylinderGeometry",
70
- "circleGeometry",
71
- "boxGeometry",
72
- "capsuleGeometry",
73
- "material",
74
- "shadowMaterial",
75
- "spriteMaterial",
76
- "rawShaderMaterial",
77
- "shaderMaterial",
78
- "pointsMaterial",
79
- "meshPhysicalMaterial",
80
- "meshStandardMaterial",
81
- "meshPhongMaterial",
82
- "meshToonMaterial",
83
- "meshNormalMaterial",
84
- "meshLambertMaterial",
85
- "meshDepthMaterial",
86
- "meshDistanceMaterial",
87
- "meshBasicMaterial",
88
- "meshMatcapMaterial",
89
- "lineDashedMaterial",
90
- "lineBasicMaterial",
91
- "primitive",
92
- "light",
93
- "spotLightShadow",
94
- "spotLight",
95
- "pointLight",
96
- "rectAreaLight",
97
- "hemisphereLight",
98
- "directionalLightShadow",
99
- "directionalLight",
100
- "ambientLight",
101
- "lightShadow",
102
- "ambientLightProbe",
103
- "hemisphereLightProbe",
104
- "lightProbe",
105
- "spotLightHelper",
106
- "skeletonHelper",
107
- "pointLightHelper",
108
- "hemisphereLightHelper",
109
- "gridHelper",
110
- "polarGridHelper",
111
- "directionalLightHelper",
112
- "cameraHelper",
113
- "boxHelper",
114
- "box3Helper",
115
- "planeHelper",
116
- "arrowHelper",
117
- "axesHelper",
118
- "texture",
119
- "videoTexture",
120
- "dataTexture",
121
- "dataTexture3D",
122
- "compressedTexture",
123
- "cubeTexture",
124
- "canvasTexture",
125
- "depthTexture",
126
- "raycaster",
127
- "vector2",
128
- "vector3",
129
- "vector4",
130
- "euler",
131
- "matrix3",
132
- "matrix4",
133
- "quaternion",
134
- "bufferAttribute",
135
- "float16BufferAttribute",
136
- "float32BufferAttribute",
137
- "float64BufferAttribute",
138
- "int8BufferAttribute",
139
- "int16BufferAttribute",
140
- "int32BufferAttribute",
141
- "uint8BufferAttribute",
142
- "uint16BufferAttribute",
143
- "uint32BufferAttribute",
144
- "instancedBufferAttribute",
145
- "color",
146
- "fog",
147
- "fogExp2",
148
- "shape",
149
- "colorShiftMaterial"
150
- ];
151
- const dreiElems = [
152
- "AsciiRenderer",
153
- "Billboard",
154
- "Clone",
155
- "ComputedAttribute",
156
- "Decal",
157
- "Edges",
158
- "Effects",
159
- "GradientTexture",
160
- "MarchingCubes",
161
- "Outlines",
162
- "PositionalAudio",
163
- "Sampler",
164
- "ScreenSizer",
165
- "ScreenSpace",
166
- "Splat",
167
- "Svg",
168
- "Text",
169
- "Text3D",
170
- "Trail",
171
- "CubeCamera",
172
- "OrthographicCamera",
173
- "PerspectiveCamera",
174
- "CameraControls",
175
- "FaceControls",
176
- "KeyboardControls",
177
- "MotionPathControls",
178
- "PresentationControls",
179
- "ScrollControls",
180
- "DragControls",
181
- "GizmoHelper",
182
- "Grid",
183
- "Helper",
184
- "PivotControls",
185
- "TransformControls",
186
- "CubeTexture",
187
- "Fbx",
188
- "Gltf",
189
- "Ktx2",
190
- "Loader",
191
- "Progress",
192
- "ScreenVideoTexture",
193
- "Texture",
194
- "TrailTexture",
195
- "VideoTexture",
196
- "WebcamVideoTexture",
197
- "CycleRaycast",
198
- "DetectGPU",
199
- "Example",
200
- "FaceLandmarker",
201
- "Fbo",
202
- "Html",
203
- "Select",
204
- "SpriteAnimator",
205
- "StatsGl",
206
- "Stats",
207
- "Trail",
208
- "Wireframe",
209
- "CurveModifier",
210
- "AdaptiveDpr",
211
- "AdaptiveEvents",
212
- "BakeShadows",
213
- "Bvh",
214
- "Detailed",
215
- "Instances",
216
- "Merged",
217
- "meshBounds",
218
- "PerformanceMonitor",
219
- "Points",
220
- "Preload",
221
- "Segments",
222
- "Fisheye",
223
- "Hud",
224
- "Mask",
225
- "MeshPortalMaterial",
226
- "RenderCubeTexture",
227
- "RenderTexture",
228
- "View",
229
- "MeshDiscardMaterial",
230
- "MeshDistortMaterial",
231
- "MeshReflectorMaterial",
232
- "MeshRefractionMaterial",
233
- "MeshTransmissionMaterial",
234
- "MeshWobbleMaterial",
235
- "PointMaterial",
236
- "shaderMaterial",
237
- "SoftShadows",
238
- "CatmullRomLine",
239
- "CubicBezierLine",
240
- "Facemesh",
241
- "Line",
242
- "Mesh",
243
- "QuadraticBezierLine",
244
- "RoundedBox",
245
- "ScreenQuad",
246
- "AccumulativeShadows",
247
- "Backdrop",
248
- "BBAnchor",
249
- "Bounds",
250
- "CameraShake",
251
- "Caustics",
252
- "Center",
253
- "Cloud",
254
- "ContactShadows",
255
- "Environment",
256
- "Float",
257
- "Lightformer",
258
- "MatcapTexture",
259
- "NormalTexture",
260
- "RandomizedLight",
261
- "Resize",
262
- "ShadowAlpha",
263
- "Shadow",
264
- "Sky",
265
- "Sparkles",
266
- "SpotLightShadow",
267
- "SpotLight",
268
- "Stage",
269
- "Stars",
270
- "OrbitControls"
271
- ];
272
- const shouldTag = (name) => !threeFiberElems.includes(name) && !dreiElems.includes(name);
273
- // ➕ Collect aliases of the Next.js <Image> component so we can reliably tag it even if it was renamed.
274
- const isNextImageAlias = (aliases, name) => aliases.has(name);
275
- const extractLiteralValue = (node) => {
276
- if (!node)
277
- return undefined;
278
- switch (node.type) {
279
- case 'StringLiteral':
280
- return node.value;
281
- case 'NumericLiteral':
282
- return node.value;
283
- case 'BooleanLiteral':
284
- return node.value;
285
- case 'ObjectExpression':
286
- const obj = {};
287
- for (const prop of node.properties) {
288
- if (prop.type === 'ObjectProperty' && !prop.computed) {
289
- const key = prop.key.type === 'Identifier' ? prop.key.name : prop.key.value;
290
- obj[key] = extractLiteralValue(prop.value);
291
- }
292
- }
293
- return obj;
294
- case 'ArrayExpression':
295
- return node.elements.map((el) => extractLiteralValue(el));
296
- default:
297
- return undefined;
44
+ const fs = require("fs");
45
+
46
+ // ─────────────────────────────────────────────────────────────────────────────
47
+ // Element Exclusion Lists
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+
50
+ const EXCLUDED_ELEMENTS = new Set([
51
+ // React Three Fiber primitives
52
+ "primitive", "mesh", "group", "scene", "object3D",
53
+ "camera", "perspectiveCamera", "orthographicCamera", "cubeCamera", "arrayCamera",
54
+ "instancedMesh", "batchedMesh", "skinnedMesh", "sprite", "lOD",
55
+ "lineSegments", "lineLoop", "points", "skeleton", "bone",
56
+ "bufferGeometry", "instancedBufferGeometry",
57
+ "boxGeometry", "sphereGeometry", "planeGeometry", "cylinderGeometry",
58
+ "coneGeometry", "torusGeometry", "torusKnotGeometry", "ringGeometry",
59
+ "circleGeometry", "tubeGeometry", "extrudeGeometry", "latheGeometry",
60
+ "shapeGeometry", "polyhedronGeometry", "icosahedronGeometry",
61
+ "octahedronGeometry", "tetrahedronGeometry", "dodecahedronGeometry",
62
+ "capsuleGeometry", "edgesGeometry", "wireframeGeometry",
63
+ "material", "meshBasicMaterial", "meshStandardMaterial", "meshPhongMaterial",
64
+ "meshLambertMaterial", "meshToonMaterial", "meshNormalMaterial",
65
+ "meshPhysicalMaterial", "meshDepthMaterial", "meshDistanceMaterial",
66
+ "meshMatcapMaterial", "shaderMaterial", "rawShaderMaterial",
67
+ "pointsMaterial", "lineBasicMaterial", "lineDashedMaterial",
68
+ "spriteMaterial", "shadowMaterial",
69
+ "light", "ambientLight", "directionalLight", "pointLight", "spotLight",
70
+ "hemisphereLight", "rectAreaLight", "lightProbe",
71
+ "texture", "videoTexture", "canvasTexture", "cubeTexture",
72
+ "dataTexture", "compressedTexture", "depthTexture",
73
+ "vector2", "vector3", "vector4", "euler", "quaternion",
74
+ "matrix3", "matrix4", "color", "raycaster", "fog", "fogExp2",
75
+ // Drei components
76
+ "Billboard", "Text", "Text3D", "Html", "Trail", "Decal", "Edges", "Outlines",
77
+ "PerspectiveCamera", "OrthographicCamera", "CubeCamera",
78
+ "OrbitControls", "CameraControls", "TransformControls", "PivotControls",
79
+ "Environment", "Sky", "Stars", "Cloud", "Sparkles", "Float", "Stage",
80
+ "RoundedBox", "Line", "Points", "Instances", "Merged",
81
+ "MeshReflectorMaterial", "MeshTransmissionMaterial", "shaderMaterial",
82
+ ]);
83
+
84
+ // ─────────────────────────────────────────────────────────────────────────────
85
+ // Simple AST Walker (fallback if estree-walker fails)
86
+ // ─────────────────────────────────────────────────────────────────────────────
87
+
88
+ function simpleWalk(node, callbacks, parent = null) {
89
+ if (!node || typeof node !== "object") return;
90
+
91
+ // Add parent reference
92
+ if (parent && !Object.prototype.hasOwnProperty.call(node, "parent")) {
93
+ Object.defineProperty(node, "parent", {
94
+ value: parent,
95
+ enumerable: false,
96
+ writable: true,
97
+ });
298
98
  }
299
- };
300
- const findVariableDeclarations = (ast) => {
301
- const variables = new Map();
302
- (0, estree_walker_1.walk)(ast, {
303
- enter(node) {
304
- var _a;
305
- // Handle const/let/var declarations
306
- if (node.type === 'VariableDeclaration') {
307
- for (const declarator of node.declarations) {
308
- if (declarator.id.type === 'Identifier' && declarator.init) {
309
- const varName = declarator.id.name;
310
- const value = extractLiteralValue(declarator.init);
311
- variables.set(varName, {
312
- name: varName,
313
- type: Array.isArray(value) ? 'array' : typeof value === 'object' ? 'object' : 'primitive',
314
- value,
315
- arrayItems: Array.isArray(value) ? value : undefined,
316
- loc: (_a = declarator.loc) === null || _a === void 0 ? void 0 : _a.start
317
- });
318
- }
99
+
100
+ if (callbacks.enter) {
101
+ callbacks.enter(node, parent);
102
+ }
103
+
104
+ // Walk children
105
+ for (const key of Object.keys(node)) {
106
+ if (key === "parent") continue;
107
+ const child = node[key];
108
+ if (Array.isArray(child)) {
109
+ for (const item of child) {
110
+ if (item && typeof item === "object" && item.type) {
111
+ simpleWalk(item, callbacks, node);
319
112
  }
320
113
  }
114
+ } else if (child && typeof child === "object" && child.type) {
115
+ simpleWalk(child, callbacks, node);
321
116
  }
322
- });
323
- return variables;
324
- };
325
- const findMapContext = (node, variables) => {
326
- var _a, _b, _c, _d, _e, _f, _g;
327
- // Walk up the tree to find if this JSX element is inside a map call
328
- let current = node;
329
- let depth = 0;
330
- const maxDepth = 10; // Prevent infinite loops
331
- while (current && depth < maxDepth) {
332
- if (current.type === 'CallExpression' &&
333
- ((_a = current.callee) === null || _a === void 0 ? void 0 : _a.type) === 'MemberExpression' &&
334
- ((_c = (_b = current.callee) === null || _b === void 0 ? void 0 : _b.property) === null || _c === void 0 ? void 0 : _c.name) === 'map') {
335
- // Found a .map() call, check if it's on a known array
336
- const arrayName = (_d = current.callee.object) === null || _d === void 0 ? void 0 : _d.name;
337
- const mapCallback = (_e = current.arguments) === null || _e === void 0 ? void 0 : _e[0];
338
- if (arrayName && (mapCallback === null || mapCallback === void 0 ? void 0 : mapCallback.type) === 'ArrowFunctionExpression') {
339
- const itemParam = (_f = mapCallback.params) === null || _f === void 0 ? void 0 : _f[0];
340
- const indexParam = (_g = mapCallback.params) === null || _g === void 0 ? void 0 : _g[1];
341
- if ((itemParam === null || itemParam === void 0 ? void 0 : itemParam.type) === 'Identifier') {
342
- const varInfo = variables.get(arrayName);
117
+ }
118
+ }
119
+
120
+ // Use estree-walker if available, otherwise use simple walker
121
+ const walkAst = walk || simpleWalk;
122
+
123
+ // ─────────────────────────────────────────────────────────────────────────────
124
+ // Helpers
125
+ // ─────────────────────────────────────────────────────────────────────────────
126
+
127
+ /**
128
+ * Quick check if source likely contains JSX
129
+ */
130
+ function hasJSX(source) {
131
+ // Look for JSX patterns: <Component, <div, etc.
132
+ return /<[A-Za-z]/.test(source);
133
+ }
134
+
135
+ /**
136
+ * Check if element should receive location attributes
137
+ */
138
+ function shouldInjectAttrs(tagName) {
139
+ if (!tagName) return false;
140
+ if (tagName === "Fragment" || tagName === "React.Fragment") return false;
141
+ if (EXCLUDED_ELEMENTS.has(tagName)) return false;
142
+ return true;
143
+ }
144
+
145
+ /**
146
+ * Extract tag name from JSX opening element
147
+ */
148
+ function getTagName(node) {
149
+ try {
150
+ const { name } = node;
151
+ if (name.type === "JSXIdentifier") {
152
+ return name.name;
153
+ }
154
+ if (name.type === "JSXMemberExpression") {
155
+ return `${name.object.name}.${name.property.name}`;
156
+ }
157
+ } catch {
158
+ return null;
159
+ }
160
+ return null;
161
+ }
162
+
163
+ /**
164
+ * Detect if JSX element is inside a .map() call
165
+ */
166
+ function detectMapContext(node) {
167
+ try {
168
+ let current = node;
169
+ let depth = 0;
170
+
171
+ while (current && depth < 15) {
172
+ if (
173
+ current.type === "CallExpression" &&
174
+ current.callee?.type === "MemberExpression" &&
175
+ current.callee.property?.name === "map"
176
+ ) {
177
+ const arrayRef = current.callee.object?.name;
178
+ const callback = current.arguments?.[0];
179
+
180
+ if (arrayRef && callback?.type === "ArrowFunctionExpression") {
181
+ const indexArg = callback.params?.[1];
343
182
  return {
344
- arrayName,
345
- itemVarName: itemParam.name,
346
- arrayItems: varInfo === null || varInfo === void 0 ? void 0 : varInfo.arrayItems,
347
- arrayLoc: varInfo === null || varInfo === void 0 ? void 0 : varInfo.loc,
348
- indexVarName: (indexParam === null || indexParam === void 0 ? void 0 : indexParam.type) === 'Identifier' ? indexParam.name : undefined
183
+ arrayName: arrayRef,
184
+ indexName: indexArg?.type === "Identifier" ? indexArg.name : null,
349
185
  };
350
186
  }
351
187
  }
188
+ current = current.parent;
189
+ depth++;
352
190
  }
353
- current = current.parent;
354
- depth++;
191
+ } catch {
192
+ // Ignore errors
355
193
  }
356
194
  return null;
357
- };
358
- const getSemanticName = (node, mapContext, imageAliases) => {
359
- const getName = () => {
360
- if (node.name.type === 'JSXIdentifier')
361
- return node.name.name;
362
- if (node.name.type === 'JSXMemberExpression')
363
- return `${node.name.object.name}.${node.name.property.name}`;
364
- return null;
365
- };
366
- const tagName = getName();
367
- if (!tagName)
368
- return null;
369
- // For Next.js Image components, always return 'img' so the name is a valid HTML tag.
370
- if (isNextImageAlias(imageAliases, tagName)) {
371
- return 'img';
372
- }
373
- return isNextImageAlias(imageAliases, tagName) ? 'img' : tagName;
374
- };
375
- /* ───────────────────────────────────────────── Loader */
376
- function componentTagger(src, map) {
377
- const done = this.async();
195
+ }
196
+
197
+ /**
198
+ * Collect Next.js Image import aliases
199
+ */
200
+ function collectImageAliases(ast) {
201
+ const aliases = new Set();
202
+
378
203
  try {
379
- if (/node_modules/.test(this.resourcePath))
380
- return done(null, src, map);
381
- const ast = (0, parser_1.parse)(src, {
382
- sourceType: 'module',
383
- plugins: ['jsx', 'typescript'],
384
- });
385
- const ms = new magic_string_1.default(src);
386
- const rel = path.relative(process.cwd(), this.resourcePath);
387
- let mutated = false;
388
- // Add parent references to AST nodes for upward traversal (non-enumerable to avoid infinite recursion)
389
- (0, estree_walker_1.walk)(ast, {
390
- enter(node, parent) {
391
- if (parent && !Object.prototype.hasOwnProperty.call(node, 'parent')) {
392
- Object.defineProperty(node, 'parent', { value: parent, enumerable: false });
393
- }
394
- }
395
- });
396
- // 0️⃣ Collect variable declarations first
397
- const variables = findVariableDeclarations(ast);
398
- // 1️⃣ Gather local identifiers that reference `next/image`.
399
- const imageAliases = new Set();
400
- (0, estree_walker_1.walk)(ast, {
204
+ walkAst(ast, {
401
205
  enter(node) {
402
- if (node.type === 'ImportDeclaration' &&
403
- node.source.value === 'next/image') {
404
- for (const spec of node.specifiers) {
405
- imageAliases.add(spec.local.name);
206
+ if (
207
+ node.type === "ImportDeclaration" &&
208
+ node.source?.value === "next/image"
209
+ ) {
210
+ for (const spec of node.specifiers || []) {
211
+ if (spec.local?.name) {
212
+ aliases.add(spec.local.name);
213
+ }
406
214
  }
407
215
  }
408
216
  },
409
217
  });
410
- // 2️⃣ Inject attributes with enhanced semantic context.
411
- (0, estree_walker_1.walk)(ast, {
218
+ } catch {
219
+ // Ignore errors
220
+ }
221
+
222
+ return aliases;
223
+ }
224
+
225
+ // ─────────────────────────────────────────────────────────────────────────────
226
+ // Main Loader
227
+ // ─────────────────────────────────────────────────────────────────────────────
228
+
229
+ /**
230
+ * FlexApp Element Tagger Loader
231
+ * SAFE: Returns original source on any error
232
+ */
233
+ function flexElementTagger(source, sourceMap) {
234
+ const callback = this.async();
235
+ // return callback(null, source, sourceMap);
236
+ // Early exit: missing dependencies
237
+ if (!parse || !MagicString) {
238
+ return callback(null, source, sourceMap);
239
+ }
240
+
241
+ // Early exit: no resource path or it's a directory
242
+ if (!this.resourcePath) {
243
+ return callback(null, source, sourceMap);
244
+ }
245
+
246
+ // Early exit: path doesn't look like a file (no extension)
247
+ const ext = path.extname(this.resourcePath);
248
+ if (!ext || !['.tsx', '.jsx', '.ts', '.js'].includes(ext)) {
249
+ return callback(null, source, sourceMap);
250
+ }
251
+
252
+ // Early exit: check if it's actually a file (not a directory)
253
+ try {
254
+ const stat = fs.statSync(this.resourcePath);
255
+ if (!stat.isFile()) {
256
+ return callback(null, source, sourceMap);
257
+ }
258
+ } catch {
259
+ // If stat fails, still try to process (might be virtual file)
260
+ }
261
+
262
+ // Early exit: node_modules
263
+ if (/node_modules/.test(this.resourcePath)) {
264
+ return callback(null, source, sourceMap);
265
+ }
266
+
267
+ // Early exit: no JSX detected
268
+ if (!hasJSX(source)) {
269
+ return callback(null, source, sourceMap);
270
+ }
271
+
272
+ try {
273
+ // Parse source
274
+ const ast = parse(source, {
275
+ sourceType: "module",
276
+ plugins: ["jsx", "typescript"],
277
+ errorRecovery: true, // Don't fail on syntax errors
278
+ });
279
+
280
+ if (!ast || !ast.program) {
281
+ return callback(null, source, sourceMap);
282
+ }
283
+
284
+ const magicStr = new MagicString(source);
285
+ const relativePath = path.relative(process.cwd(), this.resourcePath);
286
+ const imageAliases = collectImageAliases(ast);
287
+ let hasChanges = false;
288
+
289
+ // Add parent references
290
+ walkAst(ast.program, {
291
+ enter() { }, // Just to trigger parent ref addition
292
+ });
293
+
294
+ // Process JSX elements
295
+ walkAst(ast.program, {
412
296
  enter(node) {
413
- var _a;
414
- if (node.type !== 'JSXOpeningElement')
415
- return;
416
- const mapContext = findMapContext(node, variables);
417
- const semanticName = getSemanticName(node, mapContext, imageAliases);
418
- if (!semanticName ||
419
- ['Fragment', 'React.Fragment'].includes(semanticName) ||
420
- (!isNextImageAlias(imageAliases, semanticName.split('-')[0]) &&
421
- !shouldTag(semanticName)))
422
- return;
423
- const { line, column } = node.loc.start;
424
- let orchidsId = `${rel}:${line}:${column}`;
425
- // Enhance the ID with context if we have map information
426
- if (mapContext) {
427
- orchidsId += `@${mapContext.arrayName}`;
428
- }
429
- // 🔍 Append referenced variable locations for simple identifier references in props
430
- (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.forEach((attr) => {
431
- var _a, _b;
432
- if (attr.type === 'JSXAttribute' &&
433
- ((_a = attr.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer' &&
434
- ((_b = attr.value.expression) === null || _b === void 0 ? void 0 : _b.type) === 'Identifier') {
435
- const refName = attr.value.expression.name;
436
- const varInfo = variables.get(refName);
437
- if (varInfo) {
438
- orchidsId += `@${refName}`;
439
- }
297
+ try {
298
+ if (node.type !== "JSXOpeningElement") return;
299
+
300
+ let tagName = getTagName(node);
301
+ if (!tagName) return;
302
+
303
+ // Check if already has data-flex-loc
304
+ const hasAttr = node.attributes?.some(
305
+ (attr) =>
306
+ attr.type === "JSXAttribute" &&
307
+ attr.name?.name === "data-flex-loc"
308
+ );
309
+ if (hasAttr) return;
310
+
311
+ // Normalize Next.js Image to img
312
+ const isNextImage = imageAliases.has(tagName.split(".")[0]);
313
+ const displayName = isNextImage ? "img" : tagName;
314
+
315
+ // Check if we should tag this element
316
+ if (!shouldInjectAttrs(tagName) && !isNextImage) return;
317
+
318
+ // Ensure we have location info
319
+ if (!node.loc?.start || !node.name?.end) return;
320
+
321
+ // Build location identifier
322
+ const { line, column } = node.loc.start;
323
+ let locId = `${relativePath}:${line}:${column}`;
324
+
325
+ // Add iteration context if inside .map()
326
+ const mapCtx = detectMapContext(node);
327
+ if (mapCtx?.arrayName) {
328
+ locId += `#${mapCtx.arrayName}`;
329
+ }
330
+
331
+ // Inject data-flex-iter for map index if available
332
+ if (mapCtx?.indexName) {
333
+ magicStr.appendLeft(
334
+ node.name.end,
335
+ ` data-flex-iter=${mapCtx.indexName}`
336
+ );
440
337
  }
441
- });
442
- // 📍 If inside a map context and we have an index variable, inject data-map-index
443
- if (mapContext === null || mapContext === void 0 ? void 0 : mapContext.indexVarName) {
444
- ms.appendLeft(node.name.end, ` data-map-index={${mapContext.indexVarName}}`);
338
+
339
+ // Inject location and name attributes
340
+ magicStr.appendLeft(
341
+ node.name.end,
342
+ ` data-flex-loc="${locId}" data-flex-name="${displayName}"`
343
+ );
344
+
345
+ hasChanges = true;
346
+ } catch {
347
+ // Ignore errors for individual nodes
445
348
  }
446
- ms.appendLeft(node.name.end, ` data-orchids-id="${orchidsId}" data-orchids-name="${semanticName}"`);
447
- mutated = true;
448
349
  },
449
350
  });
450
- if (!mutated)
451
- return done(null, src, map);
452
- const out = ms.toString();
453
- const outMap = ms.generateMap({ hires: true });
454
- /* Turbopack expects the sourcemap as a JSON *string*. */
455
- done(null, out, JSON.stringify(outMap));
456
- }
457
- catch (err) {
458
- done(err);
351
+
352
+ // Return original if no changes
353
+ if (!hasChanges) {
354
+ return callback(null, source, sourceMap);
355
+ }
356
+
357
+ // Generate output
358
+ const output = magicStr.toString();
359
+
360
+ // Return without sourcemap - Turbopack handles it better
361
+ callback(null, output);
362
+
363
+ } catch (error) {
364
+ // On ANY error, return original source unchanged
365
+ console.warn("[flex-element-tagger] Skipping file due to error:", this.resourcePath);
366
+ callback(null, source, sourceMap);
459
367
  }
460
368
  }
461
369
 
370
+ module.exports = flexElementTagger;
371
+ module.exports.default = flexElementTagger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibexdotnew/inspector",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Visual inspection and element tagging for Next.js and Expo applications",
5
5
  "author": "Vibex",
6
6
  "license": "MIT",