tailwind-styled-v4 5.0.0 → 5.0.1
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/CHANGELOG.md +398 -0
- package/LICENSE +21 -0
- package/README.md +532 -0
- package/dist/analyzer.d.mts +114 -0
- package/dist/analyzer.d.ts +114 -0
- package/dist/analyzer.js +1555 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/analyzer.mjs +1544 -0
- package/dist/analyzer.mjs.map +1 -0
- package/dist/{animate.d.cts → animate.d.mts} +3 -30
- package/dist/animate.d.ts +3 -30
- package/dist/animate.js +149 -99
- package/dist/animate.js.map +1 -1
- package/dist/{animate.cjs → animate.mjs} +130 -119
- package/dist/animate.mjs.map +1 -0
- package/dist/atomic.d.mts +18 -0
- package/dist/atomic.d.ts +18 -0
- package/dist/atomic.js +191 -0
- package/dist/atomic.js.map +1 -0
- package/dist/atomic.mjs +185 -0
- package/dist/atomic.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +6063 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +6053 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/compiler.d.mts +1009 -0
- package/dist/compiler.d.ts +1009 -0
- package/dist/compiler.js +4518 -0
- package/dist/compiler.js.map +1 -0
- package/dist/compiler.mjs +4443 -0
- package/dist/compiler.mjs.map +1 -0
- package/dist/dashboard.d.mts +272 -0
- package/dist/dashboard.d.ts +272 -0
- package/dist/dashboard.js +249 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/dashboard.mjs +239 -0
- package/dist/dashboard.mjs.map +1 -0
- package/dist/devtools.js +170 -157
- package/dist/devtools.js.map +1 -1
- package/dist/{devtools.cjs → devtools.mjs} +165 -166
- package/dist/devtools.mjs.map +1 -0
- package/dist/engine.d.mts +84 -0
- package/dist/engine.d.ts +84 -0
- package/dist/engine.js +3014 -0
- package/dist/engine.js.map +1 -0
- package/dist/engine.mjs +3005 -0
- package/dist/engine.mjs.map +1 -0
- package/dist/{index.d.cts → index.d.mts} +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +945 -36
- package/dist/index.js.map +1 -1
- package/dist/{index.cjs → index.mjs} +899 -90
- package/dist/index.mjs.map +1 -0
- package/dist/liveTokenEngine-DYN3Zale.d.mts +34 -0
- package/dist/liveTokenEngine-DYN3Zale.d.ts +34 -0
- package/dist/{next.d.cts → next.d.mts} +2 -1
- package/dist/next.d.ts +2 -1
- package/dist/next.js +6853 -35
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +7050 -0
- package/dist/next.mjs.map +1 -0
- package/dist/plugin.d.mts +90 -0
- package/dist/plugin.d.ts +90 -0
- package/dist/plugin.js +185 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugin.mjs +174 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/pluginRegistry.d.mts +83 -0
- package/dist/pluginRegistry.d.ts +83 -0
- package/dist/pluginRegistry.js +303 -0
- package/dist/pluginRegistry.js.map +1 -0
- package/dist/pluginRegistry.mjs +298 -0
- package/dist/pluginRegistry.mjs.map +1 -0
- package/dist/preset.js +9 -4
- package/dist/preset.js.map +1 -1
- package/dist/{preset.cjs → preset.mjs} +5 -14
- package/dist/preset.mjs.map +1 -0
- package/dist/rspack.d.mts +33 -0
- package/dist/rspack.d.ts +33 -0
- package/dist/rspack.js +55 -0
- package/dist/rspack.js.map +1 -0
- package/dist/rspack.mjs +45 -0
- package/dist/rspack.mjs.map +1 -0
- package/dist/runtime.d.mts +62 -0
- package/dist/runtime.d.ts +62 -0
- package/dist/runtime.js +207 -0
- package/dist/runtime.js.map +1 -0
- package/dist/runtime.mjs +188 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/runtimeCss.d.mts +65 -0
- package/dist/runtimeCss.d.ts +65 -0
- package/dist/{css.cjs → runtimeCss.js} +71 -4
- package/dist/runtimeCss.js.map +1 -0
- package/dist/{css.js → runtimeCss.mjs} +66 -5
- package/dist/runtimeCss.mjs.map +1 -0
- package/dist/scanner.d.mts +25 -0
- package/dist/scanner.d.ts +25 -0
- package/dist/scanner.js +717 -0
- package/dist/scanner.js.map +1 -0
- package/dist/scanner.mjs +703 -0
- package/dist/scanner.mjs.map +1 -0
- package/dist/shared.d.mts +85 -0
- package/dist/shared.d.ts +85 -0
- package/dist/shared.js +255 -0
- package/dist/shared.js.map +1 -0
- package/dist/shared.mjs +233 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/storybookAddon.d.mts +108 -0
- package/dist/storybookAddon.d.ts +108 -0
- package/dist/storybookAddon.js +95 -0
- package/dist/storybookAddon.js.map +1 -0
- package/dist/storybookAddon.mjs +88 -0
- package/dist/storybookAddon.mjs.map +1 -0
- package/dist/svelte.d.mts +114 -0
- package/dist/svelte.d.ts +114 -0
- package/dist/svelte.js +67 -0
- package/dist/svelte.js.map +1 -0
- package/dist/svelte.mjs +59 -0
- package/dist/svelte.mjs.map +1 -0
- package/dist/testing.d.mts +185 -0
- package/dist/testing.d.ts +185 -0
- package/dist/testing.js +173 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +158 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/theme.d.mts +188 -0
- package/dist/theme.d.ts +188 -0
- package/dist/theme.js +334 -0
- package/dist/theme.js.map +1 -0
- package/dist/theme.mjs +311 -0
- package/dist/theme.mjs.map +1 -0
- package/dist/types-DXr2PmGP.d.mts +31 -0
- package/dist/types-DXr2PmGP.d.ts +31 -0
- package/dist/vite.js +4181 -16
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +4281 -0
- package/dist/vite.mjs.map +1 -0
- package/dist/vue.d.mts +89 -0
- package/dist/vue.d.ts +89 -0
- package/dist/vue.js +104 -0
- package/dist/vue.js.map +1 -0
- package/dist/vue.mjs +96 -0
- package/dist/vue.mjs.map +1 -0
- package/package.json +168 -65
- package/dist/animate.cjs.map +0 -1
- package/dist/chunk-VZEJV27B.js +0 -11
- package/dist/chunk-VZEJV27B.js.map +0 -1
- package/dist/chunk-Y5D3E72P.cjs +0 -13
- package/dist/chunk-Y5D3E72P.cjs.map +0 -1
- package/dist/css.cjs.map +0 -1
- package/dist/css.d.cts +0 -30
- package/dist/css.d.ts +0 -30
- package/dist/css.js.map +0 -1
- package/dist/devtools.cjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/next.cjs +0 -248
- package/dist/next.cjs.map +0 -1
- package/dist/preset.cjs.map +0 -1
- package/dist/turbopackLoader.cjs +0 -37
- package/dist/turbopackLoader.cjs.map +0 -1
- package/dist/turbopackLoader.d.cts +0 -12
- package/dist/turbopackLoader.d.ts +0 -12
- package/dist/turbopackLoader.js +0 -35
- package/dist/turbopackLoader.js.map +0 -1
- package/dist/vite.cjs +0 -138
- package/dist/vite.cjs.map +0 -1
- package/dist/webpackLoader.cjs +0 -51
- package/dist/webpackLoader.cjs.map +0 -1
- package/dist/webpackLoader.d.cts +0 -17
- package/dist/webpackLoader.d.ts +0 -17
- package/dist/webpackLoader.js +0 -49
- package/dist/webpackLoader.js.map +0 -1
- /package/dist/{devtools.d.cts → devtools.d.mts} +0 -0
- /package/dist/{preset.d.cts → preset.d.mts} +0 -0
- /package/dist/{vite.d.cts → vite.d.mts} +0 -0
package/dist/vite.js
CHANGED
|
@@ -1,11 +1,4177 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tailwindMerge = require('tailwind-merge');
|
|
6
|
+
var fs3 = require('fs');
|
|
7
|
+
var module$1 = require('module');
|
|
8
|
+
var os = require('os');
|
|
9
|
+
var path10 = require('path');
|
|
10
|
+
var url = require('url');
|
|
11
|
+
var crypto = require('crypto');
|
|
12
|
+
var worker_threads = require('worker_threads');
|
|
13
|
+
|
|
14
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
+
|
|
17
|
+
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
18
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
19
|
+
var path10__default = /*#__PURE__*/_interopDefault(path10);
|
|
20
|
+
|
|
21
|
+
/* tailwind-styled-v4 v5.0.1 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
|
|
22
|
+
var __defProp = Object.defineProperty;
|
|
23
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
24
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
25
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
26
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
27
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
28
|
+
}) : x)(function(x) {
|
|
29
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
30
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
31
|
+
});
|
|
32
|
+
var __esm = (fn, res) => function __init() {
|
|
33
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
34
|
+
};
|
|
35
|
+
var __export = (target, all) => {
|
|
36
|
+
for (var name in all)
|
|
37
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
38
|
+
};
|
|
39
|
+
var __copyProps = (to, from, except, desc) => {
|
|
40
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
41
|
+
for (let key of __getOwnPropNames(from))
|
|
42
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
43
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
44
|
+
}
|
|
45
|
+
return to;
|
|
46
|
+
};
|
|
47
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
48
|
+
function mergeClassesStatic(classes) {
|
|
49
|
+
return tailwindMerge.twMerge(classes);
|
|
50
|
+
}
|
|
51
|
+
var init_classMerger = __esm({
|
|
52
|
+
"packages/compiler/src/classMerger.ts"() {
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
function getPlatformExtension() {
|
|
56
|
+
const platform = os__default.default.platform();
|
|
57
|
+
switch (platform) {
|
|
58
|
+
case "win32":
|
|
59
|
+
return ".node";
|
|
60
|
+
case "darwin":
|
|
61
|
+
return ".dylib";
|
|
62
|
+
case "linux":
|
|
63
|
+
return ".so";
|
|
64
|
+
default:
|
|
65
|
+
return ".node";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function formatErrorMessage(error) {
|
|
69
|
+
return error instanceof Error ? error.message : String(error);
|
|
70
|
+
}
|
|
71
|
+
function resolveRuntimeDir(dirnameValue, moduleImportUrl) {
|
|
72
|
+
if (typeof dirnameValue === "string" && dirnameValue.length > 0) return dirnameValue;
|
|
73
|
+
return path10__default.default.dirname(url.fileURLToPath(moduleImportUrl));
|
|
74
|
+
}
|
|
75
|
+
function resolveNativeBindingCandidates(options) {
|
|
76
|
+
const out = [];
|
|
77
|
+
const envVarNames = options.envVarNames ?? ["TWS_NATIVE_PATH"];
|
|
78
|
+
for (const envVarName of envVarNames) {
|
|
79
|
+
const raw = process.env[envVarName]?.trim();
|
|
80
|
+
if (!raw) continue;
|
|
81
|
+
const resolved = path10__default.default.resolve(raw);
|
|
82
|
+
if (options.enforceNodeExtensionForEnvPath) {
|
|
83
|
+
if (path10__default.default.extname(resolved).toLowerCase() !== ".node") {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Invalid native binding path from ${envVarName}="${raw}". Expected a .node file.`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
out.push(resolved);
|
|
90
|
+
}
|
|
91
|
+
if (options.includeDefaultCandidates !== false) {
|
|
92
|
+
const ext = options.platformExtension ?? getPlatformExtension();
|
|
93
|
+
const defaultBindingName = `tailwind_styled_parser${ext}`;
|
|
94
|
+
out.push(path10__default.default.resolve(process.cwd(), "native", defaultBindingName));
|
|
95
|
+
out.push(path10__default.default.resolve(options.runtimeDir, "..", "..", "..", "native", defaultBindingName));
|
|
96
|
+
}
|
|
97
|
+
return Array.from(new Set(out));
|
|
98
|
+
}
|
|
99
|
+
function parseDebugToken(namespace, token) {
|
|
100
|
+
if (token === "*" || token === namespace || token === "tailwind-styled:*") return true;
|
|
101
|
+
return token.endsWith("*") && namespace.startsWith(token.slice(0, -1));
|
|
102
|
+
}
|
|
103
|
+
function isDebugNamespaceEnabled(namespace) {
|
|
104
|
+
if (process.env.TWS_DEBUG === "1" || process.env.TAILWIND_STYLED_DEBUG === "1") return true;
|
|
105
|
+
const raw = process.env.DEBUG;
|
|
106
|
+
if (!raw) return false;
|
|
107
|
+
return raw.split(",").map((token) => token.trim()).some((token) => parseDebugToken(namespace, token));
|
|
108
|
+
}
|
|
109
|
+
function createDebugLogger(namespace, label = namespace) {
|
|
110
|
+
const debugEnabled = isDebugNamespaceEnabled(namespace);
|
|
111
|
+
return (message) => {
|
|
112
|
+
if (!debugEnabled) return;
|
|
113
|
+
console.debug(`[${label}] ${message}`);
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function loadNativeBinding(options) {
|
|
117
|
+
const req = module$1.createRequire(path10__default.default.join(options.runtimeDir, "noop.cjs"));
|
|
118
|
+
const loadErrors = [];
|
|
119
|
+
for (const candidate of options.candidates) {
|
|
120
|
+
if (!fs3__default.default.existsSync(candidate)) continue;
|
|
121
|
+
try {
|
|
122
|
+
const mod = req(candidate);
|
|
123
|
+
if (options.isValid(mod)) {
|
|
124
|
+
return {
|
|
125
|
+
binding: mod,
|
|
126
|
+
loadedPath: candidate,
|
|
127
|
+
loadErrors
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
loadErrors.push({
|
|
131
|
+
path: candidate,
|
|
132
|
+
message: options.invalidExportMessage
|
|
133
|
+
});
|
|
134
|
+
} catch (error) {
|
|
135
|
+
loadErrors.push({
|
|
136
|
+
path: candidate,
|
|
137
|
+
message: formatErrorMessage(error)
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
binding: null,
|
|
143
|
+
loadedPath: null,
|
|
144
|
+
loadErrors
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
var init_nativeBinding = __esm({
|
|
148
|
+
"packages/shared/src/nativeBinding.ts"() {
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// packages/shared/src/logger.ts
|
|
153
|
+
function getEnvLevel() {
|
|
154
|
+
const env = process.env.TWS_LOG_LEVEL?.toLowerCase();
|
|
155
|
+
if (env && env in LEVELS) return env;
|
|
156
|
+
return process.env.TWS_DEBUG_SCANNER === "1" ? "debug" : "info";
|
|
157
|
+
}
|
|
158
|
+
function createLogger(prefix, level) {
|
|
159
|
+
let currentLevel = getEnvLevel();
|
|
160
|
+
const log5 = (msgLevel, stream, args) => {
|
|
161
|
+
if (LEVELS[msgLevel] > LEVELS[currentLevel]) return;
|
|
162
|
+
const line = `[${prefix}] ${args.map(String).join(" ")}
|
|
163
|
+
`;
|
|
164
|
+
process[stream].write(line);
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
error: (...a) => log5("error", "stderr", a),
|
|
168
|
+
warn: (...a) => log5("warn", "stderr", a),
|
|
169
|
+
info: (...a) => log5("info", "stdout", a),
|
|
170
|
+
debug: (...a) => log5("debug", "stderr", a),
|
|
171
|
+
setLevel: (l) => {
|
|
172
|
+
currentLevel = l;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
var LEVELS;
|
|
177
|
+
var init_logger = __esm({
|
|
178
|
+
"packages/shared/src/logger.ts"() {
|
|
179
|
+
LEVELS = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
|
|
180
|
+
createLogger("tailwind-styled");
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
function hashContent(content, algorithm = "md5", length = 8) {
|
|
184
|
+
return crypto.createHash(algorithm).update(content).digest("hex").slice(0, length);
|
|
185
|
+
}
|
|
186
|
+
var init_hash = __esm({
|
|
187
|
+
"packages/shared/src/hash.ts"() {
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// packages/shared/src/index.ts
|
|
192
|
+
var init_src = __esm({
|
|
193
|
+
"packages/shared/src/index.ts"() {
|
|
194
|
+
init_nativeBinding();
|
|
195
|
+
init_logger();
|
|
196
|
+
init_hash();
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// packages/compiler/src/nativeBridge.ts
|
|
201
|
+
var nativeBridge_exports = {};
|
|
202
|
+
__export(nativeBridge_exports, {
|
|
203
|
+
adaptNativeResult: () => adaptNativeResult,
|
|
204
|
+
getNativeBridge: () => getNativeBridge,
|
|
205
|
+
resetNativeBridgeCache: () => resetNativeBridgeCache
|
|
206
|
+
});
|
|
207
|
+
function tryRequire(id) {
|
|
208
|
+
try {
|
|
209
|
+
const mod = requireFromRuntime(id);
|
|
210
|
+
return mod ?? null;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
log.debug(
|
|
213
|
+
`native bridge load miss ${id}: ${error instanceof Error ? error.message : String(error)}`
|
|
214
|
+
);
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function getNativeBridge() {
|
|
219
|
+
if (cachedBridge !== void 0) {
|
|
220
|
+
if (cachedBridge === null) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`[tailwind-styled/compiler v5] Native binding is required but not available.
|
|
223
|
+
Please ensure:
|
|
224
|
+
1. The native module is properly installed
|
|
225
|
+
2. You have run: npm run build:native (or use prebuilt binary)
|
|
226
|
+
3. TWS_NO_NATIVE environment variable is not set
|
|
227
|
+
|
|
228
|
+
For help, see: https://tailwind-styled.dev/docs/install`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
return cachedBridge;
|
|
232
|
+
}
|
|
233
|
+
if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1") {
|
|
234
|
+
cachedBridge = null;
|
|
235
|
+
throw new Error(
|
|
236
|
+
`[tailwind-styled/compiler v5] Native binding is required.
|
|
237
|
+
The TWS_NO_NATIVE or TWS_NO_RUST environment variable is set, which disables native binding.
|
|
238
|
+
Please unset this environment variable to use the native compiler.`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
const candidates = [
|
|
242
|
+
"@tailwind-styled/native",
|
|
243
|
+
path10__default.default.resolve(process.cwd(), "native", "index.mjs"),
|
|
244
|
+
path10__default.default.resolve(runtimeDir, "..", "..", "native", "index.mjs"),
|
|
245
|
+
path10__default.default.resolve(runtimeDir, "..", "..", "..", "native", "index.mjs"),
|
|
246
|
+
path10__default.default.resolve(process.cwd(), "native", "index.node"),
|
|
247
|
+
path10__default.default.resolve(runtimeDir, "..", "..", "native", "index.node"),
|
|
248
|
+
path10__default.default.resolve(runtimeDir, "..", "..", "..", "native", "index.node")
|
|
249
|
+
];
|
|
250
|
+
for (const candidate of candidates) {
|
|
251
|
+
const bridge = tryRequire(candidate);
|
|
252
|
+
if (bridge) {
|
|
253
|
+
log.debug(`native bridge loaded from ${candidate}`);
|
|
254
|
+
cachedBridge = bridge;
|
|
255
|
+
return cachedBridge;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
cachedBridge = null;
|
|
259
|
+
throw new Error(
|
|
260
|
+
`[tailwind-styled/compiler v5] Native binding not found.
|
|
261
|
+
Tried loading from:
|
|
262
|
+
` + candidates.map((c) => ` - ${c}`).join("\n") + `
|
|
263
|
+
|
|
264
|
+
Please build the native module:
|
|
265
|
+
npm run build:native
|
|
266
|
+
|
|
267
|
+
Or install a prebuilt binary for your platform.`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
function resetNativeBridgeCache() {
|
|
271
|
+
cachedBridge = void 0;
|
|
272
|
+
}
|
|
273
|
+
function adaptNativeResult(raw) {
|
|
274
|
+
let rsc;
|
|
275
|
+
if (raw.rscJson) {
|
|
276
|
+
try {
|
|
277
|
+
const parsed = JSON.parse(raw.rscJson);
|
|
278
|
+
rsc = {
|
|
279
|
+
isServer: parsed.isServer,
|
|
280
|
+
needsClientDirective: parsed.needsClientDirective,
|
|
281
|
+
clientReasons: []
|
|
282
|
+
};
|
|
283
|
+
} catch {
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
let metadata;
|
|
287
|
+
if (raw.metadataJson) {
|
|
288
|
+
try {
|
|
289
|
+
metadata = JSON.parse(raw.metadataJson);
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
code: raw.code,
|
|
295
|
+
classes: raw.classes,
|
|
296
|
+
changed: raw.changed,
|
|
297
|
+
rsc,
|
|
298
|
+
metadata
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
var runtimeDir, requireFromRuntime, cachedBridge, log;
|
|
302
|
+
var init_nativeBridge = __esm({
|
|
303
|
+
"packages/compiler/src/nativeBridge.ts"() {
|
|
304
|
+
init_src();
|
|
305
|
+
runtimeDir = typeof __dirname === "string" && __dirname.length > 0 ? __dirname : process.cwd();
|
|
306
|
+
requireFromRuntime = typeof module !== "undefined" && typeof module.require === "function" ? module.require.bind(module) : module$1.createRequire(path10__default.default.join(runtimeDir, "noop.cjs"));
|
|
307
|
+
log = createLogger("compiler:native");
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// packages/compiler/src/twDetector.ts
|
|
312
|
+
var TEMPLATE_RE, OBJECT_RE, EXTEND_RE;
|
|
313
|
+
var init_twDetector = __esm({
|
|
314
|
+
"packages/compiler/src/twDetector.ts"() {
|
|
315
|
+
TEMPLATE_RE = /\btw\.(server\.)?(\w+)`((?:[^`\\]|\\.)*)`/g;
|
|
316
|
+
OBJECT_RE = /\btw\.(server\.)?(\w+)\(\s*(\{[\s\S]*?\})\s*\)/g;
|
|
317
|
+
EXTEND_RE = /(\w+)\.extend`((?:[^`\\]|\\.)*)`/g;
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// packages/compiler/src/cssCompiler.ts
|
|
322
|
+
var cssCompiler_exports = {};
|
|
323
|
+
__export(cssCompiler_exports, {
|
|
324
|
+
buildStyleTag: () => buildStyleTag,
|
|
325
|
+
compileCssFromClasses: () => compileCssFromClasses
|
|
326
|
+
});
|
|
327
|
+
function getBinding() {
|
|
328
|
+
if (_binding !== void 0) {
|
|
329
|
+
if (_binding === null) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`[tailwind-styled/compiler v5] Native CSS binding is required but not available.
|
|
332
|
+
Please ensure the native module is properly built.`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
return _binding;
|
|
336
|
+
}
|
|
337
|
+
if (process.env.TWS_NO_NATIVE === "1") {
|
|
338
|
+
_binding = null;
|
|
339
|
+
throw new Error(
|
|
340
|
+
`[tailwind-styled/compiler v5] Native binding is required.
|
|
341
|
+
The TWS_NO_NATIVE environment variable is set, which disables native binding.`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
const req = typeof __require === "function" ? __require : module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite.js', document.baseURI).href)));
|
|
345
|
+
const candidates = [
|
|
346
|
+
path10__default.default.resolve(process.cwd(), "native", "tailwind_styled_parser.node"),
|
|
347
|
+
path10__default.default.resolve(__dirname, "..", "..", "..", "..", "native", "tailwind_styled_parser.node")
|
|
348
|
+
];
|
|
349
|
+
for (const c of candidates) {
|
|
350
|
+
try {
|
|
351
|
+
const mod = req(c);
|
|
352
|
+
if (mod?.compileCss) {
|
|
353
|
+
_binding = mod;
|
|
354
|
+
return _binding;
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
_binding = null;
|
|
360
|
+
throw new Error(
|
|
361
|
+
`[tailwind-styled/compiler v5] Native CSS binding not found.
|
|
362
|
+
Tried loading from:
|
|
363
|
+
` + candidates.map((c) => ` - ${c}`).join("\n") + `
|
|
364
|
+
|
|
365
|
+
Please build the native module.`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
function compileCssFromClasses(classes, options = {}) {
|
|
369
|
+
const binding = getBinding();
|
|
370
|
+
const prefix = options.prefix ?? null;
|
|
371
|
+
const r = binding.compileCss(classes, prefix);
|
|
372
|
+
return {
|
|
373
|
+
css: r.css,
|
|
374
|
+
resolvedClasses: r.resolvedClasses,
|
|
375
|
+
unknownClasses: r.unknownClasses,
|
|
376
|
+
sizeBytes: r.sizeBytes,
|
|
377
|
+
engine: "rust"
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function buildStyleTag(classes) {
|
|
381
|
+
const { css } = compileCssFromClasses(classes);
|
|
382
|
+
return css ? `<style data-tailwind-styled>${css}</style>` : "";
|
|
383
|
+
}
|
|
384
|
+
var _binding;
|
|
385
|
+
var init_cssCompiler = __esm({
|
|
386
|
+
"packages/compiler/src/cssCompiler.ts"() {
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// packages/compiler/src/classExtractor.ts
|
|
391
|
+
function extractAllClasses(source) {
|
|
392
|
+
const { getNativeBridge: getNativeBridge2 } = (init_nativeBridge(), __toCommonJS(nativeBridge_exports));
|
|
393
|
+
const native = getNativeBridge2();
|
|
394
|
+
if (!native?.extractClassesFromSourceNative) {
|
|
395
|
+
throw new Error(
|
|
396
|
+
`[tailwind-styled/compiler v5] extractClassesFromSourceNative is required but not available.
|
|
397
|
+
Please ensure the native module is properly built.`
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
const result = native.extractClassesFromSourceNative(source);
|
|
401
|
+
if (!result || result.length < 0) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
`[tailwind-styled/compiler v5] extractClassesFromSourceNative returned invalid result.`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
return result.sort();
|
|
407
|
+
}
|
|
408
|
+
var init_classExtractor = __esm({
|
|
409
|
+
"packages/compiler/src/classExtractor.ts"() {
|
|
410
|
+
init_twDetector();
|
|
411
|
+
new RegExp(TEMPLATE_RE.source, "g");
|
|
412
|
+
new RegExp(OBJECT_RE.source, "g");
|
|
413
|
+
new RegExp(EXTEND_RE.source, "g");
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
function ensureCacheDir() {
|
|
417
|
+
if (!fs3__default.default.existsSync(CACHE_DIR)) {
|
|
418
|
+
fs3__default.default.mkdirSync(CACHE_DIR, { recursive: true });
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function loadHashCache() {
|
|
422
|
+
try {
|
|
423
|
+
if (fs3__default.default.existsSync(HASH_CACHE_FILE)) {
|
|
424
|
+
const raw = fs3__default.default.readFileSync(HASH_CACHE_FILE, "utf-8");
|
|
425
|
+
return new Map(Object.entries(JSON.parse(raw)));
|
|
426
|
+
}
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
return /* @__PURE__ */ new Map();
|
|
430
|
+
}
|
|
431
|
+
function saveHashCache(cache) {
|
|
432
|
+
try {
|
|
433
|
+
ensureCacheDir();
|
|
434
|
+
const obj = Object.fromEntries(cache);
|
|
435
|
+
fs3__default.default.writeFileSync(HASH_CACHE_FILE, JSON.stringify(obj, null, 2));
|
|
436
|
+
} catch {
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function loadGraphCache() {
|
|
440
|
+
try {
|
|
441
|
+
if (fs3__default.default.existsSync(GRAPH_CACHE_FILE)) {
|
|
442
|
+
const raw = fs3__default.default.readFileSync(GRAPH_CACHE_FILE, "utf-8");
|
|
443
|
+
const data = JSON.parse(raw);
|
|
444
|
+
return new Map(Object.entries(data));
|
|
445
|
+
}
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
return /* @__PURE__ */ new Map();
|
|
449
|
+
}
|
|
450
|
+
function saveGraphCache(graph) {
|
|
451
|
+
try {
|
|
452
|
+
ensureCacheDir();
|
|
453
|
+
const obj = Object.fromEntries(graph);
|
|
454
|
+
fs3__default.default.writeFileSync(GRAPH_CACHE_FILE, JSON.stringify(obj, null, 2));
|
|
455
|
+
} catch {
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function fnv1a(str) {
|
|
459
|
+
let h = 2166136261;
|
|
460
|
+
for (let i = 0; i < str.length; i++) {
|
|
461
|
+
h ^= str.charCodeAt(i);
|
|
462
|
+
h = h * 16777619 >>> 0;
|
|
463
|
+
}
|
|
464
|
+
return h;
|
|
465
|
+
}
|
|
466
|
+
function toBase36(n, len = 4) {
|
|
467
|
+
const chars = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
468
|
+
let result = "";
|
|
469
|
+
let num = n;
|
|
470
|
+
for (let i = 0; i < len; i++) {
|
|
471
|
+
result = chars[num % 36] + result;
|
|
472
|
+
num = Math.floor(num / 36);
|
|
473
|
+
}
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
function hashFileContent(content) {
|
|
477
|
+
return hashContent(content, "md5", 8);
|
|
478
|
+
}
|
|
479
|
+
function makeAtomicClass(declaration, modifier) {
|
|
480
|
+
const key = modifier ? `${declaration}::${modifier}` : declaration;
|
|
481
|
+
return `tw-${toBase36(fnv1a(key))}`;
|
|
482
|
+
}
|
|
483
|
+
function computeDiff(oldNodes, newNodes) {
|
|
484
|
+
const oldMap = new Map(oldNodes.map((n) => [n.atomicClass, n]));
|
|
485
|
+
const newMap = new Map(newNodes.map((n) => [n.atomicClass, n]));
|
|
486
|
+
const added = [];
|
|
487
|
+
const removed = [];
|
|
488
|
+
for (const [cls, node] of newMap) {
|
|
489
|
+
if (!oldMap.has(cls)) added.push(node);
|
|
490
|
+
}
|
|
491
|
+
for (const cls of oldMap.keys()) {
|
|
492
|
+
if (!newMap.has(cls)) removed.push(cls);
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
added,
|
|
496
|
+
removed,
|
|
497
|
+
noChange: added.length === 0 && removed.length === 0
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function nodeToCSS(node) {
|
|
501
|
+
const { atomicClass, declaration, modifier } = node;
|
|
502
|
+
if (!modifier) {
|
|
503
|
+
return `.${atomicClass}{${declaration}}`;
|
|
504
|
+
}
|
|
505
|
+
if (modifier.startsWith("@")) {
|
|
506
|
+
return `${modifier}{.${atomicClass}{${declaration}}}`;
|
|
507
|
+
}
|
|
508
|
+
return `.${atomicClass}${modifier}{${declaration}}`;
|
|
509
|
+
}
|
|
510
|
+
function parseClassesToNodes(classes) {
|
|
511
|
+
const nodes = [];
|
|
512
|
+
for (const cls of classes) {
|
|
513
|
+
const node = parseOneClass(cls);
|
|
514
|
+
if (node) nodes.push(node);
|
|
515
|
+
}
|
|
516
|
+
return nodes;
|
|
517
|
+
}
|
|
518
|
+
function parseOneClass(cls) {
|
|
519
|
+
const colonIdx = cls.lastIndexOf(":");
|
|
520
|
+
let modifier;
|
|
521
|
+
let utility;
|
|
522
|
+
if (colonIdx > 0) {
|
|
523
|
+
const modStr = cls.slice(0, colonIdx);
|
|
524
|
+
utility = cls.slice(colonIdx + 1);
|
|
525
|
+
modifier = resolveModifier(modStr);
|
|
526
|
+
} else {
|
|
527
|
+
utility = cls;
|
|
528
|
+
}
|
|
529
|
+
const declaration = twToDeclaration(utility);
|
|
530
|
+
if (!declaration) return null;
|
|
531
|
+
const atomicClass = makeAtomicClass(declaration, modifier);
|
|
532
|
+
return { twClass: cls, declaration, modifier, atomicClass };
|
|
533
|
+
}
|
|
534
|
+
function resolveModifier(mod) {
|
|
535
|
+
const pseudoMap = {
|
|
536
|
+
hover: ":hover",
|
|
537
|
+
focus: ":focus",
|
|
538
|
+
active: ":active",
|
|
539
|
+
disabled: ":disabled",
|
|
540
|
+
visited: ":visited",
|
|
541
|
+
checked: ":checked",
|
|
542
|
+
first: ":first-child",
|
|
543
|
+
last: ":last-child",
|
|
544
|
+
odd: ":nth-child(odd)",
|
|
545
|
+
even: ":nth-child(even)"
|
|
546
|
+
};
|
|
547
|
+
const mediaMap = {
|
|
548
|
+
sm: "@media (min-width: 640px)",
|
|
549
|
+
md: "@media (min-width: 768px)",
|
|
550
|
+
lg: "@media (min-width: 1024px)",
|
|
551
|
+
xl: "@media (min-width: 1280px)",
|
|
552
|
+
"2xl": "@media (min-width: 1536px)",
|
|
553
|
+
dark: "@media (prefers-color-scheme: dark)",
|
|
554
|
+
print: "@media print"
|
|
555
|
+
};
|
|
556
|
+
return pseudoMap[mod] ?? mediaMap[mod] ?? `:${mod}`;
|
|
557
|
+
}
|
|
558
|
+
function twToDeclaration(cls) {
|
|
559
|
+
const sp = cls.match(/^(p|px|py|pt|pb|pl|pr|m|mx|my|mt|mb|ml|mr|gap)-([\d.]+)$/);
|
|
560
|
+
if (sp) {
|
|
561
|
+
const propMap = {
|
|
562
|
+
p: "padding",
|
|
563
|
+
px: "padding-inline",
|
|
564
|
+
py: "padding-block",
|
|
565
|
+
pt: "padding-top",
|
|
566
|
+
pb: "padding-bottom",
|
|
567
|
+
pl: "padding-left",
|
|
568
|
+
pr: "padding-right",
|
|
569
|
+
m: "margin",
|
|
570
|
+
mx: "margin-inline",
|
|
571
|
+
my: "margin-block",
|
|
572
|
+
mt: "margin-top",
|
|
573
|
+
mb: "margin-bottom",
|
|
574
|
+
ml: "margin-left",
|
|
575
|
+
mr: "margin-right",
|
|
576
|
+
gap: "gap"
|
|
577
|
+
};
|
|
578
|
+
return `${propMap[sp[1]]}: ${parseFloat(sp[2]) * 0.25}rem`;
|
|
579
|
+
}
|
|
580
|
+
const w = cls.match(/^w-(.+)$/);
|
|
581
|
+
if (w) return `width: ${sizeVal(w[1])}`;
|
|
582
|
+
const h = cls.match(/^h-(.+)$/);
|
|
583
|
+
if (h) return `height: ${sizeVal(h[1])}`;
|
|
584
|
+
const op = cls.match(/^opacity-(\d+)$/);
|
|
585
|
+
if (op) return `opacity: ${parseInt(op[1], 10) / 100}`;
|
|
586
|
+
const z = cls.match(/^z-(\d+)$/);
|
|
587
|
+
if (z) return `z-index: ${z[1]}`;
|
|
588
|
+
const map = {
|
|
589
|
+
block: "display: block",
|
|
590
|
+
"inline-block": "display: inline-block",
|
|
591
|
+
flex: "display: flex",
|
|
592
|
+
"inline-flex": "display: inline-flex",
|
|
593
|
+
grid: "display: grid",
|
|
594
|
+
hidden: "display: none",
|
|
595
|
+
relative: "position: relative",
|
|
596
|
+
absolute: "position: absolute",
|
|
597
|
+
fixed: "position: fixed",
|
|
598
|
+
sticky: "position: sticky",
|
|
599
|
+
"flex-row": "flex-direction: row",
|
|
600
|
+
"flex-col": "flex-direction: column",
|
|
601
|
+
"items-center": "align-items: center",
|
|
602
|
+
"items-start": "align-items: flex-start",
|
|
603
|
+
"items-end": "align-items: flex-end",
|
|
604
|
+
"justify-center": "justify-content: center",
|
|
605
|
+
"justify-between": "justify-content: space-between",
|
|
606
|
+
"justify-start": "justify-content: flex-start",
|
|
607
|
+
"justify-end": "justify-content: flex-end",
|
|
608
|
+
"font-thin": "font-weight: 100",
|
|
609
|
+
"font-light": "font-weight: 300",
|
|
610
|
+
"font-normal": "font-weight: 400",
|
|
611
|
+
"font-medium": "font-weight: 500",
|
|
612
|
+
"font-semibold": "font-weight: 600",
|
|
613
|
+
"font-bold": "font-weight: 700",
|
|
614
|
+
"font-extrabold": "font-weight: 800",
|
|
615
|
+
"text-xs": "font-size: 0.75rem",
|
|
616
|
+
"text-sm": "font-size: 0.875rem",
|
|
617
|
+
"text-base": "font-size: 1rem",
|
|
618
|
+
"text-lg": "font-size: 1.125rem",
|
|
619
|
+
"text-xl": "font-size: 1.25rem",
|
|
620
|
+
"text-2xl": "font-size: 1.5rem",
|
|
621
|
+
"text-3xl": "font-size: 1.875rem",
|
|
622
|
+
"text-4xl": "font-size: 2.25rem",
|
|
623
|
+
rounded: "border-radius: 0.25rem",
|
|
624
|
+
"rounded-md": "border-radius: 0.375rem",
|
|
625
|
+
"rounded-lg": "border-radius: 0.5rem",
|
|
626
|
+
"rounded-xl": "border-radius: 0.75rem",
|
|
627
|
+
"rounded-full": "border-radius: 9999px",
|
|
628
|
+
"overflow-hidden": "overflow: hidden",
|
|
629
|
+
"overflow-auto": "overflow: auto",
|
|
630
|
+
"cursor-pointer": "cursor: pointer",
|
|
631
|
+
"cursor-default": "cursor: default",
|
|
632
|
+
"select-none": "user-select: none",
|
|
633
|
+
"pointer-events-none": "pointer-events: none",
|
|
634
|
+
truncate: "overflow: hidden; text-overflow: ellipsis; white-space: nowrap",
|
|
635
|
+
transition: "transition-property: color,background-color,border-color,opacity,box-shadow,transform; transition-duration: 150ms"
|
|
636
|
+
};
|
|
637
|
+
return map[cls] ?? null;
|
|
638
|
+
}
|
|
639
|
+
function sizeVal(v) {
|
|
640
|
+
const num = parseFloat(v);
|
|
641
|
+
if (!Number.isNaN(num)) return `${num * 0.25}rem`;
|
|
642
|
+
const special = {
|
|
643
|
+
full: "100%",
|
|
644
|
+
screen: "100vw",
|
|
645
|
+
auto: "auto",
|
|
646
|
+
min: "min-content",
|
|
647
|
+
max: "max-content",
|
|
648
|
+
fit: "fit-content"
|
|
649
|
+
};
|
|
650
|
+
return special[v] ?? v;
|
|
651
|
+
}
|
|
652
|
+
function getIncrementalEngine(opts) {
|
|
653
|
+
if (!_engine) {
|
|
654
|
+
_engine = new IncrementalEngine(opts);
|
|
655
|
+
}
|
|
656
|
+
return _engine;
|
|
657
|
+
}
|
|
658
|
+
var CACHE_DIR, HASH_CACHE_FILE, GRAPH_CACHE_FILE, GlobalAtomicRegistry, CssDiffWriter, IncrementalEngine, _engine;
|
|
659
|
+
var init_incrementalEngine = __esm({
|
|
660
|
+
"packages/compiler/src/incrementalEngine.ts"() {
|
|
661
|
+
init_src();
|
|
662
|
+
CACHE_DIR = ".tw-cache";
|
|
663
|
+
HASH_CACHE_FILE = path10__default.default.join(CACHE_DIR, "file-hashes.json");
|
|
664
|
+
GRAPH_CACHE_FILE = path10__default.default.join(CACHE_DIR, "dep-graph.json");
|
|
665
|
+
GlobalAtomicRegistry = class {
|
|
666
|
+
constructor() {
|
|
667
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
668
|
+
}
|
|
669
|
+
/** Tambah node dari file tertentu */
|
|
670
|
+
add(filepath, node) {
|
|
671
|
+
const existing = this.entries.get(node.atomicClass);
|
|
672
|
+
if (existing) {
|
|
673
|
+
existing.sources.add(filepath);
|
|
674
|
+
} else {
|
|
675
|
+
this.entries.set(node.atomicClass, {
|
|
676
|
+
node,
|
|
677
|
+
sources: /* @__PURE__ */ new Set([filepath])
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/** Hapus referensi dari file tertentu; jika tidak ada source lain, rule dihapus */
|
|
682
|
+
remove(filepath, atomicClass) {
|
|
683
|
+
const entry = this.entries.get(atomicClass);
|
|
684
|
+
if (!entry) return false;
|
|
685
|
+
entry.sources.delete(filepath);
|
|
686
|
+
if (entry.sources.size === 0) {
|
|
687
|
+
this.entries.delete(atomicClass);
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
/** Cek apakah rule ada di registry global */
|
|
693
|
+
has(atomicClass) {
|
|
694
|
+
return this.entries.has(atomicClass);
|
|
695
|
+
}
|
|
696
|
+
/** Semua entries untuk CSS generation */
|
|
697
|
+
all() {
|
|
698
|
+
return Array.from(this.entries.values()).map((e) => e.node);
|
|
699
|
+
}
|
|
700
|
+
/** Total unique rules */
|
|
701
|
+
size() {
|
|
702
|
+
return this.entries.size;
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
CssDiffWriter = class {
|
|
706
|
+
constructor(outputPath) {
|
|
707
|
+
this.ruleMap = /* @__PURE__ */ new Map();
|
|
708
|
+
this.dirty = false;
|
|
709
|
+
this.outputPath = outputPath;
|
|
710
|
+
this.loadFromDisk();
|
|
711
|
+
}
|
|
712
|
+
loadFromDisk() {
|
|
713
|
+
try {
|
|
714
|
+
if (fs3__default.default.existsSync(this.outputPath)) {
|
|
715
|
+
const css = fs3__default.default.readFileSync(this.outputPath, "utf-8");
|
|
716
|
+
const ruleRe = /(\.tw-[a-z0-9]+(?::[\w-]+)?)\{([^}]+)\}|(@[^{]+)\{(\.tw-[a-z0-9]+)\{([^}]+)\}\}/g;
|
|
717
|
+
let m;
|
|
718
|
+
while ((m = ruleRe.exec(css)) !== null) {
|
|
719
|
+
if (m[1]) {
|
|
720
|
+
const cls = m[1].replace(/\.[^:]+:.*/, (match) => match.split(".")[1].split(":")[0]);
|
|
721
|
+
this.ruleMap.set(cls, m[0]);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
} catch {
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
/** Apply diff ke internal map */
|
|
729
|
+
applyDiff(diff) {
|
|
730
|
+
if (diff.noChange) return;
|
|
731
|
+
for (const node of diff.added) {
|
|
732
|
+
this.ruleMap.set(node.atomicClass, nodeToCSS(node));
|
|
733
|
+
}
|
|
734
|
+
for (const cls of diff.removed) {
|
|
735
|
+
this.ruleMap.delete(cls);
|
|
736
|
+
}
|
|
737
|
+
this.dirty = true;
|
|
738
|
+
}
|
|
739
|
+
/** Write ke disk jika ada perubahan. Async untuk tidak block loader. */
|
|
740
|
+
async flush() {
|
|
741
|
+
if (!this.dirty) return;
|
|
742
|
+
try {
|
|
743
|
+
ensureCacheDir();
|
|
744
|
+
const css = Array.from(this.ruleMap.values()).join("\n");
|
|
745
|
+
await fs3__default.default.promises.writeFile(this.outputPath, css, "utf-8");
|
|
746
|
+
this.dirty = false;
|
|
747
|
+
} catch {
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
/** Sync flush untuk build end */
|
|
751
|
+
flushSync() {
|
|
752
|
+
if (!this.dirty) return;
|
|
753
|
+
try {
|
|
754
|
+
ensureCacheDir();
|
|
755
|
+
const css = Array.from(this.ruleMap.values()).join("\n");
|
|
756
|
+
fs3__default.default.writeFileSync(this.outputPath, css, "utf-8");
|
|
757
|
+
this.dirty = false;
|
|
758
|
+
} catch {
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
size() {
|
|
762
|
+
return this.ruleMap.size;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
IncrementalEngine = class {
|
|
766
|
+
constructor(opts = {}) {
|
|
767
|
+
// Stats untuk current build session
|
|
768
|
+
this.stats = {
|
|
769
|
+
totalFiles: 0,
|
|
770
|
+
changedFiles: 0,
|
|
771
|
+
skippedFiles: 0,
|
|
772
|
+
addedRules: 0,
|
|
773
|
+
removedRules: 0,
|
|
774
|
+
buildTimeMs: 0
|
|
775
|
+
};
|
|
776
|
+
this.sessionStart = Date.now();
|
|
777
|
+
this.opts = {
|
|
778
|
+
outputPath: opts.outputPath ?? path10__default.default.join(CACHE_DIR, "atomic.css"),
|
|
779
|
+
persistCache: opts.persistCache ?? true,
|
|
780
|
+
verbose: opts.verbose ?? false
|
|
781
|
+
};
|
|
782
|
+
this.hashCache = this.opts.persistCache ? loadHashCache() : /* @__PURE__ */ new Map();
|
|
783
|
+
this.depGraph = this.opts.persistCache ? loadGraphCache() : /* @__PURE__ */ new Map();
|
|
784
|
+
this.globalReg = new GlobalAtomicRegistry();
|
|
785
|
+
this.cssWriter = new CssDiffWriter(this.opts.outputPath);
|
|
786
|
+
for (const [filepath, nodes] of this.depGraph) {
|
|
787
|
+
for (const node of nodes) {
|
|
788
|
+
this.globalReg.add(filepath, node);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Proses satu file. Core method dipanggil oleh webpack/turbopack loader.
|
|
794
|
+
*
|
|
795
|
+
* @param filepath - Absolute path ke file
|
|
796
|
+
* @param source - Source code file (untuk hashing)
|
|
797
|
+
* @param extractedNodes - Style nodes yang di-extract compiler dari file ini
|
|
798
|
+
* @returns ProcessResult dengan diff dan stats
|
|
799
|
+
*/
|
|
800
|
+
processFile(filepath, source, extractedNodes) {
|
|
801
|
+
const t0 = Date.now();
|
|
802
|
+
this.stats.totalFiles++;
|
|
803
|
+
const currentHash = hashFileContent(source);
|
|
804
|
+
const cachedHash = this.hashCache.get(filepath);
|
|
805
|
+
if (cachedHash === currentHash) {
|
|
806
|
+
this.stats.skippedFiles++;
|
|
807
|
+
this.log(`[skip] ${path10__default.default.relative(process.cwd(), filepath)}`);
|
|
808
|
+
return {
|
|
809
|
+
filepath,
|
|
810
|
+
changed: false,
|
|
811
|
+
diff: { added: [], removed: [], noChange: true },
|
|
812
|
+
durationMs: Date.now() - t0
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
this.hashCache.set(filepath, currentHash);
|
|
816
|
+
this.stats.changedFiles++;
|
|
817
|
+
this.log(`[change] ${path10__default.default.relative(process.cwd(), filepath)}`);
|
|
818
|
+
const oldNodes = this.depGraph.get(filepath) ?? [];
|
|
819
|
+
const diff = computeDiff(oldNodes, extractedNodes);
|
|
820
|
+
this.depGraph.set(filepath, extractedNodes);
|
|
821
|
+
const trulyRemoved = [];
|
|
822
|
+
for (const cls of diff.removed) {
|
|
823
|
+
const wasRemoved = this.globalReg.remove(filepath, cls);
|
|
824
|
+
if (wasRemoved) trulyRemoved.push(cls);
|
|
825
|
+
}
|
|
826
|
+
const trulyAdded = [];
|
|
827
|
+
for (const node of diff.added) {
|
|
828
|
+
if (!this.globalReg.has(node.atomicClass)) {
|
|
829
|
+
trulyAdded.push(node);
|
|
830
|
+
}
|
|
831
|
+
this.globalReg.add(filepath, node);
|
|
832
|
+
}
|
|
833
|
+
const finalDiff = {
|
|
834
|
+
added: trulyAdded,
|
|
835
|
+
removed: trulyRemoved,
|
|
836
|
+
noChange: trulyAdded.length === 0 && trulyRemoved.length === 0
|
|
837
|
+
};
|
|
838
|
+
this.cssWriter.applyDiff(finalDiff);
|
|
839
|
+
this.stats.addedRules += trulyAdded.length;
|
|
840
|
+
this.stats.removedRules += trulyRemoved.length;
|
|
841
|
+
return {
|
|
842
|
+
filepath,
|
|
843
|
+
changed: true,
|
|
844
|
+
diff: finalDiff,
|
|
845
|
+
durationMs: Date.now() - t0
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Dipanggil di akhir build. Flush CSS ke disk, persist cache.
|
|
850
|
+
*/
|
|
851
|
+
async buildEnd() {
|
|
852
|
+
this.stats.buildTimeMs = Date.now() - this.sessionStart;
|
|
853
|
+
await this.cssWriter.flush();
|
|
854
|
+
if (this.opts.persistCache) {
|
|
855
|
+
saveHashCache(this.hashCache);
|
|
856
|
+
saveGraphCache(this.depGraph);
|
|
857
|
+
}
|
|
858
|
+
this.log(
|
|
859
|
+
`[build] done in ${this.stats.buildTimeMs}ms | changed: ${this.stats.changedFiles}/${this.stats.totalFiles} files | +${this.stats.addedRules} -${this.stats.removedRules} rules | total rules: ${this.cssWriter.size()}`
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
/** Sync version untuk webpack buildEnd hook */
|
|
863
|
+
buildEndSync() {
|
|
864
|
+
this.stats.buildTimeMs = Date.now() - this.sessionStart;
|
|
865
|
+
this.cssWriter.flushSync();
|
|
866
|
+
if (this.opts.persistCache) {
|
|
867
|
+
saveHashCache(this.hashCache);
|
|
868
|
+
saveGraphCache(this.depGraph);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Invalidate satu file (untuk hot reload — file dihapus atau renamed).
|
|
873
|
+
*/
|
|
874
|
+
invalidateFile(filepath) {
|
|
875
|
+
const oldNodes = this.depGraph.get(filepath) ?? [];
|
|
876
|
+
for (const node of oldNodes) {
|
|
877
|
+
this.globalReg.remove(filepath, node.atomicClass);
|
|
878
|
+
}
|
|
879
|
+
this.depGraph.delete(filepath);
|
|
880
|
+
this.hashCache.delete(filepath);
|
|
881
|
+
this.log(`[invalidate] ${path10__default.default.relative(process.cwd(), filepath)}`);
|
|
882
|
+
}
|
|
883
|
+
/** Get all active style nodes — untuk full CSS generation */
|
|
884
|
+
getAllNodes() {
|
|
885
|
+
return this.globalReg.all();
|
|
886
|
+
}
|
|
887
|
+
/** Get stats untuk current build session */
|
|
888
|
+
getStats() {
|
|
889
|
+
return { ...this.stats, buildTimeMs: Date.now() - this.sessionStart };
|
|
890
|
+
}
|
|
891
|
+
/** Get output CSS path */
|
|
892
|
+
getOutputPath() {
|
|
893
|
+
return this.opts.outputPath;
|
|
894
|
+
}
|
|
895
|
+
/** Reset stats untuk build session baru */
|
|
896
|
+
resetStats() {
|
|
897
|
+
this.stats = {
|
|
898
|
+
totalFiles: 0,
|
|
899
|
+
changedFiles: 0,
|
|
900
|
+
skippedFiles: 0,
|
|
901
|
+
addedRules: 0,
|
|
902
|
+
removedRules: 0,
|
|
903
|
+
buildTimeMs: 0
|
|
904
|
+
};
|
|
905
|
+
this.sessionStart = Date.now();
|
|
906
|
+
}
|
|
907
|
+
/** Reset semua cache — untuk clean build */
|
|
908
|
+
reset() {
|
|
909
|
+
this.hashCache.clear();
|
|
910
|
+
this.depGraph.clear();
|
|
911
|
+
this.globalReg = new GlobalAtomicRegistry();
|
|
912
|
+
this.cssWriter = new CssDiffWriter(this.opts.outputPath);
|
|
913
|
+
this.resetStats();
|
|
914
|
+
this.log("[reset] incremental cache cleared");
|
|
915
|
+
}
|
|
916
|
+
log(msg) {
|
|
917
|
+
if (this.opts.verbose) {
|
|
918
|
+
console.log(`[tailwind-styled/incremental] ${msg}`);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
_engine = null;
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
// packages/compiler/src/styleBucketSystem.ts
|
|
927
|
+
function classifyNode(node) {
|
|
928
|
+
if (node.modifier?.startsWith("@")) return "responsive";
|
|
929
|
+
const declarations = node.declaration.split(";").map((d) => d.trim()).filter(Boolean);
|
|
930
|
+
const firstProp = declarations[0]?.split(":")[0]?.trim();
|
|
931
|
+
if (!firstProp) return "unknown";
|
|
932
|
+
if (PROPERTY_BUCKET_MAP[firstProp]) return PROPERTY_BUCKET_MAP[firstProp];
|
|
933
|
+
for (const [prefix, bucket] of Object.entries(PROPERTY_BUCKET_MAP)) {
|
|
934
|
+
if (firstProp.startsWith(prefix)) return bucket;
|
|
935
|
+
}
|
|
936
|
+
return "unknown";
|
|
937
|
+
}
|
|
938
|
+
function nodeToCSS2(node) {
|
|
939
|
+
const { atomicClass, declaration, modifier } = node;
|
|
940
|
+
if (!modifier) {
|
|
941
|
+
return `.${atomicClass}{${declaration}}`;
|
|
942
|
+
}
|
|
943
|
+
if (modifier.startsWith("@")) {
|
|
944
|
+
return `${modifier}{.${atomicClass}{${declaration}}}`;
|
|
945
|
+
}
|
|
946
|
+
return `.${atomicClass}${modifier}{${declaration}}`;
|
|
947
|
+
}
|
|
948
|
+
function getBucketEngine() {
|
|
949
|
+
if (!_bucketEngine) _bucketEngine = new BucketEngine();
|
|
950
|
+
return _bucketEngine;
|
|
951
|
+
}
|
|
952
|
+
var BUCKET_ORDER, PROPERTY_BUCKET_MAP, BucketEngine, _bucketEngine;
|
|
953
|
+
var init_styleBucketSystem = __esm({
|
|
954
|
+
"packages/compiler/src/styleBucketSystem.ts"() {
|
|
955
|
+
BUCKET_ORDER = [
|
|
956
|
+
"reset",
|
|
957
|
+
"layout",
|
|
958
|
+
"spacing",
|
|
959
|
+
"sizing",
|
|
960
|
+
"typography",
|
|
961
|
+
"visual",
|
|
962
|
+
"interaction",
|
|
963
|
+
"responsive",
|
|
964
|
+
"unknown"
|
|
965
|
+
];
|
|
966
|
+
PROPERTY_BUCKET_MAP = {
|
|
967
|
+
// Layout
|
|
968
|
+
display: "layout",
|
|
969
|
+
position: "layout",
|
|
970
|
+
flex: "layout",
|
|
971
|
+
"flex-direction": "layout",
|
|
972
|
+
"flex-wrap": "layout",
|
|
973
|
+
"flex-grow": "layout",
|
|
974
|
+
"flex-shrink": "layout",
|
|
975
|
+
"flex-basis": "layout",
|
|
976
|
+
grid: "layout",
|
|
977
|
+
"grid-template": "layout",
|
|
978
|
+
"grid-column": "layout",
|
|
979
|
+
"grid-row": "layout",
|
|
980
|
+
"align-items": "layout",
|
|
981
|
+
"align-self": "layout",
|
|
982
|
+
"align-content": "layout",
|
|
983
|
+
"justify-content": "layout",
|
|
984
|
+
"justify-items": "layout",
|
|
985
|
+
"justify-self": "layout",
|
|
986
|
+
"place-items": "layout",
|
|
987
|
+
"place-content": "layout",
|
|
988
|
+
overflow: "layout",
|
|
989
|
+
"overflow-x": "layout",
|
|
990
|
+
"overflow-y": "layout",
|
|
991
|
+
"z-index": "layout",
|
|
992
|
+
float: "layout",
|
|
993
|
+
clear: "layout",
|
|
994
|
+
visibility: "layout",
|
|
995
|
+
// Spacing
|
|
996
|
+
padding: "spacing",
|
|
997
|
+
"padding-top": "spacing",
|
|
998
|
+
"padding-bottom": "spacing",
|
|
999
|
+
"padding-left": "spacing",
|
|
1000
|
+
"padding-right": "spacing",
|
|
1001
|
+
"padding-inline": "spacing",
|
|
1002
|
+
"padding-block": "spacing",
|
|
1003
|
+
margin: "spacing",
|
|
1004
|
+
"margin-top": "spacing",
|
|
1005
|
+
"margin-bottom": "spacing",
|
|
1006
|
+
"margin-left": "spacing",
|
|
1007
|
+
"margin-right": "spacing",
|
|
1008
|
+
"margin-inline": "spacing",
|
|
1009
|
+
"margin-block": "spacing",
|
|
1010
|
+
gap: "spacing",
|
|
1011
|
+
"column-gap": "spacing",
|
|
1012
|
+
"row-gap": "spacing",
|
|
1013
|
+
inset: "spacing",
|
|
1014
|
+
"inset-inline": "spacing",
|
|
1015
|
+
"inset-block": "spacing",
|
|
1016
|
+
top: "spacing",
|
|
1017
|
+
bottom: "spacing",
|
|
1018
|
+
left: "spacing",
|
|
1019
|
+
right: "spacing",
|
|
1020
|
+
// Sizing
|
|
1021
|
+
width: "sizing",
|
|
1022
|
+
height: "sizing",
|
|
1023
|
+
"max-width": "sizing",
|
|
1024
|
+
"min-width": "sizing",
|
|
1025
|
+
"max-height": "sizing",
|
|
1026
|
+
"min-height": "sizing",
|
|
1027
|
+
"aspect-ratio": "sizing",
|
|
1028
|
+
// Typography
|
|
1029
|
+
"font-size": "typography",
|
|
1030
|
+
"font-weight": "typography",
|
|
1031
|
+
"font-family": "typography",
|
|
1032
|
+
"font-style": "typography",
|
|
1033
|
+
"line-height": "typography",
|
|
1034
|
+
"letter-spacing": "typography",
|
|
1035
|
+
"text-align": "typography",
|
|
1036
|
+
"text-decoration": "typography",
|
|
1037
|
+
"text-transform": "typography",
|
|
1038
|
+
"text-overflow": "typography",
|
|
1039
|
+
"white-space": "typography",
|
|
1040
|
+
"word-break": "typography",
|
|
1041
|
+
"word-wrap": "typography",
|
|
1042
|
+
"vertical-align": "typography",
|
|
1043
|
+
// Visual
|
|
1044
|
+
color: "visual",
|
|
1045
|
+
background: "visual",
|
|
1046
|
+
"background-color": "visual",
|
|
1047
|
+
"background-image": "visual",
|
|
1048
|
+
"background-size": "visual",
|
|
1049
|
+
"background-position": "visual",
|
|
1050
|
+
"background-repeat": "visual",
|
|
1051
|
+
border: "visual",
|
|
1052
|
+
"border-top": "visual",
|
|
1053
|
+
"border-bottom": "visual",
|
|
1054
|
+
"border-left": "visual",
|
|
1055
|
+
"border-right": "visual",
|
|
1056
|
+
"border-inline": "visual",
|
|
1057
|
+
"border-block": "visual",
|
|
1058
|
+
"border-color": "visual",
|
|
1059
|
+
"border-width": "visual",
|
|
1060
|
+
"border-style": "visual",
|
|
1061
|
+
"border-radius": "visual",
|
|
1062
|
+
"box-shadow": "visual",
|
|
1063
|
+
opacity: "visual",
|
|
1064
|
+
outline: "visual",
|
|
1065
|
+
"outline-color": "visual",
|
|
1066
|
+
"outline-width": "visual",
|
|
1067
|
+
fill: "visual",
|
|
1068
|
+
stroke: "visual",
|
|
1069
|
+
"text-shadow": "visual",
|
|
1070
|
+
"mix-blend-mode": "visual",
|
|
1071
|
+
"object-fit": "visual",
|
|
1072
|
+
"object-position": "visual",
|
|
1073
|
+
// Interaction
|
|
1074
|
+
cursor: "interaction",
|
|
1075
|
+
"pointer-events": "interaction",
|
|
1076
|
+
"user-select": "interaction",
|
|
1077
|
+
transition: "interaction",
|
|
1078
|
+
"transition-property": "interaction",
|
|
1079
|
+
"transition-duration": "interaction",
|
|
1080
|
+
"transition-timing-function": "interaction",
|
|
1081
|
+
"transition-delay": "interaction",
|
|
1082
|
+
transform: "interaction",
|
|
1083
|
+
translate: "interaction",
|
|
1084
|
+
rotate: "interaction",
|
|
1085
|
+
scale: "interaction",
|
|
1086
|
+
animation: "interaction",
|
|
1087
|
+
"will-change": "interaction",
|
|
1088
|
+
"scroll-behavior": "interaction",
|
|
1089
|
+
"scroll-snap-type": "interaction",
|
|
1090
|
+
// Reset (jarang dipakai langsung tapi handle untuk completeness)
|
|
1091
|
+
"box-sizing": "reset",
|
|
1092
|
+
appearance: "reset",
|
|
1093
|
+
all: "reset"
|
|
1094
|
+
};
|
|
1095
|
+
BucketEngine = class {
|
|
1096
|
+
constructor() {
|
|
1097
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
1098
|
+
for (const b of BUCKET_ORDER) {
|
|
1099
|
+
this.buckets.set(b, /* @__PURE__ */ new Map());
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Tambah StyleNode ke bucket yang tepat.
|
|
1104
|
+
* Idempotent — atomic class yang sama tidak akan duplikat.
|
|
1105
|
+
*/
|
|
1106
|
+
add(node) {
|
|
1107
|
+
const bucket = classifyNode(node);
|
|
1108
|
+
this.buckets.get(bucket).set(node.atomicClass, node);
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Hapus node dari bucket (untuk incremental update).
|
|
1112
|
+
*/
|
|
1113
|
+
remove(atomicClass) {
|
|
1114
|
+
for (const bucket of this.buckets.values()) {
|
|
1115
|
+
if (bucket.delete(atomicClass)) break;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Apply CssDiff dari incremental engine.
|
|
1120
|
+
*/
|
|
1121
|
+
applyDiff(diff) {
|
|
1122
|
+
for (const node of diff.added) this.add(node);
|
|
1123
|
+
for (const cls of diff.removed) this.remove(cls);
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Emit seluruh CSS dalam urutan bucket yang deterministic.
|
|
1127
|
+
*
|
|
1128
|
+
* @param comments - Tambahkan komentar section per bucket. Default: true
|
|
1129
|
+
* @returns CSS string yang siap di-write ke file
|
|
1130
|
+
*/
|
|
1131
|
+
emit(comments = true) {
|
|
1132
|
+
const sections = [];
|
|
1133
|
+
for (const bucketName of BUCKET_ORDER) {
|
|
1134
|
+
const nodes = this.buckets.get(bucketName);
|
|
1135
|
+
if (nodes.size === 0) continue;
|
|
1136
|
+
const rules = [];
|
|
1137
|
+
for (const node of nodes.values()) {
|
|
1138
|
+
rules.push(nodeToCSS2(node));
|
|
1139
|
+
}
|
|
1140
|
+
if (rules.length === 0) continue;
|
|
1141
|
+
if (comments) {
|
|
1142
|
+
sections.push(`/* \u2500\u2500 ${bucketName} \u2500\u2500 */`);
|
|
1143
|
+
}
|
|
1144
|
+
sections.push(...rules);
|
|
1145
|
+
}
|
|
1146
|
+
return sections.join("\n");
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Emit dengan @layer CSS untuk native browser layering.
|
|
1150
|
+
* Lebih powerful — browser respects layer order untuk specificity.
|
|
1151
|
+
*
|
|
1152
|
+
* @example output:
|
|
1153
|
+
* @layer tw-layout, tw-spacing, tw-visual, tw-responsive;
|
|
1154
|
+
* @layer tw-layout { .tw-a1 { display: flex } }
|
|
1155
|
+
*/
|
|
1156
|
+
emitLayered() {
|
|
1157
|
+
const layerNames = BUCKET_ORDER.filter(
|
|
1158
|
+
(b) => b !== "unknown" && this.buckets.get(b).size > 0
|
|
1159
|
+
).map((b) => `tw-${b}`);
|
|
1160
|
+
if (layerNames.length === 0) return "";
|
|
1161
|
+
const parts = [`@layer ${layerNames.join(", ")};`, ""];
|
|
1162
|
+
for (const bucketName of BUCKET_ORDER) {
|
|
1163
|
+
const nodes = this.buckets.get(bucketName);
|
|
1164
|
+
if (nodes.size === 0) continue;
|
|
1165
|
+
const rules = Array.from(nodes.values()).map(nodeToCSS2).join("\n ");
|
|
1166
|
+
parts.push(`@layer tw-${bucketName} {
|
|
1167
|
+
${rules}
|
|
1168
|
+
}`);
|
|
1169
|
+
}
|
|
1170
|
+
return parts.join("\n");
|
|
1171
|
+
}
|
|
1172
|
+
/** Semua nodes dari semua bucket (untuk full registry access) */
|
|
1173
|
+
allNodes() {
|
|
1174
|
+
const all = [];
|
|
1175
|
+
for (const bucket of this.buckets.values()) {
|
|
1176
|
+
for (const node of bucket.values()) {
|
|
1177
|
+
all.push(node);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
return all;
|
|
1181
|
+
}
|
|
1182
|
+
/** Stats per bucket */
|
|
1183
|
+
stats() {
|
|
1184
|
+
const perBucket = {};
|
|
1185
|
+
let total = 0;
|
|
1186
|
+
for (const [name, nodes] of this.buckets) {
|
|
1187
|
+
perBucket[name] = nodes.size;
|
|
1188
|
+
total += nodes.size;
|
|
1189
|
+
}
|
|
1190
|
+
return { totalNodes: total, perBucket };
|
|
1191
|
+
}
|
|
1192
|
+
/** Clear semua bucket */
|
|
1193
|
+
clear() {
|
|
1194
|
+
for (const bucket of this.buckets.values()) {
|
|
1195
|
+
bucket.clear();
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
_bucketEngine = null;
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
// packages/compiler/src/atomicCss.ts
|
|
1204
|
+
var atomicCss_exports = {};
|
|
1205
|
+
__export(atomicCss_exports, {
|
|
1206
|
+
clearAtomicRegistry: () => clearAtomicRegistry,
|
|
1207
|
+
generateAtomicCss: () => generateAtomicCss,
|
|
1208
|
+
getAtomicRegistry: () => getAtomicRegistry,
|
|
1209
|
+
parseAtomicClass: () => parseAtomicClass,
|
|
1210
|
+
toAtomicClasses: () => toAtomicClasses
|
|
1211
|
+
});
|
|
1212
|
+
function sizeValue(v) {
|
|
1213
|
+
const num = Number(v);
|
|
1214
|
+
if (!Number.isNaN(num)) return `${num * 0.25}rem`;
|
|
1215
|
+
const special = {
|
|
1216
|
+
full: "100%",
|
|
1217
|
+
screen: "100vw",
|
|
1218
|
+
auto: "auto",
|
|
1219
|
+
min: "min-content",
|
|
1220
|
+
max: "max-content",
|
|
1221
|
+
fit: "fit-content",
|
|
1222
|
+
svw: "100svw",
|
|
1223
|
+
svh: "100svh"
|
|
1224
|
+
};
|
|
1225
|
+
return special[v] ?? v;
|
|
1226
|
+
}
|
|
1227
|
+
function textSize(v) {
|
|
1228
|
+
const map = {
|
|
1229
|
+
xs: "0.75rem",
|
|
1230
|
+
sm: "0.875rem",
|
|
1231
|
+
base: "1rem",
|
|
1232
|
+
lg: "1.125rem",
|
|
1233
|
+
xl: "1.25rem",
|
|
1234
|
+
"2xl": "1.5rem",
|
|
1235
|
+
"3xl": "1.875rem",
|
|
1236
|
+
"4xl": "2.25rem",
|
|
1237
|
+
"5xl": "3rem",
|
|
1238
|
+
"6xl": "3.75rem",
|
|
1239
|
+
"7xl": "4.5rem",
|
|
1240
|
+
"8xl": "6rem",
|
|
1241
|
+
"9xl": "8rem"
|
|
1242
|
+
};
|
|
1243
|
+
return map[v] ?? v;
|
|
1244
|
+
}
|
|
1245
|
+
function fontWeight(v) {
|
|
1246
|
+
const map = {
|
|
1247
|
+
thin: "100",
|
|
1248
|
+
extralight: "200",
|
|
1249
|
+
light: "300",
|
|
1250
|
+
normal: "400",
|
|
1251
|
+
medium: "500",
|
|
1252
|
+
semibold: "600",
|
|
1253
|
+
bold: "700",
|
|
1254
|
+
extrabold: "800",
|
|
1255
|
+
black: "900"
|
|
1256
|
+
};
|
|
1257
|
+
return map[v] ?? v;
|
|
1258
|
+
}
|
|
1259
|
+
function leadingValue(v) {
|
|
1260
|
+
const map = {
|
|
1261
|
+
none: "1",
|
|
1262
|
+
tight: "1.25",
|
|
1263
|
+
snug: "1.375",
|
|
1264
|
+
normal: "1.5",
|
|
1265
|
+
relaxed: "1.625",
|
|
1266
|
+
loose: "2"
|
|
1267
|
+
};
|
|
1268
|
+
return map[v] ?? v;
|
|
1269
|
+
}
|
|
1270
|
+
function roundedValue(v) {
|
|
1271
|
+
const map = {
|
|
1272
|
+
"": "0.25rem",
|
|
1273
|
+
sm: "0.125rem",
|
|
1274
|
+
md: "0.375rem",
|
|
1275
|
+
lg: "0.5rem",
|
|
1276
|
+
xl: "0.75rem",
|
|
1277
|
+
"2xl": "1rem",
|
|
1278
|
+
"3xl": "1.5rem",
|
|
1279
|
+
full: "9999px",
|
|
1280
|
+
none: "0"
|
|
1281
|
+
};
|
|
1282
|
+
return map[v] ?? `${v}rem`;
|
|
1283
|
+
}
|
|
1284
|
+
function sanitizeClassName(cls) {
|
|
1285
|
+
return cls.replace(/[/:[\].!%]/g, "_");
|
|
1286
|
+
}
|
|
1287
|
+
function parseAtomicClass(twClass) {
|
|
1288
|
+
if (REGISTRY.has(twClass)) return REGISTRY.get(twClass);
|
|
1289
|
+
const colonIdx = twClass.lastIndexOf(":");
|
|
1290
|
+
const modifier = colonIdx > -1 ? twClass.slice(0, colonIdx) : void 0;
|
|
1291
|
+
const base = colonIdx > -1 ? twClass.slice(colonIdx + 1) : twClass;
|
|
1292
|
+
const dashIdx = base.indexOf("-");
|
|
1293
|
+
if (dashIdx === -1) return null;
|
|
1294
|
+
const prefix = base.slice(0, dashIdx);
|
|
1295
|
+
const value = base.slice(dashIdx + 1);
|
|
1296
|
+
const mapping = TW_PROPERTY_MAP[prefix];
|
|
1297
|
+
if (!mapping) return null;
|
|
1298
|
+
const cssValue = mapping.transform ? mapping.transform(value) : value;
|
|
1299
|
+
const atomicName = `_tw_${sanitizeClassName(twClass)}`;
|
|
1300
|
+
const rule = {
|
|
1301
|
+
twClass,
|
|
1302
|
+
atomicName,
|
|
1303
|
+
property: mapping.prop,
|
|
1304
|
+
value: cssValue,
|
|
1305
|
+
modifier
|
|
1306
|
+
};
|
|
1307
|
+
REGISTRY.set(twClass, rule);
|
|
1308
|
+
return rule;
|
|
1309
|
+
}
|
|
1310
|
+
function generateAtomicCss(rules) {
|
|
1311
|
+
const lines = [];
|
|
1312
|
+
for (const rule of rules) {
|
|
1313
|
+
const selector = `.${rule.atomicName}`;
|
|
1314
|
+
if (rule.modifier) {
|
|
1315
|
+
const breakpoints = {
|
|
1316
|
+
sm: "640px",
|
|
1317
|
+
md: "768px",
|
|
1318
|
+
lg: "1024px",
|
|
1319
|
+
xl: "1280px",
|
|
1320
|
+
"2xl": "1536px"
|
|
1321
|
+
};
|
|
1322
|
+
if (breakpoints[rule.modifier]) {
|
|
1323
|
+
lines.push(
|
|
1324
|
+
`@media (min-width: ${breakpoints[rule.modifier]}) {`,
|
|
1325
|
+
` ${selector} { ${rule.property}: ${rule.value}; }`,
|
|
1326
|
+
`}`
|
|
1327
|
+
);
|
|
1328
|
+
continue;
|
|
1329
|
+
}
|
|
1330
|
+
lines.push(`${selector}:${rule.modifier} { ${rule.property}: ${rule.value}; }`);
|
|
1331
|
+
} else {
|
|
1332
|
+
lines.push(`${selector} { ${rule.property}: ${rule.value}; }`);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
return lines.join("\n");
|
|
1336
|
+
}
|
|
1337
|
+
function toAtomicClasses(twClasses) {
|
|
1338
|
+
const parts = twClasses.split(/\s+/).filter(Boolean);
|
|
1339
|
+
const atomicNames = [];
|
|
1340
|
+
const rules = [];
|
|
1341
|
+
const unknownClasses = [];
|
|
1342
|
+
for (const cls of parts) {
|
|
1343
|
+
const rule = parseAtomicClass(cls);
|
|
1344
|
+
if (rule) {
|
|
1345
|
+
atomicNames.push(rule.atomicName);
|
|
1346
|
+
rules.push(rule);
|
|
1347
|
+
} else {
|
|
1348
|
+
unknownClasses.push(cls);
|
|
1349
|
+
atomicNames.push(cls);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
return {
|
|
1353
|
+
atomicClasses: atomicNames.join(" "),
|
|
1354
|
+
rules,
|
|
1355
|
+
unknownClasses
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
function getAtomicRegistry() {
|
|
1359
|
+
return REGISTRY;
|
|
1360
|
+
}
|
|
1361
|
+
function clearAtomicRegistry() {
|
|
1362
|
+
REGISTRY.clear();
|
|
1363
|
+
}
|
|
1364
|
+
var REGISTRY, TW_PROPERTY_MAP;
|
|
1365
|
+
var init_atomicCss = __esm({
|
|
1366
|
+
"packages/compiler/src/atomicCss.ts"() {
|
|
1367
|
+
REGISTRY = /* @__PURE__ */ new Map();
|
|
1368
|
+
TW_PROPERTY_MAP = {
|
|
1369
|
+
// Spacing
|
|
1370
|
+
p: { prop: "padding", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1371
|
+
px: { prop: "padding-inline", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1372
|
+
py: { prop: "padding-block", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1373
|
+
pt: { prop: "padding-top", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1374
|
+
pb: { prop: "padding-bottom", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1375
|
+
pl: { prop: "padding-left", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1376
|
+
pr: { prop: "padding-right", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1377
|
+
m: { prop: "margin", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1378
|
+
mx: { prop: "margin-inline", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1379
|
+
my: { prop: "margin-block", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1380
|
+
mt: { prop: "margin-top", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1381
|
+
mb: { prop: "margin-bottom", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1382
|
+
ml: { prop: "margin-left", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1383
|
+
mr: { prop: "margin-right", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1384
|
+
gap: { prop: "gap", transform: (v) => `${Number(v) * 0.25}rem` },
|
|
1385
|
+
// Sizing
|
|
1386
|
+
w: { prop: "width", transform: sizeValue },
|
|
1387
|
+
h: { prop: "height", transform: sizeValue },
|
|
1388
|
+
// Typography
|
|
1389
|
+
text: { prop: "font-size", transform: textSize },
|
|
1390
|
+
font: { prop: "font-weight", transform: fontWeight },
|
|
1391
|
+
leading: { prop: "line-height", transform: leadingValue },
|
|
1392
|
+
// Misc
|
|
1393
|
+
opacity: { prop: "opacity", transform: (v) => String(Number(v) / 100) },
|
|
1394
|
+
z: { prop: "z-index" },
|
|
1395
|
+
rounded: { prop: "border-radius", transform: (v) => roundedValue(v) }
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
|
|
1400
|
+
// packages/compiler/src/context.ts
|
|
1401
|
+
var CompileContext;
|
|
1402
|
+
var init_context = __esm({
|
|
1403
|
+
"packages/compiler/src/context.ts"() {
|
|
1404
|
+
CompileContext = class {
|
|
1405
|
+
constructor(input) {
|
|
1406
|
+
this.filepath = input.filepath;
|
|
1407
|
+
this.source = input.source;
|
|
1408
|
+
this.options = input.options;
|
|
1409
|
+
this.result = null;
|
|
1410
|
+
this.done = false;
|
|
1411
|
+
this.engine = "none";
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
// packages/compiler/src/pipeline.ts
|
|
1418
|
+
var Pipeline;
|
|
1419
|
+
var init_pipeline = __esm({
|
|
1420
|
+
"packages/compiler/src/pipeline.ts"() {
|
|
1421
|
+
Pipeline = class {
|
|
1422
|
+
constructor() {
|
|
1423
|
+
this.steps = [];
|
|
1424
|
+
}
|
|
1425
|
+
use(step) {
|
|
1426
|
+
this.steps.push(step);
|
|
1427
|
+
return this;
|
|
1428
|
+
}
|
|
1429
|
+
run(ctx) {
|
|
1430
|
+
for (const step of this.steps) {
|
|
1431
|
+
step(ctx);
|
|
1432
|
+
if (ctx.done) break;
|
|
1433
|
+
}
|
|
1434
|
+
return ctx;
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
});
|
|
1439
|
+
function makeCacheKey(input) {
|
|
1440
|
+
const options = {
|
|
1441
|
+
mode: input.options.mode,
|
|
1442
|
+
autoClientBoundary: input.options.autoClientBoundary,
|
|
1443
|
+
addDataAttr: input.options.addDataAttr,
|
|
1444
|
+
hoist: input.options.hoist,
|
|
1445
|
+
filename: input.options.filename ?? input.filepath,
|
|
1446
|
+
deadStyleElimination: input.options.deadStyleElimination
|
|
1447
|
+
};
|
|
1448
|
+
return crypto.createHash("sha1").update(input.filepath).update("").update(input.source).update("").update(JSON.stringify(options)).digest("hex");
|
|
1449
|
+
}
|
|
1450
|
+
function cloneTransformResult(result) {
|
|
1451
|
+
return {
|
|
1452
|
+
code: result.code,
|
|
1453
|
+
classes: [...result.classes],
|
|
1454
|
+
changed: result.changed,
|
|
1455
|
+
rsc: result.rsc ? {
|
|
1456
|
+
isServer: result.rsc.isServer,
|
|
1457
|
+
needsClientDirective: result.rsc.needsClientDirective,
|
|
1458
|
+
clientReasons: [...result.rsc.clientReasons]
|
|
1459
|
+
} : void 0
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function cloneCoreCompileResult(result) {
|
|
1463
|
+
return {
|
|
1464
|
+
result: cloneTransformResult(result.result),
|
|
1465
|
+
engine: result.engine,
|
|
1466
|
+
cacheHit: result.cacheHit,
|
|
1467
|
+
metadata: result.metadata ? result.metadata.map((m) => ({ ...m })) : void 0,
|
|
1468
|
+
css: result.css
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
function persistCache(key, value) {
|
|
1472
|
+
compileCache.set(key, { ...value, cacheHit: false });
|
|
1473
|
+
if (compileCache.size <= MAX_CACHE_ENTRIES) return;
|
|
1474
|
+
const oldestKey = compileCache.keys().next().value;
|
|
1475
|
+
if (oldestKey) compileCache.delete(oldestKey);
|
|
1476
|
+
}
|
|
1477
|
+
function createPassthrough(source) {
|
|
1478
|
+
return { code: source, classes: [], changed: false };
|
|
1479
|
+
}
|
|
1480
|
+
function compileWithCore(input) {
|
|
1481
|
+
return compilerCore.compile(input);
|
|
1482
|
+
}
|
|
1483
|
+
var MAX_CACHE_ENTRIES, compileCache, CompilerCore, compilerCore;
|
|
1484
|
+
var init_coreCompiler = __esm({
|
|
1485
|
+
"packages/compiler/src/coreCompiler.ts"() {
|
|
1486
|
+
init_context();
|
|
1487
|
+
init_nativeBridge();
|
|
1488
|
+
init_pipeline();
|
|
1489
|
+
MAX_CACHE_ENTRIES = 512;
|
|
1490
|
+
compileCache = /* @__PURE__ */ new Map();
|
|
1491
|
+
CompilerCore = class {
|
|
1492
|
+
constructor() {
|
|
1493
|
+
this.pipeline = new Pipeline().use((ctx) => this.nativeStep(ctx));
|
|
1494
|
+
}
|
|
1495
|
+
compile(input) {
|
|
1496
|
+
const cacheKey = makeCacheKey(input);
|
|
1497
|
+
const cached = compileCache.get(cacheKey);
|
|
1498
|
+
if (cached) {
|
|
1499
|
+
const hit = cloneCoreCompileResult(cached);
|
|
1500
|
+
hit.cacheHit = true;
|
|
1501
|
+
return hit;
|
|
1502
|
+
}
|
|
1503
|
+
const ctx = new CompileContext(input);
|
|
1504
|
+
this.pipeline.run(ctx);
|
|
1505
|
+
const result = ctx.result ?? createPassthrough(input.source);
|
|
1506
|
+
let cssOutput;
|
|
1507
|
+
if (ctx.options.deadStyleElimination && result.classes.length > 0) {
|
|
1508
|
+
cssOutput = this.runDeadStyleElimination(result.classes, input.options);
|
|
1509
|
+
}
|
|
1510
|
+
const compiled = {
|
|
1511
|
+
result,
|
|
1512
|
+
engine: ctx.engine,
|
|
1513
|
+
cacheHit: false,
|
|
1514
|
+
metadata: ctx.metadata,
|
|
1515
|
+
css: cssOutput
|
|
1516
|
+
};
|
|
1517
|
+
persistCache(cacheKey, compiled);
|
|
1518
|
+
return cloneCoreCompileResult(compiled);
|
|
1519
|
+
}
|
|
1520
|
+
runDeadStyleElimination(classes, options) {
|
|
1521
|
+
if (classes.length === 0) return "";
|
|
1522
|
+
const native = getNativeBridge();
|
|
1523
|
+
if (native?.analyzeClassesNative) {
|
|
1524
|
+
try {
|
|
1525
|
+
const filesJson = JSON.stringify([{ file: "compiled", classes }]);
|
|
1526
|
+
const analysis = native.analyzeClassesNative(filesJson, process.cwd(), 0);
|
|
1527
|
+
if (analysis && analysis.safelist) {
|
|
1528
|
+
const deadClasses = /* @__PURE__ */ new Set();
|
|
1529
|
+
const safelistSet = new Set(analysis.safelist);
|
|
1530
|
+
for (const cls of classes) {
|
|
1531
|
+
if (!safelistSet.has(cls)) {
|
|
1532
|
+
deadClasses.add(cls);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
if (deadClasses.size > 0) {
|
|
1536
|
+
return "";
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
} catch {
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
return "";
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* v5: Native step now THROWS if native binding is unavailable.
|
|
1546
|
+
* Previously returned early to allow JS fallback.
|
|
1547
|
+
*/
|
|
1548
|
+
nativeStep(ctx) {
|
|
1549
|
+
const native = getNativeBridge();
|
|
1550
|
+
if (!native?.transformSourceNative) {
|
|
1551
|
+
throw new Error(
|
|
1552
|
+
`[tailwind-styled/compiler v5] transformSourceNative is required but not available.
|
|
1553
|
+
Please ensure the native module is properly built with transform support.`
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
const opts = {};
|
|
1557
|
+
if (ctx.options.mode) opts.mode = ctx.options.mode;
|
|
1558
|
+
if (ctx.options.filename ?? ctx.filepath) opts.filename = ctx.options.filename ?? ctx.filepath;
|
|
1559
|
+
const raw = native.transformSourceNative(ctx.source, opts);
|
|
1560
|
+
if (raw === null) {
|
|
1561
|
+
throw new Error(
|
|
1562
|
+
`[tailwind-styled/compiler v5] Native transform returned null for: ${ctx.filepath}
|
|
1563
|
+
This indicates an issue with the native module.`
|
|
1564
|
+
);
|
|
1565
|
+
}
|
|
1566
|
+
const adapted = adaptNativeResult(raw);
|
|
1567
|
+
ctx.result = adapted;
|
|
1568
|
+
ctx.metadata = adapted.metadata;
|
|
1569
|
+
ctx.engine = "native";
|
|
1570
|
+
ctx.done = true;
|
|
1571
|
+
}
|
|
1572
|
+
/**
|
|
1573
|
+
* v5: JS pipeline has been removed.
|
|
1574
|
+
* Previously used as fallback when native was unavailable.
|
|
1575
|
+
*
|
|
1576
|
+
* @throws Error always - JS pipeline is no longer supported in v5
|
|
1577
|
+
* @deprecated JS pipeline was removed in v5
|
|
1578
|
+
*/
|
|
1579
|
+
jsStep(ctx) {
|
|
1580
|
+
throw new Error(
|
|
1581
|
+
`[tailwind-styled/compiler v5] JS pipeline is no longer supported.
|
|
1582
|
+
The native binding is required for all transformations.`
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
compilerCore = new CompilerCore();
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
|
|
1590
|
+
// packages/compiler/src/routeCssCollector.ts
|
|
1591
|
+
function registerFileClasses(filepath, classes) {
|
|
1592
|
+
if (!_collector.files.has(filepath)) {
|
|
1593
|
+
_collector.files.set(filepath, /* @__PURE__ */ new Set());
|
|
1594
|
+
}
|
|
1595
|
+
const fileSet = _collector.files.get(filepath);
|
|
1596
|
+
classes.forEach((c) => fileSet.add(c));
|
|
1597
|
+
const route = fileToRoute(filepath);
|
|
1598
|
+
if (route) {
|
|
1599
|
+
if (!_collector.routes.has(route)) {
|
|
1600
|
+
_collector.routes.set(route, /* @__PURE__ */ new Set());
|
|
1601
|
+
}
|
|
1602
|
+
_collector.routes.get(route).add(filepath);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
function fileToRoute(filepath) {
|
|
1606
|
+
const normalized = filepath.replace(/\\/g, "/");
|
|
1607
|
+
if (normalized.includes("/layout.") || normalized.includes("/loading.") || normalized.includes("/error.")) {
|
|
1608
|
+
return "__global";
|
|
1609
|
+
}
|
|
1610
|
+
const pageMatch = normalized.match(/\/app\/(.+?)\/page\.[tj]sx?$/);
|
|
1611
|
+
if (pageMatch) return `/${pageMatch[1]}`;
|
|
1612
|
+
const rootPage = normalized.match(/\/app\/page\.[tj]sx?$/);
|
|
1613
|
+
if (rootPage) return "/";
|
|
1614
|
+
const pagesMatch = normalized.match(/\/pages\/(.+?)\.[tj]sx?$/);
|
|
1615
|
+
if (pagesMatch) {
|
|
1616
|
+
const route = pagesMatch[1].replace(/\/index$/, "");
|
|
1617
|
+
return `/${route}`;
|
|
1618
|
+
}
|
|
1619
|
+
if (normalized.includes("/components/") || normalized.includes("/ui/") || normalized.includes("/shared/")) {
|
|
1620
|
+
return "__global";
|
|
1621
|
+
}
|
|
1622
|
+
return null;
|
|
1623
|
+
}
|
|
1624
|
+
var _collector;
|
|
1625
|
+
var init_routeCssCollector = __esm({
|
|
1626
|
+
"packages/compiler/src/routeCssCollector.ts"() {
|
|
1627
|
+
_collector = {
|
|
1628
|
+
files: /* @__PURE__ */ new Map(),
|
|
1629
|
+
routes: /* @__PURE__ */ new Map(),
|
|
1630
|
+
global: /* @__PURE__ */ new Set()
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
});
|
|
1634
|
+
|
|
1635
|
+
// packages/compiler/src/loaderCore.ts
|
|
1636
|
+
function shouldSkipFile(filepath) {
|
|
1637
|
+
return SKIP_PATHS.some((p) => filepath.includes(p)) || !/\.[jt]sx?$/.test(filepath);
|
|
1638
|
+
}
|
|
1639
|
+
function runLoaderTransform(ctx) {
|
|
1640
|
+
const { filepath, source, options } = ctx;
|
|
1641
|
+
const passthrough = { code: source, changed: false, classes: [] };
|
|
1642
|
+
if (shouldSkipFile(filepath)) return passthrough;
|
|
1643
|
+
try {
|
|
1644
|
+
if (options.incremental !== false) {
|
|
1645
|
+
const engine = getIncrementalEngine({ verbose: options.verbose });
|
|
1646
|
+
const precheck = engine.processFile(filepath, source, []);
|
|
1647
|
+
if (!precheck.changed) return passthrough;
|
|
1648
|
+
}
|
|
1649
|
+
const compiled = compileWithCore({
|
|
1650
|
+
filepath,
|
|
1651
|
+
source,
|
|
1652
|
+
options: { ...options, filename: filepath }
|
|
1653
|
+
});
|
|
1654
|
+
if (!compiled.result.changed) return passthrough;
|
|
1655
|
+
return finalize(
|
|
1656
|
+
compiled.result,
|
|
1657
|
+
filepath,
|
|
1658
|
+
options,
|
|
1659
|
+
compiled.engine,
|
|
1660
|
+
compiled.cacheHit,
|
|
1661
|
+
compiled.metadata
|
|
1662
|
+
);
|
|
1663
|
+
} catch (err) {
|
|
1664
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1665
|
+
const name = filepath.split(/[/\\]/).pop();
|
|
1666
|
+
console.warn(`[tailwind-styled] Transform failed for ${name}:`, err);
|
|
1667
|
+
}
|
|
1668
|
+
return passthrough;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
function finalize(result, filepath, options, engine, cacheHit, metadata) {
|
|
1672
|
+
if (!result.changed) {
|
|
1673
|
+
return { code: result.code, changed: false, classes: [] };
|
|
1674
|
+
}
|
|
1675
|
+
if (options.routeCss && result.classes.length > 0) {
|
|
1676
|
+
registerFileClasses(filepath, result.classes);
|
|
1677
|
+
}
|
|
1678
|
+
if (options.incremental !== false) {
|
|
1679
|
+
try {
|
|
1680
|
+
const engineInst = getIncrementalEngine({ verbose: options.verbose });
|
|
1681
|
+
const nodes = parseClassesToNodes(result.classes);
|
|
1682
|
+
const diff = engineInst.processFile(filepath, result.code, nodes);
|
|
1683
|
+
getBucketEngine().applyDiff(diff.diff);
|
|
1684
|
+
} catch {
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
if (options.verbose) {
|
|
1688
|
+
const env = result.rsc?.isServer ? "server" : "client";
|
|
1689
|
+
const name = filepath.split(/[/\\]/).pop();
|
|
1690
|
+
const pathHint = result.rsc ? ` (${env})` : "";
|
|
1691
|
+
const cacheText = cacheHit ? " cache-hit" : "";
|
|
1692
|
+
const metaText = metadata?.length ? ` [${metadata.length} compound]` : "";
|
|
1693
|
+
console.log(
|
|
1694
|
+
`[tailwind-styled] ${name} -> ${result.classes.length} classes${pathHint} [${engine}${cacheText}]${metaText}`
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
return {
|
|
1698
|
+
code: result.code,
|
|
1699
|
+
changed: result.changed,
|
|
1700
|
+
classes: result.classes,
|
|
1701
|
+
rsc: result.rsc,
|
|
1702
|
+
engine,
|
|
1703
|
+
cacheHit,
|
|
1704
|
+
metadata
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
var SKIP_PATHS;
|
|
1708
|
+
var init_loaderCore = __esm({
|
|
1709
|
+
"packages/compiler/src/loaderCore.ts"() {
|
|
1710
|
+
init_coreCompiler();
|
|
1711
|
+
init_incrementalEngine();
|
|
1712
|
+
init_routeCssCollector();
|
|
1713
|
+
init_styleBucketSystem();
|
|
1714
|
+
SKIP_PATHS = ["node_modules", ".next", ".rspack-dist", ".turbo", "dist/", "out/"];
|
|
1715
|
+
}
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1718
|
+
// packages/preset/src/defaultPreset.ts
|
|
1719
|
+
var defaultPreset_exports = {};
|
|
1720
|
+
__export(defaultPreset_exports, {
|
|
1721
|
+
defaultGlobalCss: () => defaultGlobalCss,
|
|
1722
|
+
defaultPreset: () => defaultPreset,
|
|
1723
|
+
defaultThemeCss: () => defaultThemeCss,
|
|
1724
|
+
designTokens: () => designTokens,
|
|
1725
|
+
generateTailwindConfig: () => generateTailwindConfig,
|
|
1726
|
+
generateTailwindCss: () => generateTailwindCss
|
|
1727
|
+
});
|
|
1728
|
+
function generateTailwindCss(contentPaths = STANDARD_CONTENT_PATHS) {
|
|
1729
|
+
return `@import "tailwindcss";
|
|
1730
|
+
|
|
1731
|
+
@theme {
|
|
1732
|
+
/* colors */
|
|
1733
|
+
--color-primary: #3b82f6;
|
|
1734
|
+
--color-primary-hover: #2563eb;
|
|
1735
|
+
--color-primary-active: #1d4ed8;
|
|
1736
|
+
--color-primary-foreground: #ffffff;
|
|
1737
|
+
--color-secondary: #6366f1;
|
|
1738
|
+
--color-secondary-hover: #4f46e5;
|
|
1739
|
+
--color-secondary-active: #4338ca;
|
|
1740
|
+
--color-secondary-foreground: #ffffff;
|
|
1741
|
+
--color-accent: #f59e0b;
|
|
1742
|
+
--color-accent-hover: #d97706;
|
|
1743
|
+
--color-accent-active: #b45309;
|
|
1744
|
+
--color-accent-foreground: #000000;
|
|
1745
|
+
--color-success: #10b981;
|
|
1746
|
+
--color-success-foreground: #ffffff;
|
|
1747
|
+
--color-warning: #f59e0b;
|
|
1748
|
+
--color-warning-foreground: #000000;
|
|
1749
|
+
--color-danger: #ef4444;
|
|
1750
|
+
--color-danger-foreground: #ffffff;
|
|
1751
|
+
--color-info: #3b82f6;
|
|
1752
|
+
--color-info-foreground: #ffffff;
|
|
1753
|
+
--color-surface: #18181b;
|
|
1754
|
+
--color-border: #27272a;
|
|
1755
|
+
--color-muted: #71717a;
|
|
1756
|
+
--color-subtle: #3f3f46;
|
|
1757
|
+
|
|
1758
|
+
/* fonts */
|
|
1759
|
+
--font-sans: InterVariable, Inter, system-ui, sans-serif;
|
|
1760
|
+
--font-mono: JetBrains Mono, Fira Code, Consolas, monospace;
|
|
1761
|
+
|
|
1762
|
+
/* spacing */
|
|
1763
|
+
--spacing-1: 0.25rem;
|
|
1764
|
+
--spacing-2: 0.5rem;
|
|
1765
|
+
--spacing-3: 0.75rem;
|
|
1766
|
+
--spacing-4: 1rem;
|
|
1767
|
+
--spacing-5: 1.25rem;
|
|
1768
|
+
--spacing-6: 1.5rem;
|
|
1769
|
+
--spacing-8: 2rem;
|
|
1770
|
+
--spacing-10: 2.5rem;
|
|
1771
|
+
--spacing-12: 3rem;
|
|
1772
|
+
--spacing-16: 4rem;
|
|
1773
|
+
|
|
1774
|
+
/* breakpoints */
|
|
1775
|
+
--breakpoint-sm: 40rem;
|
|
1776
|
+
--breakpoint-md: 48rem;
|
|
1777
|
+
--breakpoint-lg: 64rem;
|
|
1778
|
+
--breakpoint-xl: 80rem;
|
|
1779
|
+
--breakpoint-2xl: 96rem;
|
|
1780
|
+
|
|
1781
|
+
/* border radius */
|
|
1782
|
+
--radius-sm: 0.25rem;
|
|
1783
|
+
--radius-md: 0.5rem;
|
|
1784
|
+
--radius-lg: 0.75rem;
|
|
1785
|
+
--radius-xl: 1rem;
|
|
1786
|
+
--radius-2xl: 1.5rem;
|
|
1787
|
+
--radius-full: 9999px;
|
|
1788
|
+
|
|
1789
|
+
/* animations */
|
|
1790
|
+
--animate-fade-in: fadeIn 0.2s ease-out;
|
|
1791
|
+
--animate-fade-out: fadeOut 0.2s ease-in;
|
|
1792
|
+
--animate-slide-up: slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1793
|
+
--animate-slide-down: slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1794
|
+
--animate-scale-in: scaleIn 0.2s ease-out;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
@keyframes fadeIn {
|
|
1798
|
+
from { opacity: 0; }
|
|
1799
|
+
to { opacity: 1; }
|
|
1800
|
+
}
|
|
1801
|
+
@keyframes fadeOut {
|
|
1802
|
+
from { opacity: 1; }
|
|
1803
|
+
to { opacity: 0; }
|
|
1804
|
+
}
|
|
1805
|
+
@keyframes slideUp {
|
|
1806
|
+
from { transform: translateY(8px); opacity: 0; }
|
|
1807
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1808
|
+
}
|
|
1809
|
+
@keyframes slideDown {
|
|
1810
|
+
from { transform: translateY(-8px); opacity: 0; }
|
|
1811
|
+
to { transform: translateY(0); opacity: 1; }
|
|
1812
|
+
}
|
|
1813
|
+
@keyframes scaleIn {
|
|
1814
|
+
from { transform: scale(0.95); opacity: 0; }
|
|
1815
|
+
to { transform: scale(1); opacity: 1; }
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
@source ${contentPaths.join("\n@source ")}
|
|
1819
|
+
`;
|
|
1820
|
+
}
|
|
1821
|
+
function generateTailwindConfig(safelistPath = ".tailwind-styled-safelist.json", contentPaths = STANDARD_CONTENT_PATHS) {
|
|
1822
|
+
return `import type { Config } from "tailwindcss"
|
|
1823
|
+
import { defaultPreset } from "tailwind-styled-v4/preset"
|
|
1824
|
+
|
|
1825
|
+
// Auto-generated safelist dari tailwind-styled-v4 compiler
|
|
1826
|
+
const safelist = (() => {
|
|
1827
|
+
try { return require(${JSON.stringify(safelistPath)}) as string[] }
|
|
1828
|
+
catch { return [] }
|
|
1829
|
+
})()
|
|
1830
|
+
|
|
1831
|
+
export default {
|
|
1832
|
+
presets: [defaultPreset],
|
|
1833
|
+
content: ${JSON.stringify(contentPaths, null, 2)},
|
|
1834
|
+
safelist,
|
|
1835
|
+
} satisfies Config
|
|
1836
|
+
`;
|
|
1837
|
+
}
|
|
1838
|
+
var STANDARD_CONTENT_PATHS, designTokens, defaultPreset, defaultThemeCss, defaultGlobalCss;
|
|
1839
|
+
var init_defaultPreset = __esm({
|
|
1840
|
+
"packages/preset/src/defaultPreset.ts"() {
|
|
1841
|
+
STANDARD_CONTENT_PATHS = [
|
|
1842
|
+
// Next.js App Router
|
|
1843
|
+
"./src/**/*.{tsx,ts,jsx,js,mdx}",
|
|
1844
|
+
"./app/**/*.{tsx,ts,jsx,js,mdx}",
|
|
1845
|
+
"./pages/**/*.{tsx,ts,jsx,js,mdx}",
|
|
1846
|
+
"./components/**/*.{tsx,ts,jsx,js,mdx}",
|
|
1847
|
+
// Vite / React
|
|
1848
|
+
"./src/**/*.{tsx,ts,jsx,js}",
|
|
1849
|
+
"./index.html",
|
|
1850
|
+
// Monorepo
|
|
1851
|
+
"../../packages/**/src/**/*.{tsx,ts,jsx,js}"
|
|
1852
|
+
];
|
|
1853
|
+
designTokens = {
|
|
1854
|
+
colors: {
|
|
1855
|
+
primary: { DEFAULT: "#3b82f6", hover: "#2563eb", active: "#1d4ed8", foreground: "#ffffff" },
|
|
1856
|
+
secondary: { DEFAULT: "#6366f1", hover: "#4f46e5", active: "#4338ca", foreground: "#ffffff" },
|
|
1857
|
+
accent: { DEFAULT: "#f59e0b", hover: "#d97706", active: "#b45309", foreground: "#000000" },
|
|
1858
|
+
success: { DEFAULT: "#10b981", foreground: "#ffffff" },
|
|
1859
|
+
warning: { DEFAULT: "#f59e0b", foreground: "#000000" },
|
|
1860
|
+
danger: { DEFAULT: "#ef4444", foreground: "#ffffff" },
|
|
1861
|
+
info: { DEFAULT: "#3b82f6", foreground: "#ffffff" },
|
|
1862
|
+
surface: "#18181b",
|
|
1863
|
+
border: "#27272a",
|
|
1864
|
+
muted: "#71717a",
|
|
1865
|
+
subtle: "#3f3f46"
|
|
1866
|
+
},
|
|
1867
|
+
spacing: {
|
|
1868
|
+
1: "0.25rem",
|
|
1869
|
+
2: "0.5rem",
|
|
1870
|
+
3: "0.75rem",
|
|
1871
|
+
4: "1rem",
|
|
1872
|
+
5: "1.25rem",
|
|
1873
|
+
6: "1.5rem",
|
|
1874
|
+
8: "2rem",
|
|
1875
|
+
10: "2.5rem",
|
|
1876
|
+
12: "3rem",
|
|
1877
|
+
16: "4rem"
|
|
1878
|
+
},
|
|
1879
|
+
breakpoints: {
|
|
1880
|
+
sm: "40rem",
|
|
1881
|
+
md: "48rem",
|
|
1882
|
+
lg: "64rem",
|
|
1883
|
+
xl: "80rem",
|
|
1884
|
+
"2xl": "96rem"
|
|
1885
|
+
},
|
|
1886
|
+
fontWeight: {
|
|
1887
|
+
normal: "400",
|
|
1888
|
+
medium: "500",
|
|
1889
|
+
semibold: "600",
|
|
1890
|
+
bold: "700"
|
|
1891
|
+
},
|
|
1892
|
+
fontFamily: {
|
|
1893
|
+
sans: ["InterVariable", "Inter", "system-ui", "sans-serif"],
|
|
1894
|
+
mono: ["JetBrains Mono", "Fira Code", "Consolas", "monospace"]
|
|
1895
|
+
},
|
|
1896
|
+
borderRadius: {
|
|
1897
|
+
sm: "0.25rem",
|
|
1898
|
+
DEFAULT: "0.5rem",
|
|
1899
|
+
md: "0.5rem",
|
|
1900
|
+
lg: "0.75rem",
|
|
1901
|
+
xl: "1rem",
|
|
1902
|
+
"2xl": "1.5rem",
|
|
1903
|
+
full: "9999px"
|
|
1904
|
+
},
|
|
1905
|
+
animation: {
|
|
1906
|
+
"fade-in": "fadeIn 0.2s ease-out",
|
|
1907
|
+
"fade-out": "fadeOut 0.2s ease-in",
|
|
1908
|
+
"slide-up": "slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1)",
|
|
1909
|
+
"slide-down": "slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1)",
|
|
1910
|
+
"scale-in": "scaleIn 0.2s ease-out"
|
|
1911
|
+
},
|
|
1912
|
+
keyframes: {
|
|
1913
|
+
fadeIn: { from: { opacity: "0" }, to: { opacity: "1" } },
|
|
1914
|
+
fadeOut: { from: { opacity: "1" }, to: { opacity: "0" } },
|
|
1915
|
+
slideUp: {
|
|
1916
|
+
from: { transform: "translateY(8px)", opacity: "0" },
|
|
1917
|
+
to: { transform: "translateY(0)", opacity: "1" }
|
|
1918
|
+
},
|
|
1919
|
+
slideDown: {
|
|
1920
|
+
from: { transform: "translateY(-8px)", opacity: "0" },
|
|
1921
|
+
to: { transform: "translateY(0)", opacity: "1" }
|
|
1922
|
+
},
|
|
1923
|
+
scaleIn: {
|
|
1924
|
+
from: { transform: "scale(0.95)", opacity: "0" },
|
|
1925
|
+
to: { transform: "scale(1)", opacity: "1" }
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
};
|
|
1929
|
+
defaultPreset = {
|
|
1930
|
+
content: STANDARD_CONTENT_PATHS,
|
|
1931
|
+
darkMode: "class",
|
|
1932
|
+
theme: {
|
|
1933
|
+
extend: {
|
|
1934
|
+
colors: designTokens.colors,
|
|
1935
|
+
fontFamily: designTokens.fontFamily,
|
|
1936
|
+
borderRadius: designTokens.borderRadius,
|
|
1937
|
+
animation: designTokens.animation,
|
|
1938
|
+
keyframes: designTokens.keyframes
|
|
1939
|
+
}
|
|
1940
|
+
},
|
|
1941
|
+
plugins: []
|
|
1942
|
+
};
|
|
1943
|
+
defaultThemeCss = `@import "tailwindcss";
|
|
1944
|
+
|
|
1945
|
+
@theme {
|
|
1946
|
+
/* colors */
|
|
1947
|
+
--color-primary: #3b82f6;
|
|
1948
|
+
--color-primary-hover: #2563eb;
|
|
1949
|
+
--color-primary-active: #1d4ed8;
|
|
1950
|
+
--color-primary-foreground: #ffffff;
|
|
1951
|
+
--color-secondary: #6366f1;
|
|
1952
|
+
--color-secondary-hover: #4f46e5;
|
|
1953
|
+
--color-secondary-active: #4338ca;
|
|
1954
|
+
--color-secondary-foreground: #ffffff;
|
|
1955
|
+
--color-accent: #f59e0b;
|
|
1956
|
+
--color-accent-hover: #d97706;
|
|
1957
|
+
--color-accent-active: #b45309;
|
|
1958
|
+
--color-accent-foreground: #000000;
|
|
1959
|
+
--color-success: #10b981;
|
|
1960
|
+
--color-success-foreground: #ffffff;
|
|
1961
|
+
--color-warning: #f59e0b;
|
|
1962
|
+
--color-warning-foreground: #000000;
|
|
1963
|
+
--color-danger: #ef4444;
|
|
1964
|
+
--color-danger-foreground: #ffffff;
|
|
1965
|
+
--color-info: #3b82f6;
|
|
1966
|
+
--color-info-foreground: #ffffff;
|
|
1967
|
+
--color-surface: #18181b;
|
|
1968
|
+
--color-border: #27272a;
|
|
1969
|
+
--color-muted: #71717a;
|
|
1970
|
+
--color-subtle: #3f3f46;
|
|
1971
|
+
|
|
1972
|
+
/* fonts */
|
|
1973
|
+
--font-sans: InterVariable, Inter, system-ui, sans-serif;
|
|
1974
|
+
--font-mono: JetBrains Mono, Fira Code, Consolas, monospace;
|
|
1975
|
+
|
|
1976
|
+
/* spacing */
|
|
1977
|
+
--spacing-1: 0.25rem;
|
|
1978
|
+
--spacing-2: 0.5rem;
|
|
1979
|
+
--spacing-3: 0.75rem;
|
|
1980
|
+
--spacing-4: 1rem;
|
|
1981
|
+
--spacing-5: 1.25rem;
|
|
1982
|
+
--spacing-6: 1.5rem;
|
|
1983
|
+
--spacing-8: 2rem;
|
|
1984
|
+
--spacing-10: 2.5rem;
|
|
1985
|
+
--spacing-12: 3rem;
|
|
1986
|
+
--spacing-16: 4rem;
|
|
1987
|
+
|
|
1988
|
+
/* breakpoints */
|
|
1989
|
+
--breakpoint-sm: 40rem;
|
|
1990
|
+
--breakpoint-md: 48rem;
|
|
1991
|
+
--breakpoint-lg: 64rem;
|
|
1992
|
+
--breakpoint-xl: 80rem;
|
|
1993
|
+
--breakpoint-2xl: 96rem;
|
|
1994
|
+
|
|
1995
|
+
/* border radius */
|
|
1996
|
+
--radius-sm: 0.25rem;
|
|
1997
|
+
--radius-md: 0.5rem;
|
|
1998
|
+
--radius-lg: 0.75rem;
|
|
1999
|
+
--radius-xl: 1rem;
|
|
2000
|
+
--radius-2xl: 1.5rem;
|
|
2001
|
+
--radius-full: 9999px;
|
|
2002
|
+
|
|
2003
|
+
/* animations */
|
|
2004
|
+
--animate-fade-in: fadeIn 0.2s ease-out;
|
|
2005
|
+
--animate-fade-out: fadeOut 0.2s ease-in;
|
|
2006
|
+
--animate-slide-up: slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
2007
|
+
--animate-slide-down: slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
2008
|
+
--animate-scale-in: scaleIn 0.2s ease-out;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
@keyframes fadeIn {
|
|
2012
|
+
from { opacity: 0; }
|
|
2013
|
+
to { opacity: 1; }
|
|
2014
|
+
}
|
|
2015
|
+
@keyframes fadeOut {
|
|
2016
|
+
from { opacity: 1; }
|
|
2017
|
+
to { opacity: 0; }
|
|
2018
|
+
}
|
|
2019
|
+
@keyframes slideUp {
|
|
2020
|
+
from { transform: translateY(8px); opacity: 0; }
|
|
2021
|
+
to { transform: translateY(0); opacity: 1; }
|
|
2022
|
+
}
|
|
2023
|
+
@keyframes slideDown {
|
|
2024
|
+
from { transform: translateY(-8px); opacity: 0; }
|
|
2025
|
+
to { transform: translateY(0); opacity: 1; }
|
|
2026
|
+
}
|
|
2027
|
+
@keyframes scaleIn {
|
|
2028
|
+
from { transform: scale(0.95); opacity: 0; }
|
|
2029
|
+
to { transform: scale(1); opacity: 1; }
|
|
2030
|
+
}`;
|
|
2031
|
+
defaultGlobalCss = `@import "tailwindcss";
|
|
2032
|
+
|
|
2033
|
+
@theme {
|
|
2034
|
+
/* colors */
|
|
2035
|
+
--color-primary: #3b82f6;
|
|
2036
|
+
--color-primary-hover: #2563eb;
|
|
2037
|
+
--color-primary-active: #1d4ed8;
|
|
2038
|
+
--color-primary-foreground: #ffffff;
|
|
2039
|
+
--color-secondary: #6366f1;
|
|
2040
|
+
--color-secondary-hover: #4f46e5;
|
|
2041
|
+
--color-secondary-active: #4338ca;
|
|
2042
|
+
--color-secondary-foreground: #ffffff;
|
|
2043
|
+
--color-accent: #f59e0b;
|
|
2044
|
+
--color-accent-hover: #d97706;
|
|
2045
|
+
--color-accent-active: #b45309;
|
|
2046
|
+
--color-accent-foreground: #000000;
|
|
2047
|
+
--color-success: #10b981;
|
|
2048
|
+
--color-success-foreground: #ffffff;
|
|
2049
|
+
--color-warning: #f59e0b;
|
|
2050
|
+
--color-warning-foreground: #000000;
|
|
2051
|
+
--color-danger: #ef4444;
|
|
2052
|
+
--color-danger-foreground: #ffffff;
|
|
2053
|
+
--color-info: #3b82f6;
|
|
2054
|
+
--color-info-foreground: #ffffff;
|
|
2055
|
+
--color-surface: #18181b;
|
|
2056
|
+
--color-border: #27272a;
|
|
2057
|
+
--color-muted: #71717a;
|
|
2058
|
+
--color-subtle: #3f3f46;
|
|
2059
|
+
|
|
2060
|
+
/* fonts */
|
|
2061
|
+
--font-sans: InterVariable, Inter, system-ui, sans-serif;
|
|
2062
|
+
--font-mono: JetBrains Mono, Fira Code, Consolas, monospace;
|
|
2063
|
+
|
|
2064
|
+
/* spacing */
|
|
2065
|
+
--spacing-1: 0.25rem;
|
|
2066
|
+
--spacing-2: 0.5rem;
|
|
2067
|
+
--spacing-3: 0.75rem;
|
|
2068
|
+
--spacing-4: 1rem;
|
|
2069
|
+
--spacing-5: 1.25rem;
|
|
2070
|
+
--spacing-6: 1.5rem;
|
|
2071
|
+
--spacing-8: 2rem;
|
|
2072
|
+
--spacing-10: 2.5rem;
|
|
2073
|
+
--spacing-12: 3rem;
|
|
2074
|
+
--spacing-16: 4rem;
|
|
2075
|
+
|
|
2076
|
+
/* breakpoints */
|
|
2077
|
+
--breakpoint-sm: 40rem;
|
|
2078
|
+
--breakpoint-md: 48rem;
|
|
2079
|
+
--breakpoint-lg: 64rem;
|
|
2080
|
+
--breakpoint-xl: 80rem;
|
|
2081
|
+
--breakpoint-2xl: 96rem;
|
|
2082
|
+
|
|
2083
|
+
/* border radius */
|
|
2084
|
+
--radius-sm: 0.25rem;
|
|
2085
|
+
--radius-md: 0.5rem;
|
|
2086
|
+
--radius-lg: 0.75rem;
|
|
2087
|
+
--radius-xl: 1rem;
|
|
2088
|
+
--radius-2xl: 1.5rem;
|
|
2089
|
+
--radius-full: 9999px;
|
|
2090
|
+
|
|
2091
|
+
/* animations */
|
|
2092
|
+
--animate-fade-in: fadeIn 0.2s ease-out;
|
|
2093
|
+
--animate-fade-out: fadeOut 0.2s ease-in;
|
|
2094
|
+
--animate-slide-up: slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
2095
|
+
--animate-slide-down: slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
2096
|
+
--animate-scale-in: scaleIn 0.2s ease-out;
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
@keyframes fadeIn {
|
|
2100
|
+
from { opacity: 0; }
|
|
2101
|
+
to { opacity: 1; }
|
|
2102
|
+
}
|
|
2103
|
+
@keyframes fadeOut {
|
|
2104
|
+
from { opacity: 1; }
|
|
2105
|
+
to { opacity: 0; }
|
|
2106
|
+
}
|
|
2107
|
+
@keyframes slideUp {
|
|
2108
|
+
from { transform: translateY(8px); opacity: 0; }
|
|
2109
|
+
to { transform: translateY(0); opacity: 1; }
|
|
2110
|
+
}
|
|
2111
|
+
@keyframes slideDown {
|
|
2112
|
+
from { transform: translateY(-8px); opacity: 0; }
|
|
2113
|
+
to { transform: translateY(0); opacity: 1; }
|
|
2114
|
+
}
|
|
2115
|
+
@keyframes scaleIn {
|
|
2116
|
+
from { transform: scale(0.95); opacity: 0; }
|
|
2117
|
+
to { transform: scale(1); opacity: 1; }
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
/* tailwind-styled-v4 \u2014 zero-config base styles */
|
|
2121
|
+
*, *::before, *::after {
|
|
2122
|
+
box-sizing: border-box;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
html {
|
|
2126
|
+
-webkit-font-smoothing: antialiased;
|
|
2127
|
+
-moz-osx-font-smoothing: grayscale;
|
|
2128
|
+
text-rendering: optimizeLegibility;
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
body {
|
|
2132
|
+
margin: 0;
|
|
2133
|
+
font-family: var(--font-sans, system-ui, sans-serif);
|
|
2134
|
+
background: var(--color-surface, #18181b);
|
|
2135
|
+
color: var(--color-foreground, #fafafa);
|
|
2136
|
+
}
|
|
2137
|
+
`;
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
function loadTailwindConfig(cwd = process.cwd()) {
|
|
2141
|
+
if (_cachedConfig && _cachedCwd === cwd) return _cachedConfig;
|
|
2142
|
+
_cachedCwd = cwd;
|
|
2143
|
+
for (const file of CONFIG_FILES) {
|
|
2144
|
+
const fullPath = path10__default.default.join(cwd, file);
|
|
2145
|
+
if (fs3__default.default.existsSync(fullPath)) {
|
|
2146
|
+
try {
|
|
2147
|
+
const mod = __require(fullPath);
|
|
2148
|
+
const config = mod.default ?? mod;
|
|
2149
|
+
_cachedConfig = config;
|
|
2150
|
+
console.log(`[tailwind-styled-v4] Using config: ${file}`);
|
|
2151
|
+
return config;
|
|
2152
|
+
} catch {
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
console.log("[tailwind-styled-v4] No tailwind config found \u2192 using built-in preset");
|
|
2157
|
+
const { defaultPreset: defaultPreset2 } = (init_defaultPreset(), __toCommonJS(defaultPreset_exports));
|
|
2158
|
+
_cachedConfig = defaultPreset2;
|
|
2159
|
+
return defaultPreset2;
|
|
2160
|
+
}
|
|
2161
|
+
var CONFIG_FILES, _cachedConfig, _cachedCwd;
|
|
2162
|
+
var init_loadTailwindConfig = __esm({
|
|
2163
|
+
"packages/compiler/src/loadTailwindConfig.ts"() {
|
|
2164
|
+
CONFIG_FILES = [
|
|
2165
|
+
"tailwind.config.ts",
|
|
2166
|
+
"tailwind.config.js",
|
|
2167
|
+
"tailwind.config.mjs",
|
|
2168
|
+
"tailwind.config.cjs"
|
|
2169
|
+
];
|
|
2170
|
+
_cachedConfig = null;
|
|
2171
|
+
_cachedCwd = "";
|
|
2172
|
+
}
|
|
2173
|
+
});
|
|
2174
|
+
function scanDir(dir, files = []) {
|
|
2175
|
+
if (!fs3__default.default.existsSync(dir)) return files;
|
|
2176
|
+
const entries = fs3__default.default.readdirSync(dir, { withFileTypes: true });
|
|
2177
|
+
for (const entry of entries) {
|
|
2178
|
+
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
|
|
2179
|
+
const fullPath = path10__default.default.join(dir, entry.name);
|
|
2180
|
+
if (entry.isDirectory()) {
|
|
2181
|
+
scanDir(fullPath, files);
|
|
2182
|
+
} else if (SCAN_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
|
|
2183
|
+
files.push(fullPath);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
return files;
|
|
2187
|
+
}
|
|
2188
|
+
function generateSafelist(scanDirs, outputPath = ".tailwind-styled-safelist.json", cwd = process.cwd()) {
|
|
2189
|
+
const allClasses = /* @__PURE__ */ new Set();
|
|
2190
|
+
for (const dir of scanDirs) {
|
|
2191
|
+
const absDir = path10__default.default.isAbsolute(dir) ? dir : path10__default.default.resolve(cwd, dir);
|
|
2192
|
+
const files = scanDir(absDir);
|
|
2193
|
+
for (const file of files) {
|
|
2194
|
+
try {
|
|
2195
|
+
const source = fs3__default.default.readFileSync(file, "utf-8");
|
|
2196
|
+
const classes = extractAllClasses(source);
|
|
2197
|
+
classes.forEach((c) => allClasses.add(c));
|
|
2198
|
+
} catch {
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
const sorted = Array.from(allClasses).sort();
|
|
2203
|
+
const absOutput = path10__default.default.isAbsolute(outputPath) ? outputPath : path10__default.default.resolve(cwd, outputPath);
|
|
2204
|
+
fs3__default.default.writeFileSync(absOutput, JSON.stringify(sorted, null, 2));
|
|
2205
|
+
console.log(`[tailwind-styled-v4] Safelist: ${sorted.length} classes \u2192 ${absOutput}`);
|
|
2206
|
+
return sorted;
|
|
2207
|
+
}
|
|
2208
|
+
var SCAN_EXTENSIONS;
|
|
2209
|
+
var init_safelistGenerator = __esm({
|
|
2210
|
+
"packages/compiler/src/safelistGenerator.ts"() {
|
|
2211
|
+
init_classExtractor();
|
|
2212
|
+
SCAN_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
|
|
2213
|
+
}
|
|
2214
|
+
});
|
|
2215
|
+
async function generateCssForClasses(classes, config, cwd = process.cwd()) {
|
|
2216
|
+
try {
|
|
2217
|
+
const { compileCssFromClasses: compileCssFromClasses2 } = (init_cssCompiler(), __toCommonJS(cssCompiler_exports));
|
|
2218
|
+
const result = compileCssFromClasses2(classes);
|
|
2219
|
+
if (result?.css && result.resolvedClasses.length > 0) {
|
|
2220
|
+
const resolveRate = result.resolvedClasses.length / classes.length;
|
|
2221
|
+
if (resolveRate >= 0.5) return result.css;
|
|
2222
|
+
}
|
|
2223
|
+
} catch {
|
|
2224
|
+
}
|
|
2225
|
+
const twConfig = config ?? loadTailwindConfig(cwd);
|
|
2226
|
+
try {
|
|
2227
|
+
return await generateViaTailwindV4(classes, twConfig, cwd);
|
|
2228
|
+
} catch {
|
|
2229
|
+
}
|
|
2230
|
+
return generateManualCss(classes);
|
|
2231
|
+
}
|
|
2232
|
+
async function generateViaTailwindV4(classes, _config, cwd) {
|
|
2233
|
+
const virtualCss = [
|
|
2234
|
+
`@import "tailwindcss";`,
|
|
2235
|
+
`@layer utilities {`,
|
|
2236
|
+
` /* Generated by tailwind-styled-v4 */`,
|
|
2237
|
+
`}`
|
|
2238
|
+
].join("\n");
|
|
2239
|
+
const postcss = __require("postcss");
|
|
2240
|
+
const tailwindcss = __require("@tailwindcss/postcss");
|
|
2241
|
+
const result = await postcss([
|
|
2242
|
+
tailwindcss({
|
|
2243
|
+
optimize: { minify: false }
|
|
2244
|
+
})
|
|
2245
|
+
]).process(virtualCss, {
|
|
2246
|
+
from: path10__default.default.join(cwd, "virtual.css")
|
|
2247
|
+
});
|
|
2248
|
+
return filterCssForClasses(result.css, classes);
|
|
2249
|
+
}
|
|
2250
|
+
function generateManualCss(classes) {
|
|
2251
|
+
const { generateAtomicCss: generateAtomicCss2, parseAtomicClass: parseAtomicClass2 } = (init_atomicCss(), __toCommonJS(atomicCss_exports));
|
|
2252
|
+
const rules = classes.map((c) => parseAtomicClass2(c)).filter(Boolean);
|
|
2253
|
+
if (rules.length === 0) return "";
|
|
2254
|
+
const header = `/* Generated by tailwind-styled-v4 \u2014 ${(/* @__PURE__ */ new Date()).toISOString()} */
|
|
2255
|
+
`;
|
|
2256
|
+
return header + generateAtomicCss2(rules);
|
|
2257
|
+
}
|
|
2258
|
+
function filterCssForClasses(fullCss, classes) {
|
|
2259
|
+
new Set(classes);
|
|
2260
|
+
const lines = fullCss.split("\n");
|
|
2261
|
+
const kept = [];
|
|
2262
|
+
let inBlock = false;
|
|
2263
|
+
let keepBlock = false;
|
|
2264
|
+
let braceDepth = 0;
|
|
2265
|
+
for (const line of lines) {
|
|
2266
|
+
if (line.includes("@layer base") || line.includes("*, *::before")) {
|
|
2267
|
+
kept.push(line);
|
|
2268
|
+
continue;
|
|
2269
|
+
}
|
|
2270
|
+
if (!inBlock) {
|
|
2271
|
+
const isOurClass = classes.some((cls) => {
|
|
2272
|
+
const escaped = cls.replace(/[:/[\].!%]/g, "\\$&");
|
|
2273
|
+
return line.includes(`.${escaped}`) || line.includes(`.${cls}`);
|
|
2274
|
+
});
|
|
2275
|
+
if (isOurClass) {
|
|
2276
|
+
keepBlock = true;
|
|
2277
|
+
inBlock = true;
|
|
2278
|
+
braceDepth = 0;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
if (inBlock) {
|
|
2282
|
+
if (keepBlock) kept.push(line);
|
|
2283
|
+
if (line.includes("{")) braceDepth++;
|
|
2284
|
+
if (line.includes("}")) {
|
|
2285
|
+
braceDepth--;
|
|
2286
|
+
if (braceDepth <= 0) {
|
|
2287
|
+
inBlock = false;
|
|
2288
|
+
keepBlock = false;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
return kept.join("\n");
|
|
2294
|
+
}
|
|
2295
|
+
var init_tailwindEngine = __esm({
|
|
2296
|
+
"packages/compiler/src/tailwindEngine.ts"() {
|
|
2297
|
+
init_loadTailwindConfig();
|
|
2298
|
+
}
|
|
2299
|
+
});
|
|
2300
|
+
|
|
2301
|
+
// packages/compiler/src/index.ts
|
|
2302
|
+
var init_src2 = __esm({
|
|
2303
|
+
"packages/compiler/src/index.ts"() {
|
|
2304
|
+
init_classExtractor();
|
|
2305
|
+
init_classMerger();
|
|
2306
|
+
init_loaderCore();
|
|
2307
|
+
init_safelistGenerator();
|
|
2308
|
+
init_tailwindEngine();
|
|
2309
|
+
}
|
|
2310
|
+
});
|
|
2311
|
+
|
|
2312
|
+
// packages/scanner/src/native-bridge.ts
|
|
2313
|
+
var native_bridge_exports = {};
|
|
2314
|
+
__export(native_bridge_exports, {
|
|
2315
|
+
cachePriorityNative: () => cachePriorityNative,
|
|
2316
|
+
cacheReadNative: () => cacheReadNative,
|
|
2317
|
+
cacheWriteNative: () => cacheWriteNative,
|
|
2318
|
+
extractClassesNative: () => extractClassesNative,
|
|
2319
|
+
hasNativeScannerBinding: () => hasNativeScannerBinding,
|
|
2320
|
+
hashContentNative: () => hashContentNative,
|
|
2321
|
+
isRustCacheAvailable: () => isRustCacheAvailable,
|
|
2322
|
+
scanWorkspaceNative: () => scanWorkspaceNative
|
|
2323
|
+
});
|
|
2324
|
+
function getBinding2() {
|
|
2325
|
+
if (_binding2 !== void 0) {
|
|
2326
|
+
if (_binding2 === null) {
|
|
2327
|
+
throwNativeBindingError();
|
|
2328
|
+
}
|
|
2329
|
+
return _binding2;
|
|
2330
|
+
}
|
|
2331
|
+
if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1") {
|
|
2332
|
+
_loadError = "Native loading is disabled by TWS_NO_NATIVE or TWS_NO_RUST environment variable.";
|
|
2333
|
+
_binding2 = null;
|
|
2334
|
+
_candidatePaths = [];
|
|
2335
|
+
throwNativeBindingError();
|
|
2336
|
+
}
|
|
2337
|
+
const runtimeDir2 = typeof __dirname === "string" ? __dirname : process.cwd();
|
|
2338
|
+
_candidatePaths = [
|
|
2339
|
+
path10__default.default.resolve(process.cwd(), "native", "tailwind_styled_parser.node"),
|
|
2340
|
+
path10__default.default.resolve(runtimeDir2, "..", "..", "..", "native", "tailwind_styled_parser.node")
|
|
2341
|
+
];
|
|
2342
|
+
const req = typeof __require === "function" ? __require : module$1.createRequire(path10__default.default.join(runtimeDir2, "noop.cjs"));
|
|
2343
|
+
for (const c of _candidatePaths) {
|
|
2344
|
+
try {
|
|
2345
|
+
const mod = req(c);
|
|
2346
|
+
if (mod?.scanWorkspace || mod?.extractClassesFromSource || mod?.hashFileContent || mod?.cacheRead || mod?.cacheWrite) {
|
|
2347
|
+
_binding2 = mod;
|
|
2348
|
+
return _binding2;
|
|
2349
|
+
}
|
|
2350
|
+
} catch (error) {
|
|
2351
|
+
_loadError = error instanceof Error ? error.message : String(error);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
_binding2 = null;
|
|
2355
|
+
throwNativeBindingError();
|
|
2356
|
+
}
|
|
2357
|
+
function throwNativeBindingError() {
|
|
2358
|
+
const lines = [
|
|
2359
|
+
"FATAL: Native scanner binding not found.",
|
|
2360
|
+
"",
|
|
2361
|
+
"This package requires the Rust native binding 'tailwind_styled_parser.node'.",
|
|
2362
|
+
"The binding was not found in any of these paths:",
|
|
2363
|
+
..._candidatePaths.map((p) => ` - ${p}`),
|
|
2364
|
+
""
|
|
2365
|
+
];
|
|
2366
|
+
if (_loadError) {
|
|
2367
|
+
lines.push("Load error:", ` ${_loadError}`, "");
|
|
2368
|
+
}
|
|
2369
|
+
lines.push(
|
|
2370
|
+
"To fix this, run:",
|
|
2371
|
+
" npm run build:rust",
|
|
2372
|
+
"",
|
|
2373
|
+
"This will build the native Rust module from the 'native/' directory.",
|
|
2374
|
+
"If you're using this package in a CI/CD environment, ensure Rust toolchain is installed",
|
|
2375
|
+
"and 'npm run build:rust' is executed before running tests or building."
|
|
2376
|
+
);
|
|
2377
|
+
throw new Error(lines.join("\n"));
|
|
2378
|
+
}
|
|
2379
|
+
function scanWorkspaceNative(root, extensions) {
|
|
2380
|
+
return getBinding2().scanWorkspace(root, extensions ?? null);
|
|
2381
|
+
}
|
|
2382
|
+
function extractClassesNative(source) {
|
|
2383
|
+
const result = getBinding2().extractClassesFromSource?.(source);
|
|
2384
|
+
if (result === null || result === void 0) {
|
|
2385
|
+
throw new Error("Native extractClassesFromSource returned null/undefined");
|
|
2386
|
+
}
|
|
2387
|
+
return result;
|
|
2388
|
+
}
|
|
2389
|
+
function hashContentNative(content) {
|
|
2390
|
+
const result = getBinding2().hashFileContent?.(content);
|
|
2391
|
+
if (result === null || result === void 0) {
|
|
2392
|
+
throw new Error("Native hashFileContent returned null/undefined");
|
|
2393
|
+
}
|
|
2394
|
+
return result;
|
|
2395
|
+
}
|
|
2396
|
+
function isRustCacheAvailable() {
|
|
2397
|
+
return true;
|
|
2398
|
+
}
|
|
2399
|
+
function hasNativeScannerBinding() {
|
|
2400
|
+
try {
|
|
2401
|
+
getBinding2();
|
|
2402
|
+
return true;
|
|
2403
|
+
} catch {
|
|
2404
|
+
return false;
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
function cacheReadNative(cachePath) {
|
|
2408
|
+
const result = getBinding2().cacheRead?.(cachePath);
|
|
2409
|
+
if (result === null || result === void 0) {
|
|
2410
|
+
throw new Error("Native cacheRead returned null/undefined");
|
|
2411
|
+
}
|
|
2412
|
+
return result;
|
|
2413
|
+
}
|
|
2414
|
+
function cacheWriteNative(cachePath, entries) {
|
|
2415
|
+
const result = getBinding2().cacheWrite?.(cachePath, entries);
|
|
2416
|
+
if (result === null || result === void 0) {
|
|
2417
|
+
throw new Error("Native cacheWrite returned null/undefined");
|
|
2418
|
+
}
|
|
2419
|
+
return result;
|
|
2420
|
+
}
|
|
2421
|
+
function cachePriorityNative(mtimeMs, size, cachedMtimeMs, cachedSize, cachedHitCount, cachedLastSeenMs, nowMs = Date.now()) {
|
|
2422
|
+
const result = getBinding2().cachePriority?.(
|
|
2423
|
+
mtimeMs,
|
|
2424
|
+
size,
|
|
2425
|
+
cachedMtimeMs,
|
|
2426
|
+
cachedSize,
|
|
2427
|
+
cachedHitCount,
|
|
2428
|
+
cachedLastSeenMs,
|
|
2429
|
+
nowMs
|
|
2430
|
+
);
|
|
2431
|
+
if (result === null || result === void 0) {
|
|
2432
|
+
throw new Error("Native cachePriority returned null/undefined");
|
|
2433
|
+
}
|
|
2434
|
+
return result;
|
|
2435
|
+
}
|
|
2436
|
+
var _binding2, _loadError, _candidatePaths;
|
|
2437
|
+
var init_native_bridge = __esm({
|
|
2438
|
+
"packages/scanner/src/native-bridge.ts"() {
|
|
2439
|
+
_binding2 = void 0;
|
|
2440
|
+
_loadError = null;
|
|
2441
|
+
_candidatePaths = [];
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
2444
|
+
function defaultCachePath(rootDir, cacheDir) {
|
|
2445
|
+
const dir = cacheDir ? path10__default.default.resolve(rootDir, cacheDir) : path10__default.default.join(process.cwd(), ".cache", "tailwind-styled");
|
|
2446
|
+
return path10__default.default.join(dir, "scanner-cache.json");
|
|
2447
|
+
}
|
|
2448
|
+
function readCache(rootDir, cacheDir) {
|
|
2449
|
+
const cachePath = defaultCachePath(rootDir, cacheDir);
|
|
2450
|
+
const result = cacheReadNative(cachePath);
|
|
2451
|
+
return result.entries.map((e) => ({
|
|
2452
|
+
file: e.file,
|
|
2453
|
+
classes: e.classes,
|
|
2454
|
+
hash: e.hash,
|
|
2455
|
+
mtimeMs: e.mtimeMs,
|
|
2456
|
+
size: e.size,
|
|
2457
|
+
hitCount: e.hitCount
|
|
2458
|
+
}));
|
|
2459
|
+
}
|
|
2460
|
+
function writeCache(rootDir, entries, cacheDir) {
|
|
2461
|
+
const cachePath = defaultCachePath(rootDir, cacheDir);
|
|
2462
|
+
const success = cacheWriteNative(cachePath, entries);
|
|
2463
|
+
if (!success) {
|
|
2464
|
+
throw new Error(
|
|
2465
|
+
"Native cacheWrite failed. Run 'npm run build:rust' to rebuild native bindings."
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
function filePriority(mtimeMs, size, cached, nowMs = Date.now()) {
|
|
2470
|
+
return cachePriorityNative(
|
|
2471
|
+
mtimeMs,
|
|
2472
|
+
size,
|
|
2473
|
+
cached?.mtimeMs ?? 0,
|
|
2474
|
+
cached?.size ?? 0,
|
|
2475
|
+
cached?.hitCount ?? 0,
|
|
2476
|
+
cached?.lastSeenMs ?? 0,
|
|
2477
|
+
nowMs
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2480
|
+
var init_cache_native = __esm({
|
|
2481
|
+
"packages/scanner/src/cache-native.ts"() {
|
|
2482
|
+
init_native_bridge();
|
|
2483
|
+
}
|
|
2484
|
+
});
|
|
2485
|
+
function canUseCjsRequire() {
|
|
2486
|
+
return typeof __require === "function";
|
|
2487
|
+
}
|
|
2488
|
+
function debugNative(message) {
|
|
2489
|
+
log2.debug(`[native] ${message}`);
|
|
2490
|
+
}
|
|
2491
|
+
function loadNativeParserBinding() {
|
|
2492
|
+
if (nativeParserBinding !== void 0) return nativeParserBinding;
|
|
2493
|
+
if (!canUseCjsRequire()) {
|
|
2494
|
+
nativeParserBinding = null;
|
|
2495
|
+
nativeParserInitError = "require is unavailable in current module format";
|
|
2496
|
+
debugNative(`fallback to JS: ${nativeParserInitError}`);
|
|
2497
|
+
return nativeParserBinding;
|
|
2498
|
+
}
|
|
2499
|
+
const candidates = [
|
|
2500
|
+
path10__default.default.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
|
|
2501
|
+
path10__default.default.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node")
|
|
2502
|
+
];
|
|
2503
|
+
for (const fullPath of candidates) {
|
|
2504
|
+
if (!fs3__default.default.existsSync(fullPath)) continue;
|
|
2505
|
+
try {
|
|
2506
|
+
const required = __require(fullPath);
|
|
2507
|
+
if (required && typeof required.parse_classes === "function") {
|
|
2508
|
+
nativeParserBinding = required;
|
|
2509
|
+
debugNative(`using native parser from ${fullPath}`);
|
|
2510
|
+
return nativeParserBinding;
|
|
2511
|
+
}
|
|
2512
|
+
} catch (error) {
|
|
2513
|
+
nativeParserInitError = error instanceof Error ? error.message : String(error);
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
nativeParserBinding = null;
|
|
2517
|
+
if (!nativeParserInitError) {
|
|
2518
|
+
nativeParserInitError = "native .node binding not found";
|
|
2519
|
+
}
|
|
2520
|
+
debugNative(`fallback to JS: ${nativeParserInitError}`);
|
|
2521
|
+
return nativeParserBinding;
|
|
2522
|
+
}
|
|
2523
|
+
function normalizeWithNativeParser(tokens) {
|
|
2524
|
+
const binding = loadNativeParserBinding();
|
|
2525
|
+
if (!binding || typeof binding.parse_classes !== "function") {
|
|
2526
|
+
throw new Error(
|
|
2527
|
+
"Native parser binding is required but not available. Run 'npm run build:rust' to build it."
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
try {
|
|
2531
|
+
const parsed = binding.parse_classes(tokens.join(" "));
|
|
2532
|
+
const normalized = parsed.map((item) => item.raw?.trim() ?? "").filter(Boolean);
|
|
2533
|
+
return Array.from(new Set(normalized));
|
|
2534
|
+
} catch (error) {
|
|
2535
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2536
|
+
throw new Error(`Native parser failed: ${errorMessage}. Run 'npm run build:rust' to rebuild.`);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
function resolveScannerWorkerModulePath() {
|
|
2540
|
+
const runtimeDir2 = typeof __dirname === "string" && __dirname.length > 0 ? __dirname : path10__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite.js', document.baseURI).href))));
|
|
2541
|
+
const candidates = [
|
|
2542
|
+
path10__default.default.resolve(runtimeDir2, "index.cjs"),
|
|
2543
|
+
path10__default.default.resolve(runtimeDir2, "index.js"),
|
|
2544
|
+
path10__default.default.resolve(runtimeDir2, "index.ts")
|
|
2545
|
+
];
|
|
2546
|
+
for (const candidate of candidates) {
|
|
2547
|
+
if (fs3__default.default.existsSync(candidate)) return candidate;
|
|
2548
|
+
}
|
|
2549
|
+
return null;
|
|
2550
|
+
}
|
|
2551
|
+
function scanWorkspaceInWorker(rootDir, options) {
|
|
2552
|
+
const modulePath = resolveScannerWorkerModulePath();
|
|
2553
|
+
if (!modulePath) {
|
|
2554
|
+
return Promise.reject(new Error("scanner worker module path could not be resolved"));
|
|
2555
|
+
}
|
|
2556
|
+
return new Promise((resolve, reject) => {
|
|
2557
|
+
let settled = false;
|
|
2558
|
+
const worker = new worker_threads.Worker(SCAN_WORKER_BOOTSTRAP, {
|
|
2559
|
+
eval: true,
|
|
2560
|
+
workerData: { modulePath, rootDir, options }
|
|
2561
|
+
});
|
|
2562
|
+
const timeout = setTimeout(() => {
|
|
2563
|
+
if (settled) return;
|
|
2564
|
+
settled = true;
|
|
2565
|
+
void worker.terminate();
|
|
2566
|
+
reject(new Error(`scanner worker timed out after ${SCAN_WORKER_TIMEOUT_MS}ms`));
|
|
2567
|
+
}, SCAN_WORKER_TIMEOUT_MS);
|
|
2568
|
+
const finish = (callback) => {
|
|
2569
|
+
if (settled) return;
|
|
2570
|
+
settled = true;
|
|
2571
|
+
clearTimeout(timeout);
|
|
2572
|
+
callback();
|
|
2573
|
+
};
|
|
2574
|
+
worker.once("message", (payload) => {
|
|
2575
|
+
const message = payload;
|
|
2576
|
+
finish(() => {
|
|
2577
|
+
if (message?.ok) {
|
|
2578
|
+
resolve(message.result);
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
reject(new Error(message?.error ?? "scanner worker failed without an error message"));
|
|
2582
|
+
});
|
|
2583
|
+
});
|
|
2584
|
+
worker.once("error", (error) => {
|
|
2585
|
+
finish(() => reject(error));
|
|
2586
|
+
});
|
|
2587
|
+
worker.once("exit", (code) => {
|
|
2588
|
+
if (code !== 0) {
|
|
2589
|
+
finish(() => reject(new Error(`scanner worker exited with code ${code}`)));
|
|
2590
|
+
}
|
|
2591
|
+
});
|
|
2592
|
+
});
|
|
2593
|
+
}
|
|
2594
|
+
function buildExtensionSet(includeExtensions) {
|
|
2595
|
+
return new Set(includeExtensions);
|
|
2596
|
+
}
|
|
2597
|
+
function collectCandidates(rootDir, ignoreDirectories, extensionSet) {
|
|
2598
|
+
const candidates = [];
|
|
2599
|
+
const directories = [rootDir];
|
|
2600
|
+
while (directories.length > 0) {
|
|
2601
|
+
const currentDir = directories.pop();
|
|
2602
|
+
if (!currentDir) continue;
|
|
2603
|
+
let entries = [];
|
|
2604
|
+
try {
|
|
2605
|
+
entries = fs3__default.default.readdirSync(currentDir, { withFileTypes: true });
|
|
2606
|
+
} catch {
|
|
2607
|
+
continue;
|
|
2608
|
+
}
|
|
2609
|
+
for (const entry of entries) {
|
|
2610
|
+
const fullPath = path10__default.default.join(currentDir, entry.name);
|
|
2611
|
+
if (entry.isDirectory()) {
|
|
2612
|
+
if (!ignoreDirectories.has(entry.name)) directories.push(fullPath);
|
|
2613
|
+
continue;
|
|
2614
|
+
}
|
|
2615
|
+
if (!entry.isFile()) continue;
|
|
2616
|
+
if (!extensionSet.has(path10__default.default.extname(entry.name))) continue;
|
|
2617
|
+
candidates.push(fullPath);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
return candidates;
|
|
2621
|
+
}
|
|
2622
|
+
function toCacheSize(size) {
|
|
2623
|
+
if (!Number.isFinite(size)) return 0;
|
|
2624
|
+
const normalized = Math.max(0, Math.trunc(size));
|
|
2625
|
+
return Math.min(normalized, 4294967295);
|
|
2626
|
+
}
|
|
2627
|
+
function extractClassesJs(source) {
|
|
2628
|
+
return extractAllClasses(source);
|
|
2629
|
+
}
|
|
2630
|
+
function scanSource(source) {
|
|
2631
|
+
const nativeBinding = loadNativeParserBinding();
|
|
2632
|
+
if (nativeBinding && typeof nativeBinding.parse_classes === "function") {
|
|
2633
|
+
try {
|
|
2634
|
+
const baseClasses = extractClassesJs(source);
|
|
2635
|
+
const nativeNormalized = normalizeWithNativeParser(baseClasses);
|
|
2636
|
+
return nativeNormalized;
|
|
2637
|
+
} catch (error) {
|
|
2638
|
+
throw error;
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
throw new Error(
|
|
2642
|
+
"Native parser binding is required but not available. Run 'npm run build:rust' to build it."
|
|
2643
|
+
);
|
|
2644
|
+
}
|
|
2645
|
+
function isScannableFile(filePath, includeExtensions = DEFAULT_EXTENSIONS) {
|
|
2646
|
+
return includeExtensions.includes(path10__default.default.extname(filePath));
|
|
2647
|
+
}
|
|
2648
|
+
function scanFile(filePath) {
|
|
2649
|
+
const source = fs3__default.default.readFileSync(filePath, "utf8");
|
|
2650
|
+
const hash = hashContentNative(source) ?? void 0;
|
|
2651
|
+
return {
|
|
2652
|
+
file: filePath,
|
|
2653
|
+
classes: scanSource(source),
|
|
2654
|
+
...hash ? { hash } : {}
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
function scanWorkspace(rootDir, options = {}) {
|
|
2658
|
+
const includeExtensions = options.includeExtensions ?? DEFAULT_EXTENSIONS;
|
|
2659
|
+
const extensionSet = buildExtensionSet(includeExtensions);
|
|
2660
|
+
const ignoreDirectories = new Set(options.ignoreDirectories ?? DEFAULT_IGNORES);
|
|
2661
|
+
const useCache = options.useCache ?? true;
|
|
2662
|
+
options.smartInvalidation ?? true;
|
|
2663
|
+
const files = [];
|
|
2664
|
+
const unique = /* @__PURE__ */ new Set();
|
|
2665
|
+
const candidates = collectCandidates(rootDir, ignoreDirectories, extensionSet);
|
|
2666
|
+
const processResult = (result) => {
|
|
2667
|
+
files.push(result);
|
|
2668
|
+
for (const cls of result.classes) unique.add(cls);
|
|
2669
|
+
};
|
|
2670
|
+
const { scanWorkspaceNative: scanWorkspaceNative2 } = (init_native_bridge(), __toCommonJS(native_bridge_exports));
|
|
2671
|
+
if (!options.cacheDir && !useCache) {
|
|
2672
|
+
const nativeResult = scanWorkspaceNative2(rootDir, includeExtensions);
|
|
2673
|
+
if (nativeResult) {
|
|
2674
|
+
return {
|
|
2675
|
+
files: nativeResult.files.map((f) => ({
|
|
2676
|
+
file: f.file,
|
|
2677
|
+
classes: f.classes
|
|
2678
|
+
})),
|
|
2679
|
+
totalFiles: nativeResult.totalFiles,
|
|
2680
|
+
uniqueClasses: nativeResult.uniqueClasses
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
if (useCache && isRustCacheAvailable()) {
|
|
2685
|
+
let cacheEntries = [];
|
|
2686
|
+
try {
|
|
2687
|
+
cacheEntries = readCache(rootDir, options.cacheDir);
|
|
2688
|
+
} catch (error) {
|
|
2689
|
+
cacheEntries = [];
|
|
2690
|
+
log2.debug(
|
|
2691
|
+
`cache read failed, continuing without persisted cache: ${error instanceof Error ? error.message : String(error)}`
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
const cacheMap = new Map(cacheEntries.map((entry) => [entry.file, entry]));
|
|
2695
|
+
const nowMs = Date.now();
|
|
2696
|
+
const ranked = [];
|
|
2697
|
+
for (const filePath of candidates) {
|
|
2698
|
+
let stat;
|
|
2699
|
+
try {
|
|
2700
|
+
stat = fs3__default.default.statSync(filePath);
|
|
2701
|
+
} catch {
|
|
2702
|
+
continue;
|
|
2703
|
+
}
|
|
2704
|
+
const size = toCacheSize(stat.size);
|
|
2705
|
+
const cached = cacheMap.get(filePath);
|
|
2706
|
+
const priority = filePriority(
|
|
2707
|
+
stat.mtimeMs,
|
|
2708
|
+
size,
|
|
2709
|
+
cached ? {
|
|
2710
|
+
mtimeMs: cached.mtimeMs,
|
|
2711
|
+
size: cached.size,
|
|
2712
|
+
hitCount: cached.hitCount,
|
|
2713
|
+
lastSeenMs: 0
|
|
2714
|
+
} : void 0,
|
|
2715
|
+
nowMs
|
|
2716
|
+
);
|
|
2717
|
+
ranked.push({ filePath, stat, size, cached, priority });
|
|
2718
|
+
}
|
|
2719
|
+
ranked.sort((a, b) => b.priority - a.priority);
|
|
2720
|
+
const updatedEntries = [];
|
|
2721
|
+
for (const { filePath, stat, size, cached } of ranked) {
|
|
2722
|
+
let content;
|
|
2723
|
+
try {
|
|
2724
|
+
content = fs3__default.default.readFileSync(filePath, "utf8");
|
|
2725
|
+
} catch {
|
|
2726
|
+
continue;
|
|
2727
|
+
}
|
|
2728
|
+
const hash = hashContentNative(content);
|
|
2729
|
+
if (cached && cached.hash === hash && cached.mtimeMs === stat.mtimeMs && cached.size === size) {
|
|
2730
|
+
log2.debug(`cache HIT ${filePath}`);
|
|
2731
|
+
processResult({ file: filePath, classes: cached.classes });
|
|
2732
|
+
updatedEntries.push({
|
|
2733
|
+
file: filePath,
|
|
2734
|
+
classes: cached.classes,
|
|
2735
|
+
hash: cached.hash,
|
|
2736
|
+
mtimeMs: stat.mtimeMs,
|
|
2737
|
+
size,
|
|
2738
|
+
hitCount: (cached.hitCount ?? 0) + 1
|
|
2739
|
+
});
|
|
2740
|
+
continue;
|
|
2741
|
+
}
|
|
2742
|
+
log2.debug(`cache MISS ${filePath}`);
|
|
2743
|
+
const classes = scanSource(content);
|
|
2744
|
+
processResult({ file: filePath, classes });
|
|
2745
|
+
updatedEntries.push({
|
|
2746
|
+
file: filePath,
|
|
2747
|
+
classes,
|
|
2748
|
+
hash,
|
|
2749
|
+
mtimeMs: stat.mtimeMs,
|
|
2750
|
+
size,
|
|
2751
|
+
hitCount: 1
|
|
2752
|
+
});
|
|
2753
|
+
}
|
|
2754
|
+
try {
|
|
2755
|
+
writeCache(rootDir, updatedEntries, options.cacheDir);
|
|
2756
|
+
} catch (error) {
|
|
2757
|
+
log2.debug(`cache write failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2758
|
+
}
|
|
2759
|
+
return {
|
|
2760
|
+
files,
|
|
2761
|
+
totalFiles: files.length,
|
|
2762
|
+
uniqueClasses: Array.from(unique).sort()
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
for (const filePath of candidates) {
|
|
2766
|
+
processResult(scanFile(filePath));
|
|
2767
|
+
}
|
|
2768
|
+
return {
|
|
2769
|
+
files,
|
|
2770
|
+
totalFiles: files.length,
|
|
2771
|
+
uniqueClasses: Array.from(unique).sort()
|
|
2772
|
+
};
|
|
2773
|
+
}
|
|
2774
|
+
async function scanWorkspaceAsync(rootDir, options = {}) {
|
|
2775
|
+
if (process.env.TWS_DISABLE_SCANNER_WORKER === "1") {
|
|
2776
|
+
return scanWorkspace(rootDir, options);
|
|
2777
|
+
}
|
|
2778
|
+
try {
|
|
2779
|
+
return await scanWorkspaceInWorker(rootDir, options);
|
|
2780
|
+
} catch (error) {
|
|
2781
|
+
log2.debug(
|
|
2782
|
+
`worker scan failed, falling back to sync scanner: ${error instanceof Error ? error.message : String(error)}`
|
|
2783
|
+
);
|
|
2784
|
+
return scanWorkspace(rootDir, options);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
var log2, SCAN_WORKER_TIMEOUT_MS, SCAN_WORKER_BOOTSTRAP, nativeParserBinding, nativeParserInitError, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
|
|
2788
|
+
var init_src3 = __esm({
|
|
2789
|
+
"packages/scanner/src/index.ts"() {
|
|
2790
|
+
init_src2();
|
|
2791
|
+
init_src();
|
|
2792
|
+
init_cache_native();
|
|
2793
|
+
init_native_bridge();
|
|
2794
|
+
log2 = createLogger("scanner");
|
|
2795
|
+
SCAN_WORKER_TIMEOUT_MS = 12e4;
|
|
2796
|
+
SCAN_WORKER_BOOTSTRAP = `
|
|
2797
|
+
const { parentPort, workerData } = require("node:worker_threads")
|
|
2798
|
+
try {
|
|
2799
|
+
const scanner = require(workerData.modulePath)
|
|
2800
|
+
const result = scanner.scanWorkspace(workerData.rootDir, workerData.options ?? {})
|
|
2801
|
+
parentPort.postMessage({ ok: true, result })
|
|
2802
|
+
} catch (error) {
|
|
2803
|
+
parentPort.postMessage({
|
|
2804
|
+
ok: false,
|
|
2805
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2806
|
+
})
|
|
2807
|
+
}
|
|
2808
|
+
`;
|
|
2809
|
+
nativeParserInitError = null;
|
|
2810
|
+
DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2811
|
+
DEFAULT_IGNORES = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
|
|
2812
|
+
}
|
|
2813
|
+
});
|
|
2814
|
+
function formatErrorMessage2(error) {
|
|
2815
|
+
return error instanceof Error ? error.message : String(error);
|
|
2816
|
+
}
|
|
2817
|
+
function isRecord(value) {
|
|
2818
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2819
|
+
const proto = Object.getPrototypeOf(value);
|
|
2820
|
+
return proto === Object.prototype || proto === null;
|
|
2821
|
+
}
|
|
2822
|
+
async function pathExists(filePath) {
|
|
2823
|
+
try {
|
|
2824
|
+
await fs3__default.default.promises.access(filePath, fs3__default.default.constants.F_OK);
|
|
2825
|
+
return true;
|
|
2826
|
+
} catch {
|
|
2827
|
+
return false;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
function sanitizeTopLimit(value) {
|
|
2831
|
+
if (!Number.isFinite(value)) return DEFAULT_TOP_LIMIT;
|
|
2832
|
+
return Math.max(1, Math.trunc(value));
|
|
2833
|
+
}
|
|
2834
|
+
function sanitizeFrequentThreshold(value) {
|
|
2835
|
+
if (!Number.isFinite(value)) return DEFAULT_FREQUENT_THRESHOLD;
|
|
2836
|
+
return Math.max(1, Math.trunc(value));
|
|
2837
|
+
}
|
|
2838
|
+
var DEFAULT_TOP_LIMIT, DEFAULT_FREQUENT_THRESHOLD, DEBUG_NAMESPACE, debugLog;
|
|
2839
|
+
var init_utils = __esm({
|
|
2840
|
+
"packages/analyzer/src/utils.ts"() {
|
|
2841
|
+
init_src();
|
|
2842
|
+
DEFAULT_TOP_LIMIT = 10;
|
|
2843
|
+
DEFAULT_FREQUENT_THRESHOLD = 2;
|
|
2844
|
+
DEBUG_NAMESPACE = "tailwind-styled:analyzer";
|
|
2845
|
+
debugLog = createDebugLogger(DEBUG_NAMESPACE, "tailwind-styled/analyzer");
|
|
2846
|
+
}
|
|
2847
|
+
});
|
|
2848
|
+
|
|
2849
|
+
// packages/analyzer/src/binding.ts
|
|
2850
|
+
function isAnalyzerModule(module2) {
|
|
2851
|
+
const candidate = module2;
|
|
2852
|
+
return typeof candidate?.analyzeClasses === "function";
|
|
2853
|
+
}
|
|
2854
|
+
function getNativeBinding() {
|
|
2855
|
+
if (bindingCache !== void 0) return bindingCache;
|
|
2856
|
+
if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1") {
|
|
2857
|
+
bindingCandidateCache = [];
|
|
2858
|
+
bindingLoadErrorsCache = [];
|
|
2859
|
+
loadedBindingPathCache = null;
|
|
2860
|
+
debugLog("native binding disabled by TWS_NO_NATIVE/TWS_NO_RUST");
|
|
2861
|
+
bindingCache = null;
|
|
2862
|
+
return bindingCache;
|
|
2863
|
+
}
|
|
2864
|
+
const runtimeDir2 = resolveRuntimeDir(
|
|
2865
|
+
typeof __dirname === "string" ? __dirname : void 0,
|
|
2866
|
+
(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite.js', document.baseURI).href))
|
|
2867
|
+
);
|
|
2868
|
+
const candidates = resolveNativeBindingCandidates({
|
|
2869
|
+
runtimeDir: runtimeDir2,
|
|
2870
|
+
envVarNames: ["TWS_NATIVE_PATH"]
|
|
2871
|
+
});
|
|
2872
|
+
const { binding, loadErrors, loadedPath } = loadNativeBinding({
|
|
2873
|
+
runtimeDir: runtimeDir2,
|
|
2874
|
+
candidates,
|
|
2875
|
+
isValid: isAnalyzerModule,
|
|
2876
|
+
invalidExportMessage: "Module loaded but missing `analyzeClasses` export."
|
|
2877
|
+
});
|
|
2878
|
+
bindingCandidateCache = candidates;
|
|
2879
|
+
bindingLoadErrorsCache = loadErrors;
|
|
2880
|
+
loadedBindingPathCache = loadedPath;
|
|
2881
|
+
if (binding) {
|
|
2882
|
+
debugLog(`native binding loaded from: ${loadedPath}`);
|
|
2883
|
+
bindingCache = binding;
|
|
2884
|
+
return bindingCache;
|
|
2885
|
+
}
|
|
2886
|
+
if (bindingLoadErrorsCache.length > 0) {
|
|
2887
|
+
debugLog(
|
|
2888
|
+
`native binding load failed for ${bindingLoadErrorsCache.length} candidate(s): ${bindingLoadErrorsCache.map((entry) => `${entry.path} (${entry.message})`).join("; ")}`
|
|
2889
|
+
);
|
|
2890
|
+
} else {
|
|
2891
|
+
debugLog("native binding not found in any candidate path");
|
|
2892
|
+
}
|
|
2893
|
+
bindingCache = null;
|
|
2894
|
+
return bindingCache;
|
|
2895
|
+
}
|
|
2896
|
+
function requireNativeBinding() {
|
|
2897
|
+
const binding = getNativeBinding();
|
|
2898
|
+
if (binding?.analyzeClasses) return binding;
|
|
2899
|
+
const lines = [
|
|
2900
|
+
"Native analyzer binding not found. Ensure `tailwind_styled_parser.node` is built."
|
|
2901
|
+
];
|
|
2902
|
+
if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1") {
|
|
2903
|
+
lines.push("Native loading is disabled by TWS_NO_NATIVE/TWS_NO_RUST.");
|
|
2904
|
+
} else {
|
|
2905
|
+
lines.push("Checked paths:");
|
|
2906
|
+
for (const candidate of bindingCandidateCache) lines.push(`- ${candidate}`);
|
|
2907
|
+
if (bindingLoadErrorsCache.length > 0) {
|
|
2908
|
+
lines.push("Load errors:");
|
|
2909
|
+
for (const failure of bindingLoadErrorsCache) {
|
|
2910
|
+
lines.push(`- ${failure.path}: ${failure.message}`);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
throw new Error(lines.join("\n"));
|
|
2915
|
+
}
|
|
2916
|
+
function requireNativeCssCompiler() {
|
|
2917
|
+
const binding = requireNativeBinding();
|
|
2918
|
+
if (typeof binding.compileCss === "function") return binding;
|
|
2919
|
+
const loadedPathText = loadedBindingPathCache ? ` (${loadedBindingPathCache})` : "";
|
|
2920
|
+
throw new Error(`Native analyzer compileCss binding is missing in v5${loadedPathText}.`);
|
|
2921
|
+
}
|
|
2922
|
+
var bindingCache, bindingCandidateCache, bindingLoadErrorsCache, loadedBindingPathCache;
|
|
2923
|
+
var init_binding = __esm({
|
|
2924
|
+
"packages/analyzer/src/binding.ts"() {
|
|
2925
|
+
init_src();
|
|
2926
|
+
init_utils();
|
|
2927
|
+
bindingCandidateCache = [];
|
|
2928
|
+
bindingLoadErrorsCache = [];
|
|
2929
|
+
loadedBindingPathCache = null;
|
|
2930
|
+
}
|
|
2931
|
+
});
|
|
2932
|
+
function splitVariantAndBase(className) {
|
|
2933
|
+
const parts = className.split(":");
|
|
2934
|
+
if (parts.length <= 1) return { variantKey: "", base: className };
|
|
2935
|
+
const base = parts.pop() ?? className;
|
|
2936
|
+
return { variantKey: parts.join(":"), base };
|
|
2937
|
+
}
|
|
2938
|
+
function isArbitraryUtility(baseClass) {
|
|
2939
|
+
return baseClass.includes("[") && baseClass.includes("]");
|
|
2940
|
+
}
|
|
2941
|
+
function resolveConflictGroup(base) {
|
|
2942
|
+
if (isArbitraryUtility(base)) return null;
|
|
2943
|
+
if (["block", "inline", "inline-block", "inline-flex", "flex", "grid", "hidden"].includes(base))
|
|
2944
|
+
return "display";
|
|
2945
|
+
if (base.startsWith("bg-")) return "bg";
|
|
2946
|
+
if (base.startsWith("text-")) return "text";
|
|
2947
|
+
if (base.startsWith("font-")) return "font";
|
|
2948
|
+
if (base.startsWith("rounded")) return "rounded";
|
|
2949
|
+
if (base.startsWith("shadow")) return "shadow";
|
|
2950
|
+
if (base.startsWith("border-")) return "border";
|
|
2951
|
+
if (base.startsWith("opacity-")) return "opacity";
|
|
2952
|
+
if (base.startsWith("w-") || base.startsWith("min-w-") || base.startsWith("max-w-"))
|
|
2953
|
+
return "width";
|
|
2954
|
+
if (base.startsWith("h-") || base.startsWith("min-h-") || base.startsWith("max-h-"))
|
|
2955
|
+
return "height";
|
|
2956
|
+
if (base.startsWith("p-") || base.startsWith("px-") || base.startsWith("py-")) return "padding";
|
|
2957
|
+
if (base.startsWith("m-") || base.startsWith("mx-") || base.startsWith("my-")) return "margin";
|
|
2958
|
+
return null;
|
|
2959
|
+
}
|
|
2960
|
+
function detectConflicts(usages) {
|
|
2961
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2962
|
+
for (const usage of usages) {
|
|
2963
|
+
const { variantKey, base } = splitVariantAndBase(usage.name);
|
|
2964
|
+
const group = resolveConflictGroup(base);
|
|
2965
|
+
if (!group) continue;
|
|
2966
|
+
const key = `${variantKey}::${group}`;
|
|
2967
|
+
const bucket = buckets.get(key) ?? {
|
|
2968
|
+
variantKey,
|
|
2969
|
+
group,
|
|
2970
|
+
classes: /* @__PURE__ */ new Set()
|
|
2971
|
+
};
|
|
2972
|
+
bucket.classes.add(usage.name);
|
|
2973
|
+
buckets.set(key, bucket);
|
|
2974
|
+
}
|
|
2975
|
+
const conflicts = [];
|
|
2976
|
+
const conflictedClassNames = /* @__PURE__ */ new Set();
|
|
2977
|
+
for (const bucket of buckets.values()) {
|
|
2978
|
+
if (bucket.classes.size <= 1) continue;
|
|
2979
|
+
const classes = Array.from(bucket.classes).sort();
|
|
2980
|
+
for (const className of classes) conflictedClassNames.add(className);
|
|
2981
|
+
const variantLabel = bucket.variantKey.length > 0 ? bucket.variantKey : "base";
|
|
2982
|
+
conflicts.push({
|
|
2983
|
+
className: bucket.group,
|
|
2984
|
+
variants: bucket.variantKey.length > 0 ? bucket.variantKey.split(":") : [],
|
|
2985
|
+
classes,
|
|
2986
|
+
message: `Multiple ${bucket.group} utilities detected for "${variantLabel}".`
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
conflicts.sort((left, right) => {
|
|
2990
|
+
if (right.classes.length !== left.classes.length)
|
|
2991
|
+
return right.classes.length - left.classes.length;
|
|
2992
|
+
return left.className.localeCompare(right.className);
|
|
2993
|
+
});
|
|
2994
|
+
return { conflicts, conflictedClassNames };
|
|
2995
|
+
}
|
|
2996
|
+
function isSupportedTailwindConfigPath(configPath) {
|
|
2997
|
+
return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path10__default.default.extname(configPath).toLowerCase());
|
|
2998
|
+
}
|
|
2999
|
+
async function resolveTailwindConfigPath(root, explicitPath) {
|
|
3000
|
+
if (explicitPath) {
|
|
3001
|
+
const resolved = path10__default.default.resolve(root, explicitPath);
|
|
3002
|
+
if (!await pathExists(resolved)) return null;
|
|
3003
|
+
return resolved;
|
|
3004
|
+
}
|
|
3005
|
+
const candidates = [
|
|
3006
|
+
"tailwind.config.ts",
|
|
3007
|
+
"tailwind.config.js",
|
|
3008
|
+
"tailwind.config.cjs",
|
|
3009
|
+
"tailwind.config.mjs"
|
|
3010
|
+
];
|
|
3011
|
+
for (const candidate of candidates) {
|
|
3012
|
+
const fullPath = path10__default.default.resolve(root, candidate);
|
|
3013
|
+
if (await pathExists(fullPath)) return fullPath;
|
|
3014
|
+
}
|
|
3015
|
+
return null;
|
|
3016
|
+
}
|
|
3017
|
+
function collectSafelistFromConfig(config) {
|
|
3018
|
+
const raw = config.safelist;
|
|
3019
|
+
if (!Array.isArray(raw)) return [];
|
|
3020
|
+
const out = /* @__PURE__ */ new Set();
|
|
3021
|
+
for (const entry of raw) {
|
|
3022
|
+
if (typeof entry === "string" && entry.length > 0) {
|
|
3023
|
+
out.add(entry);
|
|
3024
|
+
continue;
|
|
3025
|
+
}
|
|
3026
|
+
if (!entry || typeof entry !== "object") continue;
|
|
3027
|
+
const pattern = entry.pattern;
|
|
3028
|
+
if (typeof pattern === "string" && pattern.length > 0) {
|
|
3029
|
+
out.add(pattern);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
return Array.from(out);
|
|
3033
|
+
}
|
|
3034
|
+
function collectCustomUtilities(config) {
|
|
3035
|
+
const out = /* @__PURE__ */ new Set();
|
|
3036
|
+
const theme = config.theme;
|
|
3037
|
+
if (!theme || typeof theme !== "object") return out;
|
|
3038
|
+
const extend = theme.extend;
|
|
3039
|
+
if (!extend || typeof extend !== "object") return out;
|
|
3040
|
+
for (const [section, value] of Object.entries(extend)) {
|
|
3041
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
3042
|
+
for (const key of Object.keys(value)) {
|
|
3043
|
+
out.add(`${section}-${key}`);
|
|
3044
|
+
if (section === "colors") {
|
|
3045
|
+
out.add(`bg-${key}`);
|
|
3046
|
+
out.add(`text-${key}`);
|
|
3047
|
+
out.add(`border-${key}`);
|
|
3048
|
+
} else if (section === "spacing") {
|
|
3049
|
+
out.add(`p-${key}`);
|
|
3050
|
+
out.add(`m-${key}`);
|
|
3051
|
+
out.add(`gap-${key}`);
|
|
3052
|
+
out.add(`w-${key}`);
|
|
3053
|
+
out.add(`h-${key}`);
|
|
3054
|
+
} else if (section === "fontSize") {
|
|
3055
|
+
out.add(`text-${key}`);
|
|
3056
|
+
} else if (section === "borderRadius") {
|
|
3057
|
+
out.add(`rounded-${key}`);
|
|
3058
|
+
} else if (section === "boxShadow") {
|
|
3059
|
+
out.add(`shadow-${key}`);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
return out;
|
|
3064
|
+
}
|
|
3065
|
+
async function collectSafelistFromSource(configPath) {
|
|
3066
|
+
const source = await fs3__default.default.promises.readFile(configPath, "utf8");
|
|
3067
|
+
const safelistBlock = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
|
|
3068
|
+
if (!safelistBlock) return [];
|
|
3069
|
+
const out = /* @__PURE__ */ new Set();
|
|
3070
|
+
const tokenRegex = /["'`]([^"'`]+)["'`]/g;
|
|
3071
|
+
let token = tokenRegex.exec(safelistBlock);
|
|
3072
|
+
while (token) {
|
|
3073
|
+
const value = token[1].trim();
|
|
3074
|
+
if (value.length > 0) out.add(value);
|
|
3075
|
+
token = tokenRegex.exec(safelistBlock);
|
|
3076
|
+
}
|
|
3077
|
+
return Array.from(out);
|
|
3078
|
+
}
|
|
3079
|
+
async function loadTailwindConfig2(root, semanticOption) {
|
|
3080
|
+
const startMs = Date.now();
|
|
3081
|
+
const configPath = await resolveTailwindConfigPath(root, semanticOption?.tailwindConfigPath);
|
|
3082
|
+
if (!configPath) return null;
|
|
3083
|
+
if (!isSupportedTailwindConfigPath(configPath)) {
|
|
3084
|
+
return {
|
|
3085
|
+
path: configPath,
|
|
3086
|
+
loaded: false,
|
|
3087
|
+
warning: `Unsupported Tailwind config extension at "${configPath}". Supported extensions: .ts, .js, .cjs, .mjs.`,
|
|
3088
|
+
safelist: /* @__PURE__ */ new Set(),
|
|
3089
|
+
customUtilities: /* @__PURE__ */ new Set()
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
const configStat = await fs3__default.default.promises.stat(configPath).catch(() => null);
|
|
3093
|
+
if (configStat) {
|
|
3094
|
+
const cached = tailwindConfigCache.get(configPath);
|
|
3095
|
+
if (cached && cached.mtimeMs === configStat.mtimeMs && cached.size === configStat.size) {
|
|
3096
|
+
debugLog(
|
|
3097
|
+
`tailwind config cache hit: ${configPath} (${cached.config.safelist.size} safelist entries)`
|
|
3098
|
+
);
|
|
3099
|
+
return cached.config;
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
let config = null;
|
|
3103
|
+
let warning;
|
|
3104
|
+
try {
|
|
3105
|
+
const cacheBustToken = Math.trunc(configStat?.mtimeMs ?? Date.now());
|
|
3106
|
+
const imported = await import(`${url.pathToFileURL(configPath).href}?tws_mtime=${cacheBustToken}`);
|
|
3107
|
+
const candidate = imported.default ?? imported;
|
|
3108
|
+
if (isRecord(candidate)) {
|
|
3109
|
+
config = candidate;
|
|
3110
|
+
} else if (typeof candidate === "function") {
|
|
3111
|
+
const evaluated = candidate();
|
|
3112
|
+
if (isRecord(evaluated)) {
|
|
3113
|
+
config = evaluated;
|
|
3114
|
+
} else {
|
|
3115
|
+
warning = "Tailwind config export function must return an object.";
|
|
3116
|
+
}
|
|
3117
|
+
} else {
|
|
3118
|
+
warning = "Tailwind config export must be an object or a function returning an object.";
|
|
3119
|
+
}
|
|
3120
|
+
} catch (error) {
|
|
3121
|
+
warning = formatErrorMessage2(error);
|
|
3122
|
+
}
|
|
3123
|
+
const safelist = /* @__PURE__ */ new Set();
|
|
3124
|
+
const customUtilities = /* @__PURE__ */ new Set();
|
|
3125
|
+
if (config) {
|
|
3126
|
+
for (const item of collectSafelistFromConfig(config)) safelist.add(item);
|
|
3127
|
+
for (const item of collectCustomUtilities(config)) customUtilities.add(item);
|
|
3128
|
+
}
|
|
3129
|
+
if (safelist.size === 0) {
|
|
3130
|
+
try {
|
|
3131
|
+
for (const item of await collectSafelistFromSource(configPath)) safelist.add(item);
|
|
3132
|
+
} catch (error) {
|
|
3133
|
+
debugLog(
|
|
3134
|
+
`failed to parse safelist from source at "${configPath}": ${formatErrorMessage2(error)}`
|
|
3135
|
+
);
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
const loaded = {
|
|
3139
|
+
path: configPath,
|
|
3140
|
+
loaded: config !== null,
|
|
3141
|
+
warning,
|
|
3142
|
+
safelist,
|
|
3143
|
+
customUtilities
|
|
3144
|
+
};
|
|
3145
|
+
if (configStat) {
|
|
3146
|
+
tailwindConfigCache.set(configPath, {
|
|
3147
|
+
mtimeMs: configStat.mtimeMs,
|
|
3148
|
+
size: configStat.size,
|
|
3149
|
+
config: loaded
|
|
3150
|
+
});
|
|
3151
|
+
}
|
|
3152
|
+
debugLog(
|
|
3153
|
+
`tailwind config loaded from "${configPath}" in ${Date.now() - startMs}ms (loaded=${loaded.loaded}, safelist=${loaded.safelist.size}, custom=${loaded.customUtilities.size})`
|
|
3154
|
+
);
|
|
3155
|
+
return loaded;
|
|
3156
|
+
}
|
|
3157
|
+
function utilityPrefix(baseClass) {
|
|
3158
|
+
const normalized = baseClass.startsWith("-") ? baseClass.slice(1) : baseClass;
|
|
3159
|
+
if (normalized.includes("[") && normalized.includes("]")) return "arbitrary";
|
|
3160
|
+
if (normalized.startsWith("min-w-")) return "min-w";
|
|
3161
|
+
if (normalized.startsWith("max-w-")) return "max-w";
|
|
3162
|
+
if (normalized.startsWith("min-h-")) return "min-h";
|
|
3163
|
+
if (normalized.startsWith("max-h-")) return "max-h";
|
|
3164
|
+
if (normalized.startsWith("space-x-")) return "space-x";
|
|
3165
|
+
if (normalized.startsWith("space-y-")) return "space-y";
|
|
3166
|
+
if (normalized.startsWith("inline-")) return "inline";
|
|
3167
|
+
if (normalized.startsWith("border-")) return "border";
|
|
3168
|
+
if (normalized.startsWith("text-")) return "text";
|
|
3169
|
+
if (normalized.startsWith("bg-")) return "bg";
|
|
3170
|
+
if (normalized.startsWith("rounded")) return "rounded";
|
|
3171
|
+
if (normalized.startsWith("shadow")) return "shadow";
|
|
3172
|
+
const hyphen = normalized.indexOf("-");
|
|
3173
|
+
if (hyphen < 0) return normalized;
|
|
3174
|
+
return normalized.slice(0, hyphen);
|
|
3175
|
+
}
|
|
3176
|
+
function isKnownTailwindClass(className, safelist, customUtilities) {
|
|
3177
|
+
if (safelist.has(className) || customUtilities.has(className)) return true;
|
|
3178
|
+
const { base } = splitVariantAndBase(className);
|
|
3179
|
+
if (customUtilities.has(base)) return true;
|
|
3180
|
+
const prefix = utilityPrefix(base);
|
|
3181
|
+
return KNOWN_UTILITY_PREFIXES.has(prefix);
|
|
3182
|
+
}
|
|
3183
|
+
async function buildSemanticReport(usages, root, semanticOption) {
|
|
3184
|
+
const loadedConfig = await loadTailwindConfig2(root, semanticOption);
|
|
3185
|
+
const safelist = loadedConfig?.safelist ?? /* @__PURE__ */ new Set();
|
|
3186
|
+
const customUtilities = loadedConfig?.customUtilities ?? /* @__PURE__ */ new Set();
|
|
3187
|
+
const usageNames = new Set(usages.map((usage) => usage.name));
|
|
3188
|
+
const unusedClasses = Array.from(safelist).filter((className) => !usageNames.has(className)).sort().map((className) => ({ name: className, count: 0, isUnused: true }));
|
|
3189
|
+
const unknownClasses = usages.filter((usage) => !isKnownTailwindClass(usage.name, safelist, customUtilities)).map((usage) => ({ ...usage, isUnused: true }));
|
|
3190
|
+
const { conflicts } = detectConflicts(usages);
|
|
3191
|
+
return {
|
|
3192
|
+
unusedClasses,
|
|
3193
|
+
unknownClasses,
|
|
3194
|
+
conflicts,
|
|
3195
|
+
...loadedConfig ? {
|
|
3196
|
+
tailwindConfig: {
|
|
3197
|
+
path: loadedConfig.path,
|
|
3198
|
+
loaded: loadedConfig.loaded,
|
|
3199
|
+
safelistCount: loadedConfig.safelist.size,
|
|
3200
|
+
customUtilityCount: loadedConfig.customUtilities.size,
|
|
3201
|
+
...loadedConfig.warning ? { warning: loadedConfig.warning } : {}
|
|
3202
|
+
}
|
|
3203
|
+
} : {}
|
|
3204
|
+
};
|
|
3205
|
+
}
|
|
3206
|
+
var SUPPORTED_TAILWIND_CONFIG_EXTENSIONS, KNOWN_UTILITY_PREFIXES, tailwindConfigCache;
|
|
3207
|
+
var init_semantic = __esm({
|
|
3208
|
+
"packages/analyzer/src/semantic.ts"() {
|
|
3209
|
+
init_utils();
|
|
3210
|
+
SUPPORTED_TAILWIND_CONFIG_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".cjs", ".mjs"]);
|
|
3211
|
+
KNOWN_UTILITY_PREFIXES = /* @__PURE__ */ new Set([
|
|
3212
|
+
"absolute",
|
|
3213
|
+
"align",
|
|
3214
|
+
"animate",
|
|
3215
|
+
"arbitrary",
|
|
3216
|
+
"aspect",
|
|
3217
|
+
"backdrop",
|
|
3218
|
+
"basis",
|
|
3219
|
+
"bg",
|
|
3220
|
+
"block",
|
|
3221
|
+
"border",
|
|
3222
|
+
"bottom",
|
|
3223
|
+
"col",
|
|
3224
|
+
"container",
|
|
3225
|
+
"contents",
|
|
3226
|
+
"cursor",
|
|
3227
|
+
"dark",
|
|
3228
|
+
"display",
|
|
3229
|
+
"divide",
|
|
3230
|
+
"fill",
|
|
3231
|
+
"fixed",
|
|
3232
|
+
"flex",
|
|
3233
|
+
"float",
|
|
3234
|
+
"font",
|
|
3235
|
+
"from",
|
|
3236
|
+
"gap",
|
|
3237
|
+
"grid",
|
|
3238
|
+
"grow",
|
|
3239
|
+
"h",
|
|
3240
|
+
"hidden",
|
|
3241
|
+
"inset",
|
|
3242
|
+
"inline",
|
|
3243
|
+
"isolate",
|
|
3244
|
+
"items",
|
|
3245
|
+
"justify",
|
|
3246
|
+
"left",
|
|
3247
|
+
"leading",
|
|
3248
|
+
"line",
|
|
3249
|
+
"list",
|
|
3250
|
+
"m",
|
|
3251
|
+
"max-h",
|
|
3252
|
+
"max-w",
|
|
3253
|
+
"mb",
|
|
3254
|
+
"min-h",
|
|
3255
|
+
"min-w",
|
|
3256
|
+
"ml",
|
|
3257
|
+
"mr",
|
|
3258
|
+
"mt",
|
|
3259
|
+
"mx",
|
|
3260
|
+
"my",
|
|
3261
|
+
"object",
|
|
3262
|
+
"opacity",
|
|
3263
|
+
"order",
|
|
3264
|
+
"origin",
|
|
3265
|
+
"outline",
|
|
3266
|
+
"overflow",
|
|
3267
|
+
"overscroll",
|
|
3268
|
+
"p",
|
|
3269
|
+
"pb",
|
|
3270
|
+
"pe",
|
|
3271
|
+
"perspective",
|
|
3272
|
+
"place",
|
|
3273
|
+
"pl",
|
|
3274
|
+
"pointer",
|
|
3275
|
+
"position",
|
|
3276
|
+
"pr",
|
|
3277
|
+
"ps",
|
|
3278
|
+
"pt",
|
|
3279
|
+
"px",
|
|
3280
|
+
"py",
|
|
3281
|
+
"relative",
|
|
3282
|
+
"right",
|
|
3283
|
+
"ring",
|
|
3284
|
+
"rotate",
|
|
3285
|
+
"rounded",
|
|
3286
|
+
"row",
|
|
3287
|
+
"scale",
|
|
3288
|
+
"shadow",
|
|
3289
|
+
"shrink",
|
|
3290
|
+
"size",
|
|
3291
|
+
"skew",
|
|
3292
|
+
"snap",
|
|
3293
|
+
"space-x",
|
|
3294
|
+
"space-y",
|
|
3295
|
+
"sr",
|
|
3296
|
+
"start",
|
|
3297
|
+
"static",
|
|
3298
|
+
"sticky",
|
|
3299
|
+
"stroke",
|
|
3300
|
+
"table",
|
|
3301
|
+
"text",
|
|
3302
|
+
"to",
|
|
3303
|
+
"top",
|
|
3304
|
+
"touch",
|
|
3305
|
+
"tracking",
|
|
3306
|
+
"transform",
|
|
3307
|
+
"transition",
|
|
3308
|
+
"translate",
|
|
3309
|
+
"truncate",
|
|
3310
|
+
"underline",
|
|
3311
|
+
"via",
|
|
3312
|
+
"visible",
|
|
3313
|
+
"w",
|
|
3314
|
+
"whitespace",
|
|
3315
|
+
"z"
|
|
3316
|
+
]);
|
|
3317
|
+
tailwindConfigCache = /* @__PURE__ */ new Map();
|
|
3318
|
+
}
|
|
3319
|
+
});
|
|
3320
|
+
function normalizeScan(scan, includeClass) {
|
|
3321
|
+
if (!includeClass) return scan;
|
|
3322
|
+
const filteredFiles = scan.files.map((file) => ({
|
|
3323
|
+
file: file.file,
|
|
3324
|
+
classes: file.classes.filter((className) => includeClass(className))
|
|
3325
|
+
}));
|
|
3326
|
+
const unique = /* @__PURE__ */ new Set();
|
|
3327
|
+
for (const file of filteredFiles) {
|
|
3328
|
+
for (const className of file.classes) unique.add(className);
|
|
3329
|
+
}
|
|
3330
|
+
return {
|
|
3331
|
+
files: filteredFiles,
|
|
3332
|
+
totalFiles: scan.totalFiles,
|
|
3333
|
+
uniqueClasses: Array.from(unique).sort()
|
|
3334
|
+
};
|
|
3335
|
+
}
|
|
3336
|
+
function collectClassCounts(scan) {
|
|
3337
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3338
|
+
for (const file of scan.files) {
|
|
3339
|
+
for (const className of file.classes) {
|
|
3340
|
+
counts.set(className, (counts.get(className) ?? 0) + 1);
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
return counts;
|
|
3344
|
+
}
|
|
3345
|
+
function buildClassUsage(counts) {
|
|
3346
|
+
return Array.from(counts.entries()).map(([name, count]) => ({ name, count })).sort((left, right) => {
|
|
3347
|
+
if (right.count !== left.count) return right.count - left.count;
|
|
3348
|
+
return left.name.localeCompare(right.name);
|
|
3349
|
+
});
|
|
3350
|
+
}
|
|
3351
|
+
function buildDistribution(usages) {
|
|
3352
|
+
const distribution = {
|
|
3353
|
+
"1": 0,
|
|
3354
|
+
"2-3": 0,
|
|
3355
|
+
"4-7": 0,
|
|
3356
|
+
"8+": 0
|
|
3357
|
+
};
|
|
3358
|
+
for (const usage of usages) {
|
|
3359
|
+
if (usage.count === 1) {
|
|
3360
|
+
distribution["1"] += 1;
|
|
3361
|
+
continue;
|
|
3362
|
+
}
|
|
3363
|
+
if (usage.count <= 3) {
|
|
3364
|
+
distribution["2-3"] += 1;
|
|
3365
|
+
continue;
|
|
3366
|
+
}
|
|
3367
|
+
if (usage.count <= 7) {
|
|
3368
|
+
distribution["4-7"] += 1;
|
|
3369
|
+
continue;
|
|
3370
|
+
}
|
|
3371
|
+
distribution["8+"] += 1;
|
|
3372
|
+
}
|
|
3373
|
+
return distribution;
|
|
3374
|
+
}
|
|
3375
|
+
async function analyzeWorkspace(root, options = {}) {
|
|
3376
|
+
const startedAtMs = Date.now();
|
|
3377
|
+
const resolvedRoot = path10__default.default.resolve(root);
|
|
3378
|
+
const scanStartedAtMs = Date.now();
|
|
3379
|
+
let scan;
|
|
3380
|
+
try {
|
|
3381
|
+
scan = await scanWorkspaceAsync(resolvedRoot, options.scanner);
|
|
3382
|
+
} catch (error) {
|
|
3383
|
+
throw new Error(`Failed to scan workspace at "${resolvedRoot}": ${formatErrorMessage2(error)}`, {
|
|
3384
|
+
cause: error
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
debugLog(
|
|
3388
|
+
`scanWorkspaceAsync processed ${scan.totalFiles} files in ${Date.now() - scanStartedAtMs}ms`
|
|
3389
|
+
);
|
|
3390
|
+
const normalizedScan = normalizeScan(scan, options.includeClass);
|
|
3391
|
+
const topLimit = sanitizeTopLimit(options.classStats?.top);
|
|
3392
|
+
const frequentThreshold = sanitizeFrequentThreshold(options.classStats?.frequentThreshold);
|
|
3393
|
+
const binding = requireNativeBinding();
|
|
3394
|
+
const filesJson = JSON.stringify(
|
|
3395
|
+
normalizedScan.files.map((file) => ({ file: file.file, classes: file.classes }))
|
|
3396
|
+
);
|
|
3397
|
+
let nativeReport = null;
|
|
3398
|
+
try {
|
|
3399
|
+
nativeReport = binding.analyzeClasses(filesJson, resolvedRoot, topLimit);
|
|
3400
|
+
} catch (error) {
|
|
3401
|
+
throw new Error(`Native analyzer failed for "${resolvedRoot}": ${formatErrorMessage2(error)}`, {
|
|
3402
|
+
cause: error
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3405
|
+
if (!nativeReport) {
|
|
3406
|
+
throw new Error(`Native analyzer returned no report for "${resolvedRoot}".`);
|
|
3407
|
+
}
|
|
3408
|
+
const counts = collectClassCounts(normalizedScan);
|
|
3409
|
+
let all = buildClassUsage(counts);
|
|
3410
|
+
let semanticReport;
|
|
3411
|
+
if (options.semantic) {
|
|
3412
|
+
const semanticOption = typeof options.semantic === "object" ? options.semantic : void 0;
|
|
3413
|
+
const semanticStartedAtMs = Date.now();
|
|
3414
|
+
try {
|
|
3415
|
+
semanticReport = await buildSemanticReport(all, resolvedRoot, semanticOption);
|
|
3416
|
+
} catch (error) {
|
|
3417
|
+
throw new Error(
|
|
3418
|
+
`Failed to build semantic report for "${resolvedRoot}": ${formatErrorMessage2(error)}`,
|
|
3419
|
+
{ cause: error }
|
|
3420
|
+
);
|
|
3421
|
+
}
|
|
3422
|
+
debugLog(`semantic report built in ${Date.now() - semanticStartedAtMs}ms`);
|
|
3423
|
+
if (semanticReport.conflicts.length > 0) {
|
|
3424
|
+
const conflicted = new Set(semanticReport.conflicts.flatMap((conflict) => conflict.classes));
|
|
3425
|
+
all = all.map(
|
|
3426
|
+
(usage) => conflicted.has(usage.name) ? { ...usage, isConflict: true } : usage
|
|
3427
|
+
);
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
const top = all.slice(0, topLimit);
|
|
3431
|
+
const frequent = all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
|
|
3432
|
+
const unique = all.filter((usage) => usage.count === 1);
|
|
3433
|
+
const totalClassOccurrences = all.reduce((sum, usage) => sum + usage.count, 0);
|
|
3434
|
+
debugLog(
|
|
3435
|
+
`analyzeWorkspace completed in ${Date.now() - startedAtMs}ms (files=${normalizedScan.totalFiles}, uniqueClasses=${all.length})`
|
|
3436
|
+
);
|
|
3437
|
+
return {
|
|
3438
|
+
root: nativeReport.root || resolvedRoot,
|
|
3439
|
+
totalFiles: nativeReport.totalFiles,
|
|
3440
|
+
uniqueClassCount: all.length,
|
|
3441
|
+
totalClassOccurrences,
|
|
3442
|
+
classStats: {
|
|
3443
|
+
all,
|
|
3444
|
+
top,
|
|
3445
|
+
frequent,
|
|
3446
|
+
unique,
|
|
3447
|
+
distribution: buildDistribution(all)
|
|
3448
|
+
},
|
|
3449
|
+
safelist: all.map((usage) => usage.name),
|
|
3450
|
+
...semanticReport ? { semantic: semanticReport } : {}
|
|
3451
|
+
};
|
|
3452
|
+
}
|
|
3453
|
+
var init_analyzeWorkspace = __esm({
|
|
3454
|
+
"packages/analyzer/src/analyzeWorkspace.ts"() {
|
|
3455
|
+
init_src3();
|
|
3456
|
+
init_binding();
|
|
3457
|
+
init_semantic();
|
|
3458
|
+
init_utils();
|
|
3459
|
+
}
|
|
3460
|
+
});
|
|
3461
|
+
|
|
3462
|
+
// packages/analyzer/src/classToCss.ts
|
|
3463
|
+
function normalizeClassInput(input) {
|
|
3464
|
+
if (typeof input === "string") {
|
|
3465
|
+
return input.split(/\s+/).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
3466
|
+
}
|
|
3467
|
+
if (!Array.isArray(input)) {
|
|
3468
|
+
throw new TypeError("classToCss input must be a string or an array of strings.");
|
|
3469
|
+
}
|
|
3470
|
+
const out = [];
|
|
3471
|
+
for (const item of input) {
|
|
3472
|
+
if (typeof item !== "string") {
|
|
3473
|
+
throw new TypeError("classToCss input array must contain only strings.");
|
|
3474
|
+
}
|
|
3475
|
+
const value = item.trim();
|
|
3476
|
+
if (value.length > 0) out.push(value);
|
|
3477
|
+
}
|
|
3478
|
+
return out;
|
|
3479
|
+
}
|
|
3480
|
+
function normalizeClassToCssOptions(options) {
|
|
3481
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
3482
|
+
throw new TypeError("classToCss options must be an object.");
|
|
3483
|
+
}
|
|
3484
|
+
const strict = options.strict ?? false;
|
|
3485
|
+
if (typeof strict !== "boolean") {
|
|
3486
|
+
throw new TypeError("classToCss options.strict must be a boolean when provided.");
|
|
3487
|
+
}
|
|
3488
|
+
const prefix = options.prefix ?? null;
|
|
3489
|
+
if (prefix !== null && typeof prefix !== "string") {
|
|
3490
|
+
throw new TypeError("classToCss options.prefix must be a string or null when provided.");
|
|
3491
|
+
}
|
|
3492
|
+
return { prefix, strict };
|
|
3493
|
+
}
|
|
3494
|
+
function mergeDeclarationMap(target, css) {
|
|
3495
|
+
const ruleRegex = /\{([^}]*)\}/g;
|
|
3496
|
+
let ruleMatch = ruleRegex.exec(css);
|
|
3497
|
+
while (ruleMatch) {
|
|
3498
|
+
const body = ruleMatch[1];
|
|
3499
|
+
for (const raw of body.split(";")) {
|
|
3500
|
+
const declaration = raw.trim();
|
|
3501
|
+
if (declaration.length === 0) continue;
|
|
3502
|
+
const colonIndex = declaration.indexOf(":");
|
|
3503
|
+
if (colonIndex <= 0) continue;
|
|
3504
|
+
const property = declaration.slice(0, colonIndex).trim();
|
|
3505
|
+
const value = declaration.slice(colonIndex + 1).trim();
|
|
3506
|
+
if (property.length === 0 || value.length === 0) continue;
|
|
3507
|
+
if (target.has(property)) target.delete(property);
|
|
3508
|
+
target.set(property, value);
|
|
3509
|
+
}
|
|
3510
|
+
ruleMatch = ruleRegex.exec(css);
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
function declarationMapToString(declarationMap) {
|
|
3514
|
+
return Array.from(declarationMap.entries()).map(([property, value]) => `${property}: ${value}`).join("; ");
|
|
3515
|
+
}
|
|
3516
|
+
async function classToCss(input, options = {}) {
|
|
3517
|
+
const inputClasses = normalizeClassInput(input);
|
|
3518
|
+
const normalizedOptions = normalizeClassToCssOptions(options);
|
|
3519
|
+
if (inputClasses.length === 0) {
|
|
3520
|
+
return {
|
|
3521
|
+
inputClasses: [],
|
|
3522
|
+
css: "",
|
|
3523
|
+
declarations: "",
|
|
3524
|
+
resolvedClasses: [],
|
|
3525
|
+
unknownClasses: [],
|
|
3526
|
+
sizeBytes: 0
|
|
3527
|
+
};
|
|
3528
|
+
}
|
|
3529
|
+
const binding = requireNativeCssCompiler();
|
|
3530
|
+
const prefix = normalizedOptions.prefix;
|
|
3531
|
+
const cssChunks = [];
|
|
3532
|
+
const resolvedClasses = [];
|
|
3533
|
+
const unknownClasses = [];
|
|
3534
|
+
let sizeBytes = 0;
|
|
3535
|
+
const declarationMap = /* @__PURE__ */ new Map();
|
|
3536
|
+
for (const className of inputClasses) {
|
|
3537
|
+
let compiled = null;
|
|
3538
|
+
try {
|
|
3539
|
+
compiled = binding.compileCss([className], prefix);
|
|
3540
|
+
} catch (error) {
|
|
3541
|
+
throw new Error(
|
|
3542
|
+
`Native analyzer failed while compiling class "${className}": ${formatErrorMessage2(error)}`,
|
|
3543
|
+
{ cause: error }
|
|
3544
|
+
);
|
|
3545
|
+
}
|
|
3546
|
+
if (!compiled) {
|
|
3547
|
+
throw new Error(`Native analyzer returned no result for class "${className}".`);
|
|
3548
|
+
}
|
|
3549
|
+
cssChunks.push(compiled.css);
|
|
3550
|
+
resolvedClasses.push(...compiled.resolvedClasses);
|
|
3551
|
+
unknownClasses.push(...compiled.unknownClasses);
|
|
3552
|
+
sizeBytes += compiled.sizeBytes;
|
|
3553
|
+
mergeDeclarationMap(declarationMap, compiled.css);
|
|
3554
|
+
}
|
|
3555
|
+
const uniqueUnknown = Array.from(new Set(unknownClasses));
|
|
3556
|
+
if (normalizedOptions.strict && uniqueUnknown.length > 0) {
|
|
3557
|
+
throw new Error(`Unknown Tailwind classes: ${uniqueUnknown.join(", ")}`);
|
|
3558
|
+
}
|
|
3559
|
+
return {
|
|
3560
|
+
inputClasses,
|
|
3561
|
+
css: cssChunks.filter((chunk) => chunk.length > 0).join("\n"),
|
|
3562
|
+
declarations: declarationMapToString(declarationMap),
|
|
3563
|
+
resolvedClasses: Array.from(new Set(resolvedClasses)),
|
|
3564
|
+
unknownClasses: uniqueUnknown,
|
|
3565
|
+
sizeBytes
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
var init_classToCss = __esm({
|
|
3569
|
+
"packages/analyzer/src/classToCss.ts"() {
|
|
3570
|
+
init_binding();
|
|
3571
|
+
init_utils();
|
|
3572
|
+
}
|
|
3573
|
+
});
|
|
3574
|
+
|
|
3575
|
+
// packages/analyzer/src/index.ts
|
|
3576
|
+
var src_exports = {};
|
|
3577
|
+
__export(src_exports, {
|
|
3578
|
+
__internal: () => __internal,
|
|
3579
|
+
analyzeWorkspace: () => analyzeWorkspace,
|
|
3580
|
+
classToCss: () => classToCss
|
|
3581
|
+
});
|
|
3582
|
+
var __internal;
|
|
3583
|
+
var init_src4 = __esm({
|
|
3584
|
+
"packages/analyzer/src/index.ts"() {
|
|
3585
|
+
init_analyzeWorkspace();
|
|
3586
|
+
init_classToCss();
|
|
3587
|
+
init_semantic();
|
|
3588
|
+
__internal = {
|
|
3589
|
+
normalizeClassInput,
|
|
3590
|
+
splitVariantAndBase,
|
|
3591
|
+
resolveConflictGroup,
|
|
3592
|
+
collectClassCounts,
|
|
3593
|
+
buildDistribution,
|
|
3594
|
+
utilityPrefix
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3598
|
+
|
|
3599
|
+
// packages/vite/src/plugin.ts
|
|
3600
|
+
init_src2();
|
|
3601
|
+
|
|
3602
|
+
// packages/engine/src/index.ts
|
|
3603
|
+
init_src2();
|
|
3604
|
+
init_src3();
|
|
3605
|
+
init_src();
|
|
3606
|
+
|
|
3607
|
+
// packages/engine/src/incremental.ts
|
|
3608
|
+
init_src3();
|
|
3609
|
+
init_src();
|
|
3610
|
+
var _binding3 = void 0;
|
|
3611
|
+
var _loadError2 = null;
|
|
3612
|
+
var _candidatePaths2 = [];
|
|
3613
|
+
function getNativeEngineBinding() {
|
|
3614
|
+
if (_binding3 !== void 0) {
|
|
3615
|
+
if (_binding3 === null) {
|
|
3616
|
+
throwNativeBindingError2();
|
|
3617
|
+
}
|
|
3618
|
+
return _binding3;
|
|
3619
|
+
}
|
|
3620
|
+
if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1") {
|
|
3621
|
+
_loadError2 = "Native loading is disabled by TWS_NO_NATIVE or TWS_NO_RUST environment variable.";
|
|
3622
|
+
_binding3 = null;
|
|
3623
|
+
_candidatePaths2 = [];
|
|
3624
|
+
throwNativeBindingError2();
|
|
3625
|
+
}
|
|
3626
|
+
const runtimeDir2 = typeof __dirname === "string" ? __dirname : process.cwd();
|
|
3627
|
+
_candidatePaths2 = [
|
|
3628
|
+
path10__default.default.resolve(process.cwd(), "native", "tailwind_styled_parser.node"),
|
|
3629
|
+
path10__default.default.resolve(runtimeDir2, "..", "..", "..", "native", "tailwind_styled_parser.node")
|
|
3630
|
+
];
|
|
3631
|
+
const req = typeof __require === "function" ? __require : module$1.createRequire(path10__default.default.join(runtimeDir2, "noop.cjs"));
|
|
3632
|
+
for (const c of _candidatePaths2) {
|
|
3633
|
+
try {
|
|
3634
|
+
const mod = req(c);
|
|
3635
|
+
if (mod?.computeIncrementalDiff || mod?.processFileChange || mod?.hashFileContent) {
|
|
3636
|
+
_binding3 = mod;
|
|
3637
|
+
return _binding3;
|
|
3638
|
+
}
|
|
3639
|
+
} catch (error) {
|
|
3640
|
+
_loadError2 = error instanceof Error ? error.message : String(error);
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
_binding3 = null;
|
|
3644
|
+
throwNativeBindingError2();
|
|
3645
|
+
}
|
|
3646
|
+
function throwNativeBindingError2() {
|
|
3647
|
+
const lines = [
|
|
3648
|
+
"FATAL: Native engine binding not found.",
|
|
3649
|
+
"",
|
|
3650
|
+
"This package requires the Rust native binding 'tailwind_styled_parser.node'.",
|
|
3651
|
+
"The binding was not found in any of these paths:",
|
|
3652
|
+
..._candidatePaths2.map((p) => ` - ${p}`),
|
|
3653
|
+
""
|
|
3654
|
+
];
|
|
3655
|
+
if (_loadError2) {
|
|
3656
|
+
lines.push("Load error:", ` ${_loadError2}`, "");
|
|
3657
|
+
}
|
|
3658
|
+
lines.push(
|
|
3659
|
+
"To fix this, run:",
|
|
3660
|
+
" npm run build:rust",
|
|
3661
|
+
"",
|
|
3662
|
+
"This will build the native Rust module from the 'native/' directory.",
|
|
3663
|
+
"If you're using this package in a CI/CD environment, ensure Rust toolchain is installed",
|
|
3664
|
+
"and 'npm run build:rust' is executed before running tests or building."
|
|
3665
|
+
);
|
|
3666
|
+
throw new Error(lines.join("\n"));
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
// packages/engine/src/incremental.ts
|
|
3670
|
+
var DEFAULT_EXTENSIONS2 = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
3671
|
+
var log3 = createLogger("engine:incremental");
|
|
3672
|
+
function rebuildWorkspaceResult(byFile) {
|
|
3673
|
+
const files = Array.from(byFile.values());
|
|
3674
|
+
const unique = /* @__PURE__ */ new Set();
|
|
3675
|
+
for (const file of files) {
|
|
3676
|
+
for (const cls of file.classes) unique.add(cls);
|
|
3677
|
+
}
|
|
3678
|
+
return {
|
|
3679
|
+
files,
|
|
3680
|
+
totalFiles: files.length,
|
|
3681
|
+
uniqueClasses: Array.from(unique).sort()
|
|
3682
|
+
};
|
|
3683
|
+
}
|
|
3684
|
+
function applyClassDiff(existing, added, removed) {
|
|
3685
|
+
const next = new Set(existing);
|
|
3686
|
+
for (const cls of added) next.add(cls);
|
|
3687
|
+
for (const cls of removed) next.delete(cls);
|
|
3688
|
+
return Array.from(next);
|
|
3689
|
+
}
|
|
3690
|
+
function areClassSetsEqual(a, b) {
|
|
3691
|
+
if (a.length !== b.length) return false;
|
|
3692
|
+
const bSet = new Set(b);
|
|
3693
|
+
for (const cls of a) {
|
|
3694
|
+
if (!bSet.has(cls)) return false;
|
|
3695
|
+
}
|
|
3696
|
+
return true;
|
|
3697
|
+
}
|
|
3698
|
+
function applyIncrementalChange(previous, filePath, type, scanner) {
|
|
3699
|
+
const includeExtensions = scanner?.includeExtensions ?? DEFAULT_EXTENSIONS2;
|
|
3700
|
+
if (!isScannableFile(filePath, includeExtensions)) return previous;
|
|
3701
|
+
const byFile = new Map(previous.files.map((f) => [path10__default.default.resolve(f.file), f]));
|
|
3702
|
+
const normalizedPath = path10__default.default.resolve(filePath);
|
|
3703
|
+
const native = getNativeEngineBinding();
|
|
3704
|
+
if (native?.processFileChange) {
|
|
3705
|
+
try {
|
|
3706
|
+
if (type === "unlink") {
|
|
3707
|
+
const existing2 = byFile.get(normalizedPath);
|
|
3708
|
+
log3.debug(`native unlink ${normalizedPath}`);
|
|
3709
|
+
native.processFileChange(normalizedPath, existing2?.classes ?? [], null);
|
|
3710
|
+
byFile.delete(normalizedPath);
|
|
3711
|
+
return rebuildWorkspaceResult(byFile);
|
|
3712
|
+
}
|
|
3713
|
+
log3.debug(`native change ${normalizedPath}`);
|
|
3714
|
+
const scanned = scanFile(normalizedPath);
|
|
3715
|
+
const content = fs3__default.default.readFileSync(normalizedPath, "utf8");
|
|
3716
|
+
const diff = native.processFileChange(normalizedPath, scanned.classes, content);
|
|
3717
|
+
const existing = byFile.get(normalizedPath);
|
|
3718
|
+
if (diff && existing) {
|
|
3719
|
+
log3.debug(`native diff ${normalizedPath} +${diff.added.length} -${diff.removed.length}`);
|
|
3720
|
+
const diffApplied = applyClassDiff(existing.classes, diff.added, diff.removed);
|
|
3721
|
+
const classes = areClassSetsEqual(diffApplied, scanned.classes) ? diffApplied : scanned.classes;
|
|
3722
|
+
byFile.set(normalizedPath, { file: normalizedPath, classes });
|
|
3723
|
+
} else {
|
|
3724
|
+
log3.debug(`native diff cold-sync ${normalizedPath}`);
|
|
3725
|
+
byFile.set(normalizedPath, { file: normalizedPath, classes: scanned.classes });
|
|
3726
|
+
}
|
|
3727
|
+
return rebuildWorkspaceResult(byFile);
|
|
3728
|
+
} catch (error) {
|
|
3729
|
+
log3.warn(
|
|
3730
|
+
"native processFileChange failed, using JS fallback:",
|
|
3731
|
+
error instanceof Error ? error.message : String(error)
|
|
3732
|
+
);
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
log3.debug(`js fallback ${type} ${normalizedPath}`);
|
|
3736
|
+
if (type === "unlink") {
|
|
3737
|
+
byFile.delete(normalizedPath);
|
|
3738
|
+
} else {
|
|
3739
|
+
byFile.set(normalizedPath, scanFile(normalizedPath));
|
|
3740
|
+
}
|
|
3741
|
+
return rebuildWorkspaceResult(byFile);
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
// packages/engine/src/metrics.ts
|
|
3745
|
+
var EngineMetricsCollector = class {
|
|
3746
|
+
constructor() {
|
|
3747
|
+
this.eventsReceived = 0;
|
|
3748
|
+
this.eventsProcessed = 0;
|
|
3749
|
+
this.batchesProcessed = 0;
|
|
3750
|
+
this.incrementalUpdates = 0;
|
|
3751
|
+
this.fullRescans = 0;
|
|
3752
|
+
this.skippedLargeFiles = 0;
|
|
3753
|
+
this.queueMaxSize = 0;
|
|
3754
|
+
this.lastBuildMs = 0;
|
|
3755
|
+
this.totalBuildMs = 0;
|
|
3756
|
+
}
|
|
3757
|
+
markEventReceived(queueSize) {
|
|
3758
|
+
this.eventsReceived += 1;
|
|
3759
|
+
if (queueSize > this.queueMaxSize) this.queueMaxSize = queueSize;
|
|
3760
|
+
}
|
|
3761
|
+
markBatchProcessed(batchSize) {
|
|
3762
|
+
this.batchesProcessed += 1;
|
|
3763
|
+
this.eventsProcessed += batchSize;
|
|
3764
|
+
}
|
|
3765
|
+
markIncremental() {
|
|
3766
|
+
this.incrementalUpdates += 1;
|
|
3767
|
+
}
|
|
3768
|
+
markFullRescan() {
|
|
3769
|
+
this.fullRescans += 1;
|
|
3770
|
+
}
|
|
3771
|
+
markSkippedLargeFile() {
|
|
3772
|
+
this.skippedLargeFiles += 1;
|
|
3773
|
+
}
|
|
3774
|
+
markBuildDuration(ms) {
|
|
3775
|
+
this.lastBuildMs = ms;
|
|
3776
|
+
this.totalBuildMs += ms;
|
|
3777
|
+
}
|
|
3778
|
+
snapshot() {
|
|
3779
|
+
const avgBuildMs = this.batchesProcessed > 0 ? this.totalBuildMs / this.batchesProcessed : 0;
|
|
3780
|
+
return {
|
|
3781
|
+
eventsReceived: this.eventsReceived,
|
|
3782
|
+
eventsProcessed: this.eventsProcessed,
|
|
3783
|
+
batchesProcessed: this.batchesProcessed,
|
|
3784
|
+
incrementalUpdates: this.incrementalUpdates,
|
|
3785
|
+
fullRescans: this.fullRescans,
|
|
3786
|
+
skippedLargeFiles: this.skippedLargeFiles,
|
|
3787
|
+
queueMaxSize: this.queueMaxSize,
|
|
3788
|
+
lastBuildMs: this.lastBuildMs,
|
|
3789
|
+
avgBuildMs
|
|
3790
|
+
};
|
|
3791
|
+
}
|
|
3792
|
+
};
|
|
3793
|
+
|
|
3794
|
+
// packages/engine/src/plugin-api.ts
|
|
3795
|
+
async function runBeforeScan(plugins, context) {
|
|
3796
|
+
for (const plugin of plugins) {
|
|
3797
|
+
await plugin.beforeScan?.(context);
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
async function runAfterScan(plugins, scan, context) {
|
|
3801
|
+
let current = scan;
|
|
3802
|
+
for (const plugin of plugins) {
|
|
3803
|
+
const next = await plugin.afterScan?.(current, context);
|
|
3804
|
+
if (next !== void 0) current = next;
|
|
3805
|
+
}
|
|
3806
|
+
return current;
|
|
3807
|
+
}
|
|
3808
|
+
async function runTransformClasses(plugins, classes, context) {
|
|
3809
|
+
let current = classes;
|
|
3810
|
+
for (const plugin of plugins) {
|
|
3811
|
+
const next = await plugin.transformClasses?.(current, context);
|
|
3812
|
+
if (next !== void 0) current = next;
|
|
3813
|
+
}
|
|
3814
|
+
return current;
|
|
3815
|
+
}
|
|
3816
|
+
async function runBeforeBuild(plugins, scan, context) {
|
|
3817
|
+
for (const plugin of plugins) {
|
|
3818
|
+
await plugin.beforeBuild?.(scan, context);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
async function runAfterBuild(plugins, result, context) {
|
|
3822
|
+
let current = result;
|
|
3823
|
+
for (const plugin of plugins) {
|
|
3824
|
+
const next = await plugin.afterBuild?.(current, context);
|
|
3825
|
+
if (next !== void 0) current = next;
|
|
3826
|
+
}
|
|
3827
|
+
return current;
|
|
3828
|
+
}
|
|
3829
|
+
async function runOnError(plugins, error, context) {
|
|
3830
|
+
for (const plugin of plugins) {
|
|
3831
|
+
await plugin.onError?.(error, context);
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
async function runBeforeWatch(plugins, context) {
|
|
3835
|
+
for (const plugin of plugins) {
|
|
3836
|
+
await plugin.beforeWatch?.(context);
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
async function runAfterWatch(plugins, context) {
|
|
3840
|
+
for (const plugin of plugins) {
|
|
3841
|
+
await plugin.afterWatch?.(context);
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
var DEFAULT_IGNORES2 = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
|
|
3845
|
+
function watchWorkspace(rootDir, onEvent, options = {}) {
|
|
3846
|
+
const ignoreDirectories = new Set(options.ignoreDirectories ?? DEFAULT_IGNORES2);
|
|
3847
|
+
const watchers = /* @__PURE__ */ new Map();
|
|
3848
|
+
const restartTimers = /* @__PURE__ */ new Map();
|
|
3849
|
+
const debounceMs = options.debounceMs ?? 100;
|
|
3850
|
+
const pending = /* @__PURE__ */ new Map();
|
|
3851
|
+
const shouldIgnore = (targetPath) => {
|
|
3852
|
+
const parts = targetPath.split(path10__default.default.sep);
|
|
3853
|
+
return parts.some((part) => ignoreDirectories.has(part));
|
|
3854
|
+
};
|
|
3855
|
+
const enqueue = (event) => {
|
|
3856
|
+
const key = `${event.type}:${event.filePath}`;
|
|
3857
|
+
const existing = pending.get(key);
|
|
3858
|
+
if (existing) clearTimeout(existing);
|
|
3859
|
+
const timer = setTimeout(() => {
|
|
3860
|
+
pending.delete(key);
|
|
3861
|
+
onEvent(event);
|
|
3862
|
+
}, debounceMs);
|
|
3863
|
+
pending.set(key, timer);
|
|
3864
|
+
};
|
|
3865
|
+
const safeUnwatch = (dir) => {
|
|
3866
|
+
const watcher = watchers.get(dir);
|
|
3867
|
+
if (!watcher) return;
|
|
3868
|
+
try {
|
|
3869
|
+
watcher.close();
|
|
3870
|
+
} catch {
|
|
3871
|
+
}
|
|
3872
|
+
watchers.delete(dir);
|
|
3873
|
+
};
|
|
3874
|
+
const scheduleRestart = (dir) => {
|
|
3875
|
+
const previous = restartTimers.get(dir);
|
|
3876
|
+
if (previous) clearTimeout(previous);
|
|
3877
|
+
const timer = setTimeout(() => {
|
|
3878
|
+
restartTimers.delete(dir);
|
|
3879
|
+
watchDir(dir);
|
|
3880
|
+
}, 250);
|
|
3881
|
+
restartTimers.set(dir, timer);
|
|
3882
|
+
};
|
|
3883
|
+
const watchDir = (dir) => {
|
|
3884
|
+
if (watchers.has(dir) || shouldIgnore(dir) || !fs3__default.default.existsSync(dir)) return;
|
|
3885
|
+
try {
|
|
3886
|
+
const stat = fs3__default.default.lstatSync(dir);
|
|
3887
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) return;
|
|
3888
|
+
} catch {
|
|
3889
|
+
return;
|
|
3890
|
+
}
|
|
3891
|
+
const watcher = fs3__default.default.watch(dir, { persistent: true }, (_eventType, fileName) => {
|
|
3892
|
+
if (!fileName) return;
|
|
3893
|
+
const fullPath = path10__default.default.join(dir, fileName.toString());
|
|
3894
|
+
if (shouldIgnore(fullPath)) return;
|
|
3895
|
+
if (fs3__default.default.existsSync(fullPath)) {
|
|
3896
|
+
try {
|
|
3897
|
+
const stat = fs3__default.default.lstatSync(fullPath);
|
|
3898
|
+
if (stat.isSymbolicLink()) return;
|
|
3899
|
+
if (stat.isDirectory()) {
|
|
3900
|
+
watchDir(fullPath);
|
|
3901
|
+
return;
|
|
3902
|
+
}
|
|
3903
|
+
enqueue({ type: "change", filePath: fullPath });
|
|
3904
|
+
return;
|
|
3905
|
+
} catch {
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
enqueue({ type: "unlink", filePath: fullPath });
|
|
3909
|
+
});
|
|
3910
|
+
watcher.on("error", (error) => {
|
|
3911
|
+
safeUnwatch(dir);
|
|
3912
|
+
const watcherError = error instanceof Error ? error : new Error(String(error));
|
|
3913
|
+
options.onError?.(watcherError, dir);
|
|
3914
|
+
scheduleRestart(dir);
|
|
3915
|
+
});
|
|
3916
|
+
watchers.set(dir, watcher);
|
|
3917
|
+
for (const entry of fs3__default.default.readdirSync(dir, { withFileTypes: true })) {
|
|
3918
|
+
if (!entry.isDirectory()) continue;
|
|
3919
|
+
watchDir(path10__default.default.join(dir, entry.name));
|
|
3920
|
+
}
|
|
3921
|
+
};
|
|
3922
|
+
watchDir(path10__default.default.resolve(rootDir));
|
|
3923
|
+
return {
|
|
3924
|
+
close() {
|
|
3925
|
+
for (const timer of pending.values()) clearTimeout(timer);
|
|
3926
|
+
pending.clear();
|
|
3927
|
+
for (const timer of restartTimers.values()) clearTimeout(timer);
|
|
3928
|
+
restartTimers.clear();
|
|
3929
|
+
for (const watcher of watchers.values()) watcher.close();
|
|
3930
|
+
watchers.clear();
|
|
3931
|
+
}
|
|
3932
|
+
};
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
// packages/engine/src/index.ts
|
|
3936
|
+
var DEFAULT_LARGE_FILE_THRESHOLD_BYTES = 10 * 1024 * 1024;
|
|
3937
|
+
var DEFAULT_FLUSH_DEBOUNCE_MS = 100;
|
|
3938
|
+
var DEFAULT_MAX_EVENTS_PER_FLUSH = 100;
|
|
3939
|
+
var log4 = createLogger("engine");
|
|
3940
|
+
async function loadTailwindConfigFromPath(root, tailwindConfigPath) {
|
|
3941
|
+
if (!tailwindConfigPath) return void 0;
|
|
3942
|
+
const configPath = path10__default.default.resolve(root, tailwindConfigPath);
|
|
3943
|
+
if (!fs3__default.default.existsSync(configPath)) {
|
|
3944
|
+
throw new Error(`tailwindConfigPath not found: ${configPath}`);
|
|
3945
|
+
}
|
|
3946
|
+
const imported = await import(url.pathToFileURL(configPath).href);
|
|
3947
|
+
const config = imported.default ?? imported;
|
|
3948
|
+
return config;
|
|
3949
|
+
}
|
|
3950
|
+
async function tryRunAnalyzer(root, scan) {
|
|
3951
|
+
try {
|
|
3952
|
+
const { __internal: __internal2 } = await Promise.resolve().then(() => (init_src4(), src_exports));
|
|
3953
|
+
const counts = __internal2.collectClassCounts(scan);
|
|
3954
|
+
const classUsage = {};
|
|
3955
|
+
for (const [name, count] of counts) {
|
|
3956
|
+
classUsage[name] = count;
|
|
3957
|
+
}
|
|
3958
|
+
return {
|
|
3959
|
+
unusedClasses: Array.from(counts.keys()).filter((c) => counts.get(c) === 0),
|
|
3960
|
+
classConflicts: [],
|
|
3961
|
+
classUsage
|
|
3962
|
+
};
|
|
3963
|
+
} catch (e) {
|
|
3964
|
+
log4.warn("Analyzer not available:", String(e));
|
|
3965
|
+
return void 0;
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
async function buildFromScan(scan, root, options, tailwindConfig) {
|
|
3969
|
+
const plugins = options.plugins ?? [];
|
|
3970
|
+
const context = { root, timestamp: Date.now() };
|
|
3971
|
+
await runBeforeBuild(plugins, scan, context);
|
|
3972
|
+
const transformedClasses = await runTransformClasses(plugins, scan.uniqueClasses, context);
|
|
3973
|
+
const mergedClassList = mergeClassesStatic(transformedClasses.join(" "));
|
|
3974
|
+
let css = "";
|
|
3975
|
+
if (options.compileCss !== false && mergedClassList.length > 0) {
|
|
3976
|
+
css = await generateCssForClasses(
|
|
3977
|
+
mergedClassList.split(/\s+/).filter(Boolean),
|
|
3978
|
+
tailwindConfig,
|
|
3979
|
+
root
|
|
3980
|
+
);
|
|
3981
|
+
}
|
|
3982
|
+
let analysis;
|
|
3983
|
+
if (options.analyze) {
|
|
3984
|
+
analysis = await tryRunAnalyzer(root, scan);
|
|
3985
|
+
}
|
|
3986
|
+
const result = {
|
|
3987
|
+
scan,
|
|
3988
|
+
mergedClassList,
|
|
3989
|
+
css,
|
|
3990
|
+
analysis
|
|
3991
|
+
};
|
|
3992
|
+
return runAfterBuild(plugins, result, context);
|
|
3993
|
+
}
|
|
3994
|
+
async function createEngine(options = {}) {
|
|
3995
|
+
const root = options.root ?? process.cwd();
|
|
3996
|
+
const resolvedRoot = path10__default.default.resolve(root);
|
|
3997
|
+
const plugins = options.plugins ?? [];
|
|
3998
|
+
let cachedTailwindConfig;
|
|
3999
|
+
let tailwindConfigLoaded = false;
|
|
4000
|
+
const getTailwindConfig = async () => {
|
|
4001
|
+
if (tailwindConfigLoaded) return cachedTailwindConfig;
|
|
4002
|
+
cachedTailwindConfig = await loadTailwindConfigFromPath(
|
|
4003
|
+
resolvedRoot,
|
|
4004
|
+
options.tailwindConfigPath
|
|
4005
|
+
);
|
|
4006
|
+
tailwindConfigLoaded = true;
|
|
4007
|
+
return cachedTailwindConfig;
|
|
4008
|
+
};
|
|
4009
|
+
const reportEngineError = async (error) => {
|
|
4010
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
4011
|
+
const context = { root: resolvedRoot, timestamp: Date.now() };
|
|
4012
|
+
try {
|
|
4013
|
+
await runOnError(plugins, normalized, context);
|
|
4014
|
+
} catch (pluginError) {
|
|
4015
|
+
log4.error(
|
|
4016
|
+
"plugin onError hook failed:",
|
|
4017
|
+
pluginError instanceof Error ? pluginError.message : String(pluginError)
|
|
4018
|
+
);
|
|
4019
|
+
}
|
|
4020
|
+
log4.error(normalized.message);
|
|
4021
|
+
return normalized;
|
|
4022
|
+
};
|
|
4023
|
+
const doScan = async () => {
|
|
4024
|
+
try {
|
|
4025
|
+
const context = { root: resolvedRoot, timestamp: Date.now() };
|
|
4026
|
+
await runBeforeScan(plugins, context);
|
|
4027
|
+
const scan = await scanWorkspaceAsync(resolvedRoot, options.scanner);
|
|
4028
|
+
return await runAfterScan(plugins, scan, context);
|
|
4029
|
+
} catch (error) {
|
|
4030
|
+
throw await reportEngineError(error);
|
|
4031
|
+
}
|
|
4032
|
+
};
|
|
4033
|
+
return {
|
|
4034
|
+
scan: doScan,
|
|
4035
|
+
async build() {
|
|
4036
|
+
const scan = await doScan();
|
|
4037
|
+
try {
|
|
4038
|
+
return await buildFromScan(scan, resolvedRoot, options, await getTailwindConfig());
|
|
4039
|
+
} catch (error) {
|
|
4040
|
+
throw await reportEngineError(error);
|
|
4041
|
+
}
|
|
4042
|
+
},
|
|
4043
|
+
async watch(onEvent, watchOptions = {}) {
|
|
4044
|
+
const flushDebounceMs = watchOptions.debounceMs ?? DEFAULT_FLUSH_DEBOUNCE_MS;
|
|
4045
|
+
const maxEventsPerFlush = watchOptions.maxEventsPerFlush ?? DEFAULT_MAX_EVENTS_PER_FLUSH;
|
|
4046
|
+
const largeFileThreshold = watchOptions.largeFileThreshold ?? DEFAULT_LARGE_FILE_THRESHOLD_BYTES;
|
|
4047
|
+
const tailwindConfig = await getTailwindConfig();
|
|
4048
|
+
const watchContext = { root: resolvedRoot, timestamp: Date.now() };
|
|
4049
|
+
await runBeforeWatch(plugins, watchContext);
|
|
4050
|
+
let currentScan = await doScan();
|
|
4051
|
+
try {
|
|
4052
|
+
onEvent({
|
|
4053
|
+
type: "initial",
|
|
4054
|
+
result: await buildFromScan(currentScan, resolvedRoot, options, tailwindConfig)
|
|
4055
|
+
});
|
|
4056
|
+
} catch (error) {
|
|
4057
|
+
const normalized = await reportEngineError(error);
|
|
4058
|
+
onEvent({ type: "error", error: normalized.message });
|
|
4059
|
+
throw normalized;
|
|
4060
|
+
}
|
|
4061
|
+
let timer = null;
|
|
4062
|
+
const queue = [];
|
|
4063
|
+
const metrics = new EngineMetricsCollector();
|
|
4064
|
+
const scheduleFlush = () => {
|
|
4065
|
+
if (timer) return;
|
|
4066
|
+
timer = setTimeout(() => {
|
|
4067
|
+
timer = null;
|
|
4068
|
+
void flushBatch();
|
|
4069
|
+
}, flushDebounceMs);
|
|
4070
|
+
};
|
|
4071
|
+
const shouldForceFullRescan = (event) => {
|
|
4072
|
+
if (event.type === "unlink") return false;
|
|
4073
|
+
try {
|
|
4074
|
+
const stat = fs3__default.default.statSync(event.filePath);
|
|
4075
|
+
if (stat.size > largeFileThreshold) {
|
|
4076
|
+
metrics.markSkippedLargeFile();
|
|
4077
|
+
return true;
|
|
4078
|
+
}
|
|
4079
|
+
} catch {
|
|
4080
|
+
return false;
|
|
4081
|
+
}
|
|
4082
|
+
return false;
|
|
4083
|
+
};
|
|
4084
|
+
const flushBatch = async () => {
|
|
4085
|
+
if (queue.length === 0) return;
|
|
4086
|
+
const batch = queue.splice(0, maxEventsPerFlush);
|
|
4087
|
+
metrics.markBatchProcessed(batch.length);
|
|
4088
|
+
let forceRescan = false;
|
|
4089
|
+
for (const event of batch) {
|
|
4090
|
+
if (shouldForceFullRescan(event)) {
|
|
4091
|
+
forceRescan = true;
|
|
4092
|
+
break;
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
const lastEvent = batch[batch.length - 1];
|
|
4096
|
+
let emittedType = lastEvent.type;
|
|
4097
|
+
try {
|
|
4098
|
+
if (forceRescan) {
|
|
4099
|
+
currentScan = await doScan();
|
|
4100
|
+
metrics.markFullRescan();
|
|
4101
|
+
emittedType = "full-rescan";
|
|
4102
|
+
} else {
|
|
4103
|
+
for (const event of batch) {
|
|
4104
|
+
currentScan = applyIncrementalChange(
|
|
4105
|
+
currentScan,
|
|
4106
|
+
event.filePath,
|
|
4107
|
+
event.type,
|
|
4108
|
+
options.scanner
|
|
4109
|
+
);
|
|
4110
|
+
metrics.markIncremental();
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
} catch (error) {
|
|
4114
|
+
const normalized = await reportEngineError(error);
|
|
4115
|
+
log4.warn("incremental path failed, forcing full rescan:", normalized.message);
|
|
4116
|
+
currentScan = await doScan();
|
|
4117
|
+
metrics.markFullRescan();
|
|
4118
|
+
emittedType = "full-rescan";
|
|
4119
|
+
}
|
|
4120
|
+
try {
|
|
4121
|
+
const started = Date.now();
|
|
4122
|
+
const result = await buildFromScan(currentScan, resolvedRoot, options, tailwindConfig);
|
|
4123
|
+
metrics.markBuildDuration(Date.now() - started);
|
|
4124
|
+
onEvent({
|
|
4125
|
+
type: emittedType,
|
|
4126
|
+
filePath: lastEvent.filePath,
|
|
4127
|
+
result,
|
|
4128
|
+
metrics: metrics.snapshot()
|
|
4129
|
+
});
|
|
4130
|
+
} catch (error) {
|
|
4131
|
+
const normalized = await reportEngineError(error);
|
|
4132
|
+
onEvent({
|
|
4133
|
+
type: "error",
|
|
4134
|
+
filePath: lastEvent.filePath,
|
|
4135
|
+
error: normalized.message,
|
|
4136
|
+
metrics: metrics.snapshot()
|
|
4137
|
+
});
|
|
4138
|
+
}
|
|
4139
|
+
if (queue.length > 0) scheduleFlush();
|
|
4140
|
+
};
|
|
4141
|
+
const watcher = watchWorkspace(
|
|
4142
|
+
resolvedRoot,
|
|
4143
|
+
(event) => {
|
|
4144
|
+
queue.push(event);
|
|
4145
|
+
metrics.markEventReceived(queue.length);
|
|
4146
|
+
scheduleFlush();
|
|
4147
|
+
},
|
|
4148
|
+
{
|
|
4149
|
+
ignoreDirectories: options.scanner?.ignoreDirectories,
|
|
4150
|
+
debounceMs: flushDebounceMs,
|
|
4151
|
+
onError: (error, directory) => {
|
|
4152
|
+
void reportEngineError(error);
|
|
4153
|
+
onEvent({
|
|
4154
|
+
type: "error",
|
|
4155
|
+
filePath: directory,
|
|
4156
|
+
error: error.message,
|
|
4157
|
+
metrics: metrics.snapshot()
|
|
4158
|
+
});
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
);
|
|
4162
|
+
return {
|
|
4163
|
+
async close() {
|
|
4164
|
+
if (timer) clearTimeout(timer);
|
|
4165
|
+
watcher.close();
|
|
4166
|
+
await runAfterWatch(plugins, watchContext);
|
|
4167
|
+
}
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
4170
|
+
};
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
// packages/vite/src/plugin.ts
|
|
4174
|
+
init_src3();
|
|
9
4175
|
function warnDeprecated(options, key, message) {
|
|
10
4176
|
if (options[key] !== void 0) {
|
|
11
4177
|
console.warn(`[tailwind-styled-v4] Warning: '${key}' is deprecated in v5. ${message}`);
|
|
@@ -54,9 +4220,7 @@ function tailwindStyledPlugin(opts = {}) {
|
|
|
54
4220
|
const output = runLoaderTransform({
|
|
55
4221
|
filepath,
|
|
56
4222
|
source,
|
|
57
|
-
options: loaderOptions
|
|
58
|
-
isDev
|
|
59
|
-
});
|
|
4223
|
+
options: loaderOptions});
|
|
60
4224
|
if (!output.changed) return null;
|
|
61
4225
|
return { code: output.code, map: null };
|
|
62
4226
|
},
|
|
@@ -65,8 +4229,8 @@ function tailwindStyledPlugin(opts = {}) {
|
|
|
65
4229
|
if (doSafelist) {
|
|
66
4230
|
try {
|
|
67
4231
|
generateSafelist(
|
|
68
|
-
scanDirs.map((d) =>
|
|
69
|
-
|
|
4232
|
+
scanDirs.map((d) => path10__default.default.resolve(root, d)),
|
|
4233
|
+
path10__default.default.resolve(root, safelistOutput),
|
|
70
4234
|
root
|
|
71
4235
|
);
|
|
72
4236
|
} catch (e) {
|
|
@@ -75,8 +4239,8 @@ function tailwindStyledPlugin(opts = {}) {
|
|
|
75
4239
|
}
|
|
76
4240
|
try {
|
|
77
4241
|
const report = await scanWorkspaceAsync(root);
|
|
78
|
-
const reportPath =
|
|
79
|
-
|
|
4242
|
+
const reportPath = path10__default.default.resolve(root, scanReportOutput);
|
|
4243
|
+
fs3__default.default.writeFileSync(
|
|
80
4244
|
reportPath,
|
|
81
4245
|
JSON.stringify(
|
|
82
4246
|
{
|
|
@@ -123,6 +4287,7 @@ function tailwindStyledPlugin(opts = {}) {
|
|
|
123
4287
|
}
|
|
124
4288
|
var plugin_default = tailwindStyledPlugin;
|
|
125
4289
|
|
|
126
|
-
|
|
4290
|
+
exports.default = plugin_default;
|
|
4291
|
+
exports.tailwindStyledPlugin = tailwindStyledPlugin;
|
|
127
4292
|
//# sourceMappingURL=vite.js.map
|
|
128
4293
|
//# sourceMappingURL=vite.js.map
|