@navecss/core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.js ADDED
@@ -0,0 +1,3318 @@
1
+ import { findingsInText, formatFinding } from './chunk-UANF3FGO.js';
2
+ import { assertOptions, resolveUsedOptions, keptAtoms, atomsWrittenIn, applyEdits, compareText, withoutRemoved, CX_SOURCE, toSourceMap, isSecondHop, buildReport, moduleReport, isListableReexport, readModule, combinedMapOf, placerFor, cxModulesArray, nodeAt, staticStringOf, pushAll, childrenOf, nodesAt, LINE_UNKNOWN_WITHOUT_MAP, LINE_UNKNOWN_UNMAPPED, exportNameOf, atomOfClass, analyze, memberReadOf, patternDestructuring, stringAt, propertyNameOf } from './chunk-E5F6YF7A.js';
3
+ import { validateExtendAtomsHostFree } from './chunk-LQSGQ2OA.js';
4
+ import { resolveExtendSpecifier, applyExtendModule } from './chunk-NKUZNRF4.js';
5
+ import { snapshotExtendMap, expandText, foldLocated } from './chunk-LADFXRWQ.js';
6
+ import { tokenize } from './chunk-NFS2REPQ.js';
7
+ import { decodeIncomingMap, formatDiagnostic } from './chunk-SYNQJNVB.js';
8
+ import './chunk-CUL5PLPI.js';
9
+ import { atomClassMap } from './chunk-GZL2VW7C.js';
10
+ import { readFile } from 'fs/promises';
11
+ import path2 from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { randomUUID } from 'crypto';
14
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, realpathSync, statSync } from 'fs';
15
+
16
+ // src/vite-builds.ts
17
+ function htmlPageOf(id) {
18
+ return !id.includes("?") && id.toLowerCase().endsWith(".html") ? id : void 0;
19
+ }
20
+ function firstHalf(pickers, configure) {
21
+ const workerPlugin = {
22
+ name: "nave:collect-worker",
23
+ enforce: "post",
24
+ transform(code, id, meta) {
25
+ const [plugin] = pickers.forHook(this).nave.config()?.worker.plugins() ?? [];
26
+ return plugin?.transform.call(this, code, id, meta) ?? Promise.resolve(void 0);
27
+ },
28
+ buildEnd(error) {
29
+ const [plugin] = pickers.forHook(this).nave.config()?.worker.plugins() ?? [];
30
+ return plugin?.buildEnd.call(this, error) ?? Promise.resolve();
31
+ }
32
+ };
33
+ return {
34
+ name: "nave",
35
+ config(userConfig, env) {
36
+ const config = pickers.latest().nave.config(userConfig, env);
37
+ return config && { ...config, worker: { plugins: () => [workerPlugin] } };
38
+ },
39
+ configEnvironment: (name, options) => pickers.latest().nave.configEnvironment(name, options),
40
+ configResolved(config) {
41
+ configure(config).nave.configResolved(config);
42
+ },
43
+ configureServer(server) {
44
+ pickers.latest().nave.configureServer(server);
45
+ },
46
+ closeBundle() {
47
+ pickers.latest().nave.closeBundle.call(this);
48
+ },
49
+ buildApp: {
50
+ order: "post",
51
+ handler(builder) {
52
+ return pickers.latest().nave.buildApp.handler.call(this, builder);
53
+ }
54
+ },
55
+ transform(code, id) {
56
+ const page = htmlPageOf(id);
57
+ if (page !== void 0) pickers.notePage(page, this, code);
58
+ return pickers.forHook(this).nave.transform.call(this, code, id);
59
+ },
60
+ hotUpdate(options) {
61
+ return pickers.forHook(this).nave.hotUpdate.call(this, options);
62
+ },
63
+ renderChunk(code, chunk) {
64
+ return pickers.forHook(this).nave.renderChunk.call(this, code, chunk);
65
+ },
66
+ generateBundle: {
67
+ order: "post",
68
+ handler(options, bundle) {
69
+ pickers.forHook(this).nave.generateBundle.handler.call(this, options, bundle);
70
+ }
71
+ }
72
+ };
73
+ }
74
+ function secondHalf(pickers) {
75
+ return {
76
+ name: "nave:collect",
77
+ enforce: "post",
78
+ transform(code, id, meta) {
79
+ return pickers.forHook(this).collect.transform.call(this, code, id, meta);
80
+ },
81
+ transformIndexHtml: {
82
+ order: "pre",
83
+ handler(html, page) {
84
+ for (const build of pickers.forPage(page.filename, html)) {
85
+ build.collect.transformIndexHtml.handler(html, page);
86
+ }
87
+ return;
88
+ }
89
+ },
90
+ buildStart() {
91
+ return pickers.forHook(this).collect.buildStart.call(this);
92
+ },
93
+ buildEnd(error) {
94
+ return pickers.forHook(this).collect.buildEnd.call(this, error);
95
+ }
96
+ };
97
+ }
98
+ function isInside(root, file) {
99
+ const base = root.endsWith("/") ? root : `${root}/`;
100
+ return file.startsWith(base);
101
+ }
102
+ function registry(assemble2) {
103
+ const byInvocation = /* @__PURE__ */ new WeakMap();
104
+ const roots = /* @__PURE__ */ new Map();
105
+ const pages = /* @__PURE__ */ new Map();
106
+ let latest = assemble2();
107
+ const find = (host) => {
108
+ const config = host.environment?.config;
109
+ if (config?.inlineConfig === void 0) return void 0;
110
+ return byInvocation.get(config.inlineConfig)?.get(config.command ?? "build");
111
+ };
112
+ const pickers = {
113
+ latest: () => latest,
114
+ forHook: (host) => find(host) ?? latest,
115
+ notePage(filename, host, code) {
116
+ const compiling = pages.get(filename) ?? /* @__PURE__ */ new Map();
117
+ const build = find(host) ?? latest;
118
+ compiling.delete(build);
119
+ pages.set(filename, compiling.set(build, code));
120
+ },
121
+ forPage(filename, html) {
122
+ if (filename === void 0) return [latest];
123
+ const compiling = pages.get(filename);
124
+ if (compiling && compiling.size > 0) {
125
+ const owner = [...compiling].find(([, code]) => code === html)?.[0] ?? compiling.keys().next().value;
126
+ compiling.delete(owner);
127
+ return [owner];
128
+ }
129
+ const holding = [...roots].filter(([, root]) => isInside(root, filename)).map(([b]) => b);
130
+ return holding.length > 0 ? holding : [latest];
131
+ }
132
+ };
133
+ const configure = (config) => {
134
+ const key = config.inlineConfig ?? config;
135
+ const commands = byInvocation.get(key) ?? /* @__PURE__ */ new Map();
136
+ byInvocation.set(key, commands);
137
+ const build = commands.get(config.command) ?? assemble2();
138
+ commands.set(config.command, build);
139
+ roots.set(build, config.root);
140
+ latest = build;
141
+ return build;
142
+ };
143
+ return { pickers, configure };
144
+ }
145
+ function shareAcrossBuilds(assemble2) {
146
+ const { pickers, configure } = registry(assemble2);
147
+ return [firstHalf(pickers, configure), secondHalf(pickers)];
148
+ }
149
+
150
+ // src/vite-css-id.ts
151
+ var STYLESHEET = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
152
+ var SPECIAL_QUERY = /[?&](?:worker|sharedworker|raw|url)\b/;
153
+ function isStylesheetPath(id) {
154
+ return STYLESHEET.test(id);
155
+ }
156
+ function isStylesheetId(id) {
157
+ return STYLESHEET.test(id) && !SPECIAL_QUERY.test(id);
158
+ }
159
+ function canHoldDirective(code) {
160
+ return /@[n\\]/i.test(code);
161
+ }
162
+ function filePathOf(id) {
163
+ const query = id.indexOf("?");
164
+ return query === -1 ? id : id.slice(0, query);
165
+ }
166
+
167
+ // src/vite-cx-text-test.ts
168
+ function literalPattern(text) {
169
+ return text.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`);
170
+ }
171
+ var INSIDE = String.raw`[^\n'"\x60\\]{0,512}`;
172
+ var EXTENSION = String.raw`\.[^\n'"\x60\\/?#.]*`;
173
+ var QUOTE = String.raw`['"\x60]`;
174
+ function textTestOf(names) {
175
+ if (names.size === 0) return void 0;
176
+ const listed = [...names].map((name) => literalPattern(name)).join("|");
177
+ const named = `${QUOTE}(?:${INSIDE}/)?(?:${listed})(?:${EXTENSION})?/*(?:[?#]${INSIDE})?${QUOTE}`;
178
+ const directory = String.raw`(?:\bfrom|\bimport)\s*(?:\(\s*)?${QUOTE}\.{1,2}(?:/\.{1,2})*/?${QUOTE}`;
179
+ return new RegExp(names.has("index") ? `${named}|${directory}` : named);
180
+ }
181
+
182
+ // src/vite-cx-modules.ts
183
+ function isRelative(text) {
184
+ const cut = text.search(/[#?]/);
185
+ const path10 = cut === -1 ? text : text.slice(0, cut);
186
+ return path10 === "." || path10 === ".." || path10.startsWith("./") || path10.startsWith("../");
187
+ }
188
+ function fileOf(id) {
189
+ return filePathOf(id).replaceAll("\\", "/");
190
+ }
191
+ function namesOf(file) {
192
+ const name = path2.basename(file, path2.extname(file));
193
+ return name === "index" ? [name, path2.basename(path2.dirname(file))] : [name];
194
+ }
195
+ function entriesNaming(declared, id) {
196
+ const file = fileOf(id);
197
+ return declared.ids.entries().filter(([, resolved]) => fileOf(resolved) === file).map(([entry]) => entry).toArray();
198
+ }
199
+ async function declaredModulesFor(context, resolver, environment) {
200
+ const { cxModules } = context.options;
201
+ if (cxModules.length === 0) return void 0;
202
+ const known = context.state.declared.get(environment);
203
+ if (known) return known;
204
+ const made = resolveEntries(context, resolver);
205
+ context.state.declared.set(environment, made);
206
+ return made;
207
+ }
208
+ async function resolveOrNull(resolver, source, importer) {
209
+ try {
210
+ return await resolver.resolve?.(source, importer) ?? void 0;
211
+ } catch {
212
+ return void 0;
213
+ }
214
+ }
215
+ async function resolveEntries(context, resolver) {
216
+ const from = path2.join(context.root, "index.html");
217
+ const nave = await resolveOrNull(resolver, CX_SOURCE, from);
218
+ const naveFile = nave === void 0 ? void 0 : fileOf(nave.id);
219
+ const resolved = await Promise.all(
220
+ context.options.cxModules.map(async (entry) => {
221
+ const found = await resolveOrNull(resolver, entry, from);
222
+ return [entry, found?.id];
223
+ })
224
+ );
225
+ const kept = resolved.filter(
226
+ ([entry, id]) => entry !== CX_SOURCE && (id === void 0 || fileOf(id) !== naveFile)
227
+ );
228
+ const ids = new Map(kept.filter((pair) => pair[1] !== void 0));
229
+ const files = new Set(ids.values().map((id) => fileOf(id)));
230
+ const names = new Set(files.values().flatMap((file) => namesOf(file)));
231
+ return {
232
+ entries: new Set(kept.map(([entry]) => entry).filter((entry) => !isRelative(entry))),
233
+ ids,
234
+ files,
235
+ names,
236
+ textTest: textTestOf(names)
237
+ };
238
+ }
239
+ function forgetDeclared(state, environment) {
240
+ state.declared.delete(environment);
241
+ const prefix = `${environment}\0`;
242
+ for (const key of state.recognised.keys())
243
+ if (key.startsWith(prefix)) state.recognised.delete(key);
244
+ }
245
+ function withoutTrailingSlashes(text) {
246
+ let end = text.length;
247
+ while (end > 0 && text[end - 1] === "/") end -= 1;
248
+ return text.slice(0, end);
249
+ }
250
+ function lastSegmentOf(specifier) {
251
+ const cut = specifier.slice(1).search(/[#?]/);
252
+ const bare = withoutTrailingSlashes(cut === -1 ? specifier : specifier.slice(0, cut + 1));
253
+ const segment = bare.slice(bare.lastIndexOf("/") + 1);
254
+ return segment === "." || segment === ".." ? "index" : segment;
255
+ }
256
+ function isNamingListed(specifier, declared) {
257
+ const segment = lastSegmentOf(specifier);
258
+ if (declared.names.has(segment)) return true;
259
+ const extension = path2.extname(segment);
260
+ return extension !== "" && declared.names.has(segment.slice(0, -extension.length));
261
+ }
262
+ function isAboutListed(input, declared) {
263
+ if (!declared) return false;
264
+ return isListedFile(declared, input.id) || isMentioningDeclared(input.code, declared);
265
+ }
266
+ function isListedFile(declared, id) {
267
+ return declared.files.has(fileOf(id));
268
+ }
269
+ function isMentioningDeclared(code, declared) {
270
+ for (const entry of declared.entries) if (code.includes(entry)) return true;
271
+ return declared.textTest?.test(code) ?? false;
272
+ }
273
+ function recognisedKey(environment, file, importer) {
274
+ return `${environment}\0${file}\0${importer}`;
275
+ }
276
+ var NAVE_MODULE_DIRS = ["src", "dist"].map(
277
+ (name) => `${path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "..", name).replaceAll("\\", "/")}/`
278
+ );
279
+ function pathOfId(id) {
280
+ return filePathOf(id).replaceAll("\\", "/");
281
+ }
282
+ function isNaveOwn(id) {
283
+ const file = pathOfId(id);
284
+ return NAVE_MODULE_DIRS.some((directory) => file.startsWith(directory));
285
+ }
286
+ function isDependencyId(id) {
287
+ return pathOfId(id).includes("/node_modules/");
288
+ }
289
+ async function packageNameOf(file, cache) {
290
+ const directory = path2.dirname(file);
291
+ const cached = cache.get(directory);
292
+ if (cached) return cached;
293
+ const found = nameAbove(directory, cache);
294
+ cache.set(directory, found);
295
+ return found;
296
+ }
297
+ async function nameAbove(directory, cache) {
298
+ const name = await readName(directory);
299
+ const parent = path2.dirname(directory);
300
+ if (name !== void 0 || parent === directory) return name;
301
+ return packageNameOf(directory, cache);
302
+ }
303
+ async function readName(directory) {
304
+ try {
305
+ const manifest = JSON.parse(await readFile(path2.join(directory, "package.json"), "utf8"));
306
+ return typeof manifest.name === "string" ? manifest.name : void 0;
307
+ } catch {
308
+ return void 0;
309
+ }
310
+ }
311
+ function moduleLabel(root, id) {
312
+ const file = filePathOf(id);
313
+ if (file.startsWith("\0")) return String.raw`\0${file.slice(1)}`;
314
+ if (!path2.isAbsolute(file)) return file;
315
+ return path2.relative(root, file).replaceAll("\\", "/");
316
+ }
317
+
318
+ // src/vite-cx-importers.ts
319
+ function importerIdsOf(ctx, cxId) {
320
+ const info = ctx.getModuleInfo?.(cxId);
321
+ return [.../* @__PURE__ */ new Set([...info?.importers ?? [], ...info?.dynamicImporters ?? []])];
322
+ }
323
+ async function isStoodInFor(context, id) {
324
+ if (!isDependencyId(id)) return false;
325
+ const pkg = await packageNameOf(filePathOf(id), context.packageNames);
326
+ return pkg !== void 0 && Object.hasOwn(context.options.keepFor, pkg);
327
+ }
328
+ async function candidateOf(ctx, context, id) {
329
+ const code = ctx.getModuleInfo?.(id)?.code;
330
+ if (code === null || code === void 0 || isNaveOwn(id)) return void 0;
331
+ return await isStoodInFor(context, id) ? void 0 : { id, code };
332
+ }
333
+ function specifiersIn(program) {
334
+ const found = /* @__PURE__ */ new Map();
335
+ const stack = [program];
336
+ while (stack.length > 0) {
337
+ const node = stack.pop();
338
+ const where = nodeAt(node, "source");
339
+ const source = staticStringOf(where);
340
+ if (where !== void 0 && source !== void 0) {
341
+ found.set(source, Math.min(found.get(source) ?? Infinity, where.start));
342
+ }
343
+ pushAll(stack, childrenOf(node));
344
+ }
345
+ return [...found].toSorted(([, a], [, b]) => a - b).map(([source]) => source);
346
+ }
347
+ function specifiersOf(ctx, importer) {
348
+ try {
349
+ return specifiersIn(ctx.parse?.(importer.code));
350
+ } catch {
351
+ return void 0;
352
+ }
353
+ }
354
+ async function isResolvingToCx(ctx, specifier, importer, known) {
355
+ if (specifier === CX_SOURCE) return false;
356
+ const key = `${importer.id}\0${specifier}`;
357
+ const answered = known.answers.get(key);
358
+ if (answered !== void 0) return answered;
359
+ const resolved = await ctx.resolve?.(specifier, importer.id);
360
+ const isCx = resolved?.id === known.cxId;
361
+ known.answers.set(key, isCx);
362
+ return isCx;
363
+ }
364
+ function lineFor(label, specifiers) {
365
+ if (specifiers.length === 0) {
366
+ return `${label}: imports cx through a specifier the build does not read.`;
367
+ }
368
+ return `${label}: imports cx from ${specifiers.map((specifier) => `'${specifier}'`).join(", ")}.`;
369
+ }
370
+ async function lineOf(ctx, context, importer, known) {
371
+ const written = specifiersOf(ctx, importer);
372
+ const unread = [];
373
+ const specifiers = written ?? [];
374
+ for (const specifier of specifiers) {
375
+ if (await isResolvingToCx(ctx, specifier, importer, known)) unread.push(specifier);
376
+ }
377
+ const label = moduleLabel(context.root, importer.id);
378
+ if (unread.length > 0) return lineFor(label, unread);
379
+ const isRead = written?.includes(CX_SOURCE) ?? importer.code.includes(CX_SOURCE);
380
+ return isRead ? void 0 : lineFor(label, []);
381
+ }
382
+ async function checkCxImporters(ctx, context) {
383
+ const resolved = await ctx.resolve?.(CX_SOURCE, path2.join(context.root, "index.html"));
384
+ if (!resolved) return;
385
+ const known = { cxId: resolved.id, answers: /* @__PURE__ */ new Map() };
386
+ const lines = [];
387
+ for (const id of importerIdsOf(ctx, resolved.id)) {
388
+ const importer = await candidateOf(ctx, context, id);
389
+ const line = importer && await lineOf(ctx, context, importer, known);
390
+ if (line) lines.push(line);
391
+ }
392
+ if (lines.length === 0) return;
393
+ const count = lines.length === 1 ? "1 module imports" : `${lines.length} modules import`;
394
+ ctx.error(
395
+ [
396
+ `${count} cx through a specifier the build does not follow, so the atoms its calls name would not ship:`,
397
+ ...lines.toSorted(compareText),
398
+ "Import cx from '@navecss/core/cx' directly where it is called."
399
+ ].join("\n")
400
+ );
401
+ }
402
+
403
+ // src/vite-cx-reading.ts
404
+ async function declaredReadingOf(context, resolver, declared, input) {
405
+ const { environment, module } = input;
406
+ const declaredSources = /* @__PURE__ */ new Set();
407
+ if (!declared) return { declaredSources, isDeclared: false, onlyVia: void 0 };
408
+ const files = /* @__PURE__ */ new Set();
409
+ let isOnlyListed = true;
410
+ for (const source of specifiersIn(module.program)) {
411
+ if (source === CX_SOURCE) {
412
+ isOnlyListed = false;
413
+ continue;
414
+ }
415
+ const found = await listedFileOf(resolver, declared, source, module.id);
416
+ if (!found) continue;
417
+ declaredSources.add(source);
418
+ if (found.file === void 0) {
419
+ isOnlyListed = false;
420
+ continue;
421
+ }
422
+ files.add(found.file);
423
+ const key = recognisedKey(environment, found.file, module.id);
424
+ context.state.recognised.set(
425
+ key,
426
+ /* @__PURE__ */ new Set([...context.state.recognised.get(key) ?? [], source])
427
+ );
428
+ }
429
+ return {
430
+ declaredSources,
431
+ isDeclared: isListedFile(declared, module.id),
432
+ onlyVia: isOnlyListed && files.size > 0 ? files : void 0
433
+ };
434
+ }
435
+ async function listedFileFrom(resolver, declared, source, importer) {
436
+ const resolved = await resolveOrNull(resolver, source, importer);
437
+ const file = resolved ? fileOf(resolved.id) : void 0;
438
+ return file !== void 0 && declared.files.has(file) ? file : void 0;
439
+ }
440
+ async function listedFileOf(resolver, declared, source, importer) {
441
+ if (declared.entries.has(source)) {
442
+ const id = source.startsWith("#") ? void 0 : declared.ids.get(source);
443
+ if (id !== void 0) return { file: fileOf(id) };
444
+ const file2 = await listedFileFrom(resolver, declared, source, importer);
445
+ return file2 === void 0 && source.startsWith("#") ? void 0 : { file: file2 };
446
+ }
447
+ if (!isNamingListed(source, declared)) return void 0;
448
+ const file = await listedFileFrom(resolver, declared, source, importer);
449
+ return file === void 0 ? void 0 : { file };
450
+ }
451
+
452
+ // src/vite-dev-keep.ts
453
+ var KEEP_CONSTANT = "__NAVE_KEEP_CLASSES__";
454
+ function keepMap(kept) {
455
+ return Object.fromEntries(
456
+ kept.filter((atom) => Object.hasOwn(atomClassMap, atom)).map((atom) => [atom, atomClassMap[atom]])
457
+ );
458
+ }
459
+ function devKeepMap(map, atoms) {
460
+ return new Proxy(map, {
461
+ getOwnPropertyDescriptor(target, key) {
462
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
463
+ if (descriptor === void 0 && typeof key === "string") {
464
+ const quoted2 = JSON.stringify(key);
465
+ console.error(
466
+ atoms.includes(key) ? `[nave] cx.dynamic(${quoted2}) applied no class: ${quoted2} is not in keep or in a keepFor list, and navePlugin() gives cx.dynamic() only the atoms in those lists, in a build as in dev. Add ${quoted2} to keep in navePlugin(), or, when a dependency makes the call, to its list in keepFor.` : `[nave] cx.dynamic(${quoted2}) applied no class: ${quoted2} is not a Nave atom.`
467
+ );
468
+ }
469
+ return descriptor;
470
+ }
471
+ });
472
+ }
473
+ function devKeepExpression(map, atoms) {
474
+ return `(${devKeepMap.toString()})(${JSON.stringify(map)}, ${JSON.stringify(atoms)})`;
475
+ }
476
+ var installs = [];
477
+ var baseline = { held: false, value: void 0 };
478
+ function publish() {
479
+ const newest = installs.at(-1);
480
+ if (newest !== void 0) Object.assign(globalThis, { [KEEP_CONSTANT]: newest.map });
481
+ else if (baseline.held) Object.assign(globalThis, { [KEEP_CONSTANT]: baseline.value });
482
+ else Reflect.deleteProperty(globalThis, KEEP_CONSTANT);
483
+ }
484
+ function installServerKeepMap(context, owner) {
485
+ if (context.options.atomic !== "used") return;
486
+ const map = devKeepMap(keepMap(context.kept), Object.keys(atomClassMap));
487
+ if (installs.length === 0) {
488
+ baseline.held = Object.hasOwn(globalThis, KEEP_CONSTANT);
489
+ baseline.value = globalThis[KEEP_CONSTANT];
490
+ }
491
+ installs.push({ owner, map });
492
+ publish();
493
+ }
494
+ function removeServerKeepMap(owner) {
495
+ const index = installs.findIndex((install) => install.owner === owner);
496
+ if (index === -1) return;
497
+ installs.splice(index, 1);
498
+ publish();
499
+ }
500
+
501
+ // src/vite-dev-reloads.ts
502
+ function freshReloads() {
503
+ return {
504
+ stale: /* @__PURE__ */ new Set(),
505
+ reloading: /* @__PURE__ */ new Map(),
506
+ listening: 0,
507
+ unheard: /* @__PURE__ */ new Set(),
508
+ reloadTimer: void 0,
509
+ readAhead: 0
510
+ };
511
+ }
512
+ function noteReloadSent(state, id) {
513
+ state.reloading.set(id, Date.now());
514
+ if (state.listening === 0) state.unheard.add(id);
515
+ }
516
+
517
+ // src/vite-state.ts
518
+ var byConfig = /* @__PURE__ */ new WeakMap();
519
+ var byBuild = /* @__PURE__ */ new WeakMap();
520
+ function buildOf(config) {
521
+ return config.command === "build" ? config.inlineConfig : void 0;
522
+ }
523
+ function mapOf(registry2, owner) {
524
+ const found = registry2.get(owner) ?? /* @__PURE__ */ new Map();
525
+ registry2.set(owner, found);
526
+ return found;
527
+ }
528
+ function freshState() {
529
+ return {
530
+ started: false,
531
+ modules: /* @__PURE__ */ new Map(),
532
+ exposures: /* @__PURE__ */ new Map(),
533
+ templateLinks: /* @__PURE__ */ new Map(),
534
+ packages: /* @__PURE__ */ new Set(),
535
+ declared: /* @__PURE__ */ new Map(),
536
+ recognised: /* @__PURE__ */ new Map(),
537
+ sheets: /* @__PURE__ */ new Map(),
538
+ pages: /* @__PURE__ */ new Map(),
539
+ emitted: void 0,
540
+ externals: /* @__PURE__ */ new Set(),
541
+ clientEnded: false,
542
+ serverImports: [],
543
+ client: void 0,
544
+ expectedEnvironments: void 0,
545
+ builtEnvironments: /* @__PURE__ */ new Set(),
546
+ warned: /* @__PURE__ */ new Set(),
547
+ served: /* @__PURE__ */ new Map(),
548
+ ...freshReloads(),
549
+ htmlRead: false,
550
+ serverTransformed: false,
551
+ directiveExpanded: false,
552
+ markupJudged: false,
553
+ warmedUp: false,
554
+ requested: /* @__PURE__ */ new Set()
555
+ };
556
+ }
557
+ function stateFor(root, config) {
558
+ const known = byConfig.get(config)?.get(root);
559
+ if (known) return known;
560
+ const build = buildOf(config);
561
+ const shared = build && byBuild.get(build)?.get(root);
562
+ const state = shared && !shared.started ? shared : freshState();
563
+ mapOf(byConfig, config).set(root, state);
564
+ if (build) mapOf(byBuild, build).set(root, state);
565
+ return state;
566
+ }
567
+ function moduleKey(environment, id) {
568
+ return `${environment}\0${id}`;
569
+ }
570
+ function collectedAtoms(state, kept) {
571
+ const atoms = new Set(kept);
572
+ for (const record of state.modules.values()) for (const atom of record.atoms) atoms.add(atom);
573
+ for (const page of state.pages.values()) for (const atom of page) atoms.add(atom);
574
+ return atoms;
575
+ }
576
+ function withRestorers(atoms) {
577
+ if (atoms.has("srOnly")) atoms.add("srOnlyFocusable");
578
+ return atoms;
579
+ }
580
+ function servedAtoms(state, kept) {
581
+ return withRestorers(collectedAtoms(state, kept));
582
+ }
583
+ function recordsOf(state, environment) {
584
+ const prefix = `${environment}\0`;
585
+ return [...state.modules].filter(([key]) => key.startsWith(prefix)).map(([, record]) => record);
586
+ }
587
+
588
+ // src/vite-setup-link.ts
589
+ function importsContaining(program, marker) {
590
+ const sources = nodesAt(program, "body").map(
591
+ (node) => node.type === "ImportDeclaration" ? staticStringOf(nodeAt(node, "source")) : void 0
592
+ );
593
+ return sources.filter((source) => source?.includes(marker) === true);
594
+ }
595
+ async function resolveId(ctx, source, importer) {
596
+ const resolved = await ctx.resolve?.(source, importer);
597
+ return resolved?.id;
598
+ }
599
+ async function linkTemplates(context, ctx, input, scriptId) {
600
+ const environment = ctx.environment?.name ?? "client";
601
+ for (const template of importsContaining(input.program, "type=template")) {
602
+ const templateId = await resolveId(ctx, template, input.id);
603
+ if (templateId !== void 0) {
604
+ context.state.templateLinks.set(moduleKey(environment, templateId), scriptId);
605
+ }
606
+ }
607
+ }
608
+ async function setupExposuresFor(context, ctx, input) {
609
+ const environment = ctx.environment?.name ?? "client";
610
+ const [script] = importsContaining(input.program, "type=script");
611
+ const scriptId = script === void 0 ? void 0 : await resolveId(ctx, script, input.id);
612
+ await linkTemplates(context, ctx, input, scriptId ?? input.id);
613
+ if (!input.code.includes("$setup")) return void 0;
614
+ const owner = scriptId ?? context.state.templateLinks.get(moduleKey(environment, input.id));
615
+ if (owner === void 0) return void 0;
616
+ await ctx.load?.({ id: owner });
617
+ return context.state.exposures.get(moduleKey(environment, owner));
618
+ }
619
+
620
+ // src/vite-unread-record.ts
621
+ function isListed(context, pkg) {
622
+ return pkg !== void 0 && Object.hasOwn(context.options.keepFor, pkg);
623
+ }
624
+ var NOT_PARSED = "the module could not be read, so the atoms it names would not ship: it did not parse as JavaScript. TypeScript and JSX must be compiled by Vite's own transform first, so leave oxc on for this file.";
625
+ var TOO_DEEP = "the module could not be read, so the atoms it names would not ship: it is nested too deeply.";
626
+ function unreadableRecord(context, input, text) {
627
+ const { code, id, pkg } = input;
628
+ const file = moduleLabel(context.root, id);
629
+ const problem = {
630
+ kind: "unreadable",
631
+ offset: 0,
632
+ construct: "",
633
+ text,
634
+ file,
635
+ pkg,
636
+ line: 1,
637
+ column: 1
638
+ };
639
+ const isStandingIn = isListed(context, pkg);
640
+ return {
641
+ // The classes written whole need no parse to be found.
642
+ atoms: atomsWrittenIn(code),
643
+ problems: isStandingIn ? [] : [problem],
644
+ suppressed: isStandingIn ? [problem] : [],
645
+ dynamicCalls: [],
646
+ pkg,
647
+ file
648
+ };
649
+ }
650
+ var SOURCE_TYPES = /* @__PURE__ */ new Set(["js", "jsx", "ts", "tsx"]);
651
+ function jsonStrings(code) {
652
+ let parsed2;
653
+ try {
654
+ parsed2 = JSON.parse(code);
655
+ } catch {
656
+ return [];
657
+ }
658
+ const strings = [];
659
+ const stack = [parsed2];
660
+ while (stack.length > 0) {
661
+ const value = stack.pop();
662
+ if (typeof value === "string") strings.push(value);
663
+ else if (Array.isArray(value)) {
664
+ for (const item of value) stack.push(item);
665
+ } else if (typeof value === "object" && value !== null) {
666
+ for (const key of Object.keys(value)) strings.push(key);
667
+ for (const item of Object.values(value)) stack.push(item);
668
+ }
669
+ }
670
+ return strings;
671
+ }
672
+ function textRecord(context, input) {
673
+ const { code, id, moduleType, pkg } = input;
674
+ const decoded = moduleType === "json" ? jsonStrings(code) : [];
675
+ return {
676
+ atoms: new Set(
677
+ [atomsWrittenIn(code), ...decoded.map((text) => atomsWrittenIn(text))].flatMap((found) => [
678
+ ...found
679
+ ])
680
+ ),
681
+ problems: [],
682
+ suppressed: [],
683
+ dynamicCalls: [],
684
+ pkg,
685
+ file: moduleLabel(context.root, id)
686
+ };
687
+ }
688
+
689
+ // src/vite-used.ts
690
+ function createUsedContext(options, extend) {
691
+ return {
692
+ options,
693
+ extend,
694
+ kept: keptAtoms(options),
695
+ packageNames: /* @__PURE__ */ new Map(),
696
+ root: process.cwd(),
697
+ command: "build",
698
+ cacheDir: "",
699
+ buildSourcemap: false,
700
+ inProcess: false,
701
+ isLibrary: false,
702
+ logger: void 0,
703
+ state: stateFor("", {})
704
+ };
705
+ }
706
+ function configureUsed(context, config) {
707
+ context.root = config.root;
708
+ context.command = config.command;
709
+ context.cacheDir = config.cacheDir ?? "";
710
+ context.buildSourcemap = Boolean(config.build?.sourcemap);
711
+ context.inProcess = config.builder !== void 0;
712
+ context.isLibrary = Boolean(config.build?.lib);
713
+ context.logger = config.logger;
714
+ context.state = stateFor(config.root, config);
715
+ }
716
+ function isUsed(context) {
717
+ return context.options.atomic === "used";
718
+ }
719
+ function ignoreWatch() {
720
+ }
721
+ async function ownAtomNames(context, watch = ignoreWatch) {
722
+ try {
723
+ const atoms = await context.extend.current(watch);
724
+ return new Set(Object.keys(atoms).filter((name) => atoms[name]));
725
+ } catch {
726
+ return /* @__PURE__ */ new Set();
727
+ }
728
+ }
729
+
730
+ // src/vite-collect-module.ts
731
+ var ESCAPED_SPECIFIER = /(?:\bfrom|\bimport)[\s(]*(?:'[^'\\\n]*\\|"[^"\\\n]*\\|`[^`\\\n]*\\)/;
732
+ function isMentioningAtoms(code) {
733
+ return code.includes(CX_SOURCE) || code.includes("nave-") || code.includes("$setup") || code.includes("vue&type=") || ESCAPED_SPECIFIER.test(code);
734
+ }
735
+ var NO_PLACE = { line: 0, column: 0 };
736
+ function isInlineScript(id) {
737
+ return /[?&]html-proxy\b/.test(id);
738
+ }
739
+ function lineUnknownNote(context, id) {
740
+ const isBuildWithoutMaps = context.command === "build" && !context.buildSourcemap;
741
+ return isBuildWithoutMaps && !isInlineScript(id) ? LINE_UNKNOWN_WITHOUT_MAP : LINE_UNKNOWN_UNMAPPED;
742
+ }
743
+ function locate(problems, placing) {
744
+ return problems.map((problem) => {
745
+ const place = placing.place(problem.offset);
746
+ const where = place ?? { ...NO_PLACE, unknownLine: placing.unknownLine };
747
+ return { ...problem, file: placing.file, pkg: placing.pkg, moduleId: placing.id, ...where };
748
+ });
749
+ }
750
+ function locateDynamic(reading, placing) {
751
+ return reading.dynamicCalls.map(({ offset, construct }) => {
752
+ const place = placing.place(offset);
753
+ return {
754
+ file: placing.file,
755
+ construct,
756
+ ...place ?? { ...NO_PLACE, unknownLine: placing.unknownLine }
757
+ };
758
+ });
759
+ }
760
+ var COMPILED_LANGS = /* @__PURE__ */ new Map([
761
+ ["jsx", "jsx"],
762
+ ["ts", "ts"],
763
+ ["tsx", "tsx"]
764
+ ]);
765
+ function parseOrUndefined(ctx, code, moduleType) {
766
+ try {
767
+ const lang = moduleType === void 0 ? void 0 : COMPILED_LANGS.get(moduleType);
768
+ return ctx.parse(code, lang && { lang });
769
+ } catch {
770
+ return void 0;
771
+ }
772
+ }
773
+ async function authoredTextOf(id) {
774
+ try {
775
+ return await readFile(filePathOf(id), "utf8");
776
+ } catch {
777
+ return void 0;
778
+ }
779
+ }
780
+ async function recordOf(context, ctx, input, reading) {
781
+ const { code, id, pkg } = input;
782
+ const hasPlaces = reading.problems.length + reading.dynamicCalls.length > 0;
783
+ const map = hasPlaces ? combinedMapOf(ctx) : void 0;
784
+ const authored = map ? await authoredTextOf(id) : void 0;
785
+ const placing = {
786
+ code,
787
+ id,
788
+ file: moduleLabel(context.root, id),
789
+ pkg,
790
+ place: placerFor(code, map, authored),
791
+ unknownLine: lineUnknownNote(context, id)
792
+ };
793
+ const isStandingIn = isListed(context, pkg);
794
+ return {
795
+ atoms: /* @__PURE__ */ new Set([...reading.atoms, ...reading.classes]),
796
+ problems: isStandingIn ? [] : locate(reading.problems, placing),
797
+ suppressed: isStandingIn ? locate(reading.problems, placing) : [],
798
+ dynamicCalls: locateDynamic(reading, placing),
799
+ pkg,
800
+ file: placing.file,
801
+ ...reading.edits.length > 0 && { edits: reading.edits }
802
+ };
803
+ }
804
+ function readOrUndefined(code, program, options) {
805
+ try {
806
+ return readModule(code, program, options);
807
+ } catch (error) {
808
+ if (error instanceof RangeError) return void 0;
809
+ throw error;
810
+ }
811
+ }
812
+ async function recordParsed(context, ctx, input, key) {
813
+ const { code, id, pkg, program, declared } = input;
814
+ const { declaredSources, isDeclared, onlyVia } = await declaredReadingOf(context, ctx, declared, {
815
+ environment: ctx.environment?.name ?? "client",
816
+ module: { code, id, program }
817
+ });
818
+ const reading = readOrUndefined(code, program, {
819
+ cxSources: /* @__PURE__ */ new Set([CX_SOURCE, ...declaredSources]),
820
+ declaredSources,
821
+ isDeclared,
822
+ ownAtoms: await ownAtomNames(context, (file) => {
823
+ ctx.addWatchFile(file);
824
+ }),
825
+ isDependency: isDependencyId(id),
826
+ isVueScript: /\.vue(?:$|\?)/.test(id),
827
+ setup: await setupExposuresFor(context, ctx, { program, code, id }),
828
+ // A build turns each call into the string it returns; the dev server keeps the functions.
829
+ ...context.command === "build" && { rewrite: { keep: keepMap(context.kept) } }
830
+ });
831
+ if (!reading) {
832
+ context.state.exposures.delete(key);
833
+ return unreadableRecord(context, { code, id, pkg }, TOO_DEEP);
834
+ }
835
+ if (reading.exposes.size > 0) context.state.exposures.set(key, reading.exposes);
836
+ else context.state.exposures.delete(key);
837
+ if (pkg !== void 0 && reading.usesCx) context.state.packages.add(pkg);
838
+ const record = await recordOf(context, ctx, { code, id, pkg }, reading);
839
+ return onlyVia === void 0 ? record : { ...record, onlyVia };
840
+ }
841
+ async function recordModule(context, ctx, module) {
842
+ const { code, id, moduleType } = module;
843
+ const environment = ctx.environment?.name ?? "client";
844
+ const key = moduleKey(environment, id);
845
+ const declared = await declaredModulesFor(context, ctx, environment);
846
+ if (!isMentioningAtoms(code) && !isAboutListed({ code, id }, declared)) {
847
+ context.state.modules.delete(key);
848
+ return void 0;
849
+ }
850
+ const isDependency = isDependencyId(id);
851
+ const pkg = isDependency ? await packageNameOf(filePathOf(id), context.packageNames) : void 0;
852
+ if (moduleType !== void 0 && !SOURCE_TYPES.has(moduleType)) {
853
+ context.state.exposures.delete(key);
854
+ const record2 = textRecord(context, { code, id, moduleType, pkg });
855
+ context.state.modules.set(key, record2);
856
+ return record2;
857
+ }
858
+ const program = parseOrUndefined(ctx, code, moduleType);
859
+ const record = program ? await recordParsed(context, ctx, { code, id, pkg, program, declared }, key) : unreadableRecord(context, { code, id, pkg }, NOT_PARSED);
860
+ if (!program) context.state.exposures.delete(key);
861
+ context.state.modules.set(key, record);
862
+ return record;
863
+ }
864
+
865
+ // src/vite-collect-problems.ts
866
+ function listedAtomsOf(record, context) {
867
+ if (record.pkg === void 0) return context.options.keep;
868
+ const { keepFor } = context.options;
869
+ return Object.hasOwn(keepFor, record.pkg) ? keepFor[record.pkg] : [];
870
+ }
871
+ function dynamicProblems(record, context) {
872
+ const isCovered = listedAtomsOf(record, context).length > 0;
873
+ if (isCovered) return [];
874
+ return record.dynamicCalls.map((call) => ({
875
+ kind: "dynamic",
876
+ offset: 0,
877
+ construct: call.construct,
878
+ text: "",
879
+ file: call.file,
880
+ line: call.line,
881
+ column: call.column,
882
+ pkg: record.pkg,
883
+ ...call.unknownLine !== void 0 && { unknownLine: call.unknownLine }
884
+ }));
885
+ }
886
+ function problemsOf(record, context) {
887
+ return [...record.problems, ...dynamicProblems(record, context)];
888
+ }
889
+ function failModule(ctx, context, input) {
890
+ const { home, id, problems } = input;
891
+ const message = moduleReport(problems, context.options.cxModules, home);
892
+ const first = problems[0];
893
+ return ctx.error({
894
+ message,
895
+ id,
896
+ loc: { file: id, line: Math.max(first.line, 1), column: Math.max(first.column - 1, 0) }
897
+ });
898
+ }
899
+ function failDevModule(ctx, context, input) {
900
+ const { home, id, record } = input;
901
+ if (context.command !== "serve" || record.pkg !== void 0) return;
902
+ const problems = problemsOf(record, context);
903
+ if (problems.length > 0) failModule(ctx, context, { home, id, problems });
904
+ }
905
+
906
+ // src/vite-cx-module-lines.ts
907
+ function quoted(specifiers) {
908
+ return specifiers.map((specifier) => `'${specifier}'`).join(", ");
909
+ }
910
+ function applicationLinesOf(item) {
911
+ const entry = `'${item.entry}'`;
912
+ const relative = item.specifiers.filter((specifier) => isRelative(specifier));
913
+ const other = item.specifiers.filter((specifier) => !isRelative(specifier));
914
+ const place = relative.length === 1 ? "its" : "their";
915
+ return {
916
+ relative: relative.length === 0 ? [] : [
917
+ `${item.label}: imports ${entry} as ${quoted(relative)}. Write '${item.replacement}' in ${place} place.`
918
+ ],
919
+ other: other.length === 0 ? [] : [`${item.label}: imports ${entry} as ${quoted(other)}.`],
920
+ none: item.specifiers.length > 0 ? [] : [
921
+ `${item.label}: imports ${entry} through a specifier the build could not find in the file.`
922
+ ]
923
+ };
924
+ }
925
+ function dependencyLineOf(item) {
926
+ const entry = `'${item.entry}'`;
927
+ const found = item.specifiers.length === 0 ? `imports ${entry} through a specifier the build could not find in the file.` : `imports ${entry} as ${quoted(item.specifiers)}.`;
928
+ return `${item.label}: ${found} The file is in ${item.pkg}, a dependency, so it is not yours to change.`;
929
+ }
930
+ var RELATIVE_REMEDY = "Adding a relative specifier to cxModules would not clear this: a relative entry is read from the project root. Instead of the rewrite";
931
+ var TYPESCRIPT_CONDITION = "Where a rewrite ends in .ts, .tsx, .mts or .cts, TypeScript accepts it only if your tsconfig sets allowImportingTsExtensions or rewriteRelativeImportExtensions; if it sets neither, use the alias the line above describes instead.";
932
+ var NO_SPECIFIER_REMEDY = "Where the build could not find the specifier, import the module there by a specifier ending in the listed file's name, or by an alias or package name added to cxModules.";
933
+ function applicationRemedyOf(items, lines, input) {
934
+ const remedy = [];
935
+ const relativeCount = lines.reduce((count, line) => count + line.relative.length, 0);
936
+ if (relativeCount === 1) {
937
+ remedy.push(
938
+ `${RELATIVE_REMEDY} its line gives, the file can import the module through an alias for it, added to cxModules.`
939
+ );
940
+ } else if (relativeCount > 1) {
941
+ remedy.push(
942
+ `${RELATIVE_REMEDY} each line gives, a file can import the module through an alias for it, added to cxModules.`
943
+ );
944
+ }
945
+ const hasTypeScriptRewrite = items.some(
946
+ (item) => item.specifiers.some((specifier) => isRelative(specifier)) && /\.(?:ts|tsx|mts|cts)$/.test(item.replacement)
947
+ );
948
+ if (hasTypeScriptRewrite) remedy.push(TYPESCRIPT_CONDITION);
949
+ if (lines.some((line) => line.none.length > 0)) remedy.push(NO_SPECIFIER_REMEDY);
950
+ const added = [
951
+ ...new Set(
952
+ items.flatMap((item) => item.specifiers.filter((specifier) => !isRelative(specifier)))
953
+ )
954
+ ];
955
+ const array = cxModulesArray(input.configured, added);
956
+ if (array !== void 0) {
957
+ const each = added.length === 1 ? "the specifier" : "each specifier";
958
+ remedy.push(`Add ${each}, as written, to cxModules in ${input.home}: cxModules: ${array}.`);
959
+ }
960
+ return remedy;
961
+ }
962
+ var LASTING_FIX_HERE = "The lasting fix there is the package's: import the module by a specifier ending in the listed file's name.";
963
+ function packageRemedyOf(pkg, files, input) {
964
+ if (input.hasKeepFor) {
965
+ const file = files === 1 ? "a file" : "files";
966
+ return `${pkg} also imports a module listed in cxModules in ${file} the build did not read; the keepFor entry above clears that too. ${LASTING_FIX_HERE}`;
967
+ }
968
+ return `For ${pkg}, list the atoms its calls can produce, from its documentation, under its name in ${input.home}: keepFor: { '${pkg}': ['<atom>'] }. Once the package is listed, its files no longer fail the build here, and the atoms you list stand in for the calls the build did not read. The lasting fix is the package's: import the module by a specifier ending in the listed file's name.`;
969
+ }
970
+ function importerErrorOf(found, input) {
971
+ const application = found.filter((item) => item.pkg === void 0);
972
+ const dependencies = found.filter((item) => item.pkg !== void 0);
973
+ const count = new Set(found.map((item) => item.importer)).size;
974
+ const first = count === 1 ? "1 file imports a module listed in cxModules through a specifier the build does not recognise, so the build did not read the cx() calls made through it." : `${count} files import a module listed in cxModules through a specifier the build does not recognise, so the build did not read the cx() calls made through those specifiers.`;
975
+ const lines = application.map((item) => applicationLinesOf(item));
976
+ const byPackage = Map.groupBy(dependencies, (item) => item.pkg);
977
+ const packages = byPackage.keys().toArray().toSorted(compareText);
978
+ return [
979
+ first,
980
+ ...lines.flatMap((line) => [...line.relative, ...line.other, ...line.none]).toSorted(compareText),
981
+ ...dependencies.map((item) => dependencyLineOf(item)).toSorted(compareText),
982
+ ...applicationRemedyOf(application, lines, input),
983
+ ...packages.map(
984
+ (pkg) => packageRemedyOf(pkg, new Set(byPackage.get(pkg).map((item) => item.importer)).size, {
985
+ hasKeepFor: input.report?.includes(`keepFor: { '${pkg}'`) ?? false,
986
+ home: input.home
987
+ })
988
+ )
989
+ ].join("\n");
990
+ }
991
+ async function isResolvingTo(ctx, input) {
992
+ try {
993
+ const resolved = await ctx.resolve?.(input.specifier, input.from);
994
+ return resolved !== null && resolved !== void 0 && fileOf(resolved.id) === input.file;
995
+ } catch {
996
+ return false;
997
+ }
998
+ }
999
+ function importersOf(ctx, id) {
1000
+ const info = ctx.getModuleInfo?.(id);
1001
+ return [.../* @__PURE__ */ new Set([...info?.importers ?? [], ...info?.dynamicImporters ?? []])];
1002
+ }
1003
+ async function specifiersWritten(ctx, input) {
1004
+ const { file, importer } = input;
1005
+ const code = ctx.getModuleInfo?.(importer)?.code;
1006
+ if (code === null || code === void 0) return [];
1007
+ const written = specifiersOf(ctx, { id: importer, code }) ?? [];
1008
+ const found = [];
1009
+ for (const specifier of written) {
1010
+ if (await isResolvingTo(ctx, { file, from: importer, specifier })) found.push(specifier);
1011
+ }
1012
+ return found;
1013
+ }
1014
+ async function specifiersInto(ctx, context, input) {
1015
+ const found = /* @__PURE__ */ new Set();
1016
+ for (const importer of importersOf(ctx, input.id)) {
1017
+ const owner = isDependencyId(importer) ? await packageNameOf(filePathOf(importer), context.packageNames) : void 0;
1018
+ if (owner === input.pkg) continue;
1019
+ const written = await specifiersWritten(ctx, { file: fileOf(input.id), importer });
1020
+ for (const specifier of written) found.add(specifier);
1021
+ }
1022
+ return found.values().toArray().toSorted(compareText);
1023
+ }
1024
+ async function clearingSpecifier(ctx, context, input) {
1025
+ const from = path2.join(context.root, "index.html");
1026
+ const file = fileOf(input.id);
1027
+ if (await isResolvingTo(ctx, { file, from, specifier: input.pkg })) return input.pkg;
1028
+ const specifiers = await specifiersInto(ctx, context, input);
1029
+ for (const specifier of specifiers) {
1030
+ if (await isResolvingTo(ctx, { file, from, specifier })) return specifier;
1031
+ }
1032
+ return void 0;
1033
+ }
1034
+ async function withClearingSpecifiers(ctx, context, problems) {
1035
+ const asked = /* @__PURE__ */ new Map();
1036
+ const clearing = (pkg, id) => {
1037
+ const known = asked.get(id);
1038
+ if (known) return known;
1039
+ const answer = clearingSpecifier(ctx, context, { id, pkg });
1040
+ asked.set(id, answer);
1041
+ return answer;
1042
+ };
1043
+ const entriesOf = async (id) => {
1044
+ const declared = await declaredModulesFor(context, ctx, ctx.environment.name);
1045
+ return declared ? entriesNaming(declared, id) : [];
1046
+ };
1047
+ const renamed = new Set(
1048
+ problems.flatMap(
1049
+ (problem) => problem.isRenamed === true && problem.moduleId !== void 0 ? [problem.moduleId] : []
1050
+ )
1051
+ );
1052
+ return await Promise.all(
1053
+ problems.map(async (problem) => {
1054
+ const { moduleId, pkg } = problem;
1055
+ if (pkg === void 0 || moduleId === void 0) return problem;
1056
+ if (problem.kind === "declared") return { ...problem, entries: await entriesOf(moduleId) };
1057
+ if (!isListableReexport(problem)) return problem;
1058
+ if (renamed.has(moduleId)) return { ...problem, isRenamed: true };
1059
+ const specifier = await clearing(pkg, moduleId);
1060
+ return specifier === void 0 ? problem : { ...problem, specifier };
1061
+ })
1062
+ );
1063
+ }
1064
+
1065
+ // src/vite-cx-module-importers.ts
1066
+ var RESOLVED_EXTENSIONS = /* @__PURE__ */ new Set([
1067
+ ".js",
1068
+ ".json",
1069
+ ".jsx",
1070
+ ".mjs",
1071
+ ".mts",
1072
+ ".ts",
1073
+ ".tsx"
1074
+ ]);
1075
+ function entryOf(declared, id) {
1076
+ const file = fileOf(id);
1077
+ for (const [entry, resolved] of declared.ids) if (fileOf(resolved) === file) return entry;
1078
+ return id;
1079
+ }
1080
+ async function replacementFor(ctx, input) {
1081
+ const file = fileOf(input.id);
1082
+ const extension = path2.posix.extname(file);
1083
+ const relativeTo = (target) => {
1084
+ const relative = path2.posix.relative(path2.posix.dirname(fileOf(input.importer)), target);
1085
+ return relative.startsWith("../") ? relative : `./${relative}`;
1086
+ };
1087
+ if (!RESOLVED_EXTENSIONS.has(extension)) return relativeTo(file);
1088
+ const short = relativeTo(file.slice(0, -extension.length));
1089
+ const isLanding = await isResolvingTo(ctx, { file, from: input.importer, specifier: short });
1090
+ return isLanding ? short : relativeTo(file);
1091
+ }
1092
+ async function unrecognisedSpecifiers(ctx, input) {
1093
+ const { answers, id, importer, recognised } = input;
1094
+ const known = { cxId: id, answers };
1095
+ const found = [];
1096
+ const unread = (specifiersOf(ctx, importer) ?? []).filter((text) => !recognised?.has(text));
1097
+ for (const specifier of unread) {
1098
+ if (await isResolvingToCx(ctx, specifier, importer, known)) found.push(specifier);
1099
+ }
1100
+ return found;
1101
+ }
1102
+ async function unrecognisedOf(ctx, context, input) {
1103
+ const { answers, declared, id } = input;
1104
+ const importer = await candidateOf(ctx, context, input.importer);
1105
+ if (!importer) return void 0;
1106
+ const recognised = context.state.recognised.get(
1107
+ recognisedKey(ctx.environment.name, fileOf(id), importer.id)
1108
+ );
1109
+ const specifiers = await unrecognisedSpecifiers(ctx, { answers, id, importer, recognised });
1110
+ if (recognised !== void 0 && specifiers.length === 0) return void 0;
1111
+ const pkg = isDependencyId(importer.id) ? await packageNameOf(filePathOf(importer.id), context.packageNames) : void 0;
1112
+ return {
1113
+ importer: importer.id,
1114
+ label: moduleLabel(context.root, importer.id),
1115
+ entry: entryOf(declared, id),
1116
+ specifiers,
1117
+ replacement: pkg === void 0 ? await replacementFor(ctx, { id, importer: importer.id }) : "",
1118
+ pkg
1119
+ };
1120
+ }
1121
+ function listedIdsIn(ctx, declared) {
1122
+ const ids = new Set(declared.ids.values());
1123
+ const graph = ctx.getModuleIds?.() ?? [];
1124
+ for (const id of graph) {
1125
+ if (declared.files.has(fileOf(id))) ids.add(id);
1126
+ }
1127
+ return ids;
1128
+ }
1129
+ function merged(found, item, id) {
1130
+ const key = `${item.importer}\0${fileOf(id)}`;
1131
+ const specifiers = /* @__PURE__ */ new Set([...found.get(key)?.specifiers ?? [], ...item.specifiers]);
1132
+ return [key, { ...item, specifiers: [...specifiers] }];
1133
+ }
1134
+ async function unrecognisedImporters(ctx, context, declared) {
1135
+ const found = /* @__PURE__ */ new Map();
1136
+ for (const id of listedIdsIn(ctx, declared)) {
1137
+ const answers = /* @__PURE__ */ new Map();
1138
+ for (const importer of importerIdsOf(ctx, id)) {
1139
+ const item = await unrecognisedOf(ctx, context, { answers, declared, id, importer });
1140
+ if (item) found.set(...merged(found, item, id));
1141
+ }
1142
+ }
1143
+ return found.values().toArray();
1144
+ }
1145
+ async function declaredImporterError(ctx, context, input) {
1146
+ const declared = await declaredModulesFor(context, ctx, ctx.environment.name);
1147
+ if (!declared) return void 0;
1148
+ const found = await unrecognisedImporters(ctx, context, declared);
1149
+ return found.length === 0 ? void 0 : importerErrorOf(found, input);
1150
+ }
1151
+
1152
+ // src/vite-declared-echoes.ts
1153
+ var ECHO_KINDS = /* @__PURE__ */ new Set([
1154
+ "argument",
1155
+ "dynamic",
1156
+ "own",
1157
+ "reference",
1158
+ "unknown"
1159
+ ]);
1160
+ function withoutEchoes(modules) {
1161
+ const broken = new Set(
1162
+ modules.flatMap(
1163
+ (module) => module.problems.flatMap(
1164
+ (problem) => problem.kind === "declared" && problem.moduleId !== void 0 && !problem.hasNaveCx ? [fileOf(problem.moduleId)] : []
1165
+ )
1166
+ )
1167
+ );
1168
+ const isEcho = (module) => module.onlyVia !== void 0 && [...module.onlyVia].every((file) => broken.has(file));
1169
+ return modules.flatMap(
1170
+ (module) => isEcho(module) ? module.problems.filter((problem) => !ECHO_KINDS.has(problem.kind)) : module.problems
1171
+ );
1172
+ }
1173
+
1174
+ // src/vite-markup.ts
1175
+ var MARKUP_WARNING = `navePlugin(): Nave read no HTML page and no server render, so your pages are likely rendered where it cannot see them, such as in a backend's own templates. A Nave class written there has no rule, in dev or in the build, unless its atom is listed in keep; if most of your Nave classes are written there, set atomic: 'all' to ship every atom. See "Which atoms the build ships" in node_modules/@navecss/core/README.md.`;
1176
+ function isMarkupCase(context) {
1177
+ const { state } = context;
1178
+ return context.options.keep.length === 0 && collectedAtoms(state, []).size === 0 && !state.directiveExpanded && !state.htmlRead && !state.serverTransformed && !context.isLibrary;
1179
+ }
1180
+ function judgeMarkup(context, warn) {
1181
+ const { state } = context;
1182
+ if (!isUsed(context) || state.markupJudged) return;
1183
+ state.markupJudged = true;
1184
+ if (isMarkupCase(context)) warn(MARKUP_WARNING);
1185
+ }
1186
+ function expectBuilds(context, builder, warn) {
1187
+ if (Object.values(builder.environments).some((environment) => environment.isBuilt)) {
1188
+ judgeMarkup(context, warn);
1189
+ return;
1190
+ }
1191
+ context.state.expectedEnvironments = new Set(Object.keys(builder.environments));
1192
+ }
1193
+ function judgeAfterLastEnvironment(context, environment, warn) {
1194
+ const { builtEnvironments, expectedEnvironments } = context.state;
1195
+ builtEnvironments.add(environment.name);
1196
+ const isLast = expectedEnvironments ? [...expectedEnvironments].every((name) => builtEnvironments.has(name)) : !context.inProcess && environment.config.consumer === "client";
1197
+ if (isLast) judgeMarkup(context, warn);
1198
+ }
1199
+
1200
+ // src/vite-dev-judge.ts
1201
+ function isServedAsStylesheet(id) {
1202
+ return isStylesheetId(id) && !/[?&]inline\b/.test(id);
1203
+ }
1204
+ function judge(context) {
1205
+ judgeMarkup(context, (message) => context.logger?.warn(message));
1206
+ }
1207
+ function judgeWhenServed(context, id) {
1208
+ const { state } = context;
1209
+ if (!state.warmedUp || state.requested.has(filePathOf(id))) judge(context);
1210
+ }
1211
+ function stylesheetUrl(request, base) {
1212
+ const url = request.url;
1213
+ if (url === void 0 || !isServedAsStylesheet(url)) return void 0;
1214
+ return base !== "/" && url.startsWith(base) ? `/${url.slice(base.length)}` : url;
1215
+ }
1216
+ async function noteRequest(context, environment, url) {
1217
+ const { state } = context;
1218
+ try {
1219
+ const resolved = await environment.pluginContainer.resolveId(decodeURI(url));
1220
+ if (resolved === null) return;
1221
+ const file = filePathOf(resolved.id);
1222
+ state.requested.add(file);
1223
+ if (state.served.keys().some((id) => filePathOf(id) === file)) judge(context);
1224
+ } catch {
1225
+ }
1226
+ }
1227
+ function noteStylesheetRequests(context, server) {
1228
+ const { state } = context;
1229
+ const environment = server.environments.client;
1230
+ state.warmedUp = environment.config.dev.warmup.length > 0;
1231
+ if (!state.warmedUp) return;
1232
+ server.middlewares.use(async (request, _response, next) => {
1233
+ const url = stylesheetUrl(request, server.config.base);
1234
+ if (url !== void 0 && !state.markupJudged) await noteRequest(context, environment, url);
1235
+ next();
1236
+ });
1237
+ }
1238
+
1239
+ // src/vite-dev-read.ts
1240
+ function graphRoots(environment) {
1241
+ return environment.moduleGraph.idToModuleMap.values().filter(
1242
+ (module) => module.importers.size === 0 && (module.id === null || !isStylesheetId(module.id))
1243
+ ).toArray();
1244
+ }
1245
+ async function transformQuietly(environment, url) {
1246
+ try {
1247
+ await environment.transformRequest(url);
1248
+ } catch {
1249
+ }
1250
+ }
1251
+ async function transformReachable(environment, roots) {
1252
+ const seen = new Set(roots);
1253
+ let level = [...roots];
1254
+ while (level.length > 0) {
1255
+ const next = [];
1256
+ await Promise.all(
1257
+ level.map(async (module) => {
1258
+ if (module.id !== null && isStylesheetId(module.id)) return;
1259
+ await transformQuietly(environment, module.url);
1260
+ for (const imported of module.importedModules) {
1261
+ if (seen.has(imported)) continue;
1262
+ seen.add(imported);
1263
+ next.push(imported);
1264
+ }
1265
+ })
1266
+ );
1267
+ level = next;
1268
+ }
1269
+ }
1270
+
1271
+ // src/vite-dev-update.ts
1272
+ function readerOf(environment) {
1273
+ return {
1274
+ transformRequest: (url) => environment.transformRequest?.(url) ?? Promise.resolve()
1275
+ };
1276
+ }
1277
+ async function readAhead(context, environment, scripts) {
1278
+ const { state } = context;
1279
+ const reader = readerOf(environment);
1280
+ state.readAhead += 1;
1281
+ try {
1282
+ for (const module of scripts) {
1283
+ const known = new Set(module.importedModules);
1284
+ environment.moduleGraph.invalidateModule(module);
1285
+ await transformQuietly(reader, module.url);
1286
+ const added = [...module.importedModules.difference(known)];
1287
+ await transformReachable(reader, added);
1288
+ }
1289
+ } finally {
1290
+ state.readAhead -= 1;
1291
+ }
1292
+ }
1293
+ function takeStaleModules(context, environment) {
1294
+ const { state } = context;
1295
+ const ids = [...state.stale];
1296
+ state.stale.clear();
1297
+ clearTimeout(state.reloadTimer);
1298
+ state.reloadTimer = void 0;
1299
+ const sheets = [];
1300
+ for (const id of ids) {
1301
+ const module = environment.moduleGraph.getModuleById(id);
1302
+ if (!module) continue;
1303
+ noteReloadSent(state, id);
1304
+ sheets.push(module);
1305
+ }
1306
+ return sheets;
1307
+ }
1308
+ async function modulesWithGrownStylesheets(context, ctx, hot) {
1309
+ const { environment } = ctx;
1310
+ if (environment.config?.consumer !== "client" || context.state.served.size === 0) return;
1311
+ const scripts = (hot.modules ?? []).filter((m) => m.id !== null && !isStylesheetId(m.id));
1312
+ if (scripts.length === 0) return;
1313
+ await readAhead(context, environment, scripts);
1314
+ const sheets = takeStaleModules(context, environment);
1315
+ return sheets.length === 0 ? void 0 : [...hot.modules ?? [], ...sheets];
1316
+ }
1317
+
1318
+ // src/vite-css-blocks.ts
1319
+ function matchBraces(tokens) {
1320
+ const matches = /* @__PURE__ */ new Map();
1321
+ const open = [];
1322
+ for (const [index, token] of tokens.entries()) {
1323
+ if (token.type === "{-token") open.push(index);
1324
+ else if (token.type === "}-token" && open.length > 0) matches.set(open.pop(), index);
1325
+ }
1326
+ return matches;
1327
+ }
1328
+ function isBlank(tokens, from, to) {
1329
+ for (let index = from; index < to; index += 1) {
1330
+ const type = tokens[index].type;
1331
+ if (type !== "whitespace-token" && type !== "comment") return false;
1332
+ }
1333
+ return true;
1334
+ }
1335
+ var OPENERS = /* @__PURE__ */ new Set(["(-token", "[-token", "function-token"]);
1336
+ var CLOSERS = /* @__PURE__ */ new Set([")-token", "]-token"]);
1337
+ function readSheet(css) {
1338
+ const tokens = tokenize(css);
1339
+ const matches = matchBraces(tokens);
1340
+ return {
1341
+ tokens,
1342
+ slice: (from, to) => css.slice(tokens[from]?.startIndex ?? css.length, tokens[to - 1]?.endIndex ?? 0),
1343
+ statements(from, to) {
1344
+ const found = [];
1345
+ let start = from;
1346
+ let index = from;
1347
+ let depth = 0;
1348
+ while (index < to) {
1349
+ const type = tokens[index].type;
1350
+ if (OPENERS.has(type)) depth += 1;
1351
+ else if (CLOSERS.has(type)) depth = Math.max(0, depth - 1);
1352
+ const close = type === "{-token" && depth === 0 ? matches.get(index) : void 0;
1353
+ if (close !== void 0 && close < to) {
1354
+ found.push({ from: start, to: close + 1, open: index, close });
1355
+ index = close + 1;
1356
+ start = index;
1357
+ } else if (type === "semicolon-token") {
1358
+ found.push({ from: start, to: index + 1 });
1359
+ index += 1;
1360
+ start = index;
1361
+ } else {
1362
+ index += 1;
1363
+ }
1364
+ }
1365
+ if (!isBlank(tokens, start, to)) found.push({ from: start, to });
1366
+ return found;
1367
+ }
1368
+ };
1369
+ }
1370
+ function firstSignificant(tokens, from, to) {
1371
+ let index = from;
1372
+ while (index < to && isBlank(tokens, index, index + 1)) index += 1;
1373
+ return index;
1374
+ }
1375
+
1376
+ // src/vite-selector-atoms.ts
1377
+ var OPENERS2 = /* @__PURE__ */ new Set(["(-token", "[-token", "function-token"]);
1378
+ var CLOSERS2 = /* @__PURE__ */ new Set([")-token", "]-token"]);
1379
+ function membersOf(sheet, from, to) {
1380
+ const members = [];
1381
+ let start = from;
1382
+ let depth = 0;
1383
+ for (let index = from; index < to; index += 1) {
1384
+ const type = sheet.tokens[index].type;
1385
+ if (OPENERS2.has(type)) depth += 1;
1386
+ else if (CLOSERS2.has(type)) depth -= 1;
1387
+ else if (type === "comma-token" && depth === 0) {
1388
+ members.push([start, index]);
1389
+ start = index + 1;
1390
+ }
1391
+ }
1392
+ members.push([start, to]);
1393
+ return members;
1394
+ }
1395
+ var closings = /* @__PURE__ */ new WeakMap();
1396
+ function closesOf(sheet) {
1397
+ const known = closings.get(sheet);
1398
+ if (known) return known;
1399
+ const closes = /* @__PURE__ */ new Map();
1400
+ const open = [];
1401
+ for (const [index, token] of sheet.tokens.entries()) {
1402
+ if (OPENERS2.has(token.type)) open.push(index);
1403
+ else if (CLOSERS2.has(token.type) && open.length > 0) closes.set(open.pop(), index);
1404
+ }
1405
+ closings.set(sheet, closes);
1406
+ return closes;
1407
+ }
1408
+ function afterGroup(sheet, index, to) {
1409
+ return Math.min((closesOf(sheet).get(index) ?? to - 1) + 1, to);
1410
+ }
1411
+ function isTransparentList(sheet, index) {
1412
+ const token = sheet.tokens[index];
1413
+ if (token.type !== "function-token" || sheet.tokens[index - 1]?.type !== "colon-token") {
1414
+ return false;
1415
+ }
1416
+ const name = token.structured.value.toLowerCase();
1417
+ return name === "is" || name === "where";
1418
+ }
1419
+ function atomAt(sheet, index, to) {
1420
+ const name = sheet.tokens[index + 1];
1421
+ if (index + 1 >= to || name?.type !== "ident-token") return void 0;
1422
+ const dot = sheet.tokens[index];
1423
+ if (dot.type !== "delim-token" || dot.raw !== ".") return void 0;
1424
+ return atomOfClass(name.structured.value);
1425
+ }
1426
+ function atomsNamedBy(sheet, from, to) {
1427
+ const atoms = [];
1428
+ let index = from;
1429
+ while (index < to) {
1430
+ const isGroup = OPENERS2.has(sheet.tokens[index].type);
1431
+ if (isGroup && !isTransparentList(sheet, index)) {
1432
+ index = afterGroup(sheet, index, to);
1433
+ continue;
1434
+ }
1435
+ const atom = isGroup ? void 0 : atomAt(sheet, index, to);
1436
+ if (atom) atoms.push(atom);
1437
+ index += 1;
1438
+ }
1439
+ return atoms;
1440
+ }
1441
+ var newNeeds = () => ({ parts: [], size: 0 });
1442
+ var newList = () => ({ finished: [], current: newNeeds() });
1443
+ function closeList(done, parent) {
1444
+ const all = [...done.finished, done.current];
1445
+ if (all.some((needs) => needs.size === 0)) return;
1446
+ for (const needs of all) {
1447
+ parent.current.parts.push(needs.parts);
1448
+ parent.current.size += needs.size;
1449
+ }
1450
+ }
1451
+ function flatten(parts) {
1452
+ const atoms = [];
1453
+ const stack = [parts];
1454
+ while (stack.length > 0) {
1455
+ const part = stack.pop();
1456
+ if (typeof part === "string") atoms.push(part);
1457
+ else for (let index = part.length - 1; index >= 0; index -= 1) stack.push(part[index]);
1458
+ }
1459
+ return atoms;
1460
+ }
1461
+ function readToken(sheet, index, limit, lists) {
1462
+ const type = sheet.tokens[index].type;
1463
+ const list = lists.at(-1);
1464
+ const isNested = lists.length > 1;
1465
+ if (OPENERS2.has(type)) {
1466
+ if (!isTransparentList(sheet, index)) return afterGroup(sheet, index, limit.to);
1467
+ lists.push(newList());
1468
+ } else if (isNested && type === ")-token") {
1469
+ closeList(lists.pop(), lists.at(-1));
1470
+ } else if (isNested && type === "comma-token") {
1471
+ list.finished.push(list.current);
1472
+ list.current = newNeeds();
1473
+ } else {
1474
+ const atom = atomAt(sheet, index, limit.to);
1475
+ if (atom && !limit.emitted.has(atom)) {
1476
+ list.current.parts.push(atom);
1477
+ list.current.size += 1;
1478
+ }
1479
+ }
1480
+ return index + 1;
1481
+ }
1482
+ function blockersOf(sheet, from, to, emitted) {
1483
+ const lists = [newList()];
1484
+ let index = from;
1485
+ while (index < to) index = readToken(sheet, index, { emitted, to }, lists);
1486
+ while (lists.length > 1) closeList(lists.pop(), lists.at(-1));
1487
+ return flatten(lists[0].current.parts);
1488
+ }
1489
+
1490
+ // src/vite-prune.ts
1491
+ var GROUPS = /* @__PURE__ */ new Set([
1492
+ "container",
1493
+ "document",
1494
+ "layer",
1495
+ "media",
1496
+ "scope",
1497
+ "starting-style",
1498
+ "supports"
1499
+ ]);
1500
+ function atKeywordAt(sheet, index) {
1501
+ const token = sheet.tokens[index];
1502
+ if (token?.type !== "at-keyword-token") return void 0;
1503
+ return token.structured.value.toLowerCase();
1504
+ }
1505
+ function isAtomicLayer(sheet, statement) {
1506
+ if (statement.open === void 0) return false;
1507
+ const significant = [];
1508
+ for (let index = statement.from; index < statement.open; index += 1) {
1509
+ const type = sheet.tokens[index].type;
1510
+ if (type !== "whitespace-token" && type !== "comment") significant.push(index);
1511
+ }
1512
+ const name = sheet.tokens[significant[1] ?? -1];
1513
+ return significant.length === 2 && atKeywordAt(sheet, significant[0]) === "layer" && name?.type === "ident-token" && name.structured.value === "atomic";
1514
+ }
1515
+ var CONDITIONALS = /* @__PURE__ */ new Set(["container", "document", "media", "scope", "supports"]);
1516
+ function layerBlocks(sheet, from, to) {
1517
+ const found = [];
1518
+ for (const statement of sheet.statements(from, to)) {
1519
+ const { open, close } = statement;
1520
+ if (open === void 0 || close === void 0) continue;
1521
+ if (isAtomicLayer(sheet, statement)) found.push(statement);
1522
+ else {
1523
+ const keyword = atKeywordAt(sheet, firstSignificant(sheet.tokens, statement.from, open));
1524
+ if (keyword !== void 0 && CONDITIONALS.has(keyword)) {
1525
+ found.push(...layerBlocks(sheet, open + 1, close));
1526
+ }
1527
+ }
1528
+ }
1529
+ return found;
1530
+ }
1531
+ function isEmptyRegion(sheet, from, to) {
1532
+ return sheet.statements(from, to).length === 0;
1533
+ }
1534
+ function pruneRule(sheet, statement, emitted) {
1535
+ const { from, open, close } = statement;
1536
+ const first = firstSignificant(sheet.tokens, from, open);
1537
+ const members = membersOf(sheet, first, open);
1538
+ const kept = members.filter(([start, end]) => blockersOf(sheet, start, end, emitted).length === 0);
1539
+ if (kept.length === members.length) return sheet.slice(from, close + 1);
1540
+ if (kept.length === 0) return "";
1541
+ let trailing = open;
1542
+ while (trailing > first && firstSignificant(sheet.tokens, trailing - 1, trailing) === trailing) {
1543
+ trailing -= 1;
1544
+ }
1545
+ const list = sheet.slice(first, trailing);
1546
+ const separator = /,\s/.test(list) ? ", " : ",";
1547
+ const text = kept.map(([start, end]) => sheet.slice(start, end).trim()).join(separator);
1548
+ return `${sheet.slice(from, first)}${text}${sheet.slice(trailing, open)}${sheet.slice(open, close + 1)}`;
1549
+ }
1550
+ function pruneRegion(sheet, from, to, emitted) {
1551
+ const statements = sheet.statements(from, to);
1552
+ let out = "";
1553
+ for (const statement of statements) out += pruneStatement(sheet, statement, emitted);
1554
+ const last = statements.at(-1);
1555
+ return last ? out + sheet.slice(last.to, to) : sheet.slice(from, to);
1556
+ }
1557
+ function pruneStatement(sheet, statement, emitted) {
1558
+ const { open, close } = statement;
1559
+ if (open === void 0 || close === void 0) return sheet.slice(statement.from, statement.to);
1560
+ const first = firstSignificant(sheet.tokens, statement.from, open);
1561
+ const keyword = atKeywordAt(sheet, first);
1562
+ if (keyword === void 0) return pruneRule(sheet, statement, emitted);
1563
+ if (!GROUPS.has(keyword)) return sheet.slice(statement.from, close + 1);
1564
+ if (isEmptyRegion(sheet, open + 1, close)) return sheet.slice(statement.from, close + 1);
1565
+ const inner = pruneRegion(sheet, open + 1, close, emitted);
1566
+ if (inner.trim() === "") return "";
1567
+ return `${sheet.slice(statement.from, open + 1)}${inner}}`;
1568
+ }
1569
+ function pruneAtomicLayer(css, emitted) {
1570
+ if (!css.includes("@")) return css;
1571
+ const sheet = readSheet(css);
1572
+ let out = "";
1573
+ let cursor = 0;
1574
+ for (const statement of layerBlocks(sheet, 0, sheet.tokens.length)) {
1575
+ const { open, close } = statement;
1576
+ out += sheet.slice(cursor, open + 1) + pruneRegion(sheet, open + 1, close, emitted);
1577
+ cursor = close;
1578
+ }
1579
+ return cursor === 0 ? css : out + sheet.slice(cursor, sheet.tokens.length);
1580
+ }
1581
+ function visitMembers(sheet, from, to, visit) {
1582
+ for (const statement of sheet.statements(from, to)) {
1583
+ const { open, close } = statement;
1584
+ if (open === void 0 || close === void 0) continue;
1585
+ const first = firstSignificant(sheet.tokens, statement.from, open);
1586
+ const keyword = atKeywordAt(sheet, first);
1587
+ if (keyword === void 0) {
1588
+ for (const [start, end] of membersOf(sheet, first, open)) visit(start, end);
1589
+ } else if (GROUPS.has(keyword)) {
1590
+ visitMembers(sheet, open + 1, close, visit);
1591
+ }
1592
+ }
1593
+ }
1594
+ function inspectAtomicLayer(css) {
1595
+ const atoms = /* @__PURE__ */ new Set();
1596
+ if (!css.includes("@")) return { hasLayer: false, atoms };
1597
+ const sheet = readSheet(css);
1598
+ const blocks = layerBlocks(sheet, 0, sheet.tokens.length);
1599
+ for (const { open, close } of blocks) {
1600
+ visitMembers(sheet, open + 1, close, (start, end) => {
1601
+ for (const atom of atomsNamedBy(sheet, start, end)) atoms.add(atom);
1602
+ });
1603
+ }
1604
+ return { hasLayer: blocks.length > 0, atoms };
1605
+ }
1606
+ function unprunedAtoms(css, emitted) {
1607
+ if (!css.includes("@")) return [];
1608
+ const atoms = /* @__PURE__ */ new Set();
1609
+ const sheet = readSheet(css);
1610
+ for (const { open, close } of layerBlocks(sheet, 0, sheet.tokens.length)) {
1611
+ visitMembers(sheet, open + 1, close, (start, end) => {
1612
+ for (const atom of blockersOf(sheet, start, end, emitted)) atoms.add(atom);
1613
+ });
1614
+ }
1615
+ return [...atoms].toSorted((a, b) => a.localeCompare(b));
1616
+ }
1617
+
1618
+ // src/vite-dev.ts
1619
+ var RELOAD_ANSWER_MS = 2e3;
1620
+ var NO_MAP = JSON.stringify({ mappings: "" });
1621
+ var DIRECT = /[?&]direct\b/;
1622
+ function isInlinedInHtml(module) {
1623
+ return module.id !== null && /[?&]html-proxy\b/.test(module.id);
1624
+ }
1625
+ async function reloadQuietly(environment, module) {
1626
+ try {
1627
+ if (isInlinedInHtml(module)) environment.hot.send({ type: "full-reload", path: "*" });
1628
+ else await environment.reloadModule(module);
1629
+ } catch {
1630
+ }
1631
+ }
1632
+ function reloadStale(context) {
1633
+ const { state } = context;
1634
+ state.reloadTimer = void 0;
1635
+ const ids = [...state.stale];
1636
+ state.stale.clear();
1637
+ for (const id of ids) {
1638
+ const sheet = state.served.get(id);
1639
+ const module = sheet?.environment.moduleGraph.getModuleById(id);
1640
+ if (!sheet || !module) continue;
1641
+ noteReloadSent(state, id);
1642
+ void reloadQuietly(sheet.environment, module);
1643
+ }
1644
+ }
1645
+ function isReloading(context, id) {
1646
+ const sent = context.state.reloading.get(id);
1647
+ return sent !== void 0 && Date.now() - sent < RELOAD_ANSWER_MS;
1648
+ }
1649
+ function reloadOutgrown(context, ids) {
1650
+ const { state } = context;
1651
+ const atoms = servedAtoms(state, context.kept);
1652
+ for (const id of ids) {
1653
+ const sheet = state.served.get(id);
1654
+ if (sheet && !atoms.isSubsetOf(sheet.atoms) && !isReloading(context, id)) state.stale.add(id);
1655
+ }
1656
+ if (state.stale.size > 0 && state.reloadTimer === void 0 && state.readAhead === 0) {
1657
+ state.reloadTimer = setTimeout(() => {
1658
+ reloadStale(context);
1659
+ }, 0);
1660
+ state.reloadTimer.unref();
1661
+ }
1662
+ }
1663
+ var devServing = {
1664
+ modulesWithGrown: modulesWithGrownStylesheets,
1665
+ async hold(environment, id) {
1666
+ const module = environment.moduleGraph.getModuleById(id);
1667
+ if (!module) return;
1668
+ if (module.importers.size === 0 && DIRECT.test(id)) return;
1669
+ await environment.waitForRequestsIdle(id);
1670
+ await transformReachable(environment, graphRoots(environment));
1671
+ },
1672
+ notePages(context) {
1673
+ const { state } = context;
1674
+ const atoms = servedAtoms(state, context.kept);
1675
+ for (const sheet of state.served) {
1676
+ const [id, { atoms: served, environment }] = sheet;
1677
+ if (atoms.isSubsetOf(served)) continue;
1678
+ const module = environment.moduleGraph.getModuleById(id);
1679
+ if (module) environment.moduleGraph.invalidateModule(module);
1680
+ }
1681
+ devServing.noteGrowth(context);
1682
+ },
1683
+ noteConnect(context) {
1684
+ const { state } = context;
1685
+ state.listening += 1;
1686
+ if (state.unheard.size === 0) return;
1687
+ const ids = [...state.unheard];
1688
+ state.unheard.clear();
1689
+ for (const id of ids) state.reloading.delete(id);
1690
+ reloadOutgrown(context, ids);
1691
+ },
1692
+ noteDisconnect(context) {
1693
+ const { state } = context;
1694
+ state.listening = Math.max(0, state.listening - 1);
1695
+ },
1696
+ noteGrowth(context) {
1697
+ if (context.state.served.size === 0) return;
1698
+ reloadOutgrown(context, context.state.served.keys());
1699
+ }
1700
+ };
1701
+ async function serveStylesheet(context, ctx, stylesheet) {
1702
+ const { css, id } = stylesheet;
1703
+ const { environment } = ctx;
1704
+ if (!environment || !isServedAsStylesheet(id)) return void 0;
1705
+ const isPossible = css.includes("\\") || /layer/i.test(css);
1706
+ if (!isPossible || !inspectAtomicLayer(css).hasLayer) return void 0;
1707
+ const dev = environment;
1708
+ if (environment.config.consumer === "client") await devServing.hold(dev, id);
1709
+ judgeWhenServed(context, id);
1710
+ if (environment.config.consumer !== "client") return void 0;
1711
+ const atoms = servedAtoms(context.state, context.kept);
1712
+ context.state.served.set(id, { environment: dev, atoms });
1713
+ context.state.reloading.delete(id);
1714
+ return { code: pruneAtomicLayer(css, atoms), map: NO_MAP };
1715
+ }
1716
+ var HANDSHAKE_FILE = "nave-used-atoms.json";
1717
+ function handshakePath(cacheDir) {
1718
+ return path2.join(cacheDir, HANDSHAKE_FILE);
1719
+ }
1720
+ function readHandshake(cacheDir) {
1721
+ if (cacheDir === "") return void 0;
1722
+ try {
1723
+ const parsed2 = JSON.parse(readFileSync(handshakePath(cacheDir), "utf8"));
1724
+ return Array.isArray(parsed2.emitted) && typeof parsed2.writer === "string" ? parsed2 : void 0;
1725
+ } catch {
1726
+ return void 0;
1727
+ }
1728
+ }
1729
+ function writeHandshake(cacheDir, fields, warn) {
1730
+ if (cacheDir === "") return;
1731
+ const handshake = {
1732
+ ...fields,
1733
+ emitted: [...fields.emitted].toSorted(compareText),
1734
+ writtenAt: fields.writtenAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1735
+ build: fields.build ?? randomUUID()
1736
+ };
1737
+ try {
1738
+ mkdirSync(cacheDir, { recursive: true });
1739
+ writeFileSync(handshakePath(cacheDir), `${JSON.stringify(handshake, void 0, 2)}
1740
+ `);
1741
+ } catch (error) {
1742
+ const reason = error instanceof Error ? error.message : String(error);
1743
+ warn?.(
1744
+ `navePlugin(): could not write ${handshakePath(cacheDir)} (${reason}), so a build of the client and a build of the server run as two processes cannot share their atoms.`
1745
+ );
1746
+ }
1747
+ }
1748
+
1749
+ // src/vite-emitted.ts
1750
+ function positionText(place) {
1751
+ return place.line === 0 ? place.file : `${place.file}:${place.line}:${place.column}`;
1752
+ }
1753
+ function packageRecords(context) {
1754
+ const records = {};
1755
+ for (const pkg of Object.keys(context.options.keepFor)) {
1756
+ const modules = context.state.modules.values().filter((record) => record.pkg === pkg).toArray();
1757
+ const places = modules.flatMap((record) => [...record.suppressed, ...record.dynamicCalls]);
1758
+ records[pkg] = {
1759
+ collected: [...new Set(modules.flatMap((record) => [...record.atoms]))].toSorted(compareText),
1760
+ unreadable: places.map((place) => positionText(place))
1761
+ };
1762
+ }
1763
+ return records;
1764
+ }
1765
+ function unmatchedKeys(context) {
1766
+ const transformed = new Set(context.state.modules.values().map((record) => record.pkg));
1767
+ return Object.keys(context.options.keepFor).filter((pkg) => !transformed.has(pkg));
1768
+ }
1769
+ function takenFromCache(context) {
1770
+ const file = context.inProcess ? void 0 : readHandshake(context.cacheDir);
1771
+ if (file === void 0) return { atoms: [], took: false };
1772
+ if (file.writer !== "client") return { atoms: file.emitted, took: true };
1773
+ const pending = file.pending ?? [];
1774
+ return { atoms: pending, took: pending.length > 0 };
1775
+ }
1776
+ function emittedSet(context, environment, warn) {
1777
+ const { state } = context;
1778
+ if (state.emitted) return state.emitted;
1779
+ const atoms = collectedAtoms(state, context.kept);
1780
+ if (environment.config.consumer !== "client") return atoms;
1781
+ const taken = takenFromCache(context);
1782
+ for (const atom of taken.atoms) atoms.add(atom);
1783
+ withRestorers(atoms);
1784
+ state.emitted = atoms;
1785
+ writeHandshake(
1786
+ context.cacheDir,
1787
+ {
1788
+ emitted: [...atoms],
1789
+ writer: "client",
1790
+ consumed: taken.took,
1791
+ keepFor: packageRecords(context),
1792
+ unmatchedKeepFor: unmatchedKeys(context)
1793
+ },
1794
+ warn
1795
+ );
1796
+ return atoms;
1797
+ }
1798
+ function namingLines(ctx, context, atoms) {
1799
+ return recordsOf(context.state, ctx.environment.name).flatMap(
1800
+ (record) => atoms.filter((atom) => record.atoms.has(atom)).map((atom) => `${record.file}: names ${atom}.`)
1801
+ );
1802
+ }
1803
+ function missingFromClient(ctx, context, missing) {
1804
+ return [
1805
+ "The client build already wrote its CSS without atoms this server build names, so their rules are missing from it:",
1806
+ ...namingLines(ctx, context, missing),
1807
+ `They are recorded in ${handshakePath(context.cacheDir)} for the next client build. List the atoms in keep in navePlugin(), or build the client again, then the server (vite build, then vite build --ssr). To keep this from recurring, build the server first, then the client (vite build --ssr, then vite build).`
1808
+ ].join("\n");
1809
+ }
1810
+ function notInLastClient(ctx, context, missing) {
1811
+ return [
1812
+ `${handshakePath(context.cacheDir)} was written by a client build that was already used, so this server build could not be checked against the CSS. These atoms it names are not in that client build's set:`,
1813
+ ...namingLines(ctx, context, missing),
1814
+ "They are recorded in that file for a client build that runs next; to have them in the CSS, build the server first, then the client (vite build --ssr, then vite build)."
1815
+ ].join("\n");
1816
+ }
1817
+ function recordForNextClient(ctx, context, atoms, held) {
1818
+ writeHandshake(
1819
+ context.cacheDir,
1820
+ { emitted: [...withRestorers(new Set(atoms))], writer: ctx.environment.name, consumed: false },
1821
+ (message) => ctx.warn(message)
1822
+ );
1823
+ const missing = [...atoms].filter((atom) => !held.includes(atom)).toSorted(compareText);
1824
+ if (missing.length > 0) ctx.warn(notInLastClient(ctx, context, missing));
1825
+ }
1826
+ function checkWaitingClient(ctx, context, atoms, file) {
1827
+ const missing = [...atoms].filter((atom) => !file.emitted.includes(atom)).toSorted(compareText);
1828
+ if (missing.length === 0) {
1829
+ writeHandshake(context.cacheDir, { ...file, consumed: true, pending: [] }, (message) => {
1830
+ ctx.warn(message);
1831
+ });
1832
+ return;
1833
+ }
1834
+ const pending = [.../* @__PURE__ */ new Set([...file.pending ?? [], ...withRestorers(new Set(atoms))])];
1835
+ writeHandshake(context.cacheDir, { ...file, pending }, (message) => ctx.warn(message));
1836
+ ctx.error(missingFromClient(ctx, context, missing));
1837
+ }
1838
+ function checkServerInvocation(ctx, context) {
1839
+ if (context.cacheDir === "" || context.inProcess || context.state.emitted) return;
1840
+ const atoms = new Set(recordsOf(context.state, ctx.environment.name).flatMap((r) => [...r.atoms]));
1841
+ const file = readHandshake(context.cacheDir);
1842
+ if (file?.writer !== "client") {
1843
+ const emitted = [...withRestorers(/* @__PURE__ */ new Set([...atoms, ...file?.emitted ?? []]))];
1844
+ writeHandshake(
1845
+ context.cacheDir,
1846
+ { emitted, writer: ctx.environment.name, consumed: false },
1847
+ (message) => ctx.warn(message)
1848
+ );
1849
+ } else if (file.consumed) {
1850
+ recordForNextClient(ctx, context, atoms, file.emitted);
1851
+ } else {
1852
+ checkWaitingClient(ctx, context, atoms, file);
1853
+ }
1854
+ }
1855
+
1856
+ // src/vite-cx-reexported.ts
1857
+ function declaredNames(pattern) {
1858
+ const found = [];
1859
+ const stack = pattern ? [pattern] : [];
1860
+ while (stack.length > 0) {
1861
+ const node = stack.pop();
1862
+ if (node.type === "Identifier") {
1863
+ found.push(stringAt(node, "name") ?? "");
1864
+ } else if (node.type === "AssignmentPattern") {
1865
+ pushAll(
1866
+ stack,
1867
+ [nodeAt(node, "left")].filter((part) => part !== void 0)
1868
+ );
1869
+ } else {
1870
+ const single = ["argument", "value"].map((key) => nodeAt(node, key));
1871
+ const lists = ["properties", "elements"].flatMap((key) => nodesAt(node, key));
1872
+ pushAll(
1873
+ stack,
1874
+ single.filter((part) => part !== void 0)
1875
+ );
1876
+ pushAll(stack, lists);
1877
+ }
1878
+ }
1879
+ return found;
1880
+ }
1881
+ function ownExports(program) {
1882
+ const found = /* @__PURE__ */ new Set();
1883
+ for (const statement of nodesAt(program, "body")) {
1884
+ const namespace = statement.type === "ExportAllDeclaration" ? exportNameOf(nodeAt(statement, "exported")) : void 0;
1885
+ if (namespace !== void 0) found.add(namespace);
1886
+ if (statement.type !== "ExportNamedDeclaration") continue;
1887
+ const declaration = nodeAt(statement, "declaration");
1888
+ const declared = nodesAt(declaration ?? statement, "declarations").flatMap(
1889
+ (declarator) => declaredNames(nodeAt(declarator, "id"))
1890
+ );
1891
+ for (const name of [...declared, ...declaredNames(declaration && nodeAt(declaration, "id"))]) {
1892
+ found.add(name);
1893
+ }
1894
+ for (const specifier of nodesAt(statement, "specifiers")) {
1895
+ const name = exportNameOf(nodeAt(specifier, "exported"));
1896
+ if (name !== void 0) found.add(name);
1897
+ }
1898
+ }
1899
+ return found;
1900
+ }
1901
+ function exportedBy(node, source, own) {
1902
+ const from = staticStringOf(nodeAt(node, "source"));
1903
+ if (from === void 0 || !source.reaches.has(from)) return [];
1904
+ if (node.type === "ExportAllDeclaration") {
1905
+ const namespace = exportNameOf(nodeAt(node, "exported"));
1906
+ if (namespace !== void 0) return [namespace];
1907
+ return source.names.values().filter((name) => name !== "default" && !own.has(name) && !source.rivals.has(name)).toArray();
1908
+ }
1909
+ return nodesAt(node, "specifiers").flatMap((specifier) => {
1910
+ const local = exportNameOf(nodeAt(specifier, "local"));
1911
+ const exported = exportNameOf(nodeAt(specifier, "exported"));
1912
+ return local !== void 0 && exported !== void 0 && source.names.has(local) ? [exported] : [];
1913
+ });
1914
+ }
1915
+ function isImportedFrom(binding, source) {
1916
+ if (binding?.kind !== "import" || binding.source === void 0) return false;
1917
+ if (!source.reaches.has(binding.source)) return false;
1918
+ return binding.imported === "*" || source.names.has(binding.imported ?? "");
1919
+ }
1920
+ function exportedAs(analysis, reference) {
1921
+ const parent = analysis.parentOf.get(reference.node);
1922
+ if (parent?.type === "ExportDefaultDeclaration") return "default";
1923
+ return parent?.type === "ExportSpecifier" ? exportNameOf(nodeAt(parent, "exported")) : void 0;
1924
+ }
1925
+ function starSources(program) {
1926
+ return nodesAt(program, "body").flatMap((statement) => {
1927
+ const source = staticStringOf(nodeAt(statement, "source"));
1928
+ const isStar = statement.type === "ExportAllDeclaration" && !nodeAt(statement, "exported");
1929
+ return isStar && source !== void 0 ? [source] : [];
1930
+ });
1931
+ }
1932
+ function reexportedNames(program, source) {
1933
+ const found = /* @__PURE__ */ new Set();
1934
+ const own = ownExports(program);
1935
+ const stack = [program];
1936
+ while (stack.length > 0) {
1937
+ const node = stack.pop();
1938
+ if (node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") {
1939
+ for (const name of exportedBy(node, source, own)) found.add(name);
1940
+ }
1941
+ pushAll(stack, childrenOf(node));
1942
+ }
1943
+ const analysis = analyze(program);
1944
+ for (const reference of analysis.references) {
1945
+ const name = isImportedFrom(reference.binding, source) ? exportedAs(analysis, reference) : void 0;
1946
+ if (name !== void 0) found.add(name);
1947
+ }
1948
+ return [...found];
1949
+ }
1950
+
1951
+ // src/vite-cx-star-exports.ts
1952
+ function resolvedFile(ctx, resolutions, input) {
1953
+ const key = `${input.id}\0${input.specifier}`;
1954
+ const known = resolutions.get(key);
1955
+ if (known) return known;
1956
+ const asked = (async () => {
1957
+ try {
1958
+ const resolved = await ctx.resolve?.(input.specifier, input.id);
1959
+ return resolved ? fileOf(resolved.id) : void 0;
1960
+ } catch {
1961
+ return void 0;
1962
+ }
1963
+ })();
1964
+ resolutions.set(key, asked);
1965
+ return asked;
1966
+ }
1967
+ function ownNamesOf(program, file, cxExports) {
1968
+ const found = { names: ownExports(program), cx: /* @__PURE__ */ new Set() };
1969
+ for (const name of found.names) {
1970
+ if (cxExports.get(file)?.has(name)) found.cx.add(name);
1971
+ }
1972
+ return found;
1973
+ }
1974
+ function unreadProgram(ctx, input) {
1975
+ const { file, seen } = input;
1976
+ const code = ctx.getModuleInfo?.(file)?.code;
1977
+ const isUnread = !seen.has(file) && typeof code === "string";
1978
+ seen.add(file);
1979
+ return isUnread ? ctx.parse?.(code) : void 0;
1980
+ }
1981
+ async function addStars(ctx, input) {
1982
+ const { found, file, program, walk } = input;
1983
+ for (const specifier of starSources(program)) {
1984
+ const star = await resolvedFile(ctx, walk.resolutions, { id: file, specifier });
1985
+ const below = star ? await exportsOf(ctx, { file: star, walk }) : void 0;
1986
+ const names = below ? [...below.names] : [];
1987
+ for (const name of names) {
1988
+ found.names.add(name);
1989
+ if (below?.cx.has(name)) found.cx.add(name);
1990
+ }
1991
+ }
1992
+ }
1993
+ async function exportsOf(ctx, input) {
1994
+ const { file, walk } = input;
1995
+ const program = unreadProgram(ctx, { file, seen: walk.seen });
1996
+ if (!program) return { names: /* @__PURE__ */ new Set(), cx: /* @__PURE__ */ new Set() };
1997
+ const found = ownNamesOf(program, file, walk.cxExports);
1998
+ await addStars(ctx, { found, file, program, walk });
1999
+ return found;
2000
+ }
2001
+ async function rivalsOf(ctx, input) {
2002
+ const { cxExports, id, program, reaches, resolutions } = input;
2003
+ const rivals = /* @__PURE__ */ new Set();
2004
+ const others = starSources(program).filter((text) => !reaches.has(text));
2005
+ for (const specifier of others) {
2006
+ const file = await resolvedFile(ctx, resolutions, { id, specifier });
2007
+ const walk = { cxExports, resolutions, seen: /* @__PURE__ */ new Set() };
2008
+ const exported = file ? await exportsOf(ctx, { file, walk }) : void 0;
2009
+ const names = exported ? [...exported.names] : [];
2010
+ const own = names.filter((text) => !exported?.cx.has(text));
2011
+ for (const name of own) rivals.add(name);
2012
+ }
2013
+ return rivals;
2014
+ }
2015
+
2016
+ // src/vite-listed-holders.ts
2017
+ async function reachingSpecifiers(ctx, input) {
2018
+ const { code, file, id, resolutions } = input;
2019
+ const program = ctx.parse?.(code);
2020
+ if (!program) return void 0;
2021
+ const reaches = /* @__PURE__ */ new Set();
2022
+ for (const specifier of specifiersIn(program)) {
2023
+ if (await resolvedFile(ctx, resolutions, { id, specifier }) === file) reaches.add(specifier);
2024
+ }
2025
+ return { program, reaches };
2026
+ }
2027
+ async function reexportedBy(ctx, input) {
2028
+ const code = ctx.getModuleInfo?.(input.id)?.code;
2029
+ if (code === null || code === void 0) return [];
2030
+ try {
2031
+ const read = await reachingSpecifiers(ctx, { ...input, code });
2032
+ if (!read || read.reaches.size === 0) return [];
2033
+ const { program, reaches } = read;
2034
+ const rivals = await rivalsOf(ctx, { ...input, program, reaches });
2035
+ return reexportedNames(program, { names: input.names, reaches, rivals });
2036
+ } catch {
2037
+ return [];
2038
+ }
2039
+ }
2040
+ async function reexportsOf(ctx, input) {
2041
+ const importers = importersOf(ctx, input.id).filter((importer) => isDependencyId(importer));
2042
+ const found = /* @__PURE__ */ new Map();
2043
+ for (const importer of importers) {
2044
+ const added = await reexportedBy(ctx, { ...input, file: fileOf(input.id), id: importer });
2045
+ if (added.length > 0) found.set(importer, added);
2046
+ }
2047
+ return found;
2048
+ }
2049
+ async function holdersOf(ctx, origin) {
2050
+ const held = /* @__PURE__ */ new Map([[origin.id, origin.names]]);
2051
+ const queue = [origin.id];
2052
+ while (queue.length > 0) {
2053
+ const id = queue.shift();
2054
+ const reexports = await reexportsOf(ctx, {
2055
+ cxExports: origin.cxExports,
2056
+ id,
2057
+ names: held.get(id),
2058
+ resolutions: origin.resolutions
2059
+ });
2060
+ for (const [importer, added] of reexports) {
2061
+ const known = held.get(importer) ?? /* @__PURE__ */ new Set();
2062
+ const isNew = importer !== origin.id && added.some((name) => !known.has(name));
2063
+ if (isNew) {
2064
+ held.set(importer, /* @__PURE__ */ new Set([...known, ...added]));
2065
+ queue.push(importer);
2066
+ }
2067
+ }
2068
+ }
2069
+ return held.entries().map(([id, names]) => ({ id, names, isReached: id !== origin.id })).toArray();
2070
+ }
2071
+
2072
+ // src/vite-cx-take-keys.ts
2073
+ function isCxName(names, name) {
2074
+ return names === void 0 || names.has(name);
2075
+ }
2076
+ function patternKeys(pattern, names) {
2077
+ const taken = [];
2078
+ for (const property of nodesAt(pattern, "properties")) {
2079
+ const key = property.type === "Property" ? propertyNameOf(nodeAt(property, "key"), property.computed === true) : void 0;
2080
+ if (key === void 0) return void 0;
2081
+ if (isCxName(names, key)) taken.push(key);
2082
+ }
2083
+ return taken;
2084
+ }
2085
+ function referenceTakes(analysis, node, names) {
2086
+ const read = memberReadOf({ analysis }, node);
2087
+ if (read) {
2088
+ if (read.key === void 0) return void 0;
2089
+ return isCxName(names, read.key) ? [read.key] : [];
2090
+ }
2091
+ const pattern = patternDestructuring({ analysis }, node);
2092
+ return pattern?.type === "ObjectPattern" ? patternKeys(pattern, names) : void 0;
2093
+ }
2094
+ function outermost(analysis, node) {
2095
+ let current = node;
2096
+ let parent = analysis.parentOf.get(current);
2097
+ while (parent?.type === "ParenthesizedExpression") {
2098
+ current = parent;
2099
+ parent = analysis.parentOf.get(current);
2100
+ }
2101
+ return current;
2102
+ }
2103
+ function thenCall(analysis, node) {
2104
+ const member = analysis.parentOf.get(node);
2105
+ if (member?.type !== "MemberExpression" || nodeAt(member, "object") !== node) return void 0;
2106
+ const key = propertyNameOf(nodeAt(member, "property"), member.computed === true);
2107
+ const call = analysis.parentOf.get(member);
2108
+ return key === "then" && call?.type === "CallExpression" && nodeAt(call, "callee") === member ? call : void 0;
2109
+ }
2110
+ function thenCallback(analysis, node) {
2111
+ const call = thenCall(analysis, node);
2112
+ const callback = call && nodesAt(call, "arguments")[0];
2113
+ const isInline = callback?.type === "ArrowFunctionExpression" || callback?.type === "FunctionExpression";
2114
+ return isInline ? callback : void 0;
2115
+ }
2116
+ function referencesToParameter(analysis, owner, name) {
2117
+ return analysis.references.filter(
2118
+ ({ binding }) => binding?.kind === "param" && binding.owner === owner && binding.name === name
2119
+ );
2120
+ }
2121
+ function parameterTakes(analysis, callback, names) {
2122
+ const parameter = nodesAt(callback, "params")[0];
2123
+ if (parameter === void 0) return [];
2124
+ if (parameter.type === "ObjectPattern") return patternKeys(parameter, names);
2125
+ const name = parameter.type === "Identifier" ? stringAt(parameter, "name") : void 0;
2126
+ if (name === void 0) return void 0;
2127
+ const found = [];
2128
+ for (const { binding, node } of referencesToParameter(analysis, callback, name)) {
2129
+ const taken = binding?.writes === 0 ? referenceTakes(analysis, node, names) : void 0;
2130
+ if (taken === void 0) return void 0;
2131
+ pushAll(found, taken);
2132
+ }
2133
+ return found;
2134
+ }
2135
+ function variableTakes(analysis, init, names) {
2136
+ const declarator = analysis.parentOf.get(init);
2137
+ const declaration = declarator && analysis.parentOf.get(declarator);
2138
+ if (declaration && analysis.parentOf.get(declaration)?.type === "ExportNamedDeclaration") {
2139
+ return void 0;
2140
+ }
2141
+ const found = [];
2142
+ for (const { binding, node } of analysis.references) {
2143
+ if (binding?.init !== init) continue;
2144
+ const taken = binding.writes === 0 ? referenceTakes(analysis, node, names) : void 0;
2145
+ if (taken === void 0) return void 0;
2146
+ pushAll(found, taken);
2147
+ }
2148
+ return found;
2149
+ }
2150
+ function awaitedKeys(analysis, awaited, names) {
2151
+ const declarator = analysis.parentOf.get(awaited);
2152
+ const isVariable = declarator?.type === "VariableDeclarator" && nodeAt(declarator, "init") === awaited && nodeAt(declarator, "id")?.type === "Identifier";
2153
+ return isVariable ? variableTakes(analysis, awaited, names) : referenceTakes(analysis, awaited, names);
2154
+ }
2155
+ function dynamicKeys(analysis, node, names) {
2156
+ const awaited = analysis.parentOf.get(node);
2157
+ if (awaited?.type === "AwaitExpression") {
2158
+ return awaitedKeys(analysis, outermost(analysis, awaited), names);
2159
+ }
2160
+ const callback = thenCallback(analysis, node);
2161
+ return callback && parameterTakes(analysis, callback, names);
2162
+ }
2163
+
2164
+ // src/vite-cx-takes.ts
2165
+ var UNREADABLE = { shape: "unreadable", names: [] };
2166
+ function namespaceTakes(analysis, references, names) {
2167
+ const found = /* @__PURE__ */ new Set();
2168
+ for (const reference of references) {
2169
+ const taken = referenceTakes(analysis, reference.node, names);
2170
+ if (taken === void 0) return { shape: "namespace", names: [] };
2171
+ for (const name of taken) found.add(name);
2172
+ }
2173
+ return found.size === 0 ? void 0 : { shape: "namespace", names: [...found] };
2174
+ }
2175
+ function referencesTo(analysis, source, specifier) {
2176
+ const local = exportNameOf(nodeAt(specifier, "local"));
2177
+ return analysis.references.filter(({ binding }) => {
2178
+ return binding?.kind === "import" && binding.imported === "*" && binding.source === source && binding.name === local;
2179
+ });
2180
+ }
2181
+ function usesOf(analysis, source, specifier) {
2182
+ const local = exportNameOf(nodeAt(specifier, "local"));
2183
+ return analysis.references.filter(
2184
+ ({ binding }) => binding?.kind === "import" && binding.source === source && binding.name === local
2185
+ );
2186
+ }
2187
+ function isExportOf(analysis, reference) {
2188
+ const parent = analysis.parentOf.get(reference.node);
2189
+ return parent?.type === "ExportSpecifier" || parent?.type === "ExportDefaultDeclaration";
2190
+ }
2191
+ function passingOf(analysis, source, specifier) {
2192
+ const uses = usesOf(analysis, source, specifier);
2193
+ const exported = uses.filter((use) => isExportOf(analysis, use));
2194
+ if (exported.length === 0) return {};
2195
+ return exported.length === uses.length ? { isForward: true, isPassedOn: true } : { isPassedOn: true };
2196
+ }
2197
+ function importTakes(node, source, scan) {
2198
+ const found = [];
2199
+ for (const specifier of nodesAt(node, "specifiers")) {
2200
+ if (specifier.type === "ImportNamespaceSpecifier") {
2201
+ const references = referencesTo(scan.analysis(), source, specifier);
2202
+ const taken = namespaceTakes(scan.analysis(), references, scan.names);
2203
+ const isForward = passingOf(scan.analysis(), source, specifier).isForward;
2204
+ if (taken) found.push({ ...taken, ...isForward && { isForward } });
2205
+ continue;
2206
+ }
2207
+ const imported = specifier.type === "ImportDefaultSpecifier" ? "default" : exportNameOf(nodeAt(specifier, "imported"));
2208
+ if (imported !== void 0 && isCxName(scan.names, imported)) {
2209
+ const passing = passingOf(scan.analysis(), source, specifier);
2210
+ found.push({ shape: "names", names: [imported], ...passing });
2211
+ }
2212
+ }
2213
+ return found;
2214
+ }
2215
+ function exportTakes(node, scan) {
2216
+ if (node.type === "ExportAllDeclaration") {
2217
+ if (nodeAt(node, "exported") !== void 0) {
2218
+ return [{ shape: "namespace", names: [], isForward: true }];
2219
+ }
2220
+ const hasNamed = scan.names === void 0 || scan.names.keys().some((name) => name !== "default");
2221
+ return hasNamed ? [{ shape: "star", names: [], isForward: true }] : [];
2222
+ }
2223
+ const re = nodesAt(node, "specifiers").map((specifier) => exportNameOf(nodeAt(specifier, "local"))).filter((name) => name !== void 0 && isCxName(scan.names, name));
2224
+ return re.length === 0 ? [] : [{ shape: "names", names: re, isPassedOn: true, isForward: true }];
2225
+ }
2226
+ function dynamicTakes(node, scan) {
2227
+ const keys = dynamicKeys(scan.analysis(), node, scan.names);
2228
+ if (keys === void 0) return [{ shape: "dynamic-import", names: [] }];
2229
+ return keys.length === 0 ? [] : [{ shape: "dynamic-import", names: keys }];
2230
+ }
2231
+ function takesOf(node, scan) {
2232
+ const source = staticStringOf(nodeAt(node, "source"));
2233
+ if (source === void 0 || !scan.reaches.has(source)) return [];
2234
+ if (node.type === "ImportDeclaration") return importTakes(node, source, scan);
2235
+ if (node.type === "ImportExpression") return dynamicTakes(node, scan);
2236
+ return exportTakes(node, scan);
2237
+ }
2238
+ function takesIn(program, input) {
2239
+ let analysis;
2240
+ const scan = {
2241
+ ...input,
2242
+ analysis: () => analysis ??= analyze(program)
2243
+ };
2244
+ const found = [];
2245
+ const stack = [program];
2246
+ while (stack.length > 0) {
2247
+ const node = stack.pop();
2248
+ pushAll(found, takesOf(node, scan));
2249
+ pushAll(stack, childrenOf(node));
2250
+ }
2251
+ return found;
2252
+ }
2253
+
2254
+ // src/vite-listed-routes.ts
2255
+ async function takenBy(ctx, input) {
2256
+ const { file, id, names, resolutions } = input;
2257
+ const code = ctx.getModuleInfo?.(id)?.code;
2258
+ try {
2259
+ const read = code === null || code === void 0 ? void 0 : await reachingSpecifiers(ctx, { code, file, id, resolutions });
2260
+ if (!read || read.reaches.size === 0) return [UNREADABLE];
2261
+ return takesIn(read.program, { names, reaches: read.reaches });
2262
+ } catch {
2263
+ return [UNREADABLE];
2264
+ }
2265
+ }
2266
+ function merged2(takes) {
2267
+ const byKey = /* @__PURE__ */ new Map();
2268
+ for (const take of takes) {
2269
+ const key = `${take.taker}\0${take.shape}`;
2270
+ const known = byKey.get(key);
2271
+ const names = /* @__PURE__ */ new Set([...known?.names ?? [], ...take.names]);
2272
+ const isReached = take.isReached || known?.isReached === true;
2273
+ const isPassedOn = take.isPassedOn === true || known?.isPassedOn === true;
2274
+ byKey.set(key, { ...take, isPassedOn, isReached, names: [...names].toSorted(compareText) });
2275
+ }
2276
+ return byKey.values().toArray();
2277
+ }
2278
+ async function isCounted(context, input) {
2279
+ const { importer, isEntry, pkg, wantCalls } = input;
2280
+ if (wantCalls || !isDependencyId(importer)) return true;
2281
+ if (!isEntry) return false;
2282
+ return await packageNameOf(filePathOf(importer), context.packageNames) !== pkg;
2283
+ }
2284
+ async function routesOf(ctx, context, input) {
2285
+ const { holder, importer, isEntry, resolutions, wantCalls } = input;
2286
+ const isDependency = isDependencyId(importer);
2287
+ const taker = moduleLabel(context.root, importer);
2288
+ const taken = await takenBy(ctx, {
2289
+ file: fileOf(holder.id),
2290
+ id: importer,
2291
+ names: holder.names,
2292
+ resolutions
2293
+ });
2294
+ const takes = taken.map((take) => ({ ...take, taker, isReached: holder.isReached }));
2295
+ if (isDependency) {
2296
+ const calls = takes.filter((take) => take.isForward !== true);
2297
+ return { entry: isEntry ? calls : [], told: [], calls: wantCalls ? calls : [] };
2298
+ }
2299
+ const isCleared = (take) => isEntry && take.shape !== "unreadable";
2300
+ return {
2301
+ entry: takes.filter((take) => isCleared(take)),
2302
+ told: takes.filter((take) => !isCleared(take)),
2303
+ calls: []
2304
+ };
2305
+ }
2306
+ function serverTakesOf(found, holder) {
2307
+ const takes = [];
2308
+ for (const taken of found.takes) {
2309
+ const names = taken.names.filter((name) => holder.names.has(name));
2310
+ const isWhole = taken.names.length === 0;
2311
+ const hasNamed = holder.names.keys().some((name) => name !== "default");
2312
+ const isTaken = taken.shape === "star" ? hasNamed : isWhole || names.length > 0;
2313
+ if (isTaken) {
2314
+ const kept = isWhole ? taken.names : names;
2315
+ takes.push({
2316
+ ...taken,
2317
+ names: kept,
2318
+ taker: found.taker,
2319
+ isReached: holder.isReached,
2320
+ ...found.isRecorded === true && { isRecorded: true }
2321
+ });
2322
+ }
2323
+ }
2324
+ return takes;
2325
+ }
2326
+ async function takesFrom(ctx, context, input) {
2327
+ const { holder, isEntry, pkg, resolutions, wantCalls } = input;
2328
+ const importers = importersOf(ctx, holder.id);
2329
+ const entry = [];
2330
+ const told = [];
2331
+ const calls = [];
2332
+ for (const importer of importers) {
2333
+ if (!await isCounted(context, { importer, isEntry, pkg, wantCalls })) {
2334
+ continue;
2335
+ }
2336
+ const routes = await routesOf(ctx, context, {
2337
+ holder,
2338
+ importer,
2339
+ isEntry,
2340
+ resolutions,
2341
+ wantCalls
2342
+ });
2343
+ pushAll(entry, routes.entry);
2344
+ pushAll(told, routes.told);
2345
+ pushAll(calls, routes.calls);
2346
+ }
2347
+ return { entry: merged2(entry), told: merged2(told), calls: merged2(calls) };
2348
+ }
2349
+ function serverRoutes(holder, input) {
2350
+ const file = fileOf(holder.id);
2351
+ const fromServer = input.serverImports.filter((one) => one.file === file);
2352
+ const takes = fromServer.flatMap((found) => serverTakesOf(found, holder));
2353
+ const isCleared = (take) => input.isEntry && take.shape !== "unreadable";
2354
+ return {
2355
+ entry: takes.filter((take) => isCleared(take)),
2356
+ told: takes.filter((take) => !isCleared(take))
2357
+ };
2358
+ }
2359
+
2360
+ // src/vite-listed-takes.ts
2361
+ async function prepareOne(ctx, context, input) {
2362
+ const { isHop, problems, walk } = input;
2363
+ const first = problems[0];
2364
+ const pkg = first.pkg;
2365
+ const names = new Set(problems.flatMap((problem) => problem.exportedAs ?? []));
2366
+ const hasEntry = !isHop && problems.some((problem) => problem.specifier !== void 0);
2367
+ const holders = await holdersOf(ctx, { ...walk, id: first.moduleId, names });
2368
+ const routed = await Promise.all(
2369
+ holders.map(
2370
+ (holder) => takesFrom(ctx, context, {
2371
+ holder,
2372
+ isEntry: hasEntry && !holder.isReached,
2373
+ pkg,
2374
+ resolutions: walk.resolutions,
2375
+ wantCalls: isHop
2376
+ })
2377
+ )
2378
+ );
2379
+ const isListed2 = Object.hasOwn(context.options.keepFor, pkg);
2380
+ return { hasEntry, holders, isHop, isListed: isListed2, problems, routed };
2381
+ }
2382
+ function decideOne(prepared, serverImports) {
2383
+ const { hasEntry, holders, isHop, isListed: isListed2, problems, routed } = prepared;
2384
+ const fromServer = holders.map(
2385
+ (holder) => serverRoutes(holder, { isEntry: hasEntry && !holder.isReached, serverImports })
2386
+ );
2387
+ const entry = [...routed.flatMap((route) => route.entry), ...fromServer.flatMap((r) => r.entry)];
2388
+ if (entry.length > 0) return problems.filter((problem) => problem.specifier !== void 0);
2389
+ const told = merged2([
2390
+ ...routed.flatMap((route) => route.told),
2391
+ ...fromServer.flatMap((route) => route.told)
2392
+ ]);
2393
+ const callers = isHop && !isListed2 ? callersOf(routed) : [];
2394
+ if (told.length === 0 && callers.length === 0) return [];
2395
+ return problems.map((problem) => ({
2396
+ ...problem,
2397
+ ...told.length > 0 && { takes: told },
2398
+ ...callers.length > 0 && { callers }
2399
+ }));
2400
+ }
2401
+ function callersOf(routed) {
2402
+ const callers = new Set(routed.flatMap((route) => route.calls.map((call) => call.taker)));
2403
+ return [...callers].toSorted(compareText);
2404
+ }
2405
+ async function prepareReexports(ctx, context, standingIn) {
2406
+ const exporting = standingIn.filter((problem) => problem.exportedAs !== void 0);
2407
+ const located = await withClearingSpecifiers(ctx, context, exporting);
2408
+ const byModule = /* @__PURE__ */ new Map();
2409
+ const hops = /* @__PURE__ */ new Map();
2410
+ for (const problem of located) {
2411
+ if (problem.moduleId === void 0 || problem.pkg === void 0) continue;
2412
+ const group = isSecondHop(problem) ? hops : byModule;
2413
+ group.set(problem.moduleId, [...group.get(problem.moduleId) ?? [], problem]);
2414
+ }
2415
+ const cxExports = new Map(
2416
+ [...byModule.values(), ...hops.values()].map((problems) => [
2417
+ fileOf(problems[0].moduleId),
2418
+ new Set(problems.flatMap((problem) => problem.exportedAs ?? []))
2419
+ ])
2420
+ );
2421
+ const walk = { cxExports, resolutions: /* @__PURE__ */ new Map() };
2422
+ return await Promise.all([
2423
+ ...byModule.values().map((problems) => prepareOne(ctx, context, { isHop: false, problems, walk })),
2424
+ ...hops.values().map((problems) => prepareOne(ctx, context, { isHop: true, problems, walk }))
2425
+ ]);
2426
+ }
2427
+ function decideReexports(prepared, serverImports) {
2428
+ return prepared.flatMap((one) => decideOne(one, serverImports));
2429
+ }
2430
+
2431
+ // src/vite-order.ts
2432
+ function checkEnvironmentOrder(ctx, context) {
2433
+ const { emitted } = context.state;
2434
+ if (emitted === void 0) return;
2435
+ const lines = [];
2436
+ for (const record of recordsOf(context.state, ctx.environment.name)) {
2437
+ for (const atom of [...record.atoms].toSorted(compareText)) {
2438
+ if (!emitted.has(atom)) {
2439
+ lines.push(`${record.file}: names ${atom}, which the CSS already written does not hold.`);
2440
+ }
2441
+ }
2442
+ }
2443
+ if (lines.length === 0) return;
2444
+ ctx.error(
2445
+ [
2446
+ `The build read atoms after it wrote the CSS, so their rules are missing from it:`,
2447
+ ...lines,
2448
+ "List the atoms in keep in navePlugin(), or build the server environments first with builder.buildApp in your Vite config."
2449
+ ].join("\n")
2450
+ );
2451
+ }
2452
+ var PACKAGE_NAME = /^(@[^/]+\/[^/]+|[^./@][^/]*)(\/.*)?$/;
2453
+ var EXTENSIONS = ["", ".js", ".mjs", ".cjs", "/index.js", "/index.mjs", "/index.cjs"];
2454
+ function packageDirectory(directory, name) {
2455
+ for (let current = directory; ; current = path2.dirname(current)) {
2456
+ const found = path2.join(current, "node_modules", name);
2457
+ if (existsSync(path2.join(found, "package.json"))) return found;
2458
+ if (path2.dirname(current) === current) return void 0;
2459
+ }
2460
+ }
2461
+ function targetFile(target, input) {
2462
+ if (typeof target === "string") return target.split("*").join(input.match);
2463
+ if (Array.isArray(target)) {
2464
+ return target.map((item) => targetFile(item, input)).find((file) => file !== void 0);
2465
+ }
2466
+ if (target === null || typeof target !== "object") return void 0;
2467
+ const entries = Object.entries(target);
2468
+ const key = entries.find(([name]) => input.conditions.has(name) || name === "default");
2469
+ return key === void 0 ? void 0 : targetFile(key[1], input);
2470
+ }
2471
+ function exportsEntry(exported, subpath) {
2472
+ const isMap = exported !== null && typeof exported === "object" && !Array.isArray(exported) && Object.keys(exported).every((key) => key.startsWith("."));
2473
+ if (!isMap) return subpath === "." ? { match: "", target: exported } : void 0;
2474
+ const map = exported;
2475
+ if (Object.hasOwn(map, subpath)) return { match: "", target: map[subpath] };
2476
+ const patterns = Object.keys(map).filter((key) => key.includes("*") && subpath.startsWith(key.slice(0, key.indexOf("*")))).toSorted((a, b) => b.indexOf("*") - a.indexOf("*") || b.length - a.length);
2477
+ const pattern = patterns.find((key) => subpath.endsWith(key.slice(key.indexOf("*") + 1)));
2478
+ if (pattern === void 0) return void 0;
2479
+ const [head, tail] = pattern.split("*");
2480
+ return { match: subpath.slice(head.length, subpath.length - tail.length), target: map[pattern] };
2481
+ }
2482
+ function existingFile(base) {
2483
+ return EXTENSIONS.map((extension) => `${base}${extension}`).find(
2484
+ (candidate) => existsSync(candidate) && statSync(candidate).isFile()
2485
+ );
2486
+ }
2487
+ function manifestOf(directory) {
2488
+ try {
2489
+ return JSON.parse(readFileSync(path2.join(directory, "package.json"), "utf8"));
2490
+ } catch {
2491
+ return void 0;
2492
+ }
2493
+ }
2494
+ function relativeTarget(manifest, input) {
2495
+ const { conditions, subpath } = input;
2496
+ if (manifest.exports === void 0) {
2497
+ return subpath === "." ? manifest.main ?? "index.js" : subpath;
2498
+ }
2499
+ const entry = exportsEntry(manifest.exports, subpath);
2500
+ return entry ? targetFile(entry.target, { conditions, match: entry.match }) : void 0;
2501
+ }
2502
+ function serverFileOf(input) {
2503
+ const parts = PACKAGE_NAME.exec(input.specifier);
2504
+ const directory = parts && packageDirectory(path2.dirname(input.from), parts[1]);
2505
+ const manifest = directory ? manifestOf(directory) : void 0;
2506
+ if (!parts || !directory || !manifest) return void 0;
2507
+ const subpath = parts[2] === void 0 ? "." : `.${parts[2]}`;
2508
+ const relative = relativeTarget(manifest, { conditions: new Set(input.conditions), subpath });
2509
+ const file = relative === void 0 ? void 0 : existingFile(path2.join(directory, relative));
2510
+ return file === void 0 ? void 0 : realpathSync(file);
2511
+ }
2512
+ var PACKAGE_NAME2 = /^(@[^/]+\/[^/]+|[^./@][^/]*)/;
2513
+ function packageOfSpecifier(specifier) {
2514
+ if (specifier.startsWith("node:") || specifier.startsWith("\0")) return void 0;
2515
+ return PACKAGE_NAME2.exec(specifier)?.[1];
2516
+ }
2517
+ function isDeclaringCore(root, name) {
2518
+ for (let directory = root; ; directory = path2.dirname(directory)) {
2519
+ try {
2520
+ const manifest = JSON.parse(
2521
+ readFileSync(path2.join(directory, "node_modules", name, "package.json"), "utf8")
2522
+ );
2523
+ return ["dependencies", "peerDependencies", "optionalDependencies"].some(
2524
+ (field) => manifest[field]?.["@navecss/core"] !== void 0
2525
+ );
2526
+ } catch {
2527
+ if (path2.dirname(directory) === directory) return false;
2528
+ }
2529
+ }
2530
+ }
2531
+ function warningFor(name) {
2532
+ return `${name} depends on @navecss/core, but no environment of this build transforms it, so the atoms its cx() calls name are not read. Add it to ssr.noExternal in your Vite config so the build reads it, or list the atoms its calls can produce under its name in keepFor in navePlugin().`;
2533
+ }
2534
+ function judgeExternals(ctx, context) {
2535
+ const { state } = context;
2536
+ for (const name of state.externals) {
2537
+ if (state.packages.has(name) || state.warned.has(name)) continue;
2538
+ if (Object.hasOwn(context.options.keepFor, name)) continue;
2539
+ state.warned.add(name);
2540
+ ctx.warn(warningFor(name));
2541
+ }
2542
+ state.externals.clear();
2543
+ }
2544
+ function noteServerExternals(ctx, context) {
2545
+ const ids = ctx.getModuleIds?.() ?? [];
2546
+ for (const id of ids) {
2547
+ const name = packageOfSpecifier(id);
2548
+ if (name !== void 0 && isDeclaringCore(context.root, name)) context.state.externals.add(name);
2549
+ }
2550
+ if (!context.inProcess || context.state.clientEnded) judgeExternals(ctx, context);
2551
+ }
2552
+ function noteClientEnded(ctx, context) {
2553
+ context.state.clientEnded = true;
2554
+ judgeExternals(ctx, context);
2555
+ }
2556
+
2557
+ // src/vite-server-takes.ts
2558
+ var SERVER_TAKES_FILE = "nave-used-server-takes.json";
2559
+ function parsed(ctx, id) {
2560
+ const code = ctx.getModuleInfo?.(id)?.code;
2561
+ try {
2562
+ return code === null || code === void 0 ? void 0 : ctx.parse?.(code);
2563
+ } catch {
2564
+ return void 0;
2565
+ }
2566
+ }
2567
+ function formatOf(ctx) {
2568
+ const build = ctx.environment.config.build;
2569
+ const output = build?.rolldownOptions?.output ?? build?.rollupOptions?.output;
2570
+ const first = Array.isArray(output) ? output[0] : output;
2571
+ return first?.format;
2572
+ }
2573
+ function conditionsOf(ctx) {
2574
+ return ["node", formatOf(ctx) === "cjs" ? "require" : "import", "module-sync", "default"];
2575
+ }
2576
+ function importsOf(ctx, input) {
2577
+ const { externals, id, root } = input;
2578
+ const program = parsed(ctx, id);
2579
+ const taker = path2.relative(root, filePathOf(id)).replaceAll("\\", "/");
2580
+ const conditions = conditionsOf(ctx);
2581
+ const named = program ? specifiersIn(program).filter((one) => externals.has(one)) : [];
2582
+ const info = ctx.getModuleInfo?.(id);
2583
+ const shown = [...info?.importedIds ?? [], ...info?.dynamicallyImportedIds ?? []];
2584
+ const unread = shown.filter((one) => externals.has(one) && !named.includes(one));
2585
+ const read = named.map((specifier) => ({
2586
+ specifier,
2587
+ takes: program ? takesIn(program, { names: void 0, reaches: /* @__PURE__ */ new Set([specifier]) }) : [],
2588
+ taker
2589
+ }));
2590
+ const imports = [
2591
+ ...read.filter((found) => found.takes.length > 0),
2592
+ ...unread.map((specifier) => ({
2593
+ isUnreadable: true,
2594
+ specifier,
2595
+ takes: [UNREADABLE],
2596
+ taker
2597
+ }))
2598
+ ];
2599
+ return imports.map((found) => {
2600
+ const file = serverFileOf({
2601
+ conditions,
2602
+ from: filePathOf(id),
2603
+ specifier: found.specifier
2604
+ });
2605
+ return { ...found, ...file !== void 0 && { file } };
2606
+ });
2607
+ }
2608
+ function serverImportsOf(ctx, context) {
2609
+ const ids = [...ctx.getModuleIds?.() ?? []];
2610
+ const isListed2 = (id) => {
2611
+ const name = packageOfSpecifier(id);
2612
+ return name !== void 0 && Object.hasOwn(context.options.keepFor, name);
2613
+ };
2614
+ const externals = new Set(ids.filter((id) => isListed2(id)));
2615
+ if (externals.size === 0) return [];
2616
+ return ids.filter((id) => path2.isAbsolute(filePathOf(id)) && !isDependencyId(id) && !isNaveOwn(id)).flatMap((id) => importsOf(ctx, { externals, id, root: context.root }));
2617
+ }
2618
+ function buildKeyOf(ctx) {
2619
+ const build = ctx.environment.config.build;
2620
+ return `${ctx.environment.name}\0${JSON.stringify(build?.rolldownOptions?.input ?? build?.ssr ?? "")}`;
2621
+ }
2622
+ function readEntries(context) {
2623
+ try {
2624
+ const parsedFile = JSON.parse(
2625
+ readFileSync(path2.join(context.cacheDir, SERVER_TAKES_FILE), "utf8")
2626
+ );
2627
+ const isEntries = typeof parsedFile === "object" && parsedFile !== null && !Array.isArray(parsedFile);
2628
+ return isEntries ? parsedFile : {};
2629
+ } catch {
2630
+ return {};
2631
+ }
2632
+ }
2633
+ function writeServerImports(ctx, context, imports) {
2634
+ if (context.cacheDir === "") return;
2635
+ const file = path2.join(context.cacheDir, SERVER_TAKES_FILE);
2636
+ try {
2637
+ mkdirSync(context.cacheDir, { recursive: true });
2638
+ const entries = { ...readEntries(context), [buildKeyOf(ctx)]: imports };
2639
+ writeFileSync(file, `${JSON.stringify(entries, void 0, 2)}
2640
+ `);
2641
+ } catch (error) {
2642
+ const reason = error instanceof Error ? error.message : String(error);
2643
+ ctx.warn(
2644
+ `navePlugin(): could not write ${file} (${reason}), so a build of the client run as another process cannot check what your server code takes from a package keepFor lists.`
2645
+ );
2646
+ }
2647
+ }
2648
+ function readServerImports(context) {
2649
+ if (context.cacheDir === "") return [];
2650
+ return Object.values(readEntries(context)).flat().filter((found) => existsSync(path2.resolve(context.root, found.taker))).map((found) => ({ ...found, isRecorded: true }));
2651
+ }
2652
+ function graphOf(ctx) {
2653
+ return new Set([...ctx.getModuleIds?.() ?? []].map((id) => fileOf(id)));
2654
+ }
2655
+ function judgeable(graph, imports) {
2656
+ const known = [];
2657
+ const unknown = [];
2658
+ for (const found of imports) {
2659
+ const { file } = found;
2660
+ if (file !== void 0 && found.isUnreadable !== true && graph.has(fileOf(file))) {
2661
+ known.push({ ...found, file });
2662
+ } else {
2663
+ unknown.push(found);
2664
+ }
2665
+ }
2666
+ return { known, unknown };
2667
+ }
2668
+ function recordedSentence(takers) {
2669
+ const named = [...new Set(takers)].toSorted(compareText).join(", ");
2670
+ if (named === "") return void 0;
2671
+ return new Set(takers).size === 1 ? `${named} was read by an earlier server build, not by this one, so what this message says of its imports comes from the record that build left in Vite's cache directory; if the file has changed since, run that server build again to refresh the record, or, if you no longer run that build, delete nave-used-server-takes.json there and run each server build you do.` : `${named} were read by earlier server builds, not by this one, so what this message says of their imports comes from the records those builds left in Vite's cache directory; if one of those files has changed since, run the server build that read it again to refresh its record, or, if you no longer run that build, delete nave-used-server-takes.json there and run each server build you do.`;
2672
+ }
2673
+ function recordedTakers(imports) {
2674
+ return imports.filter((found) => found.isRecorded === true).map((found) => found.taker);
2675
+ }
2676
+ function warningFor2(pkg, input) {
2677
+ const { found, root } = input;
2678
+ const listed = found.map((one) => {
2679
+ if (one.isUnreadable === true)
2680
+ return `${one.taker} loads '${one.specifier}' in a way the build cannot read as a take, such as a require() or a # import`;
2681
+ if (one.file === void 0)
2682
+ return `${one.taker} imports '${one.specifier}', and the build cannot tell which file the server loads for it`;
2683
+ const file = path2.relative(root, one.file).replaceAll("\\", "/");
2684
+ return `${one.taker} imports '${one.specifier}', which the server loads as ${file}, a file no environment of this build transforms`;
2685
+ }).toSorted(compareText).join("; ");
2686
+ const note = recordedSentence(recordedTakers(found));
2687
+ const warning = `${pkg}, which keepFor lists, is imported by your server code where the build cannot tell whether that code takes cx from it: ${listed}. Add ${pkg} to ssr.noExternal in your Vite config so the build reads the package and checks what your server code takes; where a file takes cx from it, import cx from @navecss/core/cx there instead.`;
2688
+ return note === void 0 ? warning : `${warning} ${note}`;
2689
+ }
2690
+ function warnUnknown(ctx, context, unknown) {
2691
+ const byPackage = /* @__PURE__ */ new Map();
2692
+ for (const found of unknown) {
2693
+ const pkg = packageOfSpecifier(found.specifier);
2694
+ if (pkg === void 0 || context.state.warned.has(pkg)) continue;
2695
+ byPackage.set(pkg, [...byPackage.get(pkg) ?? [], found]);
2696
+ }
2697
+ for (const [pkg, imports] of byPackage) {
2698
+ context.state.warned.add(pkg);
2699
+ ctx.warn(warningFor2(pkg, { found: imports, root: context.root }));
2700
+ }
2701
+ }
2702
+
2703
+ // src/vite-collect-plugin.ts
2704
+ var OPTIONS_HOME = "navePlugin()";
2705
+ function isReadable(context, id) {
2706
+ return isUsed(context) && !isStylesheetId(id) && !isNaveOwn(id);
2707
+ }
2708
+ async function problemsOfBuild(ctx, context, serverImports) {
2709
+ const records = recordsOf(context.state, ctx.environment.name);
2710
+ const kept = await withClearingSpecifiers(
2711
+ ctx,
2712
+ context,
2713
+ withoutEchoes(
2714
+ records.map((record) => ({
2715
+ onlyVia: record.onlyVia,
2716
+ problems: [
2717
+ ...problemsOf(record, context),
2718
+ ...record.suppressed.filter((problem) => problem.kind === "declared")
2719
+ ]
2720
+ }))
2721
+ )
2722
+ );
2723
+ const standingIn = [
2724
+ ...records.flatMap((record) => record.suppressed),
2725
+ ...kept.filter((problem) => isSecondHop(problem))
2726
+ ];
2727
+ const rest = kept.filter((problem) => !isSecondHop(problem));
2728
+ const prepared = await prepareReexports(ctx, context, standingIn);
2729
+ return { problems: [...rest, ...decideReexports(prepared, serverImports)], prepared };
2730
+ }
2731
+ function reportOf(context, problems) {
2732
+ const report = buildReport(problems, context.options.cxModules, OPTIONS_HOME);
2733
+ const recorded = problems.flatMap((problem) => problem.takes ?? []).filter((take) => take.isRecorded === true).map((take) => take.taker);
2734
+ const note = recordedSentence(recorded);
2735
+ return note === void 0 ? report : `${report}
2736
+ ${note}`;
2737
+ }
2738
+ async function failuresOf(ctx, context, serverImports) {
2739
+ const { problems, prepared } = await problemsOfBuild(ctx, context, serverImports);
2740
+ const report = problems.length > 0 ? reportOf(context, problems) : void 0;
2741
+ const importers = await declaredImporterError(ctx, context, {
2742
+ configured: withoutRemoved(problems, context.options.cxModules),
2743
+ home: OPTIONS_HOME,
2744
+ report
2745
+ });
2746
+ return { failures: [report, importers].filter((failure) => failure !== void 0), prepared };
2747
+ }
2748
+ function serverImportsForClient(ctx, context, graph) {
2749
+ if (ctx.environment.config.consumer !== "client") return { known: [], unknown: [] };
2750
+ const imports = context.inProcess ? context.state.serverImports : readServerImports(context);
2751
+ return judgeable(graph, imports);
2752
+ }
2753
+ function noteServerImports(ctx, context) {
2754
+ const imports = serverImportsOf(ctx, context);
2755
+ if (!context.inProcess) {
2756
+ writeServerImports(ctx, context, imports);
2757
+ return;
2758
+ }
2759
+ context.state.serverImports.push(...imports);
2760
+ const { client } = context.state;
2761
+ if (client === void 0 || imports.length === 0) return;
2762
+ const { known, unknown } = judgeable(client.graph, imports);
2763
+ const problems = decideReexports(client.prepared, known);
2764
+ if (problems.length > 0) ctx.error(reportOf(context, problems));
2765
+ warnUnknown(ctx, context, unknown);
2766
+ }
2767
+ function createCollectPlugin(context) {
2768
+ const plugin = {
2769
+ name: "nave:collect",
2770
+ enforce: "post",
2771
+ async buildStart() {
2772
+ context.state.started = true;
2773
+ assertOptions(context.options, await ownAtomNames(context));
2774
+ forgetDeclared(context.state, this.environment.name);
2775
+ if (this.environment.config.consumer !== "client") return;
2776
+ context.state.emitted = void 0;
2777
+ context.state.clientEnded = false;
2778
+ },
2779
+ async transform(code, id, meta) {
2780
+ if (!isReadable(context, id)) return;
2781
+ if (this.environment?.config.consumer === "server") context.state.serverTransformed = true;
2782
+ const record = await recordModule(context, this, { code, id, moduleType: meta?.moduleType });
2783
+ if (context.command === "serve") devServing.noteGrowth(context);
2784
+ if (record?.edits) return applyEdits(code, id, record.edits);
2785
+ if (record) failDevModule(this, context, { home: OPTIONS_HOME, id, record });
2786
+ },
2787
+ transformIndexHtml: {
2788
+ order: "pre",
2789
+ handler(html, { filename }) {
2790
+ if (!isUsed(context)) return;
2791
+ context.state.htmlRead = true;
2792
+ if (filename === void 0 || !isMentioningAtoms(html)) return;
2793
+ context.state.pages.set(filename, atomsWrittenIn(html));
2794
+ if (context.command === "serve") devServing.notePages(context);
2795
+ }
2796
+ },
2797
+ async buildEnd(error) {
2798
+ if (error || !isUsed(context) || context.command !== "build") return;
2799
+ const graph = graphOf(this);
2800
+ const server = serverImportsForClient(this, context, graph);
2801
+ const { failures, prepared } = await failuresOf(this, context, server.known);
2802
+ if (failures.length > 0) this.error(failures.join("\n\n"));
2803
+ await checkCxImporters(this, context);
2804
+ checkEnvironmentOrder(this, context);
2805
+ if (this.environment.config.consumer === "server") {
2806
+ checkServerInvocation(this, context);
2807
+ noteServerExternals(this, context);
2808
+ noteServerImports(this, context);
2809
+ } else {
2810
+ noteClientEnded(this, context);
2811
+ warnUnknown(this, context, server.unknown);
2812
+ context.state.client = { graph, prepared };
2813
+ }
2814
+ judgeAfterLastEnvironment(context, this.environment, (message) => this.warn(message));
2815
+ }
2816
+ };
2817
+ return plugin;
2818
+ }
2819
+
2820
+ // src/vite-worker-collect.ts
2821
+ function workerCollectPlugins(context) {
2822
+ const plugin = {
2823
+ name: "nave:collect-worker",
2824
+ enforce: "post",
2825
+ async transform(code, id, meta) {
2826
+ if (!isReadable(context, id)) return;
2827
+ const record = await recordModule(context, this, { code, id, moduleType: meta?.moduleType });
2828
+ if (record?.edits) return applyEdits(code, id, record.edits);
2829
+ },
2830
+ async buildEnd(error) {
2831
+ if (error || !isUsed(context) || context.command !== "build") return;
2832
+ await checkCxImporters(this, context);
2833
+ }
2834
+ };
2835
+ return () => context.command === "build" ? [plugin] : [];
2836
+ }
2837
+
2838
+ // src/vite-config-hooks.ts
2839
+ function usedConfig(context, command) {
2840
+ if (context.options.atomic !== "used") return void 0;
2841
+ const map = keepMap(context.kept);
2842
+ return {
2843
+ define: {
2844
+ [KEEP_CONSTANT]: command === "serve" ? devKeepExpression(map, Object.keys(atomClassMap)) : JSON.stringify(map)
2845
+ },
2846
+ optimizeDeps: { exclude: ["@navecss/core"] },
2847
+ worker: { plugins: workerCollectPlugins(context) }
2848
+ };
2849
+ }
2850
+ function isServerEnvironment(name, options) {
2851
+ return (options.consumer ?? (name === "client" ? "client" : "server")) === "server";
2852
+ }
2853
+ function usedEnvironmentConfig(context, name, options) {
2854
+ if (context.options.atomic !== "used" || !isServerEnvironment(name, options)) return void 0;
2855
+ return { resolve: { noExternal: ["@navecss/core"] } };
2856
+ }
2857
+
2858
+ // src/vite-css-capture.ts
2859
+ var originals = /* @__PURE__ */ new WeakMap();
2860
+ function transformHandler(plugin) {
2861
+ const { transform } = plugin;
2862
+ if (typeof transform === "function") return transform;
2863
+ const handler = transform?.handler;
2864
+ return typeof handler === "function" ? handler : void 0;
2865
+ }
2866
+ function unwrapped(handler) {
2867
+ let current = handler;
2868
+ for (let next = originals.get(current); next; next = originals.get(current)) current = next;
2869
+ return current;
2870
+ }
2871
+ function remember(context, environment, id, css) {
2872
+ const key = moduleKey(environment, id);
2873
+ const isPossible = css.includes("\\") || /layer/i.test(css);
2874
+ if (isPossible && inspectAtomicLayer(css).hasLayer) context.state.sheets.set(key, css);
2875
+ else context.state.sheets.delete(key);
2876
+ }
2877
+ function captureStylesheets(context, plugins) {
2878
+ const plugin = plugins?.find((candidate) => candidate.name === "vite:css-post");
2879
+ const original = plugin && transformHandler(plugin);
2880
+ if (!plugin || !original) return;
2881
+ const wrapped = function(css, id) {
2882
+ const environment = this.environment?.name ?? "client";
2883
+ remember(context, environment, id, css);
2884
+ return original.call(this, css, id);
2885
+ };
2886
+ originals.set(wrapped, original);
2887
+ const { transform } = plugin;
2888
+ plugin.transform = typeof transform === "function" ? wrapped : { ...transform, handler: wrapped };
2889
+ }
2890
+ var decoder = new TextDecoder();
2891
+ async function refeed(ctx, css, id) {
2892
+ const plugin = ctx.environment.plugins.find((candidate) => candidate.name === "vite:css-post");
2893
+ const handler = plugin && transformHandler(plugin);
2894
+ if (!handler) {
2895
+ ctx.error(
2896
+ "nave: this version of Vite has no CSS step the plugin knows how to hand a stylesheet back to, so it cannot remove the unused atoms. Ship every atom with atomic: 'all' in navePlugin() until the plugin supports this version of Vite."
2897
+ );
2898
+ }
2899
+ await unwrapped(handler).call(ctx, css, id);
2900
+ }
2901
+ var fedPages = /* @__PURE__ */ new WeakMap();
2902
+ var warnedText = /* @__PURE__ */ new WeakMap();
2903
+ function bookFor(book, emitted) {
2904
+ const ids = book.get(emitted) ?? /* @__PURE__ */ new Set();
2905
+ book.set(emitted, ids);
2906
+ return ids;
2907
+ }
2908
+ function isPageStylesheet(id) {
2909
+ return /[?&]html-proxy\b/.test(id);
2910
+ }
2911
+ function pageStylesheets(ctx, state, emitted) {
2912
+ const prefix = `${ctx.environment.name}\0`;
2913
+ const fed = bookFor(fedPages, emitted);
2914
+ const ids = state.sheets.keys().filter((key) => key.startsWith(prefix) && isPageStylesheet(key)).map((key) => key.slice(prefix.length)).filter((id) => !fed.has(id)).toArray();
2915
+ for (const id of ids) fed.add(id);
2916
+ return ids;
2917
+ }
2918
+ function isInlineImport(id) {
2919
+ return /[?&]inline\b/.test(id) && !isPageStylesheet(id);
2920
+ }
2921
+ function isRawImport(id) {
2922
+ return /[?&]raw\b/.test(id) && isStylesheetPath(id);
2923
+ }
2924
+ function isLayerFile(id) {
2925
+ try {
2926
+ return inspectAtomicLayer(readFileSync(filePathOf(id), "utf8")).hasLayer;
2927
+ } catch {
2928
+ return false;
2929
+ }
2930
+ }
2931
+ async function refeedChunkStylesheets(ctx, chunk, state, emitted) {
2932
+ const prefix = `${ctx.environment.name}\0`;
2933
+ for (const id of [...Object.keys(chunk.modules), ...pageStylesheets(ctx, state, emitted)]) {
2934
+ const css = state.sheets.get(`${prefix}${id}`);
2935
+ if (css === void 0 || isInlineImport(id)) continue;
2936
+ await refeed(ctx, pruneAtomicLayer(css, emitted), id);
2937
+ }
2938
+ }
2939
+ function warnTextImports(ctx, chunk, context, emitted) {
2940
+ const prefix = `${ctx.environment.name}\0`;
2941
+ const warned = bookFor(warnedText, emitted);
2942
+ for (const id of Object.keys(chunk.modules)) {
2943
+ if (warned.has(id)) continue;
2944
+ const isInline = isInlineImport(id) && context.state.sheets.has(`${prefix}${id}`);
2945
+ const isRaw = !isInline && isRawImport(id) && isLayerFile(id);
2946
+ if (!isInline && !isRaw) continue;
2947
+ warned.add(id);
2948
+ const query = isInline ? "?inline" : "?raw";
2949
+ ctx.warn(
2950
+ `${moduleLabel(context.root, id)} is imported with ${query}, so its stylesheet is text in the JavaScript, which the plugin does not filter: every atom in its atomic layer ships, not only the atoms this build emits. Import it without ${query} to have the layer filtered.`
2951
+ );
2952
+ }
2953
+ }
2954
+ function textOf(entry) {
2955
+ const { source } = entry;
2956
+ if (source === void 0) return "";
2957
+ return typeof source === "string" ? source : decoder.decode(source);
2958
+ }
2959
+ function mismatchLines(assets, emitted) {
2960
+ const lines = [];
2961
+ const seenAnywhere = /* @__PURE__ */ new Set();
2962
+ let hasLayer = false;
2963
+ for (const { fileName, css } of assets) {
2964
+ const seen = inspectAtomicLayer(css);
2965
+ if (!seen.hasLayer) continue;
2966
+ hasLayer = true;
2967
+ for (const atom of seen.atoms) seenAnywhere.add(atom);
2968
+ const extra = unprunedAtoms(css, emitted);
2969
+ if (extra.length > 0) {
2970
+ lines.push(
2971
+ `${fileName}: the atomic layer holds a rule for ${extra.join(", ")}, which the build did not emit.`
2972
+ );
2973
+ }
2974
+ }
2975
+ const missing = [...emitted.difference(seenAnywhere)];
2976
+ if (hasLayer && missing.length > 0) {
2977
+ lines.push(`the atomic layers hold no rule for ${missing.join(", ")}, which the build emitted.`);
2978
+ }
2979
+ return lines;
2980
+ }
2981
+ function checkAtomicLayers(ctx, bundle, emitted) {
2982
+ const assets = Object.values(bundle).filter((entry) => entry.type === "asset" && entry.fileName.toLowerCase().endsWith(".css")).map((entry) => ({ fileName: entry.fileName, css: textOf(entry) }));
2983
+ const lines = mismatchLines(assets, emitted);
2984
+ if (lines.length === 0) return;
2985
+ ctx.error({
2986
+ message: [
2987
+ "nave: the built CSS does not hold exactly the atoms the build emitted, so the plugin could not remove the unused ones on this version of Vite.",
2988
+ ...lines,
2989
+ "Ship every atom with atomic: 'all' in navePlugin() until the plugin supports this version of Vite."
2990
+ ].join("\n")
2991
+ });
2992
+ }
2993
+
2994
+ // src/vite-extend.ts
2995
+ function snapshotAndValidate(value) {
2996
+ const snapshot = snapshotExtendMap(value);
2997
+ validateExtendAtomsHostFree(snapshot);
2998
+ return snapshot;
2999
+ }
3000
+ function objectSource(extend) {
3001
+ const snapshot = snapshotAndValidate(extend);
3002
+ return {
3003
+ current: () => Promise.resolve(snapshot)
3004
+ };
3005
+ }
3006
+ function moduleSource(specifier) {
3007
+ const cache = /* @__PURE__ */ new Map();
3008
+ let root = process.cwd();
3009
+ let file;
3010
+ return {
3011
+ configure(directory) {
3012
+ root = directory;
3013
+ file = resolveExtendSpecifier(specifier, root);
3014
+ },
3015
+ file: () => file,
3016
+ async current(watch) {
3017
+ file ??= resolveExtendSpecifier(specifier, root);
3018
+ watch(file);
3019
+ let loaded = {};
3020
+ await applyExtendModule(file, cache, (value) => {
3021
+ loaded = snapshotAndValidate(value);
3022
+ });
3023
+ return loaded;
3024
+ }
3025
+ };
3026
+ }
3027
+ function createExtendSource(option) {
3028
+ if (typeof option === "string") return moduleSource(option);
3029
+ return objectSource(option ?? {});
3030
+ }
3031
+
3032
+ // src/vite-logger.ts
3033
+ var ANSI_ESCAPE = new RegExp(String.raw`\u001B\[[\d;]*m`, "g");
3034
+ var UNKNOWN_NAVE_RULE = /Unknown at rule: @nave(?![\w-]|[^\p{ASCII}])/iu;
3035
+ function isUnknownNaveRuleWarning(message) {
3036
+ return typeof message === "string" && UNKNOWN_NAVE_RULE.test(message.replaceAll(ANSI_ESCAPE, ""));
3037
+ }
3038
+ var wrappers = /* @__PURE__ */ new WeakMap();
3039
+ function dropLightningNaveWarning(logger) {
3040
+ if (wrappers.get(logger) === logger.warn) return;
3041
+ const original = logger.warn.bind(logger);
3042
+ const wrapper = function warn(message, options) {
3043
+ if (isUnknownNaveRuleWarning(message)) return;
3044
+ original(message, options);
3045
+ };
3046
+ logger.warn = wrapper;
3047
+ wrappers.set(logger, wrapper);
3048
+ }
3049
+
3050
+ // src/vite-scan.ts
3051
+ var decoder2 = new TextDecoder();
3052
+ function isCssAsset(entry) {
3053
+ return entry.type === "asset" && entry.fileName.toLowerCase().endsWith(".css");
3054
+ }
3055
+ function textOf2(entry) {
3056
+ const { source } = entry;
3057
+ if (source === void 0) return "";
3058
+ return typeof source === "string" ? source : decoder2.decode(source);
3059
+ }
3060
+ function messageFor(findings, assetCount) {
3061
+ const noun = assetCount === 1 ? "asset" : "assets";
3062
+ return [
3063
+ "@nave survived into the built CSS:",
3064
+ ...findings.map((finding) => formatFinding(finding)),
3065
+ `Scanned ${assetCount} CSS ${noun} this build wrote.`
3066
+ ].join("\n");
3067
+ }
3068
+ function scanBundle(ctx, bundle) {
3069
+ const assets = Object.values(bundle).filter((entry) => isCssAsset(entry));
3070
+ const findings = assets.flatMap((asset) => findingsInText(asset.fileName, textOf2(asset)));
3071
+ if (findings.length > 0) ctx.error({ message: messageFor(findings, assets.length) });
3072
+ }
3073
+
3074
+ // src/vite-server-hooks.ts
3075
+ function warnThrough(ctx) {
3076
+ return (message) => {
3077
+ ctx.warn(message);
3078
+ };
3079
+ }
3080
+ function serverHooks(context) {
3081
+ return {
3082
+ configureServer(server) {
3083
+ const devServer = server;
3084
+ const owner = devServer.environments.client;
3085
+ installServerKeepMap(context, owner);
3086
+ const close = devServer.close.bind(devServer);
3087
+ const noteConnect = () => {
3088
+ devServing.noteConnect(context);
3089
+ };
3090
+ const noteDisconnect = () => {
3091
+ devServing.noteDisconnect(context);
3092
+ };
3093
+ owner.hot.on("vite:client:connect", noteConnect);
3094
+ owner.hot.on("vite:client:disconnect", noteDisconnect);
3095
+ devServer.close = () => {
3096
+ removeServerKeepMap(owner);
3097
+ owner.hot.off("vite:client:connect", noteConnect);
3098
+ owner.hot.off("vite:client:disconnect", noteDisconnect);
3099
+ return close();
3100
+ };
3101
+ noteStylesheetRequests(context, devServer);
3102
+ },
3103
+ closeBundle() {
3104
+ removeServerKeepMap(this.environment);
3105
+ },
3106
+ buildApp: {
3107
+ order: "post",
3108
+ handler(builder) {
3109
+ if (context.command === "build") expectBuilds(context, builder, warnThrough(this));
3110
+ return Promise.resolve();
3111
+ }
3112
+ }
3113
+ };
3114
+ }
3115
+
3116
+ // src/vite-report.ts
3117
+ function withSourceRoot(source, sourceRoot) {
3118
+ if (!sourceRoot || /^(?:[a-z][a-z\d+.-]*:|\/)/i.test(source)) return source;
3119
+ return `${sourceRoot.replace(/\/$/, "")}/${source}`;
3120
+ }
3121
+ function locate2(diagnostic, input) {
3122
+ const text = formatDiagnostic(diagnostic, { extend: input.extend });
3123
+ const origin = input.incoming?.originalPositionFor({
3124
+ line: diagnostic.line,
3125
+ column: diagnostic.column - 1
3126
+ });
3127
+ if (origin === void 0) {
3128
+ const position = { line: diagnostic.line, column: diagnostic.column };
3129
+ return { text, file: input.file, isProcessed: true, ...position };
3130
+ }
3131
+ return {
3132
+ text,
3133
+ file: withSourceRoot(origin.source, input.incoming?.sourceRoot),
3134
+ isProcessed: false,
3135
+ line: origin.line,
3136
+ column: origin.column + 1
3137
+ };
3138
+ }
3139
+ function withNoMapNote(body, input, at) {
3140
+ if (!at.isProcessed) return body;
3141
+ const reason = input.incoming === void 0 ? "no source map" : "the source map does not cover it";
3142
+ const note = `(position in ${input.file} as processed; ${reason})`;
3143
+ const lines = body.split("\n");
3144
+ const hasAvailable = lines.at(-1)?.startsWith("Available: ") === true;
3145
+ lines.splice(hasAvailable ? -1 : lines.length, 0, note);
3146
+ return lines.join("\n");
3147
+ }
3148
+ function logFor(message, input, at) {
3149
+ return {
3150
+ message,
3151
+ id: input.id,
3152
+ loc: { file: at.file, line: at.line, column: at.column - 1 }
3153
+ };
3154
+ }
3155
+ function frame(at) {
3156
+ return `${at.file}:${at.line}:${at.column}: `;
3157
+ }
3158
+ function reportDiagnostics(input) {
3159
+ if (input.onUnknown === "ignore" || input.diagnostics.length === 0) return;
3160
+ const inSourceOrder = input.diagnostics.toSorted((a, b) => a.offset - b.offset);
3161
+ const located = inSourceOrder.map((diagnostic) => locate2(diagnostic, input));
3162
+ if (input.onUnknown === "warn") {
3163
+ for (const at of located) {
3164
+ const message2 = withNoMapNote(`${frame(at)}${at.text}`, input, at);
3165
+ input.ctx.warn(logFor(message2, input, at));
3166
+ }
3167
+ return;
3168
+ }
3169
+ const first = located[0];
3170
+ const message = withNoMapNote(`${frame(first)}${foldLocated(located)}`, input, first);
3171
+ input.ctx.error(logFor(message, input, first));
3172
+ }
3173
+
3174
+ // src/vite-transform.ts
3175
+ function incomingMapOf(input) {
3176
+ if (!input.hasStylesheetMaps) return void 0;
3177
+ const map = input.ctx.getCombinedSourcemap();
3178
+ return map.mappings === "" ? void 0 : toSourceMap(map);
3179
+ }
3180
+ function transformStylesheet(input) {
3181
+ const file = filePathOf(input.id);
3182
+ const inputSourceMap = incomingMapOf(input);
3183
+ const result = expandText(input.code, {
3184
+ extend: input.extend,
3185
+ onUnknown: input.onUnknown,
3186
+ from: file,
3187
+ inputSourceMap
3188
+ });
3189
+ reportDiagnostics({
3190
+ ctx: input.ctx,
3191
+ diagnostics: result.diagnostics,
3192
+ extend: input.extend,
3193
+ id: input.id,
3194
+ file,
3195
+ incoming: inputSourceMap && decodeIncomingMap(inputSourceMap),
3196
+ onUnknown: input.onUnknown
3197
+ });
3198
+ return { code: result.css, map: result.map };
3199
+ }
3200
+
3201
+ // src/vite-stylesheets.ts
3202
+ function hasStylesheetMapsFor(config) {
3203
+ return config.command === "serve" ? config.css?.devSourcemap === true : Boolean(config.build?.sourcemap);
3204
+ }
3205
+ function withForwardSlashes(file) {
3206
+ return file.replaceAll("\\", "/");
3207
+ }
3208
+ function createStylesheets(extend, onUnknown) {
3209
+ let hasStylesheetMaps = false;
3210
+ const failed = /* @__PURE__ */ new Map();
3211
+ async function expand(ctx, code, id) {
3212
+ const environment = ctx.environment?.name ?? "client";
3213
+ let atoms;
3214
+ try {
3215
+ atoms = await extend.current((file) => {
3216
+ ctx.addWatchFile(file);
3217
+ });
3218
+ } catch (error) {
3219
+ failed.set(environment, (failed.get(environment) ?? /* @__PURE__ */ new Set()).add(id));
3220
+ throw error;
3221
+ }
3222
+ failed.get(environment)?.delete(id);
3223
+ return transformStylesheet({ ctx, code, id, extend: atoms, onUnknown, hasStylesheetMaps });
3224
+ }
3225
+ return {
3226
+ configure(config) {
3227
+ hasStylesheetMaps = hasStylesheetMapsFor(config);
3228
+ },
3229
+ async transform(ctx, code, id) {
3230
+ if (!isStylesheetId(id)) return;
3231
+ const environment = ctx.environment?.name ?? "client";
3232
+ const hasDirective = canHoldDirective(code);
3233
+ if (!hasDirective) failed.get(environment)?.delete(id);
3234
+ const result = hasDirective ? await expand(ctx, code, id) : void 0;
3235
+ return result;
3236
+ },
3237
+ hotUpdate(ctx, hot) {
3238
+ const ids = failed.get(ctx.environment.name);
3239
+ const file = extend.file?.();
3240
+ if (!ids || file === void 0 || ids.size === 0) return;
3241
+ if (hot.file !== withForwardSlashes(file)) return;
3242
+ const { moduleGraph } = ctx.environment;
3243
+ for (const id of ids) {
3244
+ const module = moduleGraph.getModuleById(id);
3245
+ if (module) moduleGraph.invalidateModule(module);
3246
+ }
3247
+ ids.clear();
3248
+ ctx.environment.hot.send({ type: "full-reload" });
3249
+ return [];
3250
+ }
3251
+ };
3252
+ }
3253
+
3254
+ // src/vite.ts
3255
+ function assemble(options, extend) {
3256
+ const context = createUsedContext(resolveUsedOptions(options), extend);
3257
+ const stylesheets = createStylesheets(extend, options.onUnknown ?? "error");
3258
+ const nave = {
3259
+ name: "nave",
3260
+ config: (_config, env) => usedConfig(context, env?.command),
3261
+ configEnvironment: (name, environmentOptions) => usedEnvironmentConfig(context, name, environmentOptions),
3262
+ configResolved(config) {
3263
+ extend.configure?.(config.root);
3264
+ configureUsed(context, config);
3265
+ stylesheets.configure(config);
3266
+ if (context.command === "build" && isUsed(context))
3267
+ captureStylesheets(context, config.plugins);
3268
+ if (config.css?.transformer === "lightningcss") dropLightningNaveWarning(config.logger);
3269
+ },
3270
+ ...serverHooks(context),
3271
+ async transform(code, id) {
3272
+ const expanded = await stylesheets.transform(this, code, id);
3273
+ if (expanded !== void 0 && expanded.code !== code) context.state.directiveExpanded = true;
3274
+ if (context.command !== "serve" || !isUsed(context)) return expanded;
3275
+ const served = await serveStylesheet(context, this, { css: expanded?.code ?? code, id });
3276
+ return served ?? expanded;
3277
+ },
3278
+ hotUpdate(hot) {
3279
+ const handled = stylesheets.hotUpdate(this, hot);
3280
+ if (handled || context.command !== "serve" || !isUsed(context)) return handled;
3281
+ return devServing.modulesWithGrown(context, this, hot);
3282
+ },
3283
+ async renderChunk(_code, chunk) {
3284
+ if (!isUsed(context) || this.environment.config.consumer !== "client") return;
3285
+ const emitted = emittedSet(context, this.environment, (message) => {
3286
+ this.warn(message);
3287
+ });
3288
+ await refeedChunkStylesheets(this, chunk, context.state, emitted);
3289
+ warnTextImports(this, chunk, context, emitted);
3290
+ },
3291
+ generateBundle: {
3292
+ order: "post",
3293
+ handler(_options, bundle) {
3294
+ if (isUsed(context) && this.environment?.config.consumer === "client") {
3295
+ checkAtomicLayers(
3296
+ this,
3297
+ bundle,
3298
+ emittedSet(context, this.environment, (message) => {
3299
+ this.warn(message);
3300
+ })
3301
+ );
3302
+ }
3303
+ scanBundle(this, bundle);
3304
+ }
3305
+ }
3306
+ };
3307
+ return { nave, collect: createCollectPlugin(context) };
3308
+ }
3309
+ function navePlugin(options = {}) {
3310
+ const ownAtoms = typeof options.extend === "object" ? options.extend : void 0;
3311
+ const own = typeof options.extend === "string" ? void 0 : new Set(Object.keys(ownAtoms ?? {}));
3312
+ assertOptions(options, own);
3313
+ const inline = typeof options.extend === "string" ? void 0 : createExtendSource(options.extend);
3314
+ return shareAcrossBuilds(() => assemble(options, inline ?? createExtendSource(options.extend)));
3315
+ }
3316
+ var vite_default = navePlugin;
3317
+
3318
+ export { vite_default as default, navePlugin };