tailwind-styled-v4 5.0.9 → 5.0.10
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 +15 -1
- package/dist/{analyzeWorkspace-DuJKh7Ty.d.mts → analyzeWorkspace-BS5O4rhC.d.mts} +47 -2
- package/dist/{analyzeWorkspace-Ct_NTAWt.d.ts → analyzeWorkspace-DDOQdzzI.d.ts} +47 -2
- package/dist/analyzer.d.mts +5 -3
- package/dist/analyzer.d.ts +5 -3
- package/dist/analyzer.js +563 -468
- package/dist/analyzer.js.map +1 -1
- package/dist/analyzer.mjs +562 -467
- package/dist/analyzer.mjs.map +1 -1
- package/dist/animate.d.mts +4 -7
- package/dist/animate.d.ts +4 -7
- package/dist/animate.js +171 -265
- package/dist/animate.js.map +1 -1
- package/dist/animate.mjs +165 -264
- package/dist/animate.mjs.map +1 -1
- package/dist/atomic.d.mts +22 -1
- package/dist/atomic.d.ts +22 -1
- package/dist/atomic.js +221 -165
- package/dist/atomic.js.map +1 -1
- package/dist/atomic.mjs +200 -165
- package/dist/atomic.mjs.map +1 -1
- package/dist/cli.d.mts +60 -1
- package/dist/cli.d.ts +60 -1
- package/dist/cli.js +1261 -1517
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1238 -1513
- package/dist/cli.mjs.map +1 -1
- package/dist/compiler.d.mts +38 -7
- package/dist/compiler.d.ts +38 -7
- package/dist/compiler.js +174 -197
- package/dist/compiler.js.map +1 -1
- package/dist/compiler.mjs +151 -194
- package/dist/compiler.mjs.map +1 -1
- package/dist/devtools.js +7 -31
- package/dist/devtools.js.map +1 -1
- package/dist/devtools.mjs +7 -31
- package/dist/devtools.mjs.map +1 -1
- package/dist/engine.d.mts +134 -63
- package/dist/engine.d.ts +134 -63
- package/dist/engine.js +2863 -2482
- package/dist/engine.js.map +1 -1
- package/dist/engine.mjs +2852 -2485
- package/dist/engine.mjs.map +1 -1
- package/dist/{index-eWAocnD2.d.mts → index-NDINUhLN.d.mts} +3 -1
- package/dist/{index-eWAocnD2.d.ts → index-NDINUhLN.d.ts} +3 -1
- package/dist/index.d.mts +45 -32
- package/dist/index.d.ts +45 -32
- package/dist/index.js +271 -158
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +251 -158
- package/dist/index.mjs.map +1 -1
- package/dist/{liveTokenEngine-DSUk88P6.d.ts → liveTokenEngine-CN9ian1R.d.ts} +1 -1
- package/dist/{liveTokenEngine-CX5_0c4q.d.mts → liveTokenEngine-DKoWRtqH.d.mts} +1 -1
- package/dist/next.js +20 -39
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +18 -37
- package/dist/next.mjs.map +1 -1
- package/dist/plugin-api.d.mts +8 -2
- package/dist/plugin-api.d.ts +8 -2
- package/dist/plugin-api.js +14 -2
- package/dist/plugin-api.js.map +1 -1
- package/dist/plugin-api.mjs +14 -3
- package/dist/plugin-api.mjs.map +1 -1
- package/dist/plugin-registry.js +51 -11
- package/dist/plugin-registry.js.map +1 -1
- package/dist/plugin-registry.mjs +51 -11
- package/dist/plugin-registry.mjs.map +1 -1
- package/dist/plugin.d.mts +5 -7
- package/dist/plugin.d.ts +5 -7
- package/dist/plugin.js +16 -15
- package/dist/plugin.js.map +1 -1
- package/dist/plugin.mjs +16 -16
- package/dist/plugin.mjs.map +1 -1
- package/dist/rspack.js +17 -38
- package/dist/rspack.js.map +1 -1
- package/dist/rspack.mjs +15 -36
- package/dist/rspack.mjs.map +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/scanner.d.mts +10 -1
- package/dist/scanner.d.ts +10 -1
- package/dist/scanner.js +298 -124
- package/dist/scanner.js.map +1 -1
- package/dist/scanner.mjs +296 -124
- package/dist/scanner.mjs.map +1 -1
- package/dist/shared.d.mts +1 -1
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +104 -176
- package/dist/shared.js.map +1 -1
- package/dist/shared.mjs +85 -176
- package/dist/shared.mjs.map +1 -1
- package/dist/storybook-addon.d.mts +1 -1
- package/dist/storybook-addon.d.ts +1 -1
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +166 -3
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +143 -1
- package/dist/svelte.mjs.map +1 -1
- package/dist/syntax.js +21 -21
- package/dist/syntax.js.map +1 -1
- package/dist/syntax.mjs +21 -21
- package/dist/syntax.mjs.map +1 -1
- package/dist/testing.js +9 -1
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +9 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/theme.d.mts +2 -2
- package/dist/theme.d.ts +2 -2
- package/dist/theme.js +40 -112
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +37 -110
- package/dist/theme.mjs.map +1 -1
- package/dist/turbopackLoader.js +79 -124
- package/dist/turbopackLoader.js.map +1 -1
- package/dist/turbopackLoader.mjs +63 -122
- package/dist/turbopackLoader.mjs.map +1 -1
- package/dist/tw.js +1256 -1517
- package/dist/tw.js.map +1 -1
- package/dist/tw.mjs +1236 -1513
- package/dist/tw.mjs.map +1 -1
- package/dist/vite.js +1783 -823
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +1767 -821
- package/dist/vite.mjs.map +1 -1
- package/dist/vue.d.mts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +165 -4
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +141 -1
- package/dist/vue.mjs.map +1 -1
- package/dist/webpackLoader.js +65 -108
- package/dist/webpackLoader.js.map +1 -1
- package/dist/webpackLoader.mjs +45 -104
- package/dist/webpackLoader.mjs.map +1 -1
- package/native/tailwind-styled-native.node +0 -0
- package/package.json +22 -24
package/dist/analyzer.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import 'crypto';
|
|
2
|
+
import fs3 from 'fs';
|
|
3
|
+
import path5 from 'path';
|
|
2
4
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
3
|
-
import fs from 'fs';
|
|
4
5
|
import { createRequire } from 'module';
|
|
5
|
-
import { Worker } from 'worker_threads';
|
|
6
|
+
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
|
|
7
|
+
import { availableParallelism } from 'os';
|
|
6
8
|
import { z } from 'zod';
|
|
7
9
|
|
|
8
10
|
/* tailwind-styled-v4 v5.0.4 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
|
|
@@ -10,12 +12,6 @@ var __defProp = Object.defineProperty;
|
|
|
10
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
13
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
14
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
14
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
15
|
-
}) : x)(function(x) {
|
|
16
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
17
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
18
|
-
});
|
|
19
15
|
var __esm = (fn, res) => function __init() {
|
|
20
16
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
21
17
|
};
|
|
@@ -32,41 +28,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
32
28
|
return to;
|
|
33
29
|
};
|
|
34
30
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
|
-
|
|
36
|
-
// packages/domain/shared/src/index.ts
|
|
37
|
-
function getNodeModuleRef() {
|
|
38
|
-
if (isBrowser) return null;
|
|
39
|
-
if (nodeModuleRef !== null) return nodeModuleRef;
|
|
40
|
-
try {
|
|
41
|
-
const test = typeof __require === "function" ? __require("module") : null;
|
|
42
|
-
nodeModuleRef = test;
|
|
43
|
-
return test;
|
|
44
|
-
} catch {
|
|
45
|
-
nodeModuleRef = null;
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
function getNodeFs() {
|
|
50
|
-
if (isBrowser) throw new Error("node:fs not available in browser");
|
|
51
|
-
const nodeRequire = getNodeModuleRef();
|
|
52
|
-
if (!nodeRequire) throw new Error("require not available");
|
|
53
|
-
if (!_nodeFs) _nodeFs = nodeRequire.createRequire(import.meta.url)("node:fs");
|
|
54
|
-
return _nodeFs;
|
|
55
|
-
}
|
|
56
|
-
function getNodePath() {
|
|
57
|
-
if (isBrowser) throw new Error("node:path not available in browser");
|
|
58
|
-
const nodeRequire = getNodeModuleRef();
|
|
59
|
-
if (!nodeRequire) throw new Error("require not available");
|
|
60
|
-
if (!_nodePath) _nodePath = nodeRequire.createRequire(import.meta.url)("node:path");
|
|
61
|
-
return _nodePath;
|
|
62
|
-
}
|
|
63
|
-
function getNodeUrl() {
|
|
64
|
-
if (isBrowser) throw new Error("node:url not available in browser");
|
|
65
|
-
const nodeRequire = getNodeModuleRef();
|
|
66
|
-
if (!nodeRequire) throw new Error("require not available");
|
|
67
|
-
if (!_nodeUrl) _nodeUrl = nodeRequire.createRequire(import.meta.url)("node:url");
|
|
68
|
-
return _nodeUrl;
|
|
69
|
-
}
|
|
70
31
|
function createLogger(namespace) {
|
|
71
32
|
const prefix = `[${namespace}]`;
|
|
72
33
|
return {
|
|
@@ -96,24 +57,19 @@ function createDebugLogger(namespace, label) {
|
|
|
96
57
|
}
|
|
97
58
|
};
|
|
98
59
|
}
|
|
99
|
-
function formatIssuePath(
|
|
100
|
-
if (!
|
|
101
|
-
return
|
|
60
|
+
function formatIssuePath(path8) {
|
|
61
|
+
if (!path8 || path8.length === 0) return "(root)";
|
|
62
|
+
return path8.map(
|
|
102
63
|
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
103
64
|
).join(".");
|
|
104
65
|
}
|
|
105
66
|
function loadNativeBinding(options) {
|
|
106
|
-
if (isBrowser) {
|
|
107
|
-
return { binding: null, loadErrors: [{ path: "", message: "Native bindings not available in browser" }] };
|
|
108
|
-
}
|
|
109
67
|
const { runtimeDir, candidates, isValid } = options;
|
|
110
68
|
const loadErrors = [];
|
|
111
|
-
const path6 = getNodePath();
|
|
112
|
-
const fs4 = getNodeFs();
|
|
113
69
|
for (const candidate of candidates) {
|
|
114
|
-
const candidatePath =
|
|
70
|
+
const candidatePath = path5.resolve(runtimeDir, candidate);
|
|
115
71
|
try {
|
|
116
|
-
if (!
|
|
72
|
+
if (!fs3.existsSync(candidatePath) && !fs3.existsSync(candidatePath + ".node")) {
|
|
117
73
|
continue;
|
|
118
74
|
}
|
|
119
75
|
const mod = requireNativeModule(candidatePath);
|
|
@@ -127,72 +83,56 @@ function loadNativeBinding(options) {
|
|
|
127
83
|
}
|
|
128
84
|
return { binding: null, loadErrors };
|
|
129
85
|
}
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
throw new Error("require not available in browser");
|
|
133
|
-
});
|
|
134
|
-
const nodeRequire = getNodeModuleRef();
|
|
135
|
-
if (!nodeRequire) return (() => {
|
|
136
|
-
throw new Error("require not available");
|
|
137
|
-
});
|
|
138
|
-
return nodeRequire.createRequire(import.meta.url);
|
|
139
|
-
}
|
|
140
|
-
function requireNativeModule(path6) {
|
|
141
|
-
return _require(path6);
|
|
86
|
+
function requireNativeModule(p) {
|
|
87
|
+
return _require(p);
|
|
142
88
|
}
|
|
143
89
|
function resolveNativeBindingCandidates(options) {
|
|
144
|
-
|
|
145
|
-
|
|
90
|
+
const {
|
|
91
|
+
envVarNames = ["TW_NATIVE_PATH", "TWS_NATIVE_PATH"],
|
|
92
|
+
includeDefaultCandidates = true,
|
|
93
|
+
enforceNodeExtensionForEnvPath = false
|
|
94
|
+
} = options;
|
|
95
|
+
const runtimeDir = options.runtimeDir || process.cwd();
|
|
146
96
|
const candidates = [];
|
|
147
|
-
const path6 = getNodePath();
|
|
148
|
-
const fs4 = getNodeFs();
|
|
149
97
|
for (const envVar of envVarNames) {
|
|
150
98
|
const envPath = process.env[envVar];
|
|
151
99
|
if (envPath) {
|
|
152
|
-
|
|
153
|
-
candidates.push(envPath + ".node");
|
|
154
|
-
} else {
|
|
155
|
-
candidates.push(envPath);
|
|
156
|
-
}
|
|
100
|
+
candidates.push(enforceNodeExtensionForEnvPath && !envPath.endsWith(".node") ? envPath + ".node" : envPath);
|
|
157
101
|
}
|
|
158
102
|
}
|
|
159
103
|
if (!includeDefaultCandidates) return candidates;
|
|
160
|
-
if (
|
|
104
|
+
if (fs3.existsSync(runtimeDir)) {
|
|
161
105
|
try {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
if (entry.endsWith(".node")) {
|
|
165
|
-
candidates.push(entry);
|
|
166
|
-
}
|
|
106
|
+
for (const entry of fs3.readdirSync(runtimeDir)) {
|
|
107
|
+
if (entry.endsWith(".node")) candidates.push(entry);
|
|
167
108
|
}
|
|
168
109
|
} catch {
|
|
169
110
|
}
|
|
170
111
|
}
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
112
|
+
const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
|
|
113
|
+
const napiPlatform = process.platform === "linux" && process.arch === "x64" ? "linux-x64-gnu" : process.platform === "linux" && process.arch === "arm64" ? "linux-arm64-gnu" : `${process.platform}-${process.arch}`;
|
|
114
|
+
for (const bin of BINARY_NAMES) {
|
|
115
|
+
candidates.push(path5.resolve(runtimeDir, `${bin}.node`));
|
|
116
|
+
candidates.push(path5.resolve(runtimeDir, `${bin}.${napiPlatform}.node`));
|
|
117
|
+
candidates.push(path5.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.node`));
|
|
118
|
+
candidates.push(path5.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.${napiPlatform}.node`));
|
|
119
|
+
candidates.push(path5.resolve(runtimeDir, "..", "..", "..", "native", `${bin}.node`));
|
|
120
|
+
candidates.push(path5.resolve(process.cwd(), "native", `${bin}.node`));
|
|
121
|
+
candidates.push(path5.resolve(process.cwd(), "native", `${bin}.${napiPlatform}.node`));
|
|
122
|
+
}
|
|
177
123
|
return Array.from(new Set(candidates));
|
|
178
124
|
}
|
|
179
125
|
function resolveRuntimeDir(dir, importMetaUrl) {
|
|
180
|
-
if (
|
|
181
|
-
if (dir) return getNodePath().resolve(dir);
|
|
126
|
+
if (dir) return path5.resolve(dir);
|
|
182
127
|
try {
|
|
183
|
-
return
|
|
128
|
+
return path5.dirname(fileURLToPath(importMetaUrl));
|
|
184
129
|
} catch {
|
|
185
130
|
return process.cwd();
|
|
186
131
|
}
|
|
187
132
|
}
|
|
188
|
-
var
|
|
133
|
+
var TwError, _require;
|
|
189
134
|
var init_src = __esm({
|
|
190
135
|
"packages/domain/shared/src/index.ts"() {
|
|
191
|
-
isBrowser = typeof window !== "undefined" || typeof document !== "undefined";
|
|
192
|
-
nodeModuleRef = null;
|
|
193
|
-
_nodeFs = null;
|
|
194
|
-
_nodePath = null;
|
|
195
|
-
_nodeUrl = null;
|
|
196
136
|
TwError = class _TwError extends Error {
|
|
197
137
|
/** @deprecated Gunakan source */
|
|
198
138
|
domain;
|
|
@@ -226,8 +166,8 @@ var init_src = __esm({
|
|
|
226
166
|
/** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
|
|
227
167
|
static fromZod(err) {
|
|
228
168
|
const first = err.issues?.[0] ?? err.errors?.[0];
|
|
229
|
-
const
|
|
230
|
-
const message = first ? `${
|
|
169
|
+
const path8 = formatIssuePath(first?.path);
|
|
170
|
+
const message = first ? `${path8}: ${first.message}` : "Schema validation failed";
|
|
231
171
|
return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
|
|
232
172
|
}
|
|
233
173
|
static wrap(source, code, err) {
|
|
@@ -245,21 +185,33 @@ var init_src = __esm({
|
|
|
245
185
|
return `[${this.source.toUpperCase()}:${this.code}] ${this.message}`;
|
|
246
186
|
}
|
|
247
187
|
};
|
|
248
|
-
_require =
|
|
188
|
+
_require = createRequire(import.meta.url);
|
|
249
189
|
}
|
|
250
190
|
});
|
|
251
191
|
|
|
252
192
|
// packages/domain/scanner/src/native-bridge.ts
|
|
253
193
|
var native_bridge_exports = {};
|
|
254
194
|
__export(native_bridge_exports, {
|
|
195
|
+
batchExtractClassesNative: () => batchExtractClassesNative,
|
|
255
196
|
cachePriorityNative: () => cachePriorityNative,
|
|
256
197
|
cacheReadNative: () => cacheReadNative,
|
|
257
198
|
cacheWriteNative: () => cacheWriteNative,
|
|
199
|
+
collectFilesNative: () => collectFilesNative,
|
|
200
|
+
computeCacheStatsNative: () => computeCacheStatsNative,
|
|
258
201
|
extractClassesNative: () => extractClassesNative,
|
|
202
|
+
generateSubComponentTypesNative: () => generateSubComponentTypesNative,
|
|
259
203
|
hasNativeScannerBinding: () => hasNativeScannerBinding,
|
|
260
204
|
hashContentNative: () => hashContentNative,
|
|
261
205
|
isRustCacheAvailable: () => isRustCacheAvailable,
|
|
206
|
+
pruneStaleEntriesNative: () => pruneStaleEntriesNative,
|
|
207
|
+
rebuildWorkspaceResultNative: () => rebuildWorkspaceResultNative,
|
|
262
208
|
resetScannerBridgeCache: () => resetScannerBridgeCache,
|
|
209
|
+
scanCacheGet: () => scanCacheGet,
|
|
210
|
+
scanCacheInvalidate: () => scanCacheInvalidate,
|
|
211
|
+
scanCachePut: () => scanCachePut,
|
|
212
|
+
scanCacheStats: () => scanCacheStats,
|
|
213
|
+
scanFileNative: () => scanFileNative,
|
|
214
|
+
scanFilesBatchNative: () => scanFilesBatchNative,
|
|
263
215
|
scanWorkspaceNative: () => scanWorkspaceNative
|
|
264
216
|
});
|
|
265
217
|
function getDirname() {
|
|
@@ -267,7 +219,7 @@ function getDirname() {
|
|
|
267
219
|
return __dirname;
|
|
268
220
|
}
|
|
269
221
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
270
|
-
return
|
|
222
|
+
return path5.dirname(fileURLToPath(import.meta.url));
|
|
271
223
|
}
|
|
272
224
|
return process.cwd();
|
|
273
225
|
}
|
|
@@ -348,6 +300,95 @@ function cachePriorityNative(mtimeMs, size, cachedMtimeMs, cachedSize, cachedHit
|
|
|
348
300
|
}
|
|
349
301
|
return result;
|
|
350
302
|
}
|
|
303
|
+
function batchExtractClassesNative(filePaths) {
|
|
304
|
+
const binding = scannerGetBinding();
|
|
305
|
+
if (!binding.batchExtractClasses) {
|
|
306
|
+
throw new Error("FATAL: Native binding 'batchExtractClasses' is required but not available.");
|
|
307
|
+
}
|
|
308
|
+
return binding.batchExtractClasses(filePaths) ?? [];
|
|
309
|
+
}
|
|
310
|
+
function scanCacheGet(filePath, contentHash) {
|
|
311
|
+
const binding = scannerGetBinding();
|
|
312
|
+
if (!binding.scanCacheGet) {
|
|
313
|
+
throw new Error("FATAL: Native binding 'scanCacheGet' is required but not available.");
|
|
314
|
+
}
|
|
315
|
+
return binding.scanCacheGet(filePath, contentHash) ?? null;
|
|
316
|
+
}
|
|
317
|
+
function scanCachePut(filePath, contentHash, classes, mtimeMs, size) {
|
|
318
|
+
const binding = scannerGetBinding();
|
|
319
|
+
if (!binding.scanCachePut) {
|
|
320
|
+
throw new Error("FATAL: Native binding 'scanCachePut' is required but not available.");
|
|
321
|
+
}
|
|
322
|
+
binding.scanCachePut(filePath, contentHash, classes, mtimeMs, size);
|
|
323
|
+
}
|
|
324
|
+
function scanCacheInvalidate(filePath) {
|
|
325
|
+
const binding = scannerGetBinding();
|
|
326
|
+
if (!binding.scanCacheInvalidate) {
|
|
327
|
+
throw new Error("FATAL: Native binding 'scanCacheInvalidate' is required but not available.");
|
|
328
|
+
}
|
|
329
|
+
binding.scanCacheInvalidate(filePath);
|
|
330
|
+
}
|
|
331
|
+
function scanCacheStats() {
|
|
332
|
+
const binding = scannerGetBinding();
|
|
333
|
+
if (!binding.scanCacheStats) {
|
|
334
|
+
throw new Error("FATAL: Native binding 'scanCacheStats' is required but not available.");
|
|
335
|
+
}
|
|
336
|
+
return binding.scanCacheStats();
|
|
337
|
+
}
|
|
338
|
+
function scanFileNative(filePath) {
|
|
339
|
+
const binding = scannerGetBinding();
|
|
340
|
+
if (!binding.scanFile) {
|
|
341
|
+
throw new Error("FATAL: Native binding 'scanFile' is required but not available.");
|
|
342
|
+
}
|
|
343
|
+
return binding.scanFile(filePath);
|
|
344
|
+
}
|
|
345
|
+
function collectFilesNative(root, extensions, ignoreDirs) {
|
|
346
|
+
const binding = scannerGetBinding();
|
|
347
|
+
if (!binding.collectFiles) return null;
|
|
348
|
+
return binding.collectFiles(root, extensions, ignoreDirs);
|
|
349
|
+
}
|
|
350
|
+
function scanFilesBatchNative(filePaths) {
|
|
351
|
+
const binding = scannerGetBinding();
|
|
352
|
+
if (!binding.scanFilesBatch) {
|
|
353
|
+
return filePaths.map((fp) => {
|
|
354
|
+
try {
|
|
355
|
+
const r = binding.scanFile?.(fp);
|
|
356
|
+
return r ? { file: r.file, classes: r.classes, hash: r.hash ?? "" } : { file: fp, classes: [], hash: "" };
|
|
357
|
+
} catch {
|
|
358
|
+
return { file: fp, classes: [], hash: "" };
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
return binding.scanFilesBatch(filePaths);
|
|
363
|
+
}
|
|
364
|
+
function generateSubComponentTypesNative(root, outputPath) {
|
|
365
|
+
const binding = scannerGetBinding();
|
|
366
|
+
if (!binding.generateSubComponentTypes) return null;
|
|
367
|
+
return binding.generateSubComponentTypes(root, outputPath ?? null);
|
|
368
|
+
}
|
|
369
|
+
function pruneStaleEntriesNative(entries, maxAgeMs, checkExists) {
|
|
370
|
+
const binding = scannerGetBinding();
|
|
371
|
+
if (!binding.pruneStaleEntries) return null;
|
|
372
|
+
return binding.pruneStaleEntries(
|
|
373
|
+
entries.map((e) => ({ file: e.file, lastSeenMs: e.lastSeenMs ?? 0 })),
|
|
374
|
+
maxAgeMs ?? null,
|
|
375
|
+
checkExists ?? null
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
function rebuildWorkspaceResultNative(files) {
|
|
379
|
+
const binding = scannerBridgeLoader.get();
|
|
380
|
+
if (!binding?.rebuildWorkspaceResult) return null;
|
|
381
|
+
try {
|
|
382
|
+
return binding.rebuildWorkspaceResult(files);
|
|
383
|
+
} catch {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function computeCacheStatsNative(filesClasses, sizes, top) {
|
|
388
|
+
const binding = scannerGetBinding();
|
|
389
|
+
if (!binding.computeCacheStats) return null;
|
|
390
|
+
return binding.computeCacheStats(filesClasses, sizes, top ?? null);
|
|
391
|
+
}
|
|
351
392
|
var log, isValidScannerBinding, createScannerBridgeLoader, scannerBridgeLoader, scannerGetBinding, resetScannerBridgeCache;
|
|
352
393
|
var init_native_bridge = __esm({
|
|
353
394
|
"packages/domain/scanner/src/native-bridge.ts"() {
|
|
@@ -431,15 +472,9 @@ var init_native_bridge = __esm({
|
|
|
431
472
|
resetScannerBridgeCache = scannerBridgeLoader.reset;
|
|
432
473
|
}
|
|
433
474
|
});
|
|
434
|
-
|
|
435
|
-
// packages/domain/scanner/src/index.ts
|
|
436
|
-
init_src();
|
|
437
|
-
|
|
438
|
-
// packages/domain/scanner/src/cache-native.ts
|
|
439
|
-
init_native_bridge();
|
|
440
475
|
function defaultCachePath(rootDir, cacheDir) {
|
|
441
|
-
const dir = cacheDir ?
|
|
442
|
-
return
|
|
476
|
+
const dir = cacheDir ? path5.resolve(rootDir, cacheDir) : path5.join(process.cwd(), ".cache", "tailwind-styled");
|
|
477
|
+
return path5.join(dir, "scanner-cache.json");
|
|
443
478
|
}
|
|
444
479
|
function readCache(rootDir, cacheDir) {
|
|
445
480
|
const cachePath = defaultCachePath(rootDir, cacheDir);
|
|
@@ -475,158 +510,219 @@ function filePriority(mtimeMs, size, cached, nowMs = Date.now()) {
|
|
|
475
510
|
nowMs
|
|
476
511
|
);
|
|
477
512
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
init_native_bridge();
|
|
481
|
-
|
|
482
|
-
// packages/domain/scanner/src/schemas.ts
|
|
483
|
-
init_src();
|
|
484
|
-
var formatIssuePath2 = (path6) => path6.length > 0 ? path6.map(
|
|
485
|
-
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
486
|
-
).join(".") : "<root>";
|
|
487
|
-
var formatIssues = (error) => error.issues.map((issue) => {
|
|
488
|
-
const path6 = formatIssuePath2(issue.path);
|
|
489
|
-
return `${path6}: ${issue.message}`;
|
|
490
|
-
}).join("; ");
|
|
491
|
-
var parseWithSchema = (schema, data, label) => {
|
|
492
|
-
const parsed = schema.safeParse(data);
|
|
493
|
-
if (parsed.success) return parsed.data;
|
|
494
|
-
const details = formatIssues(parsed.error);
|
|
495
|
-
throw new TwError(
|
|
496
|
-
"validation",
|
|
497
|
-
"SCHEMA_VALIDATION_FAILED",
|
|
498
|
-
details ? `${label}: ${details}` : label,
|
|
499
|
-
parsed.error
|
|
500
|
-
);
|
|
501
|
-
};
|
|
502
|
-
var NonNegativeIntegerSchema = z.number().int().min(0);
|
|
503
|
-
var ScanWorkspaceOptionsSchema = z.object({
|
|
504
|
-
includeExtensions: z.array(z.string()).optional(),
|
|
505
|
-
ignoreDirectories: z.array(z.string()).optional(),
|
|
506
|
-
useCache: z.boolean().optional(),
|
|
507
|
-
cacheDir: z.string().min(1).optional(),
|
|
508
|
-
smartInvalidation: z.boolean().optional()
|
|
509
|
-
});
|
|
510
|
-
var ScanFileResultSchema = z.object({
|
|
511
|
-
file: z.string(),
|
|
512
|
-
classes: z.array(z.string()),
|
|
513
|
-
hash: z.string().optional()
|
|
514
|
-
});
|
|
515
|
-
var ScanWorkspaceResultSchema = z.object({
|
|
516
|
-
files: z.array(ScanFileResultSchema),
|
|
517
|
-
totalFiles: NonNegativeIntegerSchema,
|
|
518
|
-
uniqueClasses: z.array(z.string())
|
|
519
|
-
}).refine((value) => value.totalFiles === value.files.length, {
|
|
520
|
-
message: "scan result totalFiles must match files.length",
|
|
521
|
-
path: ["totalFiles"]
|
|
522
|
-
});
|
|
523
|
-
z.object({
|
|
524
|
-
rootDir: z.string().min(1),
|
|
525
|
-
options: ScanWorkspaceOptionsSchema.optional()
|
|
513
|
+
var init_cache_native = __esm({
|
|
514
|
+
"packages/domain/scanner/src/cache-native.ts"() {
|
|
515
|
+
init_native_bridge();
|
|
516
|
+
}
|
|
526
517
|
});
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
518
|
+
function collectFiles(rootDir, extensions, ignoreDirs) {
|
|
519
|
+
const native = collectFilesNative(rootDir, extensions, ignoreDirs);
|
|
520
|
+
if (native !== null) return native;
|
|
521
|
+
const files = [];
|
|
522
|
+
function walk(dir) {
|
|
523
|
+
let entries;
|
|
524
|
+
try {
|
|
525
|
+
entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
526
|
+
} catch {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
for (const entry of entries) {
|
|
530
|
+
const fullPath = path5.join(dir, entry.name);
|
|
531
|
+
const rel = path5.relative(rootDir, fullPath);
|
|
532
|
+
if (entry.isDirectory()) {
|
|
533
|
+
const ignored = ignoreDirs.some((d) => entry.name === d || rel.startsWith(d + path5.sep));
|
|
534
|
+
if (!ignored) walk(fullPath);
|
|
535
|
+
} else if (isScannableFile(entry.name, extensions)) {
|
|
536
|
+
files.push(fullPath);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
walk(rootDir);
|
|
541
|
+
return files;
|
|
542
|
+
}
|
|
543
|
+
function mergeResults(batchResults) {
|
|
544
|
+
const files = batchResults.map((r) => ({
|
|
545
|
+
file: r.file,
|
|
546
|
+
classes: r.classes,
|
|
547
|
+
hash: r.content_hash
|
|
548
|
+
}));
|
|
549
|
+
const native = rebuildWorkspaceResultNative(files);
|
|
550
|
+
if (native) return native;
|
|
551
|
+
const unique = new Set(files.flatMap((f) => f.classes));
|
|
552
|
+
return { files, totalFiles: files.length, uniqueClasses: Array.from(unique).sort() };
|
|
553
|
+
}
|
|
554
|
+
function runChunkInWorker(filePaths) {
|
|
555
|
+
return new Promise((resolve, reject) => {
|
|
556
|
+
const worker = new Worker(_workerFilename, {
|
|
557
|
+
workerData: { filePaths }
|
|
558
|
+
});
|
|
559
|
+
worker.once("message", (payload) => {
|
|
560
|
+
if (payload.ok) {
|
|
561
|
+
resolve(payload.results);
|
|
562
|
+
} else {
|
|
563
|
+
reject(new Error(payload.error ?? "parallel-scanner worker failed"));
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
worker.once("error", reject);
|
|
567
|
+
worker.once("exit", (code) => {
|
|
568
|
+
if (code !== 0) reject(new Error(`parallel-scanner worker exited with code ${code}`));
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
async function scanWorkspaceParallel(rootDir, options = {}) {
|
|
573
|
+
const {
|
|
574
|
+
extensions = DEFAULT_EXTENSIONS,
|
|
575
|
+
ignoreDirs = DEFAULT_IGNORES,
|
|
576
|
+
maxWorkers = Math.max(1, availableParallelism() - 1),
|
|
577
|
+
chunkSize = DEFAULT_CHUNK_SIZE
|
|
578
|
+
} = options;
|
|
579
|
+
const files = collectFiles(path5.resolve(rootDir), extensions, ignoreDirs);
|
|
580
|
+
if (files.length < PARALLEL_THRESHOLD) {
|
|
581
|
+
return mergeResults(batchExtractClassesNative(files));
|
|
582
|
+
}
|
|
583
|
+
const chunks = [];
|
|
584
|
+
for (let i = 0; i < files.length; i += chunkSize) {
|
|
585
|
+
chunks.push(files.slice(i, i + chunkSize));
|
|
586
|
+
}
|
|
587
|
+
const allResults = [];
|
|
588
|
+
for (let i = 0; i < chunks.length; i += maxWorkers) {
|
|
589
|
+
const batch = chunks.slice(i, i + maxWorkers);
|
|
590
|
+
const batchResults = await Promise.all(batch.map(runChunkInWorker));
|
|
591
|
+
allResults.push(...batchResults.flat());
|
|
592
|
+
}
|
|
593
|
+
return mergeResults(allResults);
|
|
594
|
+
}
|
|
595
|
+
var PARALLEL_THRESHOLD, DEFAULT_CHUNK_SIZE, _workerFilename;
|
|
596
|
+
var init_parallel_scanner = __esm({
|
|
597
|
+
"packages/domain/scanner/src/parallel-scanner.ts"() {
|
|
598
|
+
init_src2();
|
|
599
|
+
init_native_bridge();
|
|
600
|
+
PARALLEL_THRESHOLD = 50;
|
|
601
|
+
DEFAULT_CHUNK_SIZE = 150;
|
|
602
|
+
if (!isMainThread && parentPort) {
|
|
603
|
+
const { filePaths } = workerData;
|
|
604
|
+
try {
|
|
605
|
+
const results = batchExtractClassesNative(filePaths);
|
|
606
|
+
const msg = { ok: true, results };
|
|
607
|
+
parentPort.postMessage(msg);
|
|
608
|
+
} catch (error) {
|
|
609
|
+
const msg = {
|
|
610
|
+
ok: false,
|
|
611
|
+
error: error instanceof Error ? error.message : String(error)
|
|
612
|
+
};
|
|
613
|
+
parentPort.postMessage(msg);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
_workerFilename = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
|
|
617
|
+
}
|
|
530
618
|
});
|
|
531
|
-
var ScannerWorkerErrorMessageSchema
|
|
532
|
-
|
|
533
|
-
|
|
619
|
+
var formatIssuePath2, formatIssues, parseWithSchema, NonNegativeIntegerSchema, ScanWorkspaceOptionsSchema, ScanFileResultSchema, ScanWorkspaceResultSchema, ScannerWorkerSuccessMessageSchema, ScannerWorkerErrorMessageSchema, ScannerWorkerMessageSchema, parseScanWorkspaceOptions, parseScanWorkspaceResult, parseScannerWorkerMessage;
|
|
620
|
+
var init_schemas = __esm({
|
|
621
|
+
"packages/domain/scanner/src/schemas.ts"() {
|
|
622
|
+
init_src();
|
|
623
|
+
formatIssuePath2 = (path8) => path8.length > 0 ? path8.map(
|
|
624
|
+
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
625
|
+
).join(".") : "<root>";
|
|
626
|
+
formatIssues = (error) => error.issues.map((issue) => {
|
|
627
|
+
const path8 = formatIssuePath2(issue.path);
|
|
628
|
+
return `${path8}: ${issue.message}`;
|
|
629
|
+
}).join("; ");
|
|
630
|
+
parseWithSchema = (schema, data, label) => {
|
|
631
|
+
const parsed = schema.safeParse(data);
|
|
632
|
+
if (parsed.success) return parsed.data;
|
|
633
|
+
const details = formatIssues(parsed.error);
|
|
634
|
+
throw new TwError(
|
|
635
|
+
"validation",
|
|
636
|
+
"SCHEMA_VALIDATION_FAILED",
|
|
637
|
+
details ? `${label}: ${details}` : label,
|
|
638
|
+
parsed.error
|
|
639
|
+
);
|
|
640
|
+
};
|
|
641
|
+
NonNegativeIntegerSchema = z.number().int().min(0);
|
|
642
|
+
ScanWorkspaceOptionsSchema = z.object({
|
|
643
|
+
includeExtensions: z.array(z.string()).optional(),
|
|
644
|
+
ignoreDirectories: z.array(z.string()).optional(),
|
|
645
|
+
useCache: z.boolean().optional(),
|
|
646
|
+
cacheDir: z.string().min(1).optional(),
|
|
647
|
+
smartInvalidation: z.boolean().optional()
|
|
648
|
+
});
|
|
649
|
+
ScanFileResultSchema = z.object({
|
|
650
|
+
file: z.string(),
|
|
651
|
+
classes: z.array(z.string()),
|
|
652
|
+
hash: z.string().optional()
|
|
653
|
+
});
|
|
654
|
+
ScanWorkspaceResultSchema = z.object({
|
|
655
|
+
files: z.array(ScanFileResultSchema),
|
|
656
|
+
totalFiles: NonNegativeIntegerSchema,
|
|
657
|
+
uniqueClasses: z.array(z.string())
|
|
658
|
+
}).refine((value) => value.totalFiles === value.files.length, {
|
|
659
|
+
message: "scan result totalFiles must match files.length",
|
|
660
|
+
path: ["totalFiles"]
|
|
661
|
+
});
|
|
662
|
+
z.object({
|
|
663
|
+
rootDir: z.string().min(1),
|
|
664
|
+
options: ScanWorkspaceOptionsSchema.optional()
|
|
665
|
+
});
|
|
666
|
+
ScannerWorkerSuccessMessageSchema = z.object({
|
|
667
|
+
ok: z.literal(true),
|
|
668
|
+
result: ScanWorkspaceResultSchema
|
|
669
|
+
});
|
|
670
|
+
ScannerWorkerErrorMessageSchema = z.object({
|
|
671
|
+
ok: z.literal(false),
|
|
672
|
+
error: z.string().optional()
|
|
673
|
+
});
|
|
674
|
+
ScannerWorkerMessageSchema = z.union([
|
|
675
|
+
ScannerWorkerSuccessMessageSchema,
|
|
676
|
+
ScannerWorkerErrorMessageSchema
|
|
677
|
+
]);
|
|
678
|
+
parseScanWorkspaceOptions = (options) => parseWithSchema(ScanWorkspaceOptionsSchema, options ?? {}, "scanner options are invalid");
|
|
679
|
+
parseScanWorkspaceResult = (result) => parseWithSchema(ScanWorkspaceResultSchema, result, "scanner workspace result is invalid");
|
|
680
|
+
parseScannerWorkerMessage = (message) => parseWithSchema(ScannerWorkerMessageSchema, message, "scanner worker message is invalid");
|
|
681
|
+
}
|
|
534
682
|
});
|
|
535
|
-
var ScannerWorkerMessageSchema = z.union([
|
|
536
|
-
ScannerWorkerSuccessMessageSchema,
|
|
537
|
-
ScannerWorkerErrorMessageSchema
|
|
538
|
-
]);
|
|
539
|
-
var parseScanWorkspaceOptions = (options) => parseWithSchema(ScanWorkspaceOptionsSchema, options ?? {}, "scanner options are invalid");
|
|
540
|
-
var parseScanWorkspaceResult = (result) => parseWithSchema(ScanWorkspaceResultSchema, result, "scanner workspace result is invalid");
|
|
541
|
-
var parseScannerWorkerMessage = (message) => parseWithSchema(ScannerWorkerMessageSchema, message, "scanner worker message is invalid");
|
|
542
683
|
|
|
543
684
|
// packages/domain/scanner/src/index.ts
|
|
544
|
-
var
|
|
545
|
-
|
|
685
|
+
var src_exports = {};
|
|
686
|
+
__export(src_exports, {
|
|
687
|
+
DEFAULT_EXTENSIONS: () => DEFAULT_EXTENSIONS,
|
|
688
|
+
DEFAULT_IGNORES: () => DEFAULT_IGNORES,
|
|
689
|
+
batchExtractClassesNative: () => batchExtractClassesNative,
|
|
690
|
+
extractClassesNative: () => extractClassesNative,
|
|
691
|
+
isScannableFile: () => isScannableFile,
|
|
692
|
+
parseScanWorkspaceOptions: () => parseScanWorkspaceOptions,
|
|
693
|
+
parseScanWorkspaceResult: () => parseScanWorkspaceResult,
|
|
694
|
+
parseScannerWorkerMessage: () => parseScannerWorkerMessage,
|
|
695
|
+
scanFile: () => scanFile,
|
|
696
|
+
scanSource: () => scanSource,
|
|
697
|
+
scanWorkspace: () => scanWorkspace,
|
|
698
|
+
scanWorkspaceAsync: () => scanWorkspaceAsync
|
|
699
|
+
});
|
|
546
700
|
function getRuntimeDir() {
|
|
547
701
|
if (typeof __dirname !== "undefined" && __dirname.length > 0) {
|
|
548
702
|
return __dirname;
|
|
549
703
|
}
|
|
550
704
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
551
|
-
return
|
|
705
|
+
return path5.dirname(fileURLToPath(import.meta.url));
|
|
552
706
|
}
|
|
553
707
|
return process.cwd();
|
|
554
708
|
}
|
|
555
|
-
var createNativeParserLoader = () => {
|
|
556
|
-
const _state = {
|
|
557
|
-
binding: void 0,
|
|
558
|
-
initError: null
|
|
559
|
-
};
|
|
560
|
-
const debugNative = (message) => {
|
|
561
|
-
log2.debug(`[native] ${message}`);
|
|
562
|
-
};
|
|
563
|
-
const loadNativeParserBinding = () => {
|
|
564
|
-
if (_state.binding !== void 0) return _state.binding;
|
|
565
|
-
const runtimeDir = getRuntimeDir();
|
|
566
|
-
const req = createRequire(path3.join(runtimeDir, "noop.cjs"));
|
|
567
|
-
const candidates = [
|
|
568
|
-
path3.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
|
|
569
|
-
path3.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
|
|
570
|
-
path3.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
|
|
571
|
-
path3.resolve(
|
|
572
|
-
runtimeDir,
|
|
573
|
-
"..",
|
|
574
|
-
"..",
|
|
575
|
-
"..",
|
|
576
|
-
"native",
|
|
577
|
-
"build",
|
|
578
|
-
"Release",
|
|
579
|
-
"tailwind_styled_parser.node"
|
|
580
|
-
)
|
|
581
|
-
];
|
|
582
|
-
for (const fullPath of candidates) {
|
|
583
|
-
if (!fs.existsSync(fullPath)) continue;
|
|
584
|
-
try {
|
|
585
|
-
const required = req(fullPath);
|
|
586
|
-
if (required && (typeof required.extractClassesFromSource === "function" || typeof required.parseClasses === "function" || typeof required.parse_classes === "function")) {
|
|
587
|
-
_state.binding = required;
|
|
588
|
-
debugNative(`using native parser from ${fullPath}`);
|
|
589
|
-
return _state.binding;
|
|
590
|
-
}
|
|
591
|
-
} catch (error) {
|
|
592
|
-
_state.initError = error instanceof Error ? error.message : String(error);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
_state.binding = null;
|
|
596
|
-
if (!_state.initError) {
|
|
597
|
-
_state.initError = "native .node binding not found";
|
|
598
|
-
}
|
|
599
|
-
debugNative(`native binding not available: ${_state.initError}`);
|
|
600
|
-
return _state.binding;
|
|
601
|
-
};
|
|
602
|
-
return {
|
|
603
|
-
get: loadNativeParserBinding,
|
|
604
|
-
reset: () => {
|
|
605
|
-
_state.binding = void 0;
|
|
606
|
-
_state.initError = null;
|
|
607
|
-
}
|
|
608
|
-
};
|
|
609
|
-
};
|
|
610
|
-
var nativeParserLoader = createNativeParserLoader();
|
|
611
|
-
var DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
612
|
-
var DEFAULT_IGNORES = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
|
|
613
709
|
function resolveScannerWorkerModulePath() {
|
|
614
710
|
const runtimeDir = (() => {
|
|
615
711
|
if (typeof __dirname !== "undefined" && __dirname.length > 0) {
|
|
616
712
|
return __dirname;
|
|
617
713
|
}
|
|
618
714
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
619
|
-
return
|
|
715
|
+
return path5.dirname(fileURLToPath(import.meta.url));
|
|
620
716
|
}
|
|
621
717
|
return process.cwd();
|
|
622
718
|
})();
|
|
623
719
|
const candidates = [
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
720
|
+
path5.resolve(runtimeDir, "worker.cjs"),
|
|
721
|
+
path5.resolve(runtimeDir, "worker.js"),
|
|
722
|
+
path5.resolve(runtimeDir, "worker.ts")
|
|
627
723
|
];
|
|
628
724
|
for (const candidate of candidates) {
|
|
629
|
-
if (
|
|
725
|
+
if (fs3.existsSync(candidate)) return candidate;
|
|
630
726
|
}
|
|
631
727
|
return null;
|
|
632
728
|
}
|
|
@@ -683,19 +779,19 @@ function collectCandidates(rootDir, ignoreDirectories, extensionSet) {
|
|
|
683
779
|
if (!currentDir) continue;
|
|
684
780
|
const entries = (() => {
|
|
685
781
|
try {
|
|
686
|
-
return
|
|
782
|
+
return fs3.readdirSync(currentDir, { withFileTypes: true });
|
|
687
783
|
} catch {
|
|
688
784
|
return [];
|
|
689
785
|
}
|
|
690
786
|
})();
|
|
691
787
|
for (const entry of entries) {
|
|
692
|
-
const fullPath =
|
|
788
|
+
const fullPath = path5.join(currentDir, entry.name);
|
|
693
789
|
if (entry.isDirectory()) {
|
|
694
790
|
if (!ignoreDirectories.has(entry.name)) directories.push(fullPath);
|
|
695
791
|
continue;
|
|
696
792
|
}
|
|
697
793
|
if (!entry.isFile()) continue;
|
|
698
|
-
if (!extensionSet.has(
|
|
794
|
+
if (!extensionSet.has(path5.extname(entry.name))) continue;
|
|
699
795
|
candidates.push(fullPath);
|
|
700
796
|
}
|
|
701
797
|
}
|
|
@@ -709,22 +805,31 @@ function toCacheSize(size) {
|
|
|
709
805
|
function scanSource(source) {
|
|
710
806
|
const nativeBinding = nativeParserLoader.get();
|
|
711
807
|
if (nativeBinding?.extractClassesFromSource) {
|
|
712
|
-
const
|
|
713
|
-
if (Array.isArray(
|
|
714
|
-
return Array.from(new Set(
|
|
808
|
+
const result = nativeBinding.extractClassesFromSource(source);
|
|
809
|
+
if (Array.isArray(result)) {
|
|
810
|
+
return Array.from(new Set(result.filter(Boolean)));
|
|
811
|
+
}
|
|
812
|
+
if (result !== null && result !== void 0 && Array.isArray(result.classes)) {
|
|
813
|
+
return Array.from(new Set(result.classes.filter(Boolean)));
|
|
715
814
|
}
|
|
716
815
|
}
|
|
717
816
|
throw new Error(
|
|
718
817
|
"FATAL: Native parser binding is required but not available.\nThis package requires native Rust bindings.\n\nResolution steps:\n1. Build the native Rust module: npm run build:rust"
|
|
719
818
|
);
|
|
720
819
|
}
|
|
820
|
+
function isScannableFile(filePath, includeExtensions = DEFAULT_EXTENSIONS) {
|
|
821
|
+
return includeExtensions.includes(path5.extname(filePath));
|
|
822
|
+
}
|
|
721
823
|
function scanFile(filePath) {
|
|
722
|
-
const
|
|
723
|
-
const
|
|
824
|
+
const { scanFileNative: scanFileNative2 } = (init_native_bridge(), __toCommonJS(native_bridge_exports));
|
|
825
|
+
const result = scanFileNative2(filePath);
|
|
826
|
+
if (!result.ok) {
|
|
827
|
+
throw new Error(`scanFile failed for ${filePath}: ${result.error ?? "unknown error"}`);
|
|
828
|
+
}
|
|
724
829
|
return {
|
|
725
|
-
file:
|
|
726
|
-
classes:
|
|
727
|
-
...hash ? { hash } : {}
|
|
830
|
+
file: result.file,
|
|
831
|
+
classes: result.classes,
|
|
832
|
+
...result.hash ? { hash: result.hash } : {}
|
|
728
833
|
};
|
|
729
834
|
}
|
|
730
835
|
function scanWorkspace(rootDir, options = {}) {
|
|
@@ -773,7 +878,7 @@ function scanWorkspace(rootDir, options = {}) {
|
|
|
773
878
|
for (const filePath of candidates) {
|
|
774
879
|
const stat = (() => {
|
|
775
880
|
try {
|
|
776
|
-
return
|
|
881
|
+
return fs3.statSync(filePath);
|
|
777
882
|
} catch {
|
|
778
883
|
return null;
|
|
779
884
|
}
|
|
@@ -799,7 +904,7 @@ function scanWorkspace(rootDir, options = {}) {
|
|
|
799
904
|
for (const { filePath, stat, size, cached } of ranked) {
|
|
800
905
|
const content = (() => {
|
|
801
906
|
try {
|
|
802
|
-
return
|
|
907
|
+
return fs3.readFileSync(filePath, "utf8");
|
|
803
908
|
} catch {
|
|
804
909
|
return null;
|
|
805
910
|
}
|
|
@@ -861,18 +966,113 @@ function scanWorkspace(rootDir, options = {}) {
|
|
|
861
966
|
}
|
|
862
967
|
async function scanWorkspaceAsync(rootDir, options = {}) {
|
|
863
968
|
const normalizedOptions = parseScanWorkspaceOptions(options);
|
|
864
|
-
|
|
865
|
-
return
|
|
969
|
+
try {
|
|
970
|
+
return await scanWorkspaceParallel(rootDir, {
|
|
971
|
+
extensions: normalizedOptions.includeExtensions,
|
|
972
|
+
ignoreDirs: normalizedOptions.ignoreDirectories
|
|
973
|
+
});
|
|
974
|
+
} catch (parallelError) {
|
|
975
|
+
log2.debug(
|
|
976
|
+
`parallel scan failed, retrying with single worker: ${parallelError instanceof Error ? parallelError.message : String(parallelError)}`
|
|
977
|
+
);
|
|
866
978
|
}
|
|
867
979
|
try {
|
|
868
980
|
return await scanWorkspaceInWorker(rootDir, normalizedOptions);
|
|
869
981
|
} catch (error) {
|
|
870
982
|
log2.debug(
|
|
871
|
-
`worker scan failed,
|
|
983
|
+
`worker scan failed, retrying with sync native scanner: ${error instanceof Error ? error.message : String(error)}`
|
|
872
984
|
);
|
|
873
985
|
return scanWorkspace(rootDir, normalizedOptions);
|
|
874
986
|
}
|
|
875
987
|
}
|
|
988
|
+
var log2, SCAN_WORKER_TIMEOUT_MS, createNativeParserLoader, nativeParserLoader, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
|
|
989
|
+
var init_src2 = __esm({
|
|
990
|
+
"packages/domain/scanner/src/index.ts"() {
|
|
991
|
+
init_src();
|
|
992
|
+
init_cache_native();
|
|
993
|
+
init_native_bridge();
|
|
994
|
+
init_parallel_scanner();
|
|
995
|
+
init_schemas();
|
|
996
|
+
init_schemas();
|
|
997
|
+
init_native_bridge();
|
|
998
|
+
log2 = createLogger("scanner");
|
|
999
|
+
SCAN_WORKER_TIMEOUT_MS = 12e4;
|
|
1000
|
+
createNativeParserLoader = () => {
|
|
1001
|
+
const _state = {
|
|
1002
|
+
binding: void 0,
|
|
1003
|
+
initError: null
|
|
1004
|
+
};
|
|
1005
|
+
const debugNative = (message) => {
|
|
1006
|
+
log2.debug(`[native] ${message}`);
|
|
1007
|
+
};
|
|
1008
|
+
const loadNativeParserBinding = () => {
|
|
1009
|
+
if (_state.binding !== void 0) return _state.binding;
|
|
1010
|
+
const runtimeDir = getRuntimeDir();
|
|
1011
|
+
const req = createRequire(path5.join(runtimeDir, "noop.cjs"));
|
|
1012
|
+
const candidates = [
|
|
1013
|
+
// ── binaryName baru: tailwind-styled-native (napi-rs naming) ──
|
|
1014
|
+
// cwd = repo root saat run dari root, atau package dir saat workspaces
|
|
1015
|
+
path5.resolve(process.cwd(), "native", "tailwind-styled-native.node"),
|
|
1016
|
+
path5.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}.node`),
|
|
1017
|
+
path5.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
|
|
1018
|
+
// runtimeDir = dist/ → naik 4 level ke repo root
|
|
1019
|
+
path5.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind-styled-native.node"),
|
|
1020
|
+
path5.resolve(runtimeDir, "..", "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
|
|
1021
|
+
// 3 level fallback (jika package di-nest lebih dangkal)
|
|
1022
|
+
path5.resolve(runtimeDir, "..", "..", "..", "native", "tailwind-styled-native.node"),
|
|
1023
|
+
path5.resolve(runtimeDir, "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
|
|
1024
|
+
// ── binaryName lama: tailwind_styled_parser (backward compat) ──
|
|
1025
|
+
path5.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
|
|
1026
|
+
path5.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
|
|
1027
|
+
path5.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind_styled_parser.node"),
|
|
1028
|
+
path5.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
|
|
1029
|
+
path5.resolve(
|
|
1030
|
+
runtimeDir,
|
|
1031
|
+
"..",
|
|
1032
|
+
"..",
|
|
1033
|
+
"..",
|
|
1034
|
+
"native",
|
|
1035
|
+
"build",
|
|
1036
|
+
"Release",
|
|
1037
|
+
"tailwind_styled_parser.node"
|
|
1038
|
+
)
|
|
1039
|
+
];
|
|
1040
|
+
for (const fullPath of candidates) {
|
|
1041
|
+
if (!fs3.existsSync(fullPath)) continue;
|
|
1042
|
+
try {
|
|
1043
|
+
const required = req(fullPath);
|
|
1044
|
+
if (required && (typeof required.extractClassesFromSource === "function" || typeof required.parseClasses === "function" || typeof required.parse_classes === "function")) {
|
|
1045
|
+
_state.binding = required;
|
|
1046
|
+
debugNative(`using native parser from ${fullPath}`);
|
|
1047
|
+
return _state.binding;
|
|
1048
|
+
}
|
|
1049
|
+
} catch (error) {
|
|
1050
|
+
_state.initError = error instanceof Error ? error.message : String(error);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
_state.binding = null;
|
|
1054
|
+
if (!_state.initError) {
|
|
1055
|
+
_state.initError = "native .node binding not found";
|
|
1056
|
+
}
|
|
1057
|
+
debugNative(`native binding not available: ${_state.initError}`);
|
|
1058
|
+
return _state.binding;
|
|
1059
|
+
};
|
|
1060
|
+
return {
|
|
1061
|
+
get: loadNativeParserBinding,
|
|
1062
|
+
reset: () => {
|
|
1063
|
+
_state.binding = void 0;
|
|
1064
|
+
_state.initError = null;
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
1067
|
+
};
|
|
1068
|
+
nativeParserLoader = createNativeParserLoader();
|
|
1069
|
+
DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1070
|
+
DEFAULT_IGNORES = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// packages/domain/analyzer/src/analyzeWorkspace.ts
|
|
1075
|
+
init_src2();
|
|
876
1076
|
|
|
877
1077
|
// packages/domain/analyzer/src/binding.ts
|
|
878
1078
|
init_src();
|
|
@@ -892,7 +1092,7 @@ function isRecord(value) {
|
|
|
892
1092
|
}
|
|
893
1093
|
async function pathExists(filePath) {
|
|
894
1094
|
try {
|
|
895
|
-
await
|
|
1095
|
+
await fs3.promises.access(filePath, fs3.constants.F_OK);
|
|
896
1096
|
return true;
|
|
897
1097
|
} catch {
|
|
898
1098
|
return false;
|
|
@@ -955,6 +1155,9 @@ var createAnalyzerBindingLoader = () => {
|
|
|
955
1155
|
};
|
|
956
1156
|
};
|
|
957
1157
|
var analyzerBindingLoader = createAnalyzerBindingLoader();
|
|
1158
|
+
async function getNativeBinding() {
|
|
1159
|
+
return analyzerBindingLoader.get();
|
|
1160
|
+
}
|
|
958
1161
|
async function requireNativeBinding() {
|
|
959
1162
|
const binding = await analyzerBindingLoader.get();
|
|
960
1163
|
if (binding?.analyzeClasses) return binding;
|
|
@@ -993,7 +1196,7 @@ async function requireNativeCssCompiler() {
|
|
|
993
1196
|
|
|
994
1197
|
// packages/domain/analyzer/src/schemas.ts
|
|
995
1198
|
init_src();
|
|
996
|
-
var formatIssuePath3 = (
|
|
1199
|
+
var formatIssuePath3 = (path8) => path8.length > 0 ? path8.map(
|
|
997
1200
|
(segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
|
|
998
1201
|
).join(".") : "<root>";
|
|
999
1202
|
var isPlainObject = (value) => {
|
|
@@ -1002,8 +1205,8 @@ var isPlainObject = (value) => {
|
|
|
1002
1205
|
return proto === Object.prototype || proto === null;
|
|
1003
1206
|
};
|
|
1004
1207
|
var formatIssues2 = (error) => error.issues.map((issue) => {
|
|
1005
|
-
const
|
|
1006
|
-
return `${
|
|
1208
|
+
const path8 = formatIssuePath3(issue.path);
|
|
1209
|
+
return `${path8}: ${issue.message}`;
|
|
1007
1210
|
}).join("; ");
|
|
1008
1211
|
var parseWithSchema2 = (schema, data, label) => {
|
|
1009
1212
|
const parsed = schema.safeParse(data);
|
|
@@ -1098,112 +1301,6 @@ var parseNativeCssCompileResult = (result, className) => parseWithSchema2(
|
|
|
1098
1301
|
);
|
|
1099
1302
|
var parseClassToCssOptions = (options) => parseWithSchema2(ClassToCssOptionsSchema, options ?? {}, "classToCss options are invalid");
|
|
1100
1303
|
var SUPPORTED_TAILWIND_CONFIG_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".cjs", ".mjs"]);
|
|
1101
|
-
var KNOWN_UTILITY_PREFIXES = /* @__PURE__ */ new Set([
|
|
1102
|
-
"absolute",
|
|
1103
|
-
"align",
|
|
1104
|
-
"animate",
|
|
1105
|
-
"arbitrary",
|
|
1106
|
-
"aspect",
|
|
1107
|
-
"backdrop",
|
|
1108
|
-
"basis",
|
|
1109
|
-
"bg",
|
|
1110
|
-
"block",
|
|
1111
|
-
"border",
|
|
1112
|
-
"bottom",
|
|
1113
|
-
"col",
|
|
1114
|
-
"container",
|
|
1115
|
-
"contents",
|
|
1116
|
-
"cursor",
|
|
1117
|
-
"dark",
|
|
1118
|
-
"display",
|
|
1119
|
-
"divide",
|
|
1120
|
-
"fill",
|
|
1121
|
-
"fixed",
|
|
1122
|
-
"flex",
|
|
1123
|
-
"float",
|
|
1124
|
-
"font",
|
|
1125
|
-
"from",
|
|
1126
|
-
"gap",
|
|
1127
|
-
"grid",
|
|
1128
|
-
"grow",
|
|
1129
|
-
"h",
|
|
1130
|
-
"hidden",
|
|
1131
|
-
"inset",
|
|
1132
|
-
"inline",
|
|
1133
|
-
"isolate",
|
|
1134
|
-
"items",
|
|
1135
|
-
"justify",
|
|
1136
|
-
"left",
|
|
1137
|
-
"leading",
|
|
1138
|
-
"line",
|
|
1139
|
-
"list",
|
|
1140
|
-
"m",
|
|
1141
|
-
"max-h",
|
|
1142
|
-
"max-w",
|
|
1143
|
-
"mb",
|
|
1144
|
-
"min-h",
|
|
1145
|
-
"min-w",
|
|
1146
|
-
"ml",
|
|
1147
|
-
"mr",
|
|
1148
|
-
"mt",
|
|
1149
|
-
"mx",
|
|
1150
|
-
"my",
|
|
1151
|
-
"object",
|
|
1152
|
-
"opacity",
|
|
1153
|
-
"order",
|
|
1154
|
-
"origin",
|
|
1155
|
-
"outline",
|
|
1156
|
-
"overflow",
|
|
1157
|
-
"overscroll",
|
|
1158
|
-
"p",
|
|
1159
|
-
"pb",
|
|
1160
|
-
"pe",
|
|
1161
|
-
"perspective",
|
|
1162
|
-
"place",
|
|
1163
|
-
"pl",
|
|
1164
|
-
"pointer",
|
|
1165
|
-
"position",
|
|
1166
|
-
"pr",
|
|
1167
|
-
"ps",
|
|
1168
|
-
"pt",
|
|
1169
|
-
"px",
|
|
1170
|
-
"py",
|
|
1171
|
-
"relative",
|
|
1172
|
-
"right",
|
|
1173
|
-
"ring",
|
|
1174
|
-
"rotate",
|
|
1175
|
-
"rounded",
|
|
1176
|
-
"row",
|
|
1177
|
-
"scale",
|
|
1178
|
-
"shadow",
|
|
1179
|
-
"shrink",
|
|
1180
|
-
"size",
|
|
1181
|
-
"skew",
|
|
1182
|
-
"snap",
|
|
1183
|
-
"space-x",
|
|
1184
|
-
"space-y",
|
|
1185
|
-
"sr",
|
|
1186
|
-
"start",
|
|
1187
|
-
"static",
|
|
1188
|
-
"sticky",
|
|
1189
|
-
"stroke",
|
|
1190
|
-
"table",
|
|
1191
|
-
"text",
|
|
1192
|
-
"to",
|
|
1193
|
-
"top",
|
|
1194
|
-
"touch",
|
|
1195
|
-
"tracking",
|
|
1196
|
-
"transform",
|
|
1197
|
-
"transition",
|
|
1198
|
-
"translate",
|
|
1199
|
-
"truncate",
|
|
1200
|
-
"underline",
|
|
1201
|
-
"via",
|
|
1202
|
-
"visible",
|
|
1203
|
-
"w",
|
|
1204
|
-
"whitespace",
|
|
1205
|
-
"z"
|
|
1206
|
-
]);
|
|
1207
1304
|
var tailwindConfigCache = /* @__PURE__ */ new Map();
|
|
1208
1305
|
var splitVariantAndBase = (className) => {
|
|
1209
1306
|
const parts = className.split(":");
|
|
@@ -1233,48 +1330,28 @@ var resolveConflictGroup = (base) => {
|
|
|
1233
1330
|
if (base.startsWith("m-") || base.startsWith("mx-") || base.startsWith("my-")) return "margin";
|
|
1234
1331
|
return null;
|
|
1235
1332
|
};
|
|
1236
|
-
var detectConflicts = (usages) => {
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
const group = resolveConflictGroup(base);
|
|
1241
|
-
if (!group) continue;
|
|
1242
|
-
const key = `${variantKey}::${group}`;
|
|
1243
|
-
const bucket = buckets.get(key) ?? {
|
|
1244
|
-
variantKey,
|
|
1245
|
-
group,
|
|
1246
|
-
classes: /* @__PURE__ */ new Set()
|
|
1247
|
-
};
|
|
1248
|
-
bucket.classes.add(usage.name);
|
|
1249
|
-
buckets.set(key, bucket);
|
|
1250
|
-
}
|
|
1251
|
-
const conflicts = [];
|
|
1252
|
-
const conflictedClassNames = /* @__PURE__ */ new Set();
|
|
1253
|
-
for (const bucket of buckets.values()) {
|
|
1254
|
-
if (bucket.classes.size <= 1) continue;
|
|
1255
|
-
const classes = Array.from(bucket.classes).sort();
|
|
1256
|
-
for (const className of classes) conflictedClassNames.add(className);
|
|
1257
|
-
const variantLabel = bucket.variantKey.length > 0 ? bucket.variantKey : "base";
|
|
1258
|
-
conflicts.push({
|
|
1259
|
-
className: bucket.group,
|
|
1260
|
-
variants: bucket.variantKey.length > 0 ? bucket.variantKey.split(":") : [],
|
|
1261
|
-
classes,
|
|
1262
|
-
message: `Multiple ${bucket.group} utilities detected for "${variantLabel}".`
|
|
1263
|
-
});
|
|
1333
|
+
var detectConflicts = async (usages) => {
|
|
1334
|
+
const native = await getNativeBinding();
|
|
1335
|
+
if (!native?.detectClassConflicts) {
|
|
1336
|
+
throw new Error("FATAL: Native binding 'detectClassConflicts' is required but not available.");
|
|
1264
1337
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1338
|
+
const result = native.detectClassConflicts(JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count }))));
|
|
1339
|
+
return {
|
|
1340
|
+
conflicts: result.conflicts.map((c) => ({
|
|
1341
|
+
className: c.group,
|
|
1342
|
+
variants: c.variantKey.length > 0 ? c.variantKey.split(":") : [],
|
|
1343
|
+
classes: c.classes,
|
|
1344
|
+
message: c.message
|
|
1345
|
+
})),
|
|
1346
|
+
conflictedClassNames: new Set(result.conflictedClassNames)
|
|
1347
|
+
};
|
|
1271
1348
|
};
|
|
1272
1349
|
var isSupportedTailwindConfigPath = (configPath) => {
|
|
1273
|
-
return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(
|
|
1350
|
+
return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path5.extname(configPath).toLowerCase());
|
|
1274
1351
|
};
|
|
1275
1352
|
var resolveTailwindConfigPath = async (root, explicitPath) => {
|
|
1276
1353
|
if (explicitPath) {
|
|
1277
|
-
const resolved =
|
|
1354
|
+
const resolved = path5.resolve(root, explicitPath);
|
|
1278
1355
|
if (!await pathExists(resolved)) return null;
|
|
1279
1356
|
return resolved;
|
|
1280
1357
|
}
|
|
@@ -1285,7 +1362,7 @@ var resolveTailwindConfigPath = async (root, explicitPath) => {
|
|
|
1285
1362
|
"tailwind.config.mjs"
|
|
1286
1363
|
];
|
|
1287
1364
|
for (const candidate of candidates) {
|
|
1288
|
-
const fullPath =
|
|
1365
|
+
const fullPath = path5.resolve(root, candidate);
|
|
1289
1366
|
if (await pathExists(fullPath)) return fullPath;
|
|
1290
1367
|
}
|
|
1291
1368
|
return null;
|
|
@@ -1339,15 +1416,19 @@ var collectCustomUtilities = (config) => {
|
|
|
1339
1416
|
return out;
|
|
1340
1417
|
};
|
|
1341
1418
|
var collectSafelistFromSource = async (configPath) => {
|
|
1342
|
-
const source = await
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
const
|
|
1346
|
-
|
|
1419
|
+
const source = await fs3.promises.readFile(configPath, "utf8");
|
|
1420
|
+
const { extractClassesNative: extractClassesNative2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
1421
|
+
const allTokens = extractClassesNative2(source);
|
|
1422
|
+
const hasSafelist = source.includes("safelist");
|
|
1423
|
+
if (!hasSafelist) return [];
|
|
1424
|
+
const safelistMatch = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
|
|
1425
|
+
if (!safelistMatch) return [];
|
|
1426
|
+
const safelistSet = /* @__PURE__ */ new Set();
|
|
1427
|
+
for (const token of safelistMatch.matchAll(/["'`]([^"'`]+)["'`]/g)) {
|
|
1347
1428
|
const value = token[1].trim();
|
|
1348
|
-
if (value.length > 0)
|
|
1429
|
+
if (value.length > 0) safelistSet.add(value);
|
|
1349
1430
|
}
|
|
1350
|
-
return
|
|
1431
|
+
return allTokens.filter((t) => safelistSet.has(t));
|
|
1351
1432
|
};
|
|
1352
1433
|
var loadTailwindConfig = async (root, semanticOption) => {
|
|
1353
1434
|
const startMs = Date.now();
|
|
@@ -1362,7 +1443,7 @@ var loadTailwindConfig = async (root, semanticOption) => {
|
|
|
1362
1443
|
customUtilities: /* @__PURE__ */ new Set()
|
|
1363
1444
|
};
|
|
1364
1445
|
}
|
|
1365
|
-
const configStat = await
|
|
1446
|
+
const configStat = await fs3.promises.stat(configPath).catch(() => null);
|
|
1366
1447
|
if (configStat) {
|
|
1367
1448
|
const cached = tailwindConfigCache.get(configPath);
|
|
1368
1449
|
if (cached && cached.mtimeMs === configStat.mtimeMs && cached.size === configStat.size) {
|
|
@@ -1448,21 +1529,27 @@ var utilityPrefix = (baseClass) => {
|
|
|
1448
1529
|
if (hyphen < 0) return normalized;
|
|
1449
1530
|
return normalized.slice(0, hyphen);
|
|
1450
1531
|
};
|
|
1451
|
-
var isKnownTailwindClass = (className, safelist, customUtilities) => {
|
|
1452
|
-
if (safelist.has(className) || customUtilities.has(className)) return true;
|
|
1453
|
-
const { base } = splitVariantAndBase(className);
|
|
1454
|
-
if (customUtilities.has(base)) return true;
|
|
1455
|
-
const prefix = utilityPrefix(base);
|
|
1456
|
-
return KNOWN_UTILITY_PREFIXES.has(prefix);
|
|
1457
|
-
};
|
|
1458
1532
|
var buildSemanticReport = async (usages, root, semanticOption) => {
|
|
1459
1533
|
const loadedConfig = await loadTailwindConfig(root, semanticOption);
|
|
1460
1534
|
const safelist = loadedConfig?.safelist ?? /* @__PURE__ */ new Set();
|
|
1461
1535
|
const customUtilities = loadedConfig?.customUtilities ?? /* @__PURE__ */ new Set();
|
|
1462
1536
|
const usageNames = new Set(usages.map((usage) => usage.name));
|
|
1463
1537
|
const unusedClasses = Array.from(safelist).filter((className) => !usageNames.has(className)).sort().map((className) => ({ name: className, count: 0, isUnused: true }));
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1538
|
+
const native = await getNativeBinding();
|
|
1539
|
+
if (!native?.classifyKnownClasses) {
|
|
1540
|
+
throw new Error("FATAL: Native binding 'classifyKnownClasses' is required but not available.");
|
|
1541
|
+
}
|
|
1542
|
+
const classNames = usages.map((u) => u.name);
|
|
1543
|
+
const results = native.classifyKnownClasses(
|
|
1544
|
+
classNames,
|
|
1545
|
+
Array.from(safelist),
|
|
1546
|
+
Array.from(customUtilities)
|
|
1547
|
+
);
|
|
1548
|
+
const unknownSet = new Set(
|
|
1549
|
+
results.filter((r) => !r.isKnown).map((r) => r.className)
|
|
1550
|
+
);
|
|
1551
|
+
const unknownClasses = usages.filter((usage) => unknownSet.has(usage.name)).map((usage) => ({ ...usage, isUnused: true }));
|
|
1552
|
+
const { conflicts } = await detectConflicts(usages);
|
|
1466
1553
|
return {
|
|
1467
1554
|
unusedClasses,
|
|
1468
1555
|
unknownClasses,
|
|
@@ -1498,13 +1585,17 @@ function normalizeScan(scan, includeClass) {
|
|
|
1498
1585
|
uniqueClasses: Array.from(unique).sort()
|
|
1499
1586
|
};
|
|
1500
1587
|
}
|
|
1501
|
-
function collectClassCounts(scan) {
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
counts.set(className, (counts.get(className) ?? 0) + 1);
|
|
1506
|
-
}
|
|
1588
|
+
async function collectClassCounts(scan) {
|
|
1589
|
+
const native = await requireNativeBinding();
|
|
1590
|
+
if (!native?.collectClassCounts) {
|
|
1591
|
+
throw new Error("FATAL: Native binding 'collectClassCounts' is required but not available.");
|
|
1507
1592
|
}
|
|
1593
|
+
const filesJson = JSON.stringify(
|
|
1594
|
+
scan.files.map((f) => ({ file: f.file ?? "", classes: f.classes }))
|
|
1595
|
+
);
|
|
1596
|
+
const result = native.collectClassCounts(filesJson);
|
|
1597
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1598
|
+
for (const entry of result) counts.set(entry.name, entry.count);
|
|
1508
1599
|
return counts;
|
|
1509
1600
|
}
|
|
1510
1601
|
function buildClassUsage(counts) {
|
|
@@ -1513,29 +1604,24 @@ function buildClassUsage(counts) {
|
|
|
1513
1604
|
return left.name.localeCompare(right.name);
|
|
1514
1605
|
});
|
|
1515
1606
|
}
|
|
1516
|
-
function buildDistribution(usages) {
|
|
1517
|
-
const
|
|
1518
|
-
|
|
1519
|
-
"
|
|
1520
|
-
"4-7": 0,
|
|
1521
|
-
"8+": 0
|
|
1522
|
-
};
|
|
1523
|
-
for (const usage of usages) {
|
|
1524
|
-
if (usage.count === 1) {
|
|
1525
|
-
distribution["1"] += 1;
|
|
1526
|
-
} else if (usage.count <= 3) {
|
|
1527
|
-
distribution["2-3"] += 1;
|
|
1528
|
-
} else if (usage.count <= 7) {
|
|
1529
|
-
distribution["4-7"] += 1;
|
|
1530
|
-
} else {
|
|
1531
|
-
distribution["8+"] += 1;
|
|
1532
|
-
}
|
|
1607
|
+
async function buildDistribution(usages, native) {
|
|
1608
|
+
const binding = native ?? await requireNativeBinding();
|
|
1609
|
+
if (!binding?.buildDistribution) {
|
|
1610
|
+
throw new Error("FATAL: Native binding 'buildDistribution' is required but not available.");
|
|
1533
1611
|
}
|
|
1534
|
-
|
|
1612
|
+
const result = binding.buildDistribution(
|
|
1613
|
+
JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count })))
|
|
1614
|
+
);
|
|
1615
|
+
return {
|
|
1616
|
+
"1": result.once,
|
|
1617
|
+
"2-3": result.few,
|
|
1618
|
+
"4-7": result.moderate,
|
|
1619
|
+
"8+": result.frequent
|
|
1620
|
+
};
|
|
1535
1621
|
}
|
|
1536
1622
|
async function analyzeWorkspace(root, options = {}) {
|
|
1537
1623
|
const startedAtMs = Date.now();
|
|
1538
|
-
const resolvedRoot =
|
|
1624
|
+
const resolvedRoot = path5.resolve(root);
|
|
1539
1625
|
const normalizedOptions = parseAnalyzerOptions(options);
|
|
1540
1626
|
const scan = await (async () => {
|
|
1541
1627
|
const scanStartedAtMs = Date.now();
|
|
@@ -1579,7 +1665,7 @@ async function analyzeWorkspace(root, options = {}) {
|
|
|
1579
1665
|
);
|
|
1580
1666
|
}
|
|
1581
1667
|
})();
|
|
1582
|
-
const counts = collectClassCounts(normalizedScan);
|
|
1668
|
+
const counts = await collectClassCounts(normalizedScan);
|
|
1583
1669
|
const baseAll = buildClassUsage(counts);
|
|
1584
1670
|
const { all, semanticReport } = await (async () => {
|
|
1585
1671
|
if (!normalizedOptions.semantic) {
|
|
@@ -1605,13 +1691,19 @@ async function analyzeWorkspace(root, options = {}) {
|
|
|
1605
1691
|
);
|
|
1606
1692
|
}
|
|
1607
1693
|
})();
|
|
1608
|
-
const
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1694
|
+
const classStatsNative = binding?.computeClassStats?.(
|
|
1695
|
+
JSON.stringify(all),
|
|
1696
|
+
topLimit,
|
|
1697
|
+
frequentThreshold
|
|
1698
|
+
);
|
|
1699
|
+
const top = classStatsNative ? JSON.parse(classStatsNative.topJson) : all.slice(0, topLimit);
|
|
1700
|
+
const frequent = classStatsNative ? JSON.parse(classStatsNative.frequentJson) : all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
|
|
1701
|
+
const unique = classStatsNative ? JSON.parse(classStatsNative.uniqueJson) : all.filter((usage) => usage.count === 1);
|
|
1702
|
+
const totalClassOccurrences = classStatsNative ? classStatsNative.totalClassOccurrences : all.reduce((sum, usage) => sum + usage.count, 0);
|
|
1612
1703
|
debugLog(
|
|
1613
1704
|
`analyzeWorkspace completed in ${Date.now() - startedAtMs}ms (files=${normalizedScan.totalFiles}, uniqueClasses=${all.length})`
|
|
1614
1705
|
);
|
|
1706
|
+
const distribution = await buildDistribution(all, binding);
|
|
1615
1707
|
return {
|
|
1616
1708
|
root: nativeReport.root || resolvedRoot,
|
|
1617
1709
|
totalFiles: nativeReport.totalFiles,
|
|
@@ -1622,16 +1714,21 @@ async function analyzeWorkspace(root, options = {}) {
|
|
|
1622
1714
|
top,
|
|
1623
1715
|
frequent,
|
|
1624
1716
|
unique,
|
|
1625
|
-
distribution
|
|
1717
|
+
distribution
|
|
1626
1718
|
},
|
|
1719
|
+
// topClasses — alias for classStats.top (test contract & backward compat)
|
|
1720
|
+
topClasses: top,
|
|
1627
1721
|
safelist: all.map((usage) => usage.name),
|
|
1628
1722
|
...semanticReport ? { semantic: semanticReport } : {}
|
|
1629
1723
|
};
|
|
1630
1724
|
}
|
|
1631
1725
|
|
|
1632
1726
|
// packages/domain/analyzer/src/classToCss.ts
|
|
1633
|
-
var normalizeClassInput = (input) => {
|
|
1727
|
+
var normalizeClassInput = (input, _binding) => {
|
|
1634
1728
|
if (typeof input === "string") {
|
|
1729
|
+
if (_binding?.normalizeClassInput) {
|
|
1730
|
+
return _binding.normalizeClassInput(input);
|
|
1731
|
+
}
|
|
1635
1732
|
return input.split(/\s+/).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
1636
1733
|
}
|
|
1637
1734
|
if (!Array.isArray(input)) {
|
|
@@ -1653,27 +1750,26 @@ var normalizeClassToCssOptions = (options) => {
|
|
|
1653
1750
|
const prefix = parsed.prefix ?? null;
|
|
1654
1751
|
return { prefix, strict };
|
|
1655
1752
|
};
|
|
1656
|
-
var mergeDeclarationMap = (target, css) => {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
const property = declaration.slice(0, colonIndex).trim();
|
|
1665
|
-
const value = declaration.slice(colonIndex + 1).trim();
|
|
1666
|
-
if (property.length === 0 || value.length === 0) continue;
|
|
1667
|
-
if (target.has(property)) target.delete(property);
|
|
1668
|
-
target.set(property, value);
|
|
1669
|
-
}
|
|
1753
|
+
var mergeDeclarationMap = (target, css, binding) => {
|
|
1754
|
+
if (!binding.parseCssRules) {
|
|
1755
|
+
throw new Error("FATAL: Native binding 'parseCssRules' is required but not available.");
|
|
1756
|
+
}
|
|
1757
|
+
const rules = binding.parseCssRules(css);
|
|
1758
|
+
for (const rule of rules) {
|
|
1759
|
+
if (target.has(rule.property)) target.delete(rule.property);
|
|
1760
|
+
target.set(rule.property, rule.isImportant ? `${rule.value} !important` : rule.value);
|
|
1670
1761
|
}
|
|
1671
1762
|
};
|
|
1672
|
-
var declarationMapToString = (declarationMap) => {
|
|
1673
|
-
|
|
1763
|
+
var declarationMapToString = (declarationMap, binding) => {
|
|
1764
|
+
const entries = Array.from(declarationMap.entries()).map(([property, value]) => ({ property, value }));
|
|
1765
|
+
if (binding?.declarationMapToString) {
|
|
1766
|
+
return binding.declarationMapToString(entries);
|
|
1767
|
+
}
|
|
1768
|
+
return entries.map(({ property, value }) => `${property}: ${value}`).join("; ");
|
|
1674
1769
|
};
|
|
1675
1770
|
var classToCss = async (input, options = {}) => {
|
|
1676
|
-
const
|
|
1771
|
+
const binding = await requireNativeCssCompiler();
|
|
1772
|
+
const inputClasses = normalizeClassInput(input, binding);
|
|
1677
1773
|
const normalizedOptions = normalizeClassToCssOptions(options);
|
|
1678
1774
|
if (inputClasses.length === 0) {
|
|
1679
1775
|
return {
|
|
@@ -1685,7 +1781,6 @@ var classToCss = async (input, options = {}) => {
|
|
|
1685
1781
|
sizeBytes: 0
|
|
1686
1782
|
};
|
|
1687
1783
|
}
|
|
1688
|
-
const binding = await requireNativeCssCompiler();
|
|
1689
1784
|
const prefix = normalizedOptions.prefix;
|
|
1690
1785
|
const results = await Promise.all(
|
|
1691
1786
|
inputClasses.map(async (className) => {
|
|
@@ -1718,7 +1813,7 @@ var classToCss = async (input, options = {}) => {
|
|
|
1718
1813
|
const sizeBytes = results.reduce((sum, r) => sum + r.sizeBytes, 0);
|
|
1719
1814
|
const declarationMap = /* @__PURE__ */ new Map();
|
|
1720
1815
|
for (const result of results) {
|
|
1721
|
-
mergeDeclarationMap(declarationMap, result.css);
|
|
1816
|
+
mergeDeclarationMap(declarationMap, result.css, binding);
|
|
1722
1817
|
}
|
|
1723
1818
|
const uniqueUnknown = Array.from(new Set(unknownClasses));
|
|
1724
1819
|
if (normalizedOptions.strict && uniqueUnknown.length > 0) {
|
|
@@ -1727,7 +1822,7 @@ var classToCss = async (input, options = {}) => {
|
|
|
1727
1822
|
return {
|
|
1728
1823
|
inputClasses,
|
|
1729
1824
|
css: cssChunks.filter((chunk) => chunk.length > 0).join("\n"),
|
|
1730
|
-
declarations: declarationMapToString(declarationMap),
|
|
1825
|
+
declarations: declarationMapToString(declarationMap, binding),
|
|
1731
1826
|
resolvedClasses: Array.from(new Set(resolvedClasses)),
|
|
1732
1827
|
unknownClasses: uniqueUnknown,
|
|
1733
1828
|
sizeBytes
|