@vibexdotnew/inspector 0.0.7 → 0.0.9
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/next/element-tagger.js +461 -0
- package/package.json +4 -14
- package/next/element-tagger.cjs +0 -372
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
|
|
2
|
+
"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");
|
|
8
|
+
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;
|
|
298
|
+
}
|
|
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
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
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);
|
|
343
|
+
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
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
current = current.parent;
|
|
354
|
+
depth++;
|
|
355
|
+
}
|
|
356
|
+
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();
|
|
378
|
+
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, {
|
|
401
|
+
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);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
// 2️⃣ Inject attributes with enhanced semantic context.
|
|
411
|
+
(0, estree_walker_1.walk)(ast, {
|
|
412
|
+
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
|
+
}
|
|
440
|
+
}
|
|
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}}`);
|
|
445
|
+
}
|
|
446
|
+
ms.appendLeft(node.name.end, ` data-orchids-id="${orchidsId}" data-orchids-name="${semanticName}"`);
|
|
447
|
+
mutated = true;
|
|
448
|
+
},
|
|
449
|
+
});
|
|
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);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibexdotnew/inspector",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Visual inspection and element tagging for Next.js and Expo applications",
|
|
5
5
|
"author": "Vibex",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,28 +27,18 @@
|
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
"./package.json": "./package.json",
|
|
30
|
+
"./loader.js": "./next/element-tagger.js",
|
|
31
|
+
"./transformer.js": "./expo/metro-transformer.cjs",
|
|
30
32
|
"./next": {
|
|
31
33
|
"types": "./dist/next/index.d.ts",
|
|
32
34
|
"import": "./dist/next/index.js",
|
|
33
35
|
"require": "./dist/next/index.cjs"
|
|
34
36
|
},
|
|
35
|
-
"./next/loader": {
|
|
36
|
-
"types": "./dist/next/loader.d.ts",
|
|
37
|
-
"import": "./dist/next/loader.js",
|
|
38
|
-
"require": "./dist/next/loader.cjs"
|
|
39
|
-
},
|
|
40
|
-
"./next/loader.js": "./next/element-tagger.cjs",
|
|
41
37
|
"./expo": {
|
|
42
38
|
"types": "./dist/expo/index.d.ts",
|
|
43
39
|
"import": "./dist/expo/index.js",
|
|
44
40
|
"require": "./dist/expo/index.cjs"
|
|
45
|
-
}
|
|
46
|
-
"./expo/config": {
|
|
47
|
-
"types": "./dist/expo/config.d.ts",
|
|
48
|
-
"import": "./dist/expo/config.js",
|
|
49
|
-
"require": "./dist/expo/config.cjs"
|
|
50
|
-
},
|
|
51
|
-
"./expo/transformer.js": "./expo/metro-transformer.cjs"
|
|
41
|
+
}
|
|
52
42
|
},
|
|
53
43
|
"files": [
|
|
54
44
|
"dist",
|
package/next/element-tagger.cjs
DELETED
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Vibex Element Tagger - Turbopack/Webpack Loader
|
|
5
|
-
*
|
|
6
|
-
* Transforms JSX to inject location attributes for visual editing.
|
|
7
|
-
* Injects: data-vibex-loc="filepath:line:col" data-vibex-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
|
-
|
|
43
|
-
const path = require("path");
|
|
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
|
-
});
|
|
98
|
-
}
|
|
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);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} else if (child && typeof child === "object" && child.type) {
|
|
115
|
-
simpleWalk(child, callbacks, node);
|
|
116
|
-
}
|
|
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];
|
|
182
|
-
return {
|
|
183
|
-
arrayName: arrayRef,
|
|
184
|
-
indexName: indexArg?.type === "Identifier" ? indexArg.name : null,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
current = current.parent;
|
|
189
|
-
depth++;
|
|
190
|
-
}
|
|
191
|
-
} catch {
|
|
192
|
-
// Ignore errors
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Collect Next.js Image import aliases
|
|
199
|
-
*/
|
|
200
|
-
function collectImageAliases(ast) {
|
|
201
|
-
const aliases = new Set();
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
walkAst(ast, {
|
|
205
|
-
enter(node) {
|
|
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
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
} catch {
|
|
219
|
-
// Ignore errors
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return aliases;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
226
|
-
// Main Loader
|
|
227
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Vibex Element Tagger Loader
|
|
231
|
-
* SAFE: Returns original source on any error
|
|
232
|
-
*/
|
|
233
|
-
function elementTagger(source, sourceMap) {
|
|
234
|
-
const callback = this.async();
|
|
235
|
-
|
|
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, {
|
|
296
|
-
enter(node) {
|
|
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-vibex-loc
|
|
304
|
-
const hasAttr = node.attributes?.some(
|
|
305
|
-
(attr) =>
|
|
306
|
-
attr.type === "JSXAttribute" &&
|
|
307
|
-
attr.name?.name === "data-vibex-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-vibex-iter for map index if available
|
|
332
|
-
if (mapCtx?.indexName) {
|
|
333
|
-
magicStr.appendLeft(
|
|
334
|
-
node.name.end,
|
|
335
|
-
` data-vibex-iter=${mapCtx.indexName}`
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Inject location and name attributes
|
|
340
|
-
magicStr.appendLeft(
|
|
341
|
-
node.name.end,
|
|
342
|
-
` data-vibex-loc="${locId}" data-vibex-name="${displayName}"`
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
hasChanges = true;
|
|
346
|
-
} catch {
|
|
347
|
-
// Ignore errors for individual nodes
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
});
|
|
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
|
-
const outputMap = magicStr.generateMap({ hires: true });
|
|
360
|
-
|
|
361
|
-
// Turbopack expects sourcemap as JSON string
|
|
362
|
-
callback(null, output, JSON.stringify(outputMap));
|
|
363
|
-
|
|
364
|
-
} catch (error) {
|
|
365
|
-
// On ANY error, return original source unchanged
|
|
366
|
-
console.warn("[element-tagger] Skipping file due to error:", this.resourcePath);
|
|
367
|
-
callback(null, source, sourceMap);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
module.exports = elementTagger;
|
|
372
|
-
module.exports.default = elementTagger;
|