@leadconnector/vibe-tagger 0.1.1 → 0.3.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.
- package/dist/index.cjs +222 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +212 -9
- package/dist/index.js.map +1 -1
- package/package.json +10 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -26,12 +36,18 @@ module.exports = __toCommonJS(src_exports);
|
|
|
26
36
|
|
|
27
37
|
// src/devRuntimeCode.ts
|
|
28
38
|
var devRuntimeCode = [
|
|
29
|
-
'import * as React from "react";',
|
|
30
39
|
'import * as ReactJSXDevRuntime from "react/jsx-dev-runtime";',
|
|
31
40
|
"",
|
|
32
41
|
"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;",
|
|
33
42
|
"export const Fragment = ReactJSXDevRuntime.Fragment;",
|
|
34
43
|
"",
|
|
44
|
+
// SSR/test guard. Vite SSR, vitest, and Node prerender contexts have no
|
|
45
|
+
// `window` — touching it at module init would crash before any component
|
|
46
|
+
// renders. We still install the wrapper so React's JSX dev runtime stays
|
|
47
|
+
// wired up, but skip the per-element tagging path entirely. Matches
|
|
48
|
+
// lovable-tagger >=1.3.0.
|
|
49
|
+
'const _isBrowser = typeof window !== "undefined";',
|
|
50
|
+
"",
|
|
35
51
|
'const SOURCE_KEY = Symbol.for("__jsxSource__");',
|
|
36
52
|
"",
|
|
37
53
|
"const cleanFileName = (fileName) => {",
|
|
@@ -47,7 +63,9 @@ var devRuntimeCode = [
|
|
|
47
63
|
"};",
|
|
48
64
|
"",
|
|
49
65
|
"const sourceElementMap = new Map();",
|
|
50
|
-
"
|
|
66
|
+
"if (_isBrowser) {",
|
|
67
|
+
" window.sourceElementMap = sourceElementMap;",
|
|
68
|
+
"}",
|
|
51
69
|
"",
|
|
52
70
|
"function getSourceKey(sourceInfo) {",
|
|
53
71
|
" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;",
|
|
@@ -87,6 +105,13 @@ var devRuntimeCode = [
|
|
|
87
105
|
"}",
|
|
88
106
|
"",
|
|
89
107
|
"export function jsxDEV(type, props, key, isStatic, source, self) {",
|
|
108
|
+
" // During SSR / non-browser execution, skip all tagging and pass",
|
|
109
|
+
" // straight through to React. Touching DOM refs or the source map",
|
|
110
|
+
" // here would crash on Node-only paths (Vite SSR, vitest, etc.).",
|
|
111
|
+
" if (!_isBrowser) {",
|
|
112
|
+
" return _jsxDEV(type, props, key, isStatic, source, self);",
|
|
113
|
+
" }",
|
|
114
|
+
"",
|
|
90
115
|
" // For custom components (like <Icon />, <Button />), tag their rendered output",
|
|
91
116
|
" // This captures the JSX element name for library components that don't have source info",
|
|
92
117
|
' if (source?.fileName && typeof type !== "string" && type !== Fragment) {',
|
|
@@ -181,33 +206,221 @@ function createJsxTaggerFeature() {
|
|
|
181
206
|
};
|
|
182
207
|
}
|
|
183
208
|
|
|
209
|
+
// src/features/tailwindConfig.ts
|
|
210
|
+
var esbuild = __toESM(require("esbuild"), 1);
|
|
211
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
212
|
+
var import_path = __toESM(require("path"), 1);
|
|
213
|
+
var import_resolveConfig = __toESM(require("tailwindcss/resolveConfig.js"), 1);
|
|
214
|
+
var V4_CSS_CANDIDATES = [
|
|
215
|
+
"src/styles.css",
|
|
216
|
+
"src/index.css",
|
|
217
|
+
"src/globals.css",
|
|
218
|
+
"src/app.css"
|
|
219
|
+
];
|
|
220
|
+
var V4_NAMESPACES = {
|
|
221
|
+
colors: "--color",
|
|
222
|
+
screens: "--breakpoint",
|
|
223
|
+
spacing: "--spacing",
|
|
224
|
+
borderRadius: "--radius",
|
|
225
|
+
fontFamily: "--font",
|
|
226
|
+
opacity: "--opacity"
|
|
227
|
+
};
|
|
228
|
+
var OUTFILE_RELATIVE = "./src/tailwind.config.vibe.json";
|
|
229
|
+
var INTERMEDIATE_RELATIVE = "./.vibe.tailwind.config.js";
|
|
230
|
+
var V3_CONFIG_RELATIVE = "./tailwind.config.ts";
|
|
231
|
+
async function findV4CssEntry(projectRoot) {
|
|
232
|
+
for (const candidate of V4_CSS_CANDIDATES) {
|
|
233
|
+
const abs = import_path.default.resolve(projectRoot, candidate);
|
|
234
|
+
try {
|
|
235
|
+
const contents = await import_promises.default.readFile(abs, "utf8");
|
|
236
|
+
if (/@import\s+["']tailwindcss/.test(contents))
|
|
237
|
+
return abs;
|
|
238
|
+
} catch {
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
async function loadDesignSystemFromProject() {
|
|
244
|
+
try {
|
|
245
|
+
const modName = "@tailwindcss/node";
|
|
246
|
+
const mod = await import(modName);
|
|
247
|
+
return mod.__unstable__loadDesignSystem ?? null;
|
|
248
|
+
} catch {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function parseRootVars(css) {
|
|
253
|
+
const vars = {};
|
|
254
|
+
const rootMatch = css.match(/:root\s*\{([^}]*)\}/s);
|
|
255
|
+
if (!rootMatch)
|
|
256
|
+
return vars;
|
|
257
|
+
for (const decl of rootMatch[1].split(";")) {
|
|
258
|
+
const trimmed = decl.trim();
|
|
259
|
+
if (!trimmed.startsWith("--"))
|
|
260
|
+
continue;
|
|
261
|
+
const colon = trimmed.indexOf(":");
|
|
262
|
+
if (colon === -1)
|
|
263
|
+
continue;
|
|
264
|
+
const key = trimmed.slice(0, colon).trim();
|
|
265
|
+
const value = trimmed.slice(colon + 1).trim();
|
|
266
|
+
if (key && value)
|
|
267
|
+
vars[key] = value;
|
|
268
|
+
}
|
|
269
|
+
return vars;
|
|
270
|
+
}
|
|
271
|
+
function resolveVars(value, rootVars, depth = 0) {
|
|
272
|
+
if (depth > 8)
|
|
273
|
+
return value;
|
|
274
|
+
return value.replace(
|
|
275
|
+
/var\(\s*(--[\w-]+)(?:\s*,\s*([^)]+))?\s*\)/g,
|
|
276
|
+
(match, name, fallback) => {
|
|
277
|
+
const resolved = rootVars[name];
|
|
278
|
+
if (resolved !== void 0)
|
|
279
|
+
return resolveVars(resolved, rootVars, depth + 1);
|
|
280
|
+
return fallback ?? match;
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
async function generateV4Config(cssEntry, outfile, load) {
|
|
285
|
+
const css = await import_promises.default.readFile(cssEntry, "utf8");
|
|
286
|
+
const ds = await load(css, { base: import_path.default.dirname(cssEntry) });
|
|
287
|
+
const rootVars = parseRootVars(css);
|
|
288
|
+
const theme = {};
|
|
289
|
+
for (const [configKey, namespace] of Object.entries(V4_NAMESPACES)) {
|
|
290
|
+
const entries = {};
|
|
291
|
+
for (const [key, rawValue] of ds.theme.namespace(namespace)) {
|
|
292
|
+
if (key === null)
|
|
293
|
+
continue;
|
|
294
|
+
entries[key] = resolveVars(rawValue, rootVars);
|
|
295
|
+
}
|
|
296
|
+
theme[configKey] = entries;
|
|
297
|
+
}
|
|
298
|
+
await import_promises.default.mkdir(import_path.default.dirname(outfile), { recursive: true });
|
|
299
|
+
await import_promises.default.writeFile(outfile, JSON.stringify({ theme }, null, 2));
|
|
300
|
+
}
|
|
301
|
+
async function generateV3Config(tailwindInputFile, tailwindIntermediateFile, tailwindJsonOutfile) {
|
|
302
|
+
await esbuild.build({
|
|
303
|
+
entryPoints: [tailwindInputFile],
|
|
304
|
+
outfile: tailwindIntermediateFile,
|
|
305
|
+
bundle: true,
|
|
306
|
+
format: "esm",
|
|
307
|
+
banner: {
|
|
308
|
+
js: 'import { createRequire } from "module"; const require = createRequire(import.meta.url);'
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
try {
|
|
312
|
+
const userConfig = await import(tailwindIntermediateFile + "?update=" + Date.now());
|
|
313
|
+
if (!userConfig || !userConfig.default) {
|
|
314
|
+
throw new Error("Invalid Tailwind config structure");
|
|
315
|
+
}
|
|
316
|
+
const resolved = (0, import_resolveConfig.default)(userConfig.default);
|
|
317
|
+
await import_promises.default.writeFile(tailwindJsonOutfile, JSON.stringify(resolved, null, 2));
|
|
318
|
+
} finally {
|
|
319
|
+
await import_promises.default.unlink(tailwindIntermediateFile).catch(() => {
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function createTailwindConfigFeature() {
|
|
324
|
+
let projectRoot = "";
|
|
325
|
+
const run = async () => {
|
|
326
|
+
if (!projectRoot)
|
|
327
|
+
return;
|
|
328
|
+
const outfile = import_path.default.resolve(projectRoot, OUTFILE_RELATIVE);
|
|
329
|
+
const cssEntry = await findV4CssEntry(projectRoot);
|
|
330
|
+
if (cssEntry) {
|
|
331
|
+
const load = await loadDesignSystemFromProject();
|
|
332
|
+
if (load) {
|
|
333
|
+
try {
|
|
334
|
+
await generateV4Config(cssEntry, outfile, load);
|
|
335
|
+
console.log(`[vibe-tagger] wrote ${outfile}`);
|
|
336
|
+
return;
|
|
337
|
+
} catch (error) {
|
|
338
|
+
console.error("[vibe-tagger] Error generating v4 tailwind config:", error);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const v3ConfigFile = import_path.default.resolve(projectRoot, V3_CONFIG_RELATIVE);
|
|
344
|
+
try {
|
|
345
|
+
await import_promises.default.access(v3ConfigFile);
|
|
346
|
+
} catch {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const intermediate = import_path.default.resolve(projectRoot, INTERMEDIATE_RELATIVE);
|
|
350
|
+
try {
|
|
351
|
+
await generateV3Config(v3ConfigFile, intermediate, outfile);
|
|
352
|
+
console.log(`[vibe-tagger] wrote ${outfile}`);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error("[vibe-tagger] Error generating v3 tailwind config:", error);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
return {
|
|
358
|
+
onConfigResolved(config) {
|
|
359
|
+
projectRoot = config.root;
|
|
360
|
+
},
|
|
361
|
+
async onBuildStart() {
|
|
362
|
+
await run();
|
|
363
|
+
},
|
|
364
|
+
onConfigureServer(server) {
|
|
365
|
+
try {
|
|
366
|
+
const v3ConfigFile = import_path.default.resolve(projectRoot, V3_CONFIG_RELATIVE);
|
|
367
|
+
const v4Candidates = V4_CSS_CANDIDATES.map(
|
|
368
|
+
(c) => import_path.default.resolve(projectRoot, c)
|
|
369
|
+
);
|
|
370
|
+
const watchPaths = [v3ConfigFile, ...v4Candidates];
|
|
371
|
+
for (const p of watchPaths)
|
|
372
|
+
server.watcher.add(p);
|
|
373
|
+
const normalized = new Set(watchPaths.map((p) => import_path.default.normalize(p)));
|
|
374
|
+
server.watcher.on("change", async (changedPath) => {
|
|
375
|
+
if (normalized.has(import_path.default.normalize(changedPath)))
|
|
376
|
+
await run();
|
|
377
|
+
});
|
|
378
|
+
} catch (error) {
|
|
379
|
+
console.error("[vibe-tagger] Error adding tailwind watcher:", error);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
184
385
|
// src/plugin.ts
|
|
185
386
|
function vibeTagger({
|
|
186
387
|
jsxSource = true,
|
|
187
|
-
|
|
388
|
+
tailwindConfig = false,
|
|
389
|
+
debug: _debug = false
|
|
188
390
|
} = {}) {
|
|
189
391
|
const features = [];
|
|
190
|
-
if (jsxSource)
|
|
392
|
+
if (jsxSource)
|
|
191
393
|
features.push(createJsxTaggerFeature());
|
|
192
|
-
|
|
394
|
+
if (tailwindConfig)
|
|
395
|
+
features.push(createTailwindConfigFeature());
|
|
193
396
|
return {
|
|
194
397
|
name: "vibe-tagger",
|
|
195
398
|
enforce: "pre",
|
|
399
|
+
configResolved(config) {
|
|
400
|
+
for (const feature of features)
|
|
401
|
+
feature.onConfigResolved?.(config);
|
|
402
|
+
},
|
|
403
|
+
async buildStart() {
|
|
404
|
+
for (const feature of features)
|
|
405
|
+
await feature.onBuildStart?.();
|
|
406
|
+
},
|
|
407
|
+
configureServer(server) {
|
|
408
|
+
for (const feature of features)
|
|
409
|
+
feature.onConfigureServer?.(server);
|
|
410
|
+
},
|
|
196
411
|
resolveId(id, importer) {
|
|
197
412
|
for (const feature of features) {
|
|
198
413
|
const result = feature.resolveId?.(id, importer);
|
|
199
|
-
if (result !== null && result !== void 0)
|
|
414
|
+
if (result !== null && result !== void 0)
|
|
200
415
|
return result;
|
|
201
|
-
}
|
|
202
416
|
}
|
|
203
417
|
return null;
|
|
204
418
|
},
|
|
205
419
|
load(id) {
|
|
206
420
|
for (const feature of features) {
|
|
207
421
|
const result = feature.load?.(id);
|
|
208
|
-
if (result !== null && result !== void 0)
|
|
422
|
+
if (result !== null && result !== void 0)
|
|
209
423
|
return result;
|
|
210
|
-
}
|
|
211
424
|
}
|
|
212
425
|
return null;
|
|
213
426
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/devRuntimeCode.ts","../src/features/jsxSource.ts","../src/plugin.ts"],"sourcesContent":["export { vibeTagger as componentTagger } from \"./plugin\";\nexport type { VibeTaggerOptions } from \"./plugin\";\n","// Runtime code that replaces react/jsx-dev-runtime in the browser.\n// Served as a virtual module by the Vite plugin.\n\nconst devRuntimeCode = [\n 'import * as React from \"react\";',\n 'import * as ReactJSXDevRuntime from \"react/jsx-dev-runtime\";',\n \"\",\n \"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;\",\n \"export const Fragment = ReactJSXDevRuntime.Fragment;\",\n \"\",\n 'const SOURCE_KEY = Symbol.for(\"__jsxSource__\");',\n \"\",\n \"const cleanFileName = (fileName) => {\",\n ' if (!fileName) return \"\";',\n ' if (fileName.includes(\"dev_server\")) {',\n ' fileName = fileName.split(\"dev_server\")[1].slice(1);',\n \" }\",\n ' if (fileName.includes(\"sandbox-scheduler/sandbox\")) {',\n ' const sandboxPart = fileName.split(\"sandbox-scheduler/\")[1];',\n ' fileName = sandboxPart.split(\"/\").slice(1).join(\"/\");',\n \" }\",\n ' return fileName.replace(/^\\\\/dev-server\\\\//, \"\");',\n \"};\",\n \"\",\n \"const sourceElementMap = new Map();\",\n \"window.sourceElementMap = sourceElementMap;\",\n \"\",\n \"function getSourceKey(sourceInfo) {\",\n \" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;\",\n \"}\",\n \"\",\n \"function unregisterElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" const refs = sourceElementMap.get(key);\",\n \" if (refs) {\",\n \" for (const ref of refs) {\",\n \" if (ref.deref() === node) {\",\n \" refs.delete(ref);\",\n \" break;\",\n \" }\",\n \" }\",\n \" if (refs.size === 0) {\",\n \" sourceElementMap.delete(key);\",\n \" }\",\n \" }\",\n \"}\",\n \"\",\n \"function registerElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" if (!sourceElementMap.has(key)) {\",\n \" sourceElementMap.set(key, new Set());\",\n \" }\",\n \" sourceElementMap.get(key).add(new WeakRef(node));\",\n \"}\",\n \"\",\n \"function getTypeName(type) {\",\n ' if (typeof type === \"string\") return type;',\n ' if (typeof type === \"function\") return type.displayName || type.name || \"Unknown\";',\n ' if (typeof type === \"object\" && type !== null) {',\n ' return type.displayName || type.render?.displayName || type.render?.name || \"Unknown\";',\n \" }\",\n ' return \"Unknown\";',\n \"}\",\n \"\",\n \"export function jsxDEV(type, props, key, isStatic, source, self) {\",\n \" // For custom components (like <Icon />, <Button />), tag their rendered output\",\n \" // This captures the JSX element name for library components that don't have source info\",\n ' if (source?.fileName && typeof type !== \"string\" && type !== Fragment) {',\n \" const typeName = getTypeName(type);\",\n \" const jsxSourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: typeName,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" // Only tag if this element doesn't already have source info\",\n \" // (library components won't have it, user components will)\",\n \" if (!node[SOURCE_KEY]) {\",\n \" node[SOURCE_KEY] = jsxSourceInfo;\",\n \" registerElement(node, jsxSourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \"\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For host elements (div, span, etc.), tag with component context\",\n ' if (source?.fileName && typeof type === \"string\") {',\n \" const sourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: type,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \"\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" const existingSource = node[SOURCE_KEY];\",\n \" if (existingSource) {\",\n \" if (getSourceKey(existingSource) !== getSourceKey(sourceInfo)) {\",\n \" unregisterElement(node, existingSource);\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" } else {\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \"}\",\n].join(\"\\n\");\n\nexport default devRuntimeCode;\n","import devRuntimeCode from \"../devRuntimeCode\";\n\nexport interface JsxSourceFeature {\n resolveId(id: string, importer?: string): string | null;\n load(id: string): string | null;\n}\n\nexport function createJsxTaggerFeature(): JsxSourceFeature {\n return {\n resolveId(id: string, importer?: string): string | null {\n if (id === \"react/jsx-dev-runtime\" && !importer?.includes(\"\\0jsx-source\")) {\n return \"\\0jsx-source/jsx-dev-runtime\";\n }\n return null;\n },\n load(id: string): string | null {\n if (id === \"\\0jsx-source/jsx-dev-runtime\") {\n return devRuntimeCode;\n }\n return null;\n },\n };\n}\n","import type { Plugin } from \"vite\";\nimport { createJsxTaggerFeature } from \"./features/jsxSource\";\n\nexport interface VibeTaggerOptions {\n /** Enable JSX source tagging. Default: true */\n jsxSource?: boolean;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\nexport function vibeTagger({\n jsxSource = true,\n debug = false,\n}: VibeTaggerOptions = {}): Plugin {\n const features: ReturnType<typeof createJsxTaggerFeature>[] = [];\n\n if (jsxSource) {\n features.push(createJsxTaggerFeature());\n }\n\n return {\n name: \"vibe-tagger\",\n enforce: \"pre\",\n\n resolveId(id: string, importer?: string) {\n for (const feature of features) {\n const result = feature.resolveId?.(id, importer);\n if (result !== null && result !== undefined) {\n return result;\n }\n }\n return null;\n },\n\n load(id: string) {\n for (const feature of features) {\n const result = feature.load?.(id);\n if (result !== null && result !== undefined) {\n return result;\n }\n }\n return null;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAEX,IAAO,yBAAQ;;;ACrIR,SAAS,yBAA2C;AACzD,SAAO;AAAA,IACL,UAAU,IAAY,UAAkC;AACtD,UAAI,OAAO,2BAA2B,CAAC,UAAU,SAAS,cAAc,GAAG;AACzE,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,IAA2B;AAC9B,UAAI,OAAO,gCAAgC;AACzC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACZO,SAAS,WAAW;AAAA,EACzB,YAAY;AAAA,EACZ,QAAQ;AACV,IAAuB,CAAC,GAAW;AACjC,QAAM,WAAwD,CAAC;AAE/D,MAAI,WAAW;AACb,aAAS,KAAK,uBAAuB,CAAC;AAAA,EACxC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IAET,UAAU,IAAY,UAAmB;AACvC,iBAAW,WAAW,UAAU;AAC9B,cAAM,SAAS,QAAQ,YAAY,IAAI,QAAQ;AAC/C,YAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,IAAY;AACf,iBAAW,WAAW,UAAU;AAC9B,cAAM,SAAS,QAAQ,OAAO,EAAE;AAChC,YAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/devRuntimeCode.ts","../src/features/jsxSource.ts","../src/features/tailwindConfig.ts","../src/plugin.ts"],"sourcesContent":["export { vibeTagger as componentTagger } from \"./plugin\";\nexport type { VibeTaggerOptions } from \"./plugin\";\n","// Runtime code that replaces react/jsx-dev-runtime in the browser.\n// Served as a virtual module by the Vite plugin.\n\nconst devRuntimeCode = [\n 'import * as ReactJSXDevRuntime from \"react/jsx-dev-runtime\";',\n \"\",\n \"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;\",\n \"export const Fragment = ReactJSXDevRuntime.Fragment;\",\n \"\",\n // SSR/test guard. Vite SSR, vitest, and Node prerender contexts have no\n // `window` — touching it at module init would crash before any component\n // renders. We still install the wrapper so React's JSX dev runtime stays\n // wired up, but skip the per-element tagging path entirely. Matches\n // lovable-tagger >=1.3.0.\n 'const _isBrowser = typeof window !== \"undefined\";',\n \"\",\n 'const SOURCE_KEY = Symbol.for(\"__jsxSource__\");',\n \"\",\n \"const cleanFileName = (fileName) => {\",\n ' if (!fileName) return \"\";',\n ' if (fileName.includes(\"dev_server\")) {',\n ' fileName = fileName.split(\"dev_server\")[1].slice(1);',\n \" }\",\n ' if (fileName.includes(\"sandbox-scheduler/sandbox\")) {',\n ' const sandboxPart = fileName.split(\"sandbox-scheduler/\")[1];',\n ' fileName = sandboxPart.split(\"/\").slice(1).join(\"/\");',\n \" }\",\n ' return fileName.replace(/^\\\\/dev-server\\\\//, \"\");',\n \"};\",\n \"\",\n \"const sourceElementMap = new Map();\",\n \"if (_isBrowser) {\",\n \" window.sourceElementMap = sourceElementMap;\",\n \"}\",\n \"\",\n \"function getSourceKey(sourceInfo) {\",\n \" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;\",\n \"}\",\n \"\",\n \"function unregisterElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" const refs = sourceElementMap.get(key);\",\n \" if (refs) {\",\n \" for (const ref of refs) {\",\n \" if (ref.deref() === node) {\",\n \" refs.delete(ref);\",\n \" break;\",\n \" }\",\n \" }\",\n \" if (refs.size === 0) {\",\n \" sourceElementMap.delete(key);\",\n \" }\",\n \" }\",\n \"}\",\n \"\",\n \"function registerElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" if (!sourceElementMap.has(key)) {\",\n \" sourceElementMap.set(key, new Set());\",\n \" }\",\n \" sourceElementMap.get(key).add(new WeakRef(node));\",\n \"}\",\n \"\",\n \"function getTypeName(type) {\",\n ' if (typeof type === \"string\") return type;',\n ' if (typeof type === \"function\") return type.displayName || type.name || \"Unknown\";',\n ' if (typeof type === \"object\" && type !== null) {',\n ' return type.displayName || type.render?.displayName || type.render?.name || \"Unknown\";',\n \" }\",\n ' return \"Unknown\";',\n \"}\",\n \"\",\n \"export function jsxDEV(type, props, key, isStatic, source, self) {\",\n \" // During SSR / non-browser execution, skip all tagging and pass\",\n \" // straight through to React. Touching DOM refs or the source map\",\n \" // here would crash on Node-only paths (Vite SSR, vitest, etc.).\",\n \" if (!_isBrowser) {\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For custom components (like <Icon />, <Button />), tag their rendered output\",\n \" // This captures the JSX element name for library components that don't have source info\",\n ' if (source?.fileName && typeof type !== \"string\" && type !== Fragment) {',\n \" const typeName = getTypeName(type);\",\n \" const jsxSourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: typeName,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" // Only tag if this element doesn't already have source info\",\n \" // (library components won't have it, user components will)\",\n \" if (!node[SOURCE_KEY]) {\",\n \" node[SOURCE_KEY] = jsxSourceInfo;\",\n \" registerElement(node, jsxSourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \"\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For host elements (div, span, etc.), tag with component context\",\n ' if (source?.fileName && typeof type === \"string\") {',\n \" const sourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: type,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \"\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" const existingSource = node[SOURCE_KEY];\",\n \" if (existingSource) {\",\n \" if (getSourceKey(existingSource) !== getSourceKey(sourceInfo)) {\",\n \" unregisterElement(node, existingSource);\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" } else {\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \"}\",\n].join(\"\\n\");\n\nexport default devRuntimeCode;\n","import devRuntimeCode from \"../devRuntimeCode\";\n\nexport interface JsxSourceFeature {\n resolveId(id: string, importer?: string): string | null;\n load(id: string): string | null;\n}\n\nexport function createJsxTaggerFeature(): JsxSourceFeature {\n return {\n resolveId(id: string, importer?: string): string | null {\n if (id === \"react/jsx-dev-runtime\" && !importer?.includes(\"\\0jsx-source\")) {\n return \"\\0jsx-source/jsx-dev-runtime\";\n }\n return null;\n },\n load(id: string): string | null {\n if (id === \"\\0jsx-source/jsx-dev-runtime\") {\n return devRuntimeCode;\n }\n return null;\n },\n };\n}\n","import type { ResolvedConfig, ViteDevServer } from \"vite\";\nimport * as esbuild from \"esbuild\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport resolveConfig from \"tailwindcss/resolveConfig.js\";\n\nexport interface TailwindConfigFeature {\n onConfigResolved(config: ResolvedConfig): void;\n onBuildStart(): Promise<void>;\n onConfigureServer(server: ViteDevServer): void;\n}\n\nconst V4_CSS_CANDIDATES = [\n \"src/styles.css\",\n \"src/index.css\",\n \"src/globals.css\",\n \"src/app.css\",\n];\n\nconst V4_NAMESPACES: Record<string, string> = {\n colors: \"--color\",\n screens: \"--breakpoint\",\n spacing: \"--spacing\",\n borderRadius: \"--radius\",\n fontFamily: \"--font\",\n opacity: \"--opacity\",\n};\n\nconst OUTFILE_RELATIVE = \"./src/tailwind.config.vibe.json\";\nconst INTERMEDIATE_RELATIVE = \"./.vibe.tailwind.config.js\";\nconst V3_CONFIG_RELATIVE = \"./tailwind.config.ts\";\n\nasync function findV4CssEntry(projectRoot: string): Promise<string | null> {\n for (const candidate of V4_CSS_CANDIDATES) {\n const abs = path.resolve(projectRoot, candidate);\n try {\n const contents = await fs.readFile(abs, \"utf8\");\n if (/@import\\s+[\"']tailwindcss/.test(contents)) return abs;\n } catch {\n // missing file — try next\n }\n }\n return null;\n}\n\ntype LoadDesignSystem = (\n css: string,\n opts: { base: string },\n) => Promise<{\n theme: {\n namespace(ns: string): Iterable<[string | null, string]>;\n };\n}>;\n\nasync function loadDesignSystemFromProject(): Promise<LoadDesignSystem | null> {\n try {\n // Dynamic import so consumers not on v4 don't need the package installed.\n const modName = \"@tailwindcss/node\";\n const mod = (await import(modName)) as {\n __unstable__loadDesignSystem?: LoadDesignSystem;\n };\n return mod.__unstable__loadDesignSystem ?? null;\n } catch {\n return null;\n }\n}\n\nfunction parseRootVars(css: string): Record<string, string> {\n const vars: Record<string, string> = {};\n const rootMatch = css.match(/:root\\s*\\{([^}]*)\\}/s);\n if (!rootMatch) return vars;\n for (const decl of rootMatch[1]!.split(\";\")) {\n const trimmed = decl.trim();\n if (!trimmed.startsWith(\"--\")) continue;\n const colon = trimmed.indexOf(\":\");\n if (colon === -1) continue;\n const key = trimmed.slice(0, colon).trim();\n const value = trimmed.slice(colon + 1).trim();\n if (key && value) vars[key] = value;\n }\n return vars;\n}\n\nfunction resolveVars(\n value: string,\n rootVars: Record<string, string>,\n depth = 0,\n): string {\n if (depth > 8) return value;\n return value.replace(\n /var\\(\\s*(--[\\w-]+)(?:\\s*,\\s*([^)]+))?\\s*\\)/g,\n (match, name: string, fallback: string | undefined) => {\n const resolved = rootVars[name];\n if (resolved !== undefined) return resolveVars(resolved, rootVars, depth + 1);\n return fallback ?? match;\n },\n );\n}\n\nasync function generateV4Config(\n cssEntry: string,\n outfile: string,\n load: LoadDesignSystem,\n): Promise<void> {\n const css = await fs.readFile(cssEntry, \"utf8\");\n const ds = await load(css, { base: path.dirname(cssEntry) });\n const rootVars = parseRootVars(css);\n const theme: Record<string, Record<string, string>> = {};\n for (const [configKey, namespace] of Object.entries(V4_NAMESPACES)) {\n const entries: Record<string, string> = {};\n for (const [key, rawValue] of ds.theme.namespace(namespace)) {\n if (key === null) continue;\n entries[key] = resolveVars(rawValue, rootVars);\n }\n theme[configKey] = entries;\n }\n await fs.mkdir(path.dirname(outfile), { recursive: true });\n await fs.writeFile(outfile, JSON.stringify({ theme }, null, 2));\n}\n\nasync function generateV3Config(\n tailwindInputFile: string,\n tailwindIntermediateFile: string,\n tailwindJsonOutfile: string,\n): Promise<void> {\n await esbuild.build({\n entryPoints: [tailwindInputFile],\n outfile: tailwindIntermediateFile,\n bundle: true,\n format: \"esm\",\n banner: {\n js: 'import { createRequire } from \"module\"; const require = createRequire(import.meta.url);',\n },\n });\n try {\n const userConfig = (await import(\n tailwindIntermediateFile + \"?update=\" + Date.now()\n )) as { default?: unknown };\n if (!userConfig || !userConfig.default) {\n throw new Error(\"Invalid Tailwind config structure\");\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const resolved = (resolveConfig as any)(userConfig.default);\n await fs.writeFile(tailwindJsonOutfile, JSON.stringify(resolved, null, 2));\n } finally {\n await fs.unlink(tailwindIntermediateFile).catch(() => {});\n }\n}\n\nexport function createTailwindConfigFeature(): TailwindConfigFeature {\n let projectRoot = \"\";\n\n const run = async (): Promise<void> => {\n if (!projectRoot) return;\n const outfile = path.resolve(projectRoot, OUTFILE_RELATIVE);\n\n // Prefer v4 when the CSS entry uses `@import \"tailwindcss\"` and\n // @tailwindcss/node is available.\n const cssEntry = await findV4CssEntry(projectRoot);\n if (cssEntry) {\n const load = await loadDesignSystemFromProject();\n if (load) {\n try {\n await generateV4Config(cssEntry, outfile, load);\n console.log(`[vibe-tagger] wrote ${outfile}`);\n return;\n } catch (error) {\n console.error(\"[vibe-tagger] Error generating v4 tailwind config:\", error);\n return;\n }\n }\n }\n\n // Fall back to v3: compile tailwind.config.ts via esbuild, then resolveConfig.\n const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);\n try {\n await fs.access(v3ConfigFile);\n } catch {\n return;\n }\n const intermediate = path.resolve(projectRoot, INTERMEDIATE_RELATIVE);\n try {\n await generateV3Config(v3ConfigFile, intermediate, outfile);\n console.log(`[vibe-tagger] wrote ${outfile}`);\n } catch (error) {\n console.error(\"[vibe-tagger] Error generating v3 tailwind config:\", error);\n }\n };\n\n return {\n onConfigResolved(config) {\n projectRoot = config.root;\n },\n async onBuildStart() {\n await run();\n },\n onConfigureServer(server) {\n try {\n const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);\n const v4Candidates = V4_CSS_CANDIDATES.map((c) =>\n path.resolve(projectRoot, c),\n );\n const watchPaths = [v3ConfigFile, ...v4Candidates];\n for (const p of watchPaths) server.watcher.add(p);\n const normalized = new Set(watchPaths.map((p) => path.normalize(p)));\n server.watcher.on(\"change\", async (changedPath) => {\n if (normalized.has(path.normalize(changedPath))) await run();\n });\n } catch (error) {\n console.error(\"[vibe-tagger] Error adding tailwind watcher:\", error);\n }\n },\n };\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer } from \"vite\";\nimport { createJsxTaggerFeature } from \"./features/jsxSource\";\nimport { createTailwindConfigFeature } from \"./features/tailwindConfig\";\n\nexport interface VibeTaggerOptions {\n /** Enable JSX source tagging. Default: true */\n jsxSource?: boolean;\n /**\n * Emit a resolved Tailwind theme JSON to `src/tailwind.config.vibe.json`\n * on build start and on config-file changes. Supports Tailwind v3\n * (reads `tailwind.config.ts`) and v4 (reads `src/styles.css` etc.).\n * Default: false\n */\n tailwindConfig?: boolean;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\ninterface Feature {\n resolveId?(id: string, importer?: string): string | null;\n load?(id: string): string | null;\n onConfigResolved?(config: ResolvedConfig): void;\n onBuildStart?(): void | Promise<void>;\n onConfigureServer?(server: ViteDevServer): void;\n}\n\nexport function vibeTagger({\n jsxSource = true,\n tailwindConfig = false,\n debug: _debug = false,\n}: VibeTaggerOptions = {}): Plugin {\n const features: Feature[] = [];\n\n if (jsxSource) features.push(createJsxTaggerFeature());\n if (tailwindConfig) features.push(createTailwindConfigFeature());\n\n return {\n name: \"vibe-tagger\",\n enforce: \"pre\",\n\n configResolved(config) {\n for (const feature of features) feature.onConfigResolved?.(config);\n },\n\n async buildStart() {\n for (const feature of features) await feature.onBuildStart?.();\n },\n\n configureServer(server) {\n for (const feature of features) feature.onConfigureServer?.(server);\n },\n\n resolveId(id: string, importer?: string) {\n for (const feature of features) {\n const result = feature.resolveId?.(id, importer);\n if (result !== null && result !== undefined) return result;\n }\n return null;\n },\n\n load(id: string) {\n for (const feature of features) {\n const result = feature.load?.(id);\n if (result !== null && result !== undefined) return result;\n }\n return null;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;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","names":["path","fs","resolveConfig"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,9 +3,16 @@ import { Plugin } from 'vite';
|
|
|
3
3
|
interface VibeTaggerOptions {
|
|
4
4
|
/** Enable JSX source tagging. Default: true */
|
|
5
5
|
jsxSource?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Emit a resolved Tailwind theme JSON to `src/tailwind.config.vibe.json`
|
|
8
|
+
* on build start and on config-file changes. Supports Tailwind v3
|
|
9
|
+
* (reads `tailwind.config.ts`) and v4 (reads `src/styles.css` etc.).
|
|
10
|
+
* Default: false
|
|
11
|
+
*/
|
|
12
|
+
tailwindConfig?: boolean;
|
|
6
13
|
/** Enable debug logging. Default: false */
|
|
7
14
|
debug?: boolean;
|
|
8
15
|
}
|
|
9
|
-
declare function vibeTagger({ jsxSource, debug, }?: VibeTaggerOptions): Plugin;
|
|
16
|
+
declare function vibeTagger({ jsxSource, tailwindConfig, debug: _debug, }?: VibeTaggerOptions): Plugin;
|
|
10
17
|
|
|
11
18
|
export { type VibeTaggerOptions, vibeTagger as componentTagger };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,16 @@ import { Plugin } from 'vite';
|
|
|
3
3
|
interface VibeTaggerOptions {
|
|
4
4
|
/** Enable JSX source tagging. Default: true */
|
|
5
5
|
jsxSource?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Emit a resolved Tailwind theme JSON to `src/tailwind.config.vibe.json`
|
|
8
|
+
* on build start and on config-file changes. Supports Tailwind v3
|
|
9
|
+
* (reads `tailwind.config.ts`) and v4 (reads `src/styles.css` etc.).
|
|
10
|
+
* Default: false
|
|
11
|
+
*/
|
|
12
|
+
tailwindConfig?: boolean;
|
|
6
13
|
/** Enable debug logging. Default: false */
|
|
7
14
|
debug?: boolean;
|
|
8
15
|
}
|
|
9
|
-
declare function vibeTagger({ jsxSource, debug, }?: VibeTaggerOptions): Plugin;
|
|
16
|
+
declare function vibeTagger({ jsxSource, tailwindConfig, debug: _debug, }?: VibeTaggerOptions): Plugin;
|
|
10
17
|
|
|
11
18
|
export { type VibeTaggerOptions, vibeTagger as componentTagger };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
// src/devRuntimeCode.ts
|
|
2
2
|
var devRuntimeCode = [
|
|
3
|
-
'import * as React from "react";',
|
|
4
3
|
'import * as ReactJSXDevRuntime from "react/jsx-dev-runtime";',
|
|
5
4
|
"",
|
|
6
5
|
"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;",
|
|
7
6
|
"export const Fragment = ReactJSXDevRuntime.Fragment;",
|
|
8
7
|
"",
|
|
8
|
+
// SSR/test guard. Vite SSR, vitest, and Node prerender contexts have no
|
|
9
|
+
// `window` — touching it at module init would crash before any component
|
|
10
|
+
// renders. We still install the wrapper so React's JSX dev runtime stays
|
|
11
|
+
// wired up, but skip the per-element tagging path entirely. Matches
|
|
12
|
+
// lovable-tagger >=1.3.0.
|
|
13
|
+
'const _isBrowser = typeof window !== "undefined";',
|
|
14
|
+
"",
|
|
9
15
|
'const SOURCE_KEY = Symbol.for("__jsxSource__");',
|
|
10
16
|
"",
|
|
11
17
|
"const cleanFileName = (fileName) => {",
|
|
@@ -21,7 +27,9 @@ var devRuntimeCode = [
|
|
|
21
27
|
"};",
|
|
22
28
|
"",
|
|
23
29
|
"const sourceElementMap = new Map();",
|
|
24
|
-
"
|
|
30
|
+
"if (_isBrowser) {",
|
|
31
|
+
" window.sourceElementMap = sourceElementMap;",
|
|
32
|
+
"}",
|
|
25
33
|
"",
|
|
26
34
|
"function getSourceKey(sourceInfo) {",
|
|
27
35
|
" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;",
|
|
@@ -61,6 +69,13 @@ var devRuntimeCode = [
|
|
|
61
69
|
"}",
|
|
62
70
|
"",
|
|
63
71
|
"export function jsxDEV(type, props, key, isStatic, source, self) {",
|
|
72
|
+
" // During SSR / non-browser execution, skip all tagging and pass",
|
|
73
|
+
" // straight through to React. Touching DOM refs or the source map",
|
|
74
|
+
" // here would crash on Node-only paths (Vite SSR, vitest, etc.).",
|
|
75
|
+
" if (!_isBrowser) {",
|
|
76
|
+
" return _jsxDEV(type, props, key, isStatic, source, self);",
|
|
77
|
+
" }",
|
|
78
|
+
"",
|
|
64
79
|
" // For custom components (like <Icon />, <Button />), tag their rendered output",
|
|
65
80
|
" // This captures the JSX element name for library components that don't have source info",
|
|
66
81
|
' if (source?.fileName && typeof type !== "string" && type !== Fragment) {',
|
|
@@ -155,33 +170,221 @@ function createJsxTaggerFeature() {
|
|
|
155
170
|
};
|
|
156
171
|
}
|
|
157
172
|
|
|
173
|
+
// src/features/tailwindConfig.ts
|
|
174
|
+
import * as esbuild from "esbuild";
|
|
175
|
+
import fs from "fs/promises";
|
|
176
|
+
import path from "path";
|
|
177
|
+
import resolveConfig from "tailwindcss/resolveConfig.js";
|
|
178
|
+
var V4_CSS_CANDIDATES = [
|
|
179
|
+
"src/styles.css",
|
|
180
|
+
"src/index.css",
|
|
181
|
+
"src/globals.css",
|
|
182
|
+
"src/app.css"
|
|
183
|
+
];
|
|
184
|
+
var V4_NAMESPACES = {
|
|
185
|
+
colors: "--color",
|
|
186
|
+
screens: "--breakpoint",
|
|
187
|
+
spacing: "--spacing",
|
|
188
|
+
borderRadius: "--radius",
|
|
189
|
+
fontFamily: "--font",
|
|
190
|
+
opacity: "--opacity"
|
|
191
|
+
};
|
|
192
|
+
var OUTFILE_RELATIVE = "./src/tailwind.config.vibe.json";
|
|
193
|
+
var INTERMEDIATE_RELATIVE = "./.vibe.tailwind.config.js";
|
|
194
|
+
var V3_CONFIG_RELATIVE = "./tailwind.config.ts";
|
|
195
|
+
async function findV4CssEntry(projectRoot) {
|
|
196
|
+
for (const candidate of V4_CSS_CANDIDATES) {
|
|
197
|
+
const abs = path.resolve(projectRoot, candidate);
|
|
198
|
+
try {
|
|
199
|
+
const contents = await fs.readFile(abs, "utf8");
|
|
200
|
+
if (/@import\s+["']tailwindcss/.test(contents))
|
|
201
|
+
return abs;
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
async function loadDesignSystemFromProject() {
|
|
208
|
+
try {
|
|
209
|
+
const modName = "@tailwindcss/node";
|
|
210
|
+
const mod = await import(modName);
|
|
211
|
+
return mod.__unstable__loadDesignSystem ?? null;
|
|
212
|
+
} catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function parseRootVars(css) {
|
|
217
|
+
const vars = {};
|
|
218
|
+
const rootMatch = css.match(/:root\s*\{([^}]*)\}/s);
|
|
219
|
+
if (!rootMatch)
|
|
220
|
+
return vars;
|
|
221
|
+
for (const decl of rootMatch[1].split(";")) {
|
|
222
|
+
const trimmed = decl.trim();
|
|
223
|
+
if (!trimmed.startsWith("--"))
|
|
224
|
+
continue;
|
|
225
|
+
const colon = trimmed.indexOf(":");
|
|
226
|
+
if (colon === -1)
|
|
227
|
+
continue;
|
|
228
|
+
const key = trimmed.slice(0, colon).trim();
|
|
229
|
+
const value = trimmed.slice(colon + 1).trim();
|
|
230
|
+
if (key && value)
|
|
231
|
+
vars[key] = value;
|
|
232
|
+
}
|
|
233
|
+
return vars;
|
|
234
|
+
}
|
|
235
|
+
function resolveVars(value, rootVars, depth = 0) {
|
|
236
|
+
if (depth > 8)
|
|
237
|
+
return value;
|
|
238
|
+
return value.replace(
|
|
239
|
+
/var\(\s*(--[\w-]+)(?:\s*,\s*([^)]+))?\s*\)/g,
|
|
240
|
+
(match, name, fallback) => {
|
|
241
|
+
const resolved = rootVars[name];
|
|
242
|
+
if (resolved !== void 0)
|
|
243
|
+
return resolveVars(resolved, rootVars, depth + 1);
|
|
244
|
+
return fallback ?? match;
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
async function generateV4Config(cssEntry, outfile, load) {
|
|
249
|
+
const css = await fs.readFile(cssEntry, "utf8");
|
|
250
|
+
const ds = await load(css, { base: path.dirname(cssEntry) });
|
|
251
|
+
const rootVars = parseRootVars(css);
|
|
252
|
+
const theme = {};
|
|
253
|
+
for (const [configKey, namespace] of Object.entries(V4_NAMESPACES)) {
|
|
254
|
+
const entries = {};
|
|
255
|
+
for (const [key, rawValue] of ds.theme.namespace(namespace)) {
|
|
256
|
+
if (key === null)
|
|
257
|
+
continue;
|
|
258
|
+
entries[key] = resolveVars(rawValue, rootVars);
|
|
259
|
+
}
|
|
260
|
+
theme[configKey] = entries;
|
|
261
|
+
}
|
|
262
|
+
await fs.mkdir(path.dirname(outfile), { recursive: true });
|
|
263
|
+
await fs.writeFile(outfile, JSON.stringify({ theme }, null, 2));
|
|
264
|
+
}
|
|
265
|
+
async function generateV3Config(tailwindInputFile, tailwindIntermediateFile, tailwindJsonOutfile) {
|
|
266
|
+
await esbuild.build({
|
|
267
|
+
entryPoints: [tailwindInputFile],
|
|
268
|
+
outfile: tailwindIntermediateFile,
|
|
269
|
+
bundle: true,
|
|
270
|
+
format: "esm",
|
|
271
|
+
banner: {
|
|
272
|
+
js: 'import { createRequire } from "module"; const require = createRequire(import.meta.url);'
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
try {
|
|
276
|
+
const userConfig = await import(tailwindIntermediateFile + "?update=" + Date.now());
|
|
277
|
+
if (!userConfig || !userConfig.default) {
|
|
278
|
+
throw new Error("Invalid Tailwind config structure");
|
|
279
|
+
}
|
|
280
|
+
const resolved = resolveConfig(userConfig.default);
|
|
281
|
+
await fs.writeFile(tailwindJsonOutfile, JSON.stringify(resolved, null, 2));
|
|
282
|
+
} finally {
|
|
283
|
+
await fs.unlink(tailwindIntermediateFile).catch(() => {
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function createTailwindConfigFeature() {
|
|
288
|
+
let projectRoot = "";
|
|
289
|
+
const run = async () => {
|
|
290
|
+
if (!projectRoot)
|
|
291
|
+
return;
|
|
292
|
+
const outfile = path.resolve(projectRoot, OUTFILE_RELATIVE);
|
|
293
|
+
const cssEntry = await findV4CssEntry(projectRoot);
|
|
294
|
+
if (cssEntry) {
|
|
295
|
+
const load = await loadDesignSystemFromProject();
|
|
296
|
+
if (load) {
|
|
297
|
+
try {
|
|
298
|
+
await generateV4Config(cssEntry, outfile, load);
|
|
299
|
+
console.log(`[vibe-tagger] wrote ${outfile}`);
|
|
300
|
+
return;
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error("[vibe-tagger] Error generating v4 tailwind config:", error);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);
|
|
308
|
+
try {
|
|
309
|
+
await fs.access(v3ConfigFile);
|
|
310
|
+
} catch {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const intermediate = path.resolve(projectRoot, INTERMEDIATE_RELATIVE);
|
|
314
|
+
try {
|
|
315
|
+
await generateV3Config(v3ConfigFile, intermediate, outfile);
|
|
316
|
+
console.log(`[vibe-tagger] wrote ${outfile}`);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error("[vibe-tagger] Error generating v3 tailwind config:", error);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
return {
|
|
322
|
+
onConfigResolved(config) {
|
|
323
|
+
projectRoot = config.root;
|
|
324
|
+
},
|
|
325
|
+
async onBuildStart() {
|
|
326
|
+
await run();
|
|
327
|
+
},
|
|
328
|
+
onConfigureServer(server) {
|
|
329
|
+
try {
|
|
330
|
+
const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);
|
|
331
|
+
const v4Candidates = V4_CSS_CANDIDATES.map(
|
|
332
|
+
(c) => path.resolve(projectRoot, c)
|
|
333
|
+
);
|
|
334
|
+
const watchPaths = [v3ConfigFile, ...v4Candidates];
|
|
335
|
+
for (const p of watchPaths)
|
|
336
|
+
server.watcher.add(p);
|
|
337
|
+
const normalized = new Set(watchPaths.map((p) => path.normalize(p)));
|
|
338
|
+
server.watcher.on("change", async (changedPath) => {
|
|
339
|
+
if (normalized.has(path.normalize(changedPath)))
|
|
340
|
+
await run();
|
|
341
|
+
});
|
|
342
|
+
} catch (error) {
|
|
343
|
+
console.error("[vibe-tagger] Error adding tailwind watcher:", error);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
158
349
|
// src/plugin.ts
|
|
159
350
|
function vibeTagger({
|
|
160
351
|
jsxSource = true,
|
|
161
|
-
|
|
352
|
+
tailwindConfig = false,
|
|
353
|
+
debug: _debug = false
|
|
162
354
|
} = {}) {
|
|
163
355
|
const features = [];
|
|
164
|
-
if (jsxSource)
|
|
356
|
+
if (jsxSource)
|
|
165
357
|
features.push(createJsxTaggerFeature());
|
|
166
|
-
|
|
358
|
+
if (tailwindConfig)
|
|
359
|
+
features.push(createTailwindConfigFeature());
|
|
167
360
|
return {
|
|
168
361
|
name: "vibe-tagger",
|
|
169
362
|
enforce: "pre",
|
|
363
|
+
configResolved(config) {
|
|
364
|
+
for (const feature of features)
|
|
365
|
+
feature.onConfigResolved?.(config);
|
|
366
|
+
},
|
|
367
|
+
async buildStart() {
|
|
368
|
+
for (const feature of features)
|
|
369
|
+
await feature.onBuildStart?.();
|
|
370
|
+
},
|
|
371
|
+
configureServer(server) {
|
|
372
|
+
for (const feature of features)
|
|
373
|
+
feature.onConfigureServer?.(server);
|
|
374
|
+
},
|
|
170
375
|
resolveId(id, importer) {
|
|
171
376
|
for (const feature of features) {
|
|
172
377
|
const result = feature.resolveId?.(id, importer);
|
|
173
|
-
if (result !== null && result !== void 0)
|
|
378
|
+
if (result !== null && result !== void 0)
|
|
174
379
|
return result;
|
|
175
|
-
}
|
|
176
380
|
}
|
|
177
381
|
return null;
|
|
178
382
|
},
|
|
179
383
|
load(id) {
|
|
180
384
|
for (const feature of features) {
|
|
181
385
|
const result = feature.load?.(id);
|
|
182
|
-
if (result !== null && result !== void 0)
|
|
386
|
+
if (result !== null && result !== void 0)
|
|
183
387
|
return result;
|
|
184
|
-
}
|
|
185
388
|
}
|
|
186
389
|
return null;
|
|
187
390
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/devRuntimeCode.ts","../src/features/jsxSource.ts","../src/plugin.ts"],"sourcesContent":["// Runtime code that replaces react/jsx-dev-runtime in the browser.\n// Served as a virtual module by the Vite plugin.\n\nconst devRuntimeCode = [\n 'import * as React from \"react\";',\n 'import * as ReactJSXDevRuntime from \"react/jsx-dev-runtime\";',\n \"\",\n \"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;\",\n \"export const Fragment = ReactJSXDevRuntime.Fragment;\",\n \"\",\n 'const SOURCE_KEY = Symbol.for(\"__jsxSource__\");',\n \"\",\n \"const cleanFileName = (fileName) => {\",\n ' if (!fileName) return \"\";',\n ' if (fileName.includes(\"dev_server\")) {',\n ' fileName = fileName.split(\"dev_server\")[1].slice(1);',\n \" }\",\n ' if (fileName.includes(\"sandbox-scheduler/sandbox\")) {',\n ' const sandboxPart = fileName.split(\"sandbox-scheduler/\")[1];',\n ' fileName = sandboxPart.split(\"/\").slice(1).join(\"/\");',\n \" }\",\n ' return fileName.replace(/^\\\\/dev-server\\\\//, \"\");',\n \"};\",\n \"\",\n \"const sourceElementMap = new Map();\",\n \"window.sourceElementMap = sourceElementMap;\",\n \"\",\n \"function getSourceKey(sourceInfo) {\",\n \" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;\",\n \"}\",\n \"\",\n \"function unregisterElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" const refs = sourceElementMap.get(key);\",\n \" if (refs) {\",\n \" for (const ref of refs) {\",\n \" if (ref.deref() === node) {\",\n \" refs.delete(ref);\",\n \" break;\",\n \" }\",\n \" }\",\n \" if (refs.size === 0) {\",\n \" sourceElementMap.delete(key);\",\n \" }\",\n \" }\",\n \"}\",\n \"\",\n \"function registerElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" if (!sourceElementMap.has(key)) {\",\n \" sourceElementMap.set(key, new Set());\",\n \" }\",\n \" sourceElementMap.get(key).add(new WeakRef(node));\",\n \"}\",\n \"\",\n \"function getTypeName(type) {\",\n ' if (typeof type === \"string\") return type;',\n ' if (typeof type === \"function\") return type.displayName || type.name || \"Unknown\";',\n ' if (typeof type === \"object\" && type !== null) {',\n ' return type.displayName || type.render?.displayName || type.render?.name || \"Unknown\";',\n \" }\",\n ' return \"Unknown\";',\n \"}\",\n \"\",\n \"export function jsxDEV(type, props, key, isStatic, source, self) {\",\n \" // For custom components (like <Icon />, <Button />), tag their rendered output\",\n \" // This captures the JSX element name for library components that don't have source info\",\n ' if (source?.fileName && typeof type !== \"string\" && type !== Fragment) {',\n \" const typeName = getTypeName(type);\",\n \" const jsxSourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: typeName,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" // Only tag if this element doesn't already have source info\",\n \" // (library components won't have it, user components will)\",\n \" if (!node[SOURCE_KEY]) {\",\n \" node[SOURCE_KEY] = jsxSourceInfo;\",\n \" registerElement(node, jsxSourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \"\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For host elements (div, span, etc.), tag with component context\",\n ' if (source?.fileName && typeof type === \"string\") {',\n \" const sourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: type,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \"\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" const existingSource = node[SOURCE_KEY];\",\n \" if (existingSource) {\",\n \" if (getSourceKey(existingSource) !== getSourceKey(sourceInfo)) {\",\n \" unregisterElement(node, existingSource);\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" } else {\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \"}\",\n].join(\"\\n\");\n\nexport default devRuntimeCode;\n","import devRuntimeCode from \"../devRuntimeCode\";\n\nexport interface JsxSourceFeature {\n resolveId(id: string, importer?: string): string | null;\n load(id: string): string | null;\n}\n\nexport function createJsxTaggerFeature(): JsxSourceFeature {\n return {\n resolveId(id: string, importer?: string): string | null {\n if (id === \"react/jsx-dev-runtime\" && !importer?.includes(\"\\0jsx-source\")) {\n return \"\\0jsx-source/jsx-dev-runtime\";\n }\n return null;\n },\n load(id: string): string | null {\n if (id === \"\\0jsx-source/jsx-dev-runtime\") {\n return devRuntimeCode;\n }\n return null;\n },\n };\n}\n","import type { Plugin } from \"vite\";\nimport { createJsxTaggerFeature } from \"./features/jsxSource\";\n\nexport interface VibeTaggerOptions {\n /** Enable JSX source tagging. Default: true */\n jsxSource?: boolean;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\nexport function vibeTagger({\n jsxSource = true,\n debug = false,\n}: VibeTaggerOptions = {}): Plugin {\n const features: ReturnType<typeof createJsxTaggerFeature>[] = [];\n\n if (jsxSource) {\n features.push(createJsxTaggerFeature());\n }\n\n return {\n name: \"vibe-tagger\",\n enforce: \"pre\",\n\n resolveId(id: string, importer?: string) {\n for (const feature of features) {\n const result = feature.resolveId?.(id, importer);\n if (result !== null && result !== undefined) {\n return result;\n }\n }\n return null;\n },\n\n load(id: string) {\n for (const feature of features) {\n const result = feature.load?.(id);\n if (result !== null && result !== undefined) {\n return result;\n }\n }\n return null;\n },\n };\n}\n"],"mappings":";AAGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAEX,IAAO,yBAAQ;;;ACrIR,SAAS,yBAA2C;AACzD,SAAO;AAAA,IACL,UAAU,IAAY,UAAkC;AACtD,UAAI,OAAO,2BAA2B,CAAC,UAAU,SAAS,cAAc,GAAG;AACzE,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,IAA2B;AAC9B,UAAI,OAAO,gCAAgC;AACzC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACZO,SAAS,WAAW;AAAA,EACzB,YAAY;AAAA,EACZ,QAAQ;AACV,IAAuB,CAAC,GAAW;AACjC,QAAM,WAAwD,CAAC;AAE/D,MAAI,WAAW;AACb,aAAS,KAAK,uBAAuB,CAAC;AAAA,EACxC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IAET,UAAU,IAAY,UAAmB;AACvC,iBAAW,WAAW,UAAU;AAC9B,cAAM,SAAS,QAAQ,YAAY,IAAI,QAAQ;AAC/C,YAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,IAAY;AACf,iBAAW,WAAW,UAAU;AAC9B,cAAM,SAAS,QAAQ,OAAO,EAAE;AAChC,YAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/devRuntimeCode.ts","../src/features/jsxSource.ts","../src/features/tailwindConfig.ts","../src/plugin.ts"],"sourcesContent":["// Runtime code that replaces react/jsx-dev-runtime in the browser.\n// Served as a virtual module by the Vite plugin.\n\nconst devRuntimeCode = [\n 'import * as ReactJSXDevRuntime from \"react/jsx-dev-runtime\";',\n \"\",\n \"const _jsxDEV = ReactJSXDevRuntime.jsxDEV;\",\n \"export const Fragment = ReactJSXDevRuntime.Fragment;\",\n \"\",\n // SSR/test guard. Vite SSR, vitest, and Node prerender contexts have no\n // `window` — touching it at module init would crash before any component\n // renders. We still install the wrapper so React's JSX dev runtime stays\n // wired up, but skip the per-element tagging path entirely. Matches\n // lovable-tagger >=1.3.0.\n 'const _isBrowser = typeof window !== \"undefined\";',\n \"\",\n 'const SOURCE_KEY = Symbol.for(\"__jsxSource__\");',\n \"\",\n \"const cleanFileName = (fileName) => {\",\n ' if (!fileName) return \"\";',\n ' if (fileName.includes(\"dev_server\")) {',\n ' fileName = fileName.split(\"dev_server\")[1].slice(1);',\n \" }\",\n ' if (fileName.includes(\"sandbox-scheduler/sandbox\")) {',\n ' const sandboxPart = fileName.split(\"sandbox-scheduler/\")[1];',\n ' fileName = sandboxPart.split(\"/\").slice(1).join(\"/\");',\n \" }\",\n ' return fileName.replace(/^\\\\/dev-server\\\\//, \"\");',\n \"};\",\n \"\",\n \"const sourceElementMap = new Map();\",\n \"if (_isBrowser) {\",\n \" window.sourceElementMap = sourceElementMap;\",\n \"}\",\n \"\",\n \"function getSourceKey(sourceInfo) {\",\n \" return `${cleanFileName(sourceInfo.fileName)}:${sourceInfo.lineNumber}:${sourceInfo.columnNumber}`;\",\n \"}\",\n \"\",\n \"function unregisterElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" const refs = sourceElementMap.get(key);\",\n \" if (refs) {\",\n \" for (const ref of refs) {\",\n \" if (ref.deref() === node) {\",\n \" refs.delete(ref);\",\n \" break;\",\n \" }\",\n \" }\",\n \" if (refs.size === 0) {\",\n \" sourceElementMap.delete(key);\",\n \" }\",\n \" }\",\n \"}\",\n \"\",\n \"function registerElement(node, sourceInfo) {\",\n \" const key = getSourceKey(sourceInfo);\",\n \" if (!sourceElementMap.has(key)) {\",\n \" sourceElementMap.set(key, new Set());\",\n \" }\",\n \" sourceElementMap.get(key).add(new WeakRef(node));\",\n \"}\",\n \"\",\n \"function getTypeName(type) {\",\n ' if (typeof type === \"string\") return type;',\n ' if (typeof type === \"function\") return type.displayName || type.name || \"Unknown\";',\n ' if (typeof type === \"object\" && type !== null) {',\n ' return type.displayName || type.render?.displayName || type.render?.name || \"Unknown\";',\n \" }\",\n ' return \"Unknown\";',\n \"}\",\n \"\",\n \"export function jsxDEV(type, props, key, isStatic, source, self) {\",\n \" // During SSR / non-browser execution, skip all tagging and pass\",\n \" // straight through to React. Touching DOM refs or the source map\",\n \" // here would crash on Node-only paths (Vite SSR, vitest, etc.).\",\n \" if (!_isBrowser) {\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For custom components (like <Icon />, <Button />), tag their rendered output\",\n \" // This captures the JSX element name for library components that don't have source info\",\n ' if (source?.fileName && typeof type !== \"string\" && type !== Fragment) {',\n \" const typeName = getTypeName(type);\",\n \" const jsxSourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: typeName,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" // Only tag if this element doesn't already have source info\",\n \" // (library components won't have it, user components will)\",\n \" if (!node[SOURCE_KEY]) {\",\n \" node[SOURCE_KEY] = jsxSourceInfo;\",\n \" registerElement(node, jsxSourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \"\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" // For host elements (div, span, etc.), tag with component context\",\n ' if (source?.fileName && typeof type === \"string\") {',\n \" const sourceInfo = {\",\n \" fileName: cleanFileName(source.fileName),\",\n \" lineNumber: source.lineNumber,\",\n \" columnNumber: source.columnNumber,\",\n \" displayName: type,\",\n \" };\",\n \"\",\n \" const originalRef = props?.ref;\",\n \"\",\n \" const enhancedProps = {\",\n \" ...props,\",\n \" ref: (node) => {\",\n \" if (node) {\",\n \" const existingSource = node[SOURCE_KEY];\",\n \" if (existingSource) {\",\n \" if (getSourceKey(existingSource) !== getSourceKey(sourceInfo)) {\",\n \" unregisterElement(node, existingSource);\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" } else {\",\n \" node[SOURCE_KEY] = sourceInfo;\",\n \" registerElement(node, sourceInfo);\",\n \" }\",\n \" }\",\n ' if (typeof originalRef === \"function\") {',\n \" originalRef(node);\",\n ' } else if (originalRef && typeof originalRef === \"object\") {',\n \" originalRef.current = node;\",\n \" }\",\n \" },\",\n \" };\",\n \" return _jsxDEV(type, enhancedProps, key, isStatic, source, self);\",\n \" }\",\n \"\",\n \" return _jsxDEV(type, props, key, isStatic, source, self);\",\n \"}\",\n].join(\"\\n\");\n\nexport default devRuntimeCode;\n","import devRuntimeCode from \"../devRuntimeCode\";\n\nexport interface JsxSourceFeature {\n resolveId(id: string, importer?: string): string | null;\n load(id: string): string | null;\n}\n\nexport function createJsxTaggerFeature(): JsxSourceFeature {\n return {\n resolveId(id: string, importer?: string): string | null {\n if (id === \"react/jsx-dev-runtime\" && !importer?.includes(\"\\0jsx-source\")) {\n return \"\\0jsx-source/jsx-dev-runtime\";\n }\n return null;\n },\n load(id: string): string | null {\n if (id === \"\\0jsx-source/jsx-dev-runtime\") {\n return devRuntimeCode;\n }\n return null;\n },\n };\n}\n","import type { ResolvedConfig, ViteDevServer } from \"vite\";\nimport * as esbuild from \"esbuild\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport resolveConfig from \"tailwindcss/resolveConfig.js\";\n\nexport interface TailwindConfigFeature {\n onConfigResolved(config: ResolvedConfig): void;\n onBuildStart(): Promise<void>;\n onConfigureServer(server: ViteDevServer): void;\n}\n\nconst V4_CSS_CANDIDATES = [\n \"src/styles.css\",\n \"src/index.css\",\n \"src/globals.css\",\n \"src/app.css\",\n];\n\nconst V4_NAMESPACES: Record<string, string> = {\n colors: \"--color\",\n screens: \"--breakpoint\",\n spacing: \"--spacing\",\n borderRadius: \"--radius\",\n fontFamily: \"--font\",\n opacity: \"--opacity\",\n};\n\nconst OUTFILE_RELATIVE = \"./src/tailwind.config.vibe.json\";\nconst INTERMEDIATE_RELATIVE = \"./.vibe.tailwind.config.js\";\nconst V3_CONFIG_RELATIVE = \"./tailwind.config.ts\";\n\nasync function findV4CssEntry(projectRoot: string): Promise<string | null> {\n for (const candidate of V4_CSS_CANDIDATES) {\n const abs = path.resolve(projectRoot, candidate);\n try {\n const contents = await fs.readFile(abs, \"utf8\");\n if (/@import\\s+[\"']tailwindcss/.test(contents)) return abs;\n } catch {\n // missing file — try next\n }\n }\n return null;\n}\n\ntype LoadDesignSystem = (\n css: string,\n opts: { base: string },\n) => Promise<{\n theme: {\n namespace(ns: string): Iterable<[string | null, string]>;\n };\n}>;\n\nasync function loadDesignSystemFromProject(): Promise<LoadDesignSystem | null> {\n try {\n // Dynamic import so consumers not on v4 don't need the package installed.\n const modName = \"@tailwindcss/node\";\n const mod = (await import(modName)) as {\n __unstable__loadDesignSystem?: LoadDesignSystem;\n };\n return mod.__unstable__loadDesignSystem ?? null;\n } catch {\n return null;\n }\n}\n\nfunction parseRootVars(css: string): Record<string, string> {\n const vars: Record<string, string> = {};\n const rootMatch = css.match(/:root\\s*\\{([^}]*)\\}/s);\n if (!rootMatch) return vars;\n for (const decl of rootMatch[1]!.split(\";\")) {\n const trimmed = decl.trim();\n if (!trimmed.startsWith(\"--\")) continue;\n const colon = trimmed.indexOf(\":\");\n if (colon === -1) continue;\n const key = trimmed.slice(0, colon).trim();\n const value = trimmed.slice(colon + 1).trim();\n if (key && value) vars[key] = value;\n }\n return vars;\n}\n\nfunction resolveVars(\n value: string,\n rootVars: Record<string, string>,\n depth = 0,\n): string {\n if (depth > 8) return value;\n return value.replace(\n /var\\(\\s*(--[\\w-]+)(?:\\s*,\\s*([^)]+))?\\s*\\)/g,\n (match, name: string, fallback: string | undefined) => {\n const resolved = rootVars[name];\n if (resolved !== undefined) return resolveVars(resolved, rootVars, depth + 1);\n return fallback ?? match;\n },\n );\n}\n\nasync function generateV4Config(\n cssEntry: string,\n outfile: string,\n load: LoadDesignSystem,\n): Promise<void> {\n const css = await fs.readFile(cssEntry, \"utf8\");\n const ds = await load(css, { base: path.dirname(cssEntry) });\n const rootVars = parseRootVars(css);\n const theme: Record<string, Record<string, string>> = {};\n for (const [configKey, namespace] of Object.entries(V4_NAMESPACES)) {\n const entries: Record<string, string> = {};\n for (const [key, rawValue] of ds.theme.namespace(namespace)) {\n if (key === null) continue;\n entries[key] = resolveVars(rawValue, rootVars);\n }\n theme[configKey] = entries;\n }\n await fs.mkdir(path.dirname(outfile), { recursive: true });\n await fs.writeFile(outfile, JSON.stringify({ theme }, null, 2));\n}\n\nasync function generateV3Config(\n tailwindInputFile: string,\n tailwindIntermediateFile: string,\n tailwindJsonOutfile: string,\n): Promise<void> {\n await esbuild.build({\n entryPoints: [tailwindInputFile],\n outfile: tailwindIntermediateFile,\n bundle: true,\n format: \"esm\",\n banner: {\n js: 'import { createRequire } from \"module\"; const require = createRequire(import.meta.url);',\n },\n });\n try {\n const userConfig = (await import(\n tailwindIntermediateFile + \"?update=\" + Date.now()\n )) as { default?: unknown };\n if (!userConfig || !userConfig.default) {\n throw new Error(\"Invalid Tailwind config structure\");\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const resolved = (resolveConfig as any)(userConfig.default);\n await fs.writeFile(tailwindJsonOutfile, JSON.stringify(resolved, null, 2));\n } finally {\n await fs.unlink(tailwindIntermediateFile).catch(() => {});\n }\n}\n\nexport function createTailwindConfigFeature(): TailwindConfigFeature {\n let projectRoot = \"\";\n\n const run = async (): Promise<void> => {\n if (!projectRoot) return;\n const outfile = path.resolve(projectRoot, OUTFILE_RELATIVE);\n\n // Prefer v4 when the CSS entry uses `@import \"tailwindcss\"` and\n // @tailwindcss/node is available.\n const cssEntry = await findV4CssEntry(projectRoot);\n if (cssEntry) {\n const load = await loadDesignSystemFromProject();\n if (load) {\n try {\n await generateV4Config(cssEntry, outfile, load);\n console.log(`[vibe-tagger] wrote ${outfile}`);\n return;\n } catch (error) {\n console.error(\"[vibe-tagger] Error generating v4 tailwind config:\", error);\n return;\n }\n }\n }\n\n // Fall back to v3: compile tailwind.config.ts via esbuild, then resolveConfig.\n const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);\n try {\n await fs.access(v3ConfigFile);\n } catch {\n return;\n }\n const intermediate = path.resolve(projectRoot, INTERMEDIATE_RELATIVE);\n try {\n await generateV3Config(v3ConfigFile, intermediate, outfile);\n console.log(`[vibe-tagger] wrote ${outfile}`);\n } catch (error) {\n console.error(\"[vibe-tagger] Error generating v3 tailwind config:\", error);\n }\n };\n\n return {\n onConfigResolved(config) {\n projectRoot = config.root;\n },\n async onBuildStart() {\n await run();\n },\n onConfigureServer(server) {\n try {\n const v3ConfigFile = path.resolve(projectRoot, V3_CONFIG_RELATIVE);\n const v4Candidates = V4_CSS_CANDIDATES.map((c) =>\n path.resolve(projectRoot, c),\n );\n const watchPaths = [v3ConfigFile, ...v4Candidates];\n for (const p of watchPaths) server.watcher.add(p);\n const normalized = new Set(watchPaths.map((p) => path.normalize(p)));\n server.watcher.on(\"change\", async (changedPath) => {\n if (normalized.has(path.normalize(changedPath))) await run();\n });\n } catch (error) {\n console.error(\"[vibe-tagger] Error adding tailwind watcher:\", error);\n }\n },\n };\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer } from \"vite\";\nimport { createJsxTaggerFeature } from \"./features/jsxSource\";\nimport { createTailwindConfigFeature } from \"./features/tailwindConfig\";\n\nexport interface VibeTaggerOptions {\n /** Enable JSX source tagging. Default: true */\n jsxSource?: boolean;\n /**\n * Emit a resolved Tailwind theme JSON to `src/tailwind.config.vibe.json`\n * on build start and on config-file changes. Supports Tailwind v3\n * (reads `tailwind.config.ts`) and v4 (reads `src/styles.css` etc.).\n * Default: false\n */\n tailwindConfig?: boolean;\n /** Enable debug logging. Default: false */\n debug?: boolean;\n}\n\ninterface Feature {\n resolveId?(id: string, importer?: string): string | null;\n load?(id: string): string | null;\n onConfigResolved?(config: ResolvedConfig): void;\n onBuildStart?(): void | Promise<void>;\n onConfigureServer?(server: ViteDevServer): void;\n}\n\nexport function vibeTagger({\n jsxSource = true,\n tailwindConfig = false,\n debug: _debug = false,\n}: VibeTaggerOptions = {}): Plugin {\n const features: Feature[] = [];\n\n if (jsxSource) features.push(createJsxTaggerFeature());\n if (tailwindConfig) features.push(createTailwindConfigFeature());\n\n return {\n name: \"vibe-tagger\",\n enforce: \"pre\",\n\n configResolved(config) {\n for (const feature of features) feature.onConfigResolved?.(config);\n },\n\n async buildStart() {\n for (const feature of features) await feature.onBuildStart?.();\n },\n\n configureServer(server) {\n for (const feature of features) feature.onConfigureServer?.(server);\n },\n\n resolveId(id: string, importer?: string) {\n for (const feature of features) {\n const result = feature.resolveId?.(id, importer);\n if (result !== null && result !== undefined) return result;\n }\n return null;\n },\n\n load(id: string) {\n for (const feature of features) {\n const result = feature.load?.(id);\n if (result !== null && result !== undefined) return result;\n }\n return null;\n },\n };\n}\n"],"mappings":";AAGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,E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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadconnector/vibe-tagger",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Vite plugin that instruments React JSX elements with source-location metadata for visual editing",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"vite": ">=5.0.0 <8.0.0"
|
|
33
33
|
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@tailwindcss/node": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"esbuild": "^0.25.0",
|
|
41
|
+
"tailwindcss": "^3.4.0"
|
|
42
|
+
},
|
|
34
43
|
"devDependencies": {
|
|
35
44
|
"@types/node": "^22.5.5",
|
|
36
45
|
"rimraf": "^5.0.10",
|