@csszyx/unplugin 0.8.0 → 0.9.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.
Files changed (48) hide show
  1. package/README.md +16 -7
  2. package/dist/css-mangler.cjs +4 -4
  3. package/dist/css-mangler.mjs +4 -4
  4. package/dist/index.cjs +23 -1
  5. package/dist/index.d.cts +100 -5
  6. package/dist/index.d.mts +99 -3
  7. package/dist/index.mjs +7 -1
  8. package/dist/next-prebuild.cjs +148 -0
  9. package/dist/next-prebuild.d.cts +66 -0
  10. package/dist/next-prebuild.d.mts +66 -0
  11. package/dist/next-prebuild.mjs +131 -0
  12. package/dist/next-turbo-loader.cjs +210 -0
  13. package/dist/next-turbo-loader.d.cts +68 -0
  14. package/dist/next-turbo-loader.d.mts +66 -0
  15. package/dist/next-turbo-loader.mjs +190 -0
  16. package/dist/next-watcher.cjs +237 -0
  17. package/dist/next-watcher.d.cts +106 -0
  18. package/dist/next-watcher.d.mts +106 -0
  19. package/dist/next-watcher.mjs +219 -0
  20. package/dist/shared/unplugin.8er8o6rn.mjs +276 -0
  21. package/dist/shared/unplugin.B_U4rZvG.cjs +281 -0
  22. package/dist/shared/unplugin.BbtspS8t.mjs +3271 -0
  23. package/dist/shared/unplugin.BceVw1eW.mjs +184 -0
  24. package/dist/shared/unplugin.BtQzlC2C.mjs +567 -0
  25. package/dist/shared/unplugin.CFp386gH.cjs +3321 -0
  26. package/dist/shared/unplugin.CPEWNSA0.d.cts +77 -0
  27. package/dist/shared/unplugin.CPEWNSA0.d.mts +77 -0
  28. package/dist/shared/unplugin.CScQRdTp.d.cts +15 -0
  29. package/dist/shared/unplugin.CScQRdTp.d.mts +15 -0
  30. package/dist/shared/unplugin.CdZxp0x-.d.mts +16 -0
  31. package/dist/shared/unplugin.DLrBgECN.d.cts +282 -0
  32. package/dist/shared/unplugin.DLrBgECN.d.mts +282 -0
  33. package/dist/shared/unplugin.DUxdYaSG.cjs +205 -0
  34. package/dist/shared/unplugin.s62yJbu1.cjs +591 -0
  35. package/dist/shared/unplugin.xeED_qwh.d.cts +16 -0
  36. package/dist/vite.cjs +7 -1
  37. package/dist/vite.d.cts +2 -1
  38. package/dist/vite.d.mts +2 -1
  39. package/dist/vite.mjs +7 -1
  40. package/dist/webpack.cjs +7 -1
  41. package/dist/webpack.d.cts +2 -1
  42. package/dist/webpack.d.mts +2 -1
  43. package/dist/webpack.mjs +7 -1
  44. package/package.json +41 -8
  45. package/dist/shared/unplugin.BNsv2szs.cjs +0 -1753
  46. package/dist/shared/unplugin.DCv0RtVZ.mjs +0 -1722
  47. package/dist/shared/unplugin.DUbr5w-N.d.cts +0 -49
  48. package/dist/shared/unplugin.DUbr5w-N.d.mts +0 -49
@@ -0,0 +1,219 @@
1
+ import * as path from 'node:path';
2
+ import { r as runNextWatcherCycle } from './shared/unplugin.BtQzlC2C.mjs';
3
+ import 'node:fs';
4
+ import 'node:crypto';
5
+ import 'node:os';
6
+ import 'proper-lockfile';
7
+
8
+ class NextWatcherLoop {
9
+ context;
10
+ cycleOptions;
11
+ debounceMs;
12
+ runCycle;
13
+ setTimeoutFn;
14
+ clearTimeoutFn;
15
+ onError;
16
+ timer;
17
+ disposed = false;
18
+ pendingReasons = /* @__PURE__ */ new Set();
19
+ lastResult;
20
+ lastError;
21
+ /**
22
+ *
23
+ * @param options
24
+ */
25
+ constructor(options) {
26
+ this.context = options.context;
27
+ this.cycleOptions = options.cycleOptions ?? {};
28
+ this.debounceMs = options.debounceMs ?? 50;
29
+ this.runCycle = options.runCycle ?? runNextWatcherCycle;
30
+ this.setTimeoutFn = options.setTimeout ?? setTimeout;
31
+ this.clearTimeoutFn = options.clearTimeout ?? clearTimeout;
32
+ this.onError = options.onError;
33
+ }
34
+ /**
35
+ *
36
+ */
37
+ get pending() {
38
+ return this.timer !== void 0;
39
+ }
40
+ /**
41
+ *
42
+ */
43
+ get reasons() {
44
+ return [...this.pendingReasons];
45
+ }
46
+ /**
47
+ *
48
+ * @param reason
49
+ */
50
+ notify(reason = "change") {
51
+ if (this.disposed) {
52
+ return;
53
+ }
54
+ this.pendingReasons.add(reason);
55
+ if (this.timer !== void 0) {
56
+ return;
57
+ }
58
+ this.timer = this.setTimeoutFn(() => {
59
+ try {
60
+ this.runPendingCycle();
61
+ } catch (error) {
62
+ this.lastError = error;
63
+ this.onError?.(error);
64
+ }
65
+ }, this.debounceMs);
66
+ }
67
+ /**
68
+ *
69
+ */
70
+ flush() {
71
+ if (this.disposed || this.timer === void 0) {
72
+ return void 0;
73
+ }
74
+ return this.runPendingCycle();
75
+ }
76
+ /**
77
+ *
78
+ */
79
+ dispose() {
80
+ if (this.timer !== void 0) {
81
+ this.clearTimeoutFn(this.timer);
82
+ }
83
+ this.timer = void 0;
84
+ this.pendingReasons.clear();
85
+ this.disposed = true;
86
+ }
87
+ /**
88
+ *
89
+ */
90
+ runPendingCycle() {
91
+ const timer = this.timer;
92
+ if (timer !== void 0) {
93
+ this.clearTimeoutFn(timer);
94
+ }
95
+ this.timer = void 0;
96
+ const reasons = [...this.pendingReasons];
97
+ this.pendingReasons.clear();
98
+ const result = this.runCycle(this.context, this.cycleOptions, reasons);
99
+ this.lastResult = result;
100
+ this.lastError = void 0;
101
+ return result;
102
+ }
103
+ }
104
+
105
+ function isNextSafelistShardPath(shardsDir, filePath) {
106
+ if (!path.isAbsolute(filePath)) {
107
+ return false;
108
+ }
109
+ const relative = path.relative(path.resolve(shardsDir), path.resolve(filePath));
110
+ return relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative) && !relative.includes(path.sep) && !relative.startsWith(".") && relative.endsWith(".json");
111
+ }
112
+ function isNextAppSourcePath(root, filePath) {
113
+ if (!path.isAbsolute(filePath)) {
114
+ return false;
115
+ }
116
+ const relative = path.relative(path.resolve(root), path.resolve(filePath));
117
+ return relative.length > 0 && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
118
+ }
119
+ class NextSafelistWatcher {
120
+ root;
121
+ shardsDir;
122
+ loop;
123
+ started = false;
124
+ closed = false;
125
+ /**
126
+ *
127
+ * @param options
128
+ */
129
+ constructor(options) {
130
+ this.root = path.resolve(options.context.root);
131
+ this.shardsDir = path.resolve(options.context.safelist.shardsDir);
132
+ this.loop = new NextWatcherLoop(options);
133
+ }
134
+ /**
135
+ *
136
+ */
137
+ get pending() {
138
+ return this.loop.pending;
139
+ }
140
+ /**
141
+ *
142
+ */
143
+ get lastResult() {
144
+ return this.loop.lastResult;
145
+ }
146
+ /**
147
+ *
148
+ */
149
+ get lastError() {
150
+ return this.loop.lastError;
151
+ }
152
+ /**
153
+ * Materialize existing shards before accepting live filesystem events.
154
+ */
155
+ start() {
156
+ if (this.closed) {
157
+ throw new Error("[csszyx] Cannot start a closed Next safelist watcher.");
158
+ }
159
+ if (this.started && this.loop.lastResult) {
160
+ return this.loop.lastResult;
161
+ }
162
+ this.started = true;
163
+ this.loop.notify("initial");
164
+ const result = this.loop.flush();
165
+ if (!result) {
166
+ throw new Error("[csszyx] Next safelist watcher failed to run its initial cycle.");
167
+ }
168
+ return result;
169
+ }
170
+ /**
171
+ * Queue a materialization cycle for one relevant shard filesystem event.
172
+ *
173
+ * @param event Normalized add/change/unlink event.
174
+ * @param filePath Absolute event path.
175
+ * @returns Whether the event was accepted.
176
+ */
177
+ notify(event, filePath) {
178
+ if (this.closed || !this.started || !isNextSafelistShardPath(this.shardsDir, filePath)) {
179
+ return false;
180
+ }
181
+ this.loop.notify(`shard:${event}`);
182
+ return true;
183
+ }
184
+ /**
185
+ * Queue tombstone cleanup after a source file is removed.
186
+ *
187
+ * @param filePath Absolute deleted source path.
188
+ * @returns Whether the event was accepted.
189
+ */
190
+ notifySourceRemoval(filePath) {
191
+ if (this.closed || !this.started || !isNextAppSourcePath(this.root, filePath)) {
192
+ return false;
193
+ }
194
+ this.loop.notify("source:unlink");
195
+ return true;
196
+ }
197
+ /**
198
+ * Flush any pending event batch immediately.
199
+ */
200
+ flush() {
201
+ return this.loop.flush();
202
+ }
203
+ /**
204
+ * Flush pending work before permanently closing the controller.
205
+ */
206
+ close() {
207
+ if (this.closed) {
208
+ return void 0;
209
+ }
210
+ this.closed = true;
211
+ try {
212
+ return this.loop.flush();
213
+ } finally {
214
+ this.loop.dispose();
215
+ }
216
+ }
217
+ }
218
+
219
+ export { NextSafelistWatcher, isNextAppSourcePath, isNextSafelistShardPath };
@@ -0,0 +1,276 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, transform } from '@csszyx/compiler';
3
+ import { c as createTransformCacheKey, a as readTransformCache, w as writeTransformCache } from './unplugin.BceVw1eW.mjs';
4
+ import { createHash } from 'node:crypto';
5
+
6
+ function readPackageVersion(relativePackageJson, fromUrl) {
7
+ try {
8
+ const packageJson = JSON.parse(
9
+ readFileSync(new URL(relativePackageJson, fromUrl), "utf8")
10
+ );
11
+ return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
12
+ } catch {
13
+ return "0.0.0";
14
+ }
15
+ }
16
+
17
+ function transformNextSource(input) {
18
+ const filename = normalizeSourceFilename(input.filename);
19
+ const producer = input.parserMode;
20
+ const cacheInput = createNextSourceTransformCacheInput(input, filename, producer);
21
+ if (input.parserMode === "rust") {
22
+ ensureRustTransformAvailable();
23
+ }
24
+ const cacheKey = input.cacheRoot ? createTransformCacheKey(cacheInput) : null;
25
+ if (input.cacheRoot && cacheKey) {
26
+ const cached = readTransformCache(input.cacheRoot, cacheInput, cacheKey);
27
+ if (cached) {
28
+ return { result: cached, cacheStatus: "hit", producer };
29
+ }
30
+ }
31
+ const result = runNextSourceTransform(input, filename);
32
+ assertNoUnsafePassThrough(input.source, result.result, filename);
33
+ if (input.cacheRoot && cacheKey && result.producer === producer) {
34
+ writeTransformCache(input.cacheRoot, cacheInput, result.result, cacheKey);
35
+ return { ...result, cacheStatus: "write" };
36
+ }
37
+ return { ...result, cacheStatus: input.cacheRoot ? "miss" : "disabled" };
38
+ }
39
+ function assertNoUnsafePassThrough(source, result, filename) {
40
+ if (!hasSzSyntax(source)) {
41
+ return;
42
+ }
43
+ if (!result.transformed && result.code === source) {
44
+ throw new Error(
45
+ `[csszyx] Next source transform failed closed for ${filename}: source still contains csszyx sz syntax.`
46
+ );
47
+ }
48
+ }
49
+ function hasSzSyntax(source) {
50
+ const cleaned = stripJsCommentsAndStrings(source);
51
+ return /\bsz\s*=/.test(cleaned) || /\bsz\s*:\s*[{"']/.test(cleaned);
52
+ }
53
+ function stripJsCommentsAndStrings(source) {
54
+ let out = "";
55
+ let index = 0;
56
+ const length = source.length;
57
+ while (index < length) {
58
+ const char = source[index];
59
+ const peek = index + 1 < length ? source[index + 1] : "";
60
+ if (char === "/" && peek === "/") {
61
+ index += 2;
62
+ while (index < length && source[index] !== "\n") {
63
+ index++;
64
+ }
65
+ continue;
66
+ }
67
+ if (char === "/" && peek === "*") {
68
+ index += 2;
69
+ while (index + 1 < length && !(source[index] === "*" && source[index + 1] === "/")) {
70
+ index++;
71
+ }
72
+ index = Math.min(length, index + 2);
73
+ continue;
74
+ }
75
+ if (char === "/" && isRegexLiteralStart(out)) {
76
+ index++;
77
+ let inCharClass = false;
78
+ while (index < length) {
79
+ const current = source[index];
80
+ if (current === "\\" && index + 1 < length) {
81
+ index += 2;
82
+ continue;
83
+ }
84
+ if (current === "[") {
85
+ inCharClass = true;
86
+ index++;
87
+ continue;
88
+ }
89
+ if (current === "]") {
90
+ inCharClass = false;
91
+ index++;
92
+ continue;
93
+ }
94
+ if (current === "/" && !inCharClass) {
95
+ index++;
96
+ while (/[a-z]/i.test(source[index] ?? "")) {
97
+ index++;
98
+ }
99
+ break;
100
+ }
101
+ index++;
102
+ }
103
+ continue;
104
+ }
105
+ if (char === '"' || char === "'" || char === "`") {
106
+ const quote = char;
107
+ index++;
108
+ while (index < length && source[index] !== quote) {
109
+ if (source[index] === "\\" && index + 1 < length) {
110
+ index += 2;
111
+ } else {
112
+ index++;
113
+ }
114
+ }
115
+ index++;
116
+ continue;
117
+ }
118
+ out += char;
119
+ index++;
120
+ }
121
+ return out;
122
+ }
123
+ function isRegexLiteralStart(emitted) {
124
+ const trimmed = emitted.trimEnd();
125
+ const previous = trimmed.length > 0 ? trimmed.charAt(trimmed.length - 1) : void 0;
126
+ return previous === void 0 || /[({[=:;,!&|?+\-*%^~<>]/.test(previous);
127
+ }
128
+ function runNextSourceTransform(input, filename) {
129
+ const compilerOptions = input.compilerOptions;
130
+ if (input.parserMode === "babel") {
131
+ return {
132
+ result: transformSourceCode(input.source, filename, compilerOptions),
133
+ producer: "babel"
134
+ };
135
+ }
136
+ if (input.parserMode === "rust") {
137
+ return {
138
+ result: transformRust(input.source, filename, compilerOptions),
139
+ producer: "rust"
140
+ };
141
+ }
142
+ try {
143
+ return {
144
+ result: transformOxc(input.source, filename, compilerOptions),
145
+ producer: "oxc"
146
+ };
147
+ } catch (error) {
148
+ if (input.allowBabelFallback === false) {
149
+ throw error;
150
+ }
151
+ const result = transformSourceCode(input.source, filename, compilerOptions);
152
+ const reason = error instanceof Error ? error.message : String(error);
153
+ result.diagnostics.push(
154
+ `[csszyx] oxc parser fell back to Babel for ${filename}: ${reason}`
155
+ );
156
+ return { result, producer: "babel-fallback" };
157
+ }
158
+ }
159
+ function createNextSourceTransformCacheInput(input, filename, producer) {
160
+ return {
161
+ pluginVersion: input.pluginVersion,
162
+ compilerVersion: input.compilerVersion,
163
+ parserMode: input.parserMode,
164
+ producer,
165
+ astBudget: input.astBudget ?? input.compilerOptions?.astBudget,
166
+ mangleVars: input.compilerOptions?.mangleVars,
167
+ mangleVarHoistMaxDepth: input.compilerOptions?.mangleVarHoistMaxDepth,
168
+ globalVarAliases: normalizeGlobalVarAliasesForCache(
169
+ input.compilerOptions?.globalVarAliases
170
+ ),
171
+ filename,
172
+ source: input.source
173
+ };
174
+ }
175
+ function normalizeSourceFilename(filename) {
176
+ return filename.replace(/\\/g, "/");
177
+ }
178
+ function normalizeGlobalVarAliasesForCache(aliases) {
179
+ if (!aliases) {
180
+ return [];
181
+ }
182
+ const entries = aliases instanceof Map ? aliases.entries() : Array.isArray(aliases) ? aliases : Object.entries(aliases);
183
+ const normalized = /* @__PURE__ */ new Map();
184
+ for (const [original, alias] of entries) {
185
+ if (original.startsWith("--") && alias.startsWith("--")) {
186
+ normalized.set(original, alias);
187
+ }
188
+ }
189
+ return [...normalized].sort(([left], [right]) => left.localeCompare(right));
190
+ }
191
+
192
+ function collectNextTransformMetadata(result, source, sourcePath) {
193
+ const classes = new Set(result.classes);
194
+ collectRuntimeStaticClasses(result, classes);
195
+ return {
196
+ sourcePath,
197
+ sourceHash: createHash("sha256").update(source).digest("hex"),
198
+ classes: [...classes].sort(),
199
+ rawClassNames: [...result.rawClassNames].sort(),
200
+ recoveryTokenCount: result.recoveryTokens.size,
201
+ cssVariableCount: result.cssVariableMap.size
202
+ };
203
+ }
204
+ function createNextSafelistShardFromMetadata(metadata, cacheKey) {
205
+ return {
206
+ cacheKey,
207
+ sourcePath: metadata.sourcePath,
208
+ sourceHash: metadata.sourceHash,
209
+ classes: metadata.classes
210
+ };
211
+ }
212
+ function collectRuntimeStaticClasses(result, discoveredClasses) {
213
+ if (!result.usesRuntime) {
214
+ return;
215
+ }
216
+ const szCallRe = /_sz\(\s*\{/g;
217
+ for (const szMatch of result.code.matchAll(szCallRe)) {
218
+ let depth = 1;
219
+ let index = (szMatch.index ?? 0) + szMatch[0].length;
220
+ while (index < result.code.length && depth > 0) {
221
+ if (result.code[index] === "{") {
222
+ depth++;
223
+ } else if (result.code[index] === "}") {
224
+ depth--;
225
+ }
226
+ index++;
227
+ }
228
+ const objectSource = result.code.slice((szMatch.index ?? 0) + szMatch[0].length, index - 1);
229
+ collectRuntimeStringClasses(objectSource, discoveredClasses);
230
+ collectRuntimeNumberClasses(objectSource, discoveredClasses);
231
+ collectRuntimeBooleanClasses(objectSource, discoveredClasses);
232
+ }
233
+ }
234
+ function collectRuntimeStringClasses(objectSource, discoveredClasses) {
235
+ const stringKeyValue = /(\w+)\s*:\s*(?:"([^"]*)"|'([^']*)')/g;
236
+ for (const match of objectSource.matchAll(stringKeyValue)) {
237
+ try {
238
+ collectTransformClasses(
239
+ transform({ [match[1]]: match[2] ?? match[3] }),
240
+ discoveredClasses
241
+ );
242
+ } catch {
243
+ }
244
+ }
245
+ }
246
+ function collectRuntimeNumberClasses(objectSource, discoveredClasses) {
247
+ const numberKeyValue = /(\w+)\s*:\s*(-?\d+(?:\.\d+)?)\s*(?=[,}\n])/g;
248
+ for (const match of objectSource.matchAll(numberKeyValue)) {
249
+ try {
250
+ collectTransformClasses(
251
+ transform({ [match[1]]: Number.parseFloat(match[2]) }),
252
+ discoveredClasses
253
+ );
254
+ } catch {
255
+ }
256
+ }
257
+ }
258
+ function collectRuntimeBooleanClasses(objectSource, discoveredClasses) {
259
+ const booleanKeyValue = /(\w+)\s*:\s*(true|false)\s*(?=[,}\n])/g;
260
+ for (const match of objectSource.matchAll(booleanKeyValue)) {
261
+ try {
262
+ collectTransformClasses(
263
+ transform({ [match[1]]: match[2] === "true" }),
264
+ discoveredClasses
265
+ );
266
+ } catch {
267
+ }
268
+ }
269
+ }
270
+ function collectTransformClasses(result, discoveredClasses) {
271
+ for (const className of result.className.split(/\s+/).filter(Boolean)) {
272
+ discoveredClasses.add(className);
273
+ }
274
+ }
275
+
276
+ export { createNextSafelistShardFromMetadata as a, collectNextTransformMetadata as c, readPackageVersion as r, transformNextSource as t };