@navecss/core 0.4.0 → 0.6.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.
@@ -1,16 +1,16 @@
1
- import { foldLocated } from './chunk-LADFXRWQ.js';
1
+ import { foldLocated } from './chunk-KDLLTOAM.js';
2
2
  import { formatDiagnostic } from './chunk-SYNQJNVB.js';
3
3
 
4
- // src/byte-order-mark.ts
5
- var BYTE_ORDER_MARK = "\uFEFF";
6
- function splitByteOrderMark(raw) {
7
- return raw.startsWith(BYTE_ORDER_MARK) ? { bom: BYTE_ORDER_MARK, text: raw.slice(BYTE_ORDER_MARK.length) } : { bom: "", text: raw };
8
- }
9
-
10
4
  // src/directive/report-text.ts
11
5
  function inSourceOrder(diagnostics) {
12
6
  return diagnostics.toSorted((a, b) => a.offset - b.offset);
13
7
  }
8
+ function framedText(file, line, column, text) {
9
+ return `${file}:${line}:${column}: ${text}`;
10
+ }
11
+ function orderWarningTexts(warnings, file) {
12
+ return warnings.map((warning) => framedText(file, warning.line, warning.column, warning.text));
13
+ }
14
14
  function warningTexts(diagnostics, file, extend) {
15
15
  return inSourceOrder(diagnostics).map(
16
16
  (diagnostic) => `${file}:${diagnostic.line}:${diagnostic.column}: ${formatDiagnostic(diagnostic, { extend })}`
@@ -28,4 +28,4 @@ function foldedText(diagnostics, file, extend) {
28
28
  return `${file}:${first.line}:${first.column}: ${foldLocated(located)}`;
29
29
  }
30
30
 
31
- export { foldedText, splitByteOrderMark, warningTexts };
31
+ export { foldedText, framedText, orderWarningTexts, warningTexts };
@@ -0,0 +1,204 @@
1
+ // src/directive/expand-text-diagnostics.ts
2
+ function lineStartOffsets(text) {
3
+ const starts = [0];
4
+ let i = 0;
5
+ while (i < text.length) {
6
+ const c = text[i];
7
+ if (c === "\r") {
8
+ i++;
9
+ if (text[i] === "\n") i++;
10
+ starts.push(i);
11
+ continue;
12
+ }
13
+ if (c === "\n" || c === "\f") {
14
+ i++;
15
+ starts.push(i);
16
+ continue;
17
+ }
18
+ i++;
19
+ }
20
+ return starts;
21
+ }
22
+ function lastAtOrBefore(starts, offset) {
23
+ let low = 0;
24
+ let high = starts.length - 1;
25
+ while (low < high) {
26
+ const mid = low + high + 1 >> 1;
27
+ if (starts[mid] <= offset) low = mid;
28
+ else high = mid - 1;
29
+ }
30
+ return low;
31
+ }
32
+ function createPositionFinder(text) {
33
+ const starts = lineStartOffsets(text);
34
+ return (offset) => {
35
+ const line = lastAtOrBefore(starts, offset);
36
+ return { line: line + 1, column: offset - starts[line] };
37
+ };
38
+ }
39
+ function reportDiagnostics(diagnostics, css, options) {
40
+ const onUnknown = options.onUnknown ?? "error";
41
+ if (onUnknown === "ignore") return [];
42
+ const severity = onUnknown === "warn" ? "warning" : "error";
43
+ const positionAt = createPositionFinder(css);
44
+ return diagnostics.map((diagnostic) => {
45
+ const position = positionAt(diagnostic.offset);
46
+ return {
47
+ ...diagnostic,
48
+ severity,
49
+ ...options.from !== void 0 && { file: options.from },
50
+ line: position.line,
51
+ column: position.column + 1
52
+ };
53
+ });
54
+ }
55
+ function positionWarnings(warnings, css, file) {
56
+ const positionAt = createPositionFinder(css);
57
+ return warnings.toSorted((a, b) => a.offset - b.offset).map(({ offset, text }) => {
58
+ const position = positionAt(offset);
59
+ return {
60
+ text,
61
+ offset,
62
+ line: position.line,
63
+ column: position.column + 1,
64
+ ...file !== void 0 && { file }
65
+ };
66
+ });
67
+ }
68
+
69
+ // src/directive/bracket-match.ts
70
+ var OPENERS = /* @__PURE__ */ new Set(["(-token", "[-token", "function-token", "{-token"]);
71
+ var CLOSERS = /* @__PURE__ */ new Set([")-token", "]-token", "}-token"]);
72
+ function isMirrorCloser(openerType, closerType) {
73
+ if (closerType === ")-token") return openerType === "(-token" || openerType === "function-token";
74
+ if (closerType === "]-token") return openerType === "[-token";
75
+ return openerType === "{-token";
76
+ }
77
+ function matchBrackets(tokens) {
78
+ const closerFor = new Int32Array(tokens.length).fill(-1);
79
+ const opens = [];
80
+ for (const [i, token] of tokens.entries()) {
81
+ const { type } = token;
82
+ if (OPENERS.has(type)) {
83
+ opens.push(i);
84
+ continue;
85
+ }
86
+ if (!CLOSERS.has(type)) continue;
87
+ const openIndex = opens.at(-1);
88
+ if (openIndex === void 0 || !isMirrorCloser(tokens[openIndex].type, type)) continue;
89
+ opens.pop();
90
+ closerFor[openIndex] = i;
91
+ }
92
+ return closerFor;
93
+ }
94
+ function matchedCloseWithin(closerFor, openIndex, limit) {
95
+ const closeIndex = closerFor[openIndex];
96
+ return closeIndex !== -1 && closeIndex < limit ? closeIndex : void 0;
97
+ }
98
+
99
+ // src/directive/block-reader.ts
100
+ function scanItem(tokens, start, limit, closerFor) {
101
+ let i = start;
102
+ while (i < limit) {
103
+ const type = tokens[i].type;
104
+ if (OPENERS.has(type)) {
105
+ const closeIndex = matchedCloseWithin(closerFor, i, limit);
106
+ if (type === "{-token") {
107
+ return {
108
+ end: closeIndex === void 0 ? limit : closeIndex + 1,
109
+ consumedSemicolon: false,
110
+ trailingBlock: { openIndex: i, closeIndex }
111
+ };
112
+ }
113
+ i = closeIndex === void 0 ? limit : closeIndex + 1;
114
+ continue;
115
+ }
116
+ if (CLOSERS.has(type)) {
117
+ if (i === start) return { end: i + 1, consumedSemicolon: false };
118
+ i++;
119
+ continue;
120
+ }
121
+ if (type === "semicolon-token") return { end: i + 1, consumedSemicolon: true };
122
+ i++;
123
+ }
124
+ return { end: i, consumedSemicolon: false };
125
+ }
126
+ function scanCustomPropertyValue(tokens, start, limit, closerFor) {
127
+ let i = start;
128
+ while (i < limit) {
129
+ const type = tokens[i].type;
130
+ if (OPENERS.has(type)) {
131
+ const closeIndex = matchedCloseWithin(closerFor, i, limit);
132
+ i = closeIndex === void 0 ? limit : closeIndex + 1;
133
+ continue;
134
+ }
135
+ if (type === "semicolon-token") return i + 1;
136
+ i++;
137
+ }
138
+ return i;
139
+ }
140
+ function isColonSoonAfter(tokens, i, limit) {
141
+ let j = i;
142
+ while (j < limit && (tokens[j].type === "whitespace-token" || tokens[j].type === "comment")) j++;
143
+ return tokens[j]?.type === "colon-token";
144
+ }
145
+ function isCustomPropertyName(token) {
146
+ return token.type === "ident-token" && (token.structured?.value).startsWith("--");
147
+ }
148
+ function atKeywordName(token) {
149
+ return (token.structured?.value).toLowerCase();
150
+ }
151
+ function toDeclarationItem(start, end) {
152
+ return { kind: "declaration", start, end };
153
+ }
154
+ function preludeEndOffset(tokens, start, scan, preludeStart) {
155
+ if (scan.trailingBlock) return tokens[scan.trailingBlock.openIndex].startIndex;
156
+ const lastContentIndex = scan.consumedSemicolon ? scan.end - 2 : scan.end - 1;
157
+ return lastContentIndex >= start ? tokens[lastContentIndex].endIndex : preludeStart;
158
+ }
159
+ function toAtRuleItem(tokens, start, scan) {
160
+ const nameToken = tokens[start];
161
+ const preludeStart = tokens[start + 1]?.startIndex ?? nameToken.endIndex;
162
+ return {
163
+ kind: "at-rule",
164
+ start,
165
+ end: scan.end,
166
+ atKeyword: atKeywordName(nameToken),
167
+ preludeOffset: preludeStart,
168
+ preludeEndOffset: preludeEndOffset(tokens, start + 1, scan, preludeStart),
169
+ ...scan.trailingBlock && {
170
+ blockStart: scan.trailingBlock.openIndex + 1,
171
+ blockEnd: scan.trailingBlock.closeIndex ?? scan.end
172
+ }
173
+ };
174
+ }
175
+ function toRuleOrInvalidItem(start, scan) {
176
+ if (!scan.trailingBlock) return { kind: "invalid", start, end: scan.end };
177
+ return {
178
+ kind: "rule",
179
+ start,
180
+ end: scan.end,
181
+ blockStart: scan.trailingBlock.openIndex + 1,
182
+ blockEnd: scan.trailingBlock.closeIndex ?? scan.end
183
+ };
184
+ }
185
+ function readItem(tokens, start, limit, closerFor) {
186
+ const first = tokens[start];
187
+ if (first.type === "at-keyword-token") {
188
+ return toAtRuleItem(tokens, start, scanItem(tokens, start + 1, limit, closerFor));
189
+ }
190
+ if (first.type === "ident-token" && isColonSoonAfter(tokens, start + 1, limit)) {
191
+ if (isCustomPropertyName(first)) {
192
+ return toDeclarationItem(start, scanCustomPropertyValue(tokens, start + 1, limit, closerFor));
193
+ }
194
+ const scan = scanItem(tokens, start + 1, limit, closerFor);
195
+ if (!scan.trailingBlock) return toDeclarationItem(start, scan.end);
196
+ return toRuleOrInvalidItem(start, scan);
197
+ }
198
+ return toRuleOrInvalidItem(start, scanItem(tokens, start, limit, closerFor));
199
+ }
200
+ function isNaveAtKeyword(token) {
201
+ return token.type === "at-keyword-token" && atKeywordName(token) === "nave";
202
+ }
203
+
204
+ export { OPENERS, atKeywordName, createPositionFinder, isNaveAtKeyword, matchBrackets, positionWarnings, readItem, reportDiagnostics };
@@ -1,4 +1,5 @@
1
- import { createPositionFinder, tokenize, matchBrackets, readItem, isNaveAtKeyword } from './chunk-NFS2REPQ.js';
1
+ import { createPositionFinder, matchBrackets, readItem, isNaveAtKeyword } from './chunk-UVHGEVMV.js';
2
+ import { tokenize } from './chunk-2K5EBBF2.js';
2
3
 
3
4
  // src/directive/find-survivors.ts
4
5
  var NATURAL_STOP_CHARS = /* @__PURE__ */ new Set(["\n", ";", "}"]);
package/dist/collect.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { R as ResolvedUsedOptions, U as UsedAtomOptions, a as assertOptions, k as keptAtoms, r as resolveUsedOptions } from './vite-options-D1-hGA9L.js';
2
- import './atom-names-2OreuBx9.js';
1
+ export { R as ResolvedUsedOptions, U as UsedAtomOptions, a as assertOptions, k as keptAtoms, r as resolveUsedOptions } from './vite-options-sOCeGn9B.js';
2
+ import './atom-names-B8Ud-7zD.js';
3
3
 
4
4
  /**
5
5
  * The few shapes of the ESTree `this.parse` returns that the collector reads, declared here
@@ -55,6 +55,13 @@ interface Problem {
55
55
  * export), so a build-end check can tell whether an importer takes it.
56
56
  */
57
57
  readonly exportedAs?: readonly string[];
58
+ /**
59
+ * For a use in a dependency that hands Nave's `cx` out of its module where the build cannot
60
+ * follow it to an export (it is assigned to something other than a name of the module, passed
61
+ * as a value, bound, or imported in a form the build does not read). A hand-out the build can
62
+ * follow carries `exportedAs` instead.
63
+ */
64
+ readonly isUnboundHandOut?: boolean;
58
65
  /**
59
66
  * For a problem in a module listed in `cxModules`: whether the module also exports Nave's own
60
67
  * `cx`. An importer's `cx` is then Nave's, so what the build says of its calls is not an echo of
@@ -169,13 +176,40 @@ declare const CX_SOURCE = "@navecss/core/cx";
169
176
  */
170
177
  declare function readModule(code: string, program: AstNode, options: ReadOptions): ModuleReading;
171
178
 
179
+ interface LayerReading {
180
+ /**
181
+ * Whether the stylesheet holds an `@layer atomic { ... }` block.
182
+ */
183
+ readonly hasLayer: boolean;
184
+ /**
185
+ * The built-in atoms whose class a rule in the layer selects.
186
+ */
187
+ readonly atoms: Set<string>;
188
+ }
189
+ /**
190
+ * `css` with every rule in an `@layer atomic` block that needs an atom outside `emitted` removed.
191
+ */
192
+ declare function pruneAtomicLayer(css: string, emitted: ReadonlySet<string>): string;
193
+ /**
194
+ * What the `@layer atomic` blocks of `css` hold.
195
+ */
196
+ declare function inspectAtomicLayer(css: string): LayerReading;
197
+ /**
198
+ * The atoms outside `emitted` that a rule left in the `@layer atomic` blocks of `css` still needs
199
+ * an element of: what a pruning to `emitted` would still remove, sorted.
200
+ */
201
+ declare function unprunedAtoms(css: string, emitted: ReadonlySet<string>): string[];
202
+
172
203
  /**
173
204
  * What an importer takes from a module that gives out Nave's `cx`: which of its `cx` exports it
174
205
  * imports, re-exports or reads off a namespace. The test is by name, not by file: an importer that
175
206
  * takes only `Button` from a module which also exports `cx` as `cn` takes no `cx` from it, so
176
207
  * nothing of its own routes calls through `cn`. A take the parse cannot tell apart (a namespace
177
208
  * passed on, a computed key, a rest element, an `import()` used any other way) counts as taken, and
178
- * so does an importer whose text names the module in no way the build reads (a `require()`).
209
+ * so does an importer whose text names the module in no way the build reads (a `require()`). A
210
+ * declaration written for the types only (`import type`, `export type`, a `type` specifier), and a
211
+ * named import that is referenced only in type positions, take nothing: TypeScript leaves them out
212
+ * of the compiled module.
179
213
  */
180
214
 
181
215
  /**
@@ -204,6 +238,12 @@ interface Taken {
204
238
  * Whether the take comes from what an earlier server command left in the cache directory.
205
239
  */
206
240
  readonly isRecorded?: boolean;
241
+ /**
242
+ * For a dependency's take: whether the build reads it neither as calls only nor as a forward, so
243
+ * it cannot tell where what is taken goes. `form` says what the dependency does, in words.
244
+ */
245
+ readonly isHeld?: boolean;
246
+ readonly form?: string;
207
247
  }
208
248
  interface Take extends Taken {
209
249
  /**
@@ -217,6 +257,46 @@ interface Take extends Taken {
217
257
  readonly isReached: boolean;
218
258
  }
219
259
 
260
+ /**
261
+ * `cxModules`: the modules a consumer lists as re-exporting Nave's `cx`, and what the post-order
262
+ * half does with them. An import is from a listed module when its specifier resolves, from the
263
+ * importing module, to a listed module's file, or, for an entry that is not relative, when it
264
+ * equals the entry as written (a relative specifier names a file relative to the module that
265
+ * writes it, so its text alone names nothing). An entry that is, or resolves to, Nave's own `cx`
266
+ * module is no entry: that module is always followed. A module is parsed only when its text can
267
+ * name a listed one (a text test, so an application of thousands of modules parses the importers
268
+ * and no more), and a build-end check compares the importers it recognised with the module
269
+ * graph's, so an import through a spelling the text test cannot see fails the build instead of
270
+ * shipping every call made through it with no rule.
271
+ */
272
+
273
+ interface DeclaredModules {
274
+ /**
275
+ * The entries a specifier may equal as written: every entry but a relative one.
276
+ */
277
+ readonly entries: ReadonlySet<string>;
278
+ /**
279
+ * The module id each entry resolves to from the project root; an entry that resolves to nothing
280
+ * has none.
281
+ */
282
+ readonly ids: ReadonlyMap<string, string>;
283
+ /**
284
+ * The files the entries resolve to.
285
+ */
286
+ readonly files: ReadonlySet<string>;
287
+ /**
288
+ * The names a specifier's last segment may carry to name a listed file: its name without its
289
+ * extension, and its directory's when it is an `index` file.
290
+ */
291
+ readonly names: ReadonlySet<string>;
292
+ /**
293
+ * Finds, in a module's text, a quoted specifier that can name a listed file: one whose last
294
+ * segment is one of `names`, or a directory specifier that writes no name when a listed file
295
+ * is an `index` file. `undefined` when no listed file resolved.
296
+ */
297
+ readonly textTest: RegExp | undefined;
298
+ }
299
+
220
300
  /**
221
301
  * The report a build fails with when it meets a use it cannot read: a first line counting the
222
302
  * problems and stating the cause, one line per problem with a 1-based, root-relative position,
@@ -261,19 +341,273 @@ interface LocatedProblem extends Problem {
261
341
  * application modules that take one of its `cx` exports, which `keepFor` does not clear.
262
342
  */
263
343
  readonly takes?: readonly Take[] | undefined;
344
+ /**
345
+ * For a problem with `takes`: how the host names the root a `cxModules` specifier resolves from,
346
+ * in the words the remedy line for those takes uses.
347
+ */
348
+ readonly rootName?: string | undefined;
264
349
  /**
265
350
  * For a dependency module that re-exports the `cx` of a module `cxModules` lists: the modules of
266
351
  * other dependencies that call through it, root-relative, which only the package's `keepFor`
267
352
  * entry can stand in for.
268
353
  */
269
354
  readonly callers?: readonly string[] | undefined;
355
+ /**
356
+ * For a dependency's problem that stays an error whatever the application imports, and that no
357
+ * `keepFor` entry clears: a hand-out of `cx` the build cannot follow to an export, or a take of a
358
+ * module that gives `cx` out that the build reads neither as calls only nor as a forward.
359
+ */
360
+ readonly isHeld?: boolean;
270
361
  }
271
362
  declare const REPORT_CAUSE = "the build cannot tell which atoms these apply, and it ships only the atoms it can read.";
363
+ /**
364
+ * The remedy lines only a host can write, given the application's problems: they print after the
365
+ * lines of the application's kinds and before any package's line.
366
+ */
367
+ type HostRemedies = (application: readonly LocatedProblem[]) => readonly string[];
368
+ /**
369
+ * What a host adds to the report besides where its options are written: the remedy lines only it
370
+ * can write, and where its own documentation says how to ship every atom, which is the Vite
371
+ * plugin's README section when it names none.
372
+ */
373
+ interface ReportHost {
374
+ readonly remedies?: HostRemedies;
375
+ readonly everyAtom?: string;
376
+ }
272
377
  /**
273
378
  * The build report for every problem of an environment. `configured` is the `cxModules` list the
274
379
  * remedies that print one extend, and `home` is how the host spells where the options are written,
275
- * the call of its plugin or its wrapper: the one place the report names its host.
380
+ * the call of its plugin or its wrapper: the one place the report names its host. `host` adds
381
+ * what only the host can write, given as a {@link ReportHost} or, as before, as its remedy lines
382
+ * alone.
383
+ */
384
+ declare function buildReport(problems: readonly LocatedProblem[], configured: readonly string[], home: string, host?: HostRemedies | ReportHost): string;
385
+
386
+ /**
387
+ * One import a server module of the consumer's makes of a listed package: the module, root
388
+ * relative, the specifier it writes, what it takes from it (any name counting as a `cx` export),
389
+ * and the file the server loads for it when that is known.
390
+ */
391
+ interface ServerImport {
392
+ readonly file?: string;
393
+ /**
394
+ * Whether the module imports the package in a way the build cannot read, such as `require()`.
395
+ */
396
+ readonly isUnreadable?: boolean;
397
+ /**
398
+ * Whether an earlier server command recorded it, not a server environment of this process.
399
+ */
400
+ readonly isRecorded?: boolean;
401
+ readonly specifier: string;
402
+ readonly takes: readonly Taken[];
403
+ readonly taker: string;
404
+ }
405
+ /**
406
+ * A server import whose target the client graph holds: the file it resolves to.
407
+ */
408
+ interface ResolvedServerImport extends ServerImport {
409
+ readonly file: string;
410
+ }
411
+
412
+ /**
413
+ * What the build-end read of who takes a `cx` that a dependency gives out needs of its host: the
414
+ * module graph (who imports a module, the text of a module, what a specifier resolves to, how to
415
+ * parse a module) and a few lookups that need the file system, which a host supplies so this
416
+ * code imports no Node module. The Vite plugin supplies them from its `RenderContext` and
417
+ * `UsedContext`; another host supplies them from its own graph.
418
+ */
419
+
420
+ /**
421
+ * What a host's module graph holds about one module.
422
+ */
423
+ interface ModuleInfo {
424
+ readonly code: string | null;
425
+ readonly importers: readonly string[];
426
+ readonly dynamicImporters: readonly string[];
427
+ }
428
+ /**
429
+ * The module graph of a build, as the read of the takes asks it.
430
+ */
431
+ interface ModuleHost {
432
+ /**
433
+ * The environment the build-end read runs for, which keys what it resolves once.
434
+ */
435
+ readonly environment: {
436
+ readonly name: string;
437
+ };
438
+ /**
439
+ * What the graph holds about the module `id`, or `null` when it holds none.
440
+ */
441
+ getModuleInfo?(id: string): ModuleInfo | null;
442
+ /**
443
+ * Resolves `source` as imported from `importer`.
444
+ */
445
+ resolve?(source: string, importer?: string): Promise<{
446
+ readonly id: string;
447
+ } | null>;
448
+ /**
449
+ * Every file id the host's build may resolve `source` to, for a host whose build resolves one
450
+ * specifier to different files (by condition, or by mode). Used instead of `resolve`, which
451
+ * answers one of them, wherever a resolution is compared to a file.
452
+ */
453
+ resolveAll?(source: string, importer?: string): Promise<readonly string[]>;
454
+ /**
455
+ * The host's parse of `code`, an ESTree.
456
+ */
457
+ parse?(code: string): unknown;
458
+ /**
459
+ * The host's parse of the module `id` whose text is `code`, for a host that reads authored
460
+ * sources whose language follows from the file. Used instead of `parse` when the host has it.
461
+ */
462
+ parseModule?(code: string, id: string): unknown;
463
+ }
464
+ /**
465
+ * What the read of the takes needs of the build: the project root, the options that decide which
466
+ * packages are listed, the modules `cxModules` lists (resolved once per environment and kept in
467
+ * `state.declared`), and the two lookups that need the file system.
468
+ */
469
+ interface TakesContext {
470
+ readonly root: string;
471
+ /**
472
+ * How the host's messages name `root`, completing the phrase a specifier that resolves from
473
+ * <rootName>.
474
+ */
475
+ readonly rootName: string;
476
+ readonly options: {
477
+ readonly cxModules: readonly string[];
478
+ readonly keepFor: Readonly<Record<string, readonly string[]>>;
479
+ };
480
+ readonly state: {
481
+ readonly declared: Map<string, Promise<DeclaredModules>>;
482
+ };
483
+ /**
484
+ * The name of the package the module `id` belongs to, when it lies under `node_modules`.
485
+ */
486
+ packageOf(id: string): Promise<string | undefined>;
487
+ /**
488
+ * The path a message names the module `id` by: relative to the project root, forward slashes.
489
+ */
490
+ labelOf(id: string): string;
491
+ }
492
+
493
+ /**
494
+ * The modules that give out `cx` through one of its `cx` exports: the module that exports Nave's
495
+ * `cx`, and every module of a dependency, of the same package or of another, that only re-exports
496
+ * one of those exports (a forward, by `export ... from` or by one of the CommonJS forms
497
+ * `vite-require-takes.ts` reads), however many modules away. A module that takes `cx` from any of
498
+ * them takes it from the first. A dependency's other takes (a call, an assignment, a wrapper, a
499
+ * take the build cannot read) end the walk: they are the package's own calls.
500
+ */
501
+
502
+ /**
503
+ * A module that gives out `cx`: the `cx` exports it holds, and whether it holds them by forwarding
504
+ * another module's rather than by exporting Nave's itself.
505
+ */
506
+ interface Holder {
507
+ readonly id: string;
508
+ readonly names: ReadonlySet<string>;
509
+ readonly isReached: boolean;
510
+ }
511
+
512
+ /**
513
+ * A dependency's take of a module that gives out `cx` that the build reads neither as calls only
514
+ * nor as a forward: the importer's module, the package it belongs to and what it does, in words.
515
+ */
516
+ interface Held {
517
+ readonly form: string;
518
+ readonly importer: string;
519
+ readonly pkg: string;
520
+ readonly taker: string;
521
+ }
522
+ interface Routes {
523
+ readonly entry: Take[];
524
+ readonly told: Take[];
525
+ /**
526
+ * The takes a dependency makes of the module that do more than re-export it: its calls.
527
+ */
528
+ readonly calls: Take[];
529
+ /**
530
+ * The takes a dependency makes of the module that the build reads neither as calls only nor as a
531
+ * forward, whatever the dependency is: they stay errors whatever the application imports.
532
+ */
533
+ readonly held: Held[];
534
+ }
535
+
536
+ /**
537
+ * One module that gives out `cx` with what the build read of its takes: the holders of its `cx`
538
+ * exports and the takes the importers of the build make of each. The imports a server environment
539
+ * makes are added when they are known, which can be after the environment that read the rest has
540
+ * ended.
541
+ */
542
+ interface Prepared {
543
+ readonly holders: readonly Holder[];
544
+ readonly isHop: boolean;
545
+ readonly isListed: boolean;
546
+ /**
547
+ * Whether the module has a clearing specifier: a take of the module itself by an application
548
+ * module or a calling dependency is then on the `cxModules` route.
549
+ */
550
+ readonly hasEntry: boolean;
551
+ readonly problems: readonly LocatedProblem[];
552
+ /**
553
+ * How the host names its root, for the remedy line of the takes.
554
+ */
555
+ readonly rootName: string;
556
+ readonly routed: readonly Routes[];
557
+ }
558
+
559
+ /**
560
+ * The build-end judgement of the re-exports of `cx` that a package `keepFor` lists gives out: which
561
+ * of them stay errors because a module of the consumer takes a `cx` export through them, with the
562
+ * line that clears each. The Vite plugin calls it at build end, and a host with another module
563
+ * graph (see `ModuleHost`) calls it over its own, so both say the same thing about the same code.
564
+ */
565
+
566
+ /**
567
+ * What reading one module found: its problems, those a `keepFor` entry stands in for set aside
568
+ * (`suppressed`), and the listed files it reads a `cx` from when it reads no other (`onlyVia`).
569
+ */
570
+ interface ModuleOutcome {
571
+ readonly onlyVia?: ReadonlySet<string> | undefined;
572
+ readonly problems: readonly LocatedProblem[];
573
+ readonly suppressed: readonly LocatedProblem[];
574
+ }
575
+ /**
576
+ * The problems the build fails with, given what each module's reading found: those of a package
577
+ * `keepFor` lists are only the ones its listing does not stand in for, a listed module that
578
+ * exports a `cx` the build does not follow and a `cx` export that a module the consumer can
579
+ * change takes. `serverImports` are the imports a server environment makes of a listed package it
580
+ * leaves external, when the host has such environments.
581
+ * @param host The module graph of the build.
582
+ * @param context The project root, the options, and the lookups that need the file system.
583
+ * @param modules What each module's reading found.
584
+ * @param serverImports What the server environments imported of a listed package.
585
+ * @returns The problems to report, and what was read of the takes of each re-exporting module.
586
+ */
587
+ declare function judgeReexports(host: ModuleHost, context: TakesContext, modules: readonly ModuleOutcome[], serverImports?: readonly ResolvedServerImport[]): Promise<{
588
+ prepared: Prepared[];
589
+ problems: LocatedProblem[];
590
+ }>;
591
+
592
+ /**
593
+ * Whether a module of a dependency hands out the Nave `cx` it imports in a form the build does not
594
+ * bind: see `isImportedCxHandedOut`.
595
+ */
596
+
597
+ /**
598
+ * Whether a module of a dependency hands out the Nave `cx` it imports in a form the build does not
599
+ * bind (a `require()`, a dynamic import, or a specifier other than the package's own), the string
600
+ * naming it starting at `offset`: its result is used for more than calls, or the build cannot find
601
+ * the import. A `cx` that is only called is the package's own call.
602
+ */
603
+ declare function isImportedCxHandedOut(program: AstNode, offset: number): boolean;
604
+
605
+ /**
606
+ * `atoms` with the atoms added that restore what an atom in it removes: `srOnlyFocusable` shows
607
+ * again on focus what `srOnly` hides, so a set that holds `srOnly` holds it too. This adds to the
608
+ * emitted set only, not to `keep` or to what `cx.dynamic()` accepts.
276
609
  */
277
- declare function buildReport(problems: readonly LocatedProblem[], configured: readonly string[], home: string): string;
610
+ declare function withRestorers(atoms: Set<string>): Set<string>;
278
611
 
279
- export { type AstNode, CX_SOURCE, type LocatedProblem, type ModuleReading, type Problem, type ProblemKind, REPORT_CAUSE, type ReadOptions, buildReport, readModule };
612
+ export { CX_SOURCE, REPORT_CAUSE, buildReport, inspectAtomicLayer, isImportedCxHandedOut, judgeReexports, pruneAtomicLayer, readModule, unprunedAtoms, withRestorers };
613
+ export type { AstNode, HostRemedies, LayerReading, LocatedProblem, ModuleHost, ModuleInfo, ModuleOutcome, ModuleReading, Problem, ProblemKind, ReadOptions, ReportHost, TakesContext };
package/dist/collect.js CHANGED
@@ -1,4 +1,41 @@
1
- export { CX_SOURCE, REPORT_CAUSE, assertOptions, buildReport, keptAtoms, readModule, resolveUsedOptions } from './chunk-E5F6YF7A.js';
1
+ import { analyze, isUsedAsCallsOnly, CX_ONLY, nodesAt, nodeAt, pushAll, childrenOf, staticStringOf, flowOf } from './chunk-EYMFWE3A.js';
2
+ export { CX_SOURCE, REPORT_CAUSE, assertOptions, buildReport, inspectAtomicLayer, judgeReexports, keptAtoms, pruneAtomicLayer, readModule, resolveUsedOptions, unprunedAtoms, withRestorers } from './chunk-EYMFWE3A.js';
2
3
  import './chunk-SYNQJNVB.js';
3
4
  import './chunk-CUL5PLPI.js';
5
+ import './chunk-2K5EBBF2.js';
4
6
  import './chunk-GZL2VW7C.js';
7
+
8
+ // src/vite-require-handed-out.ts
9
+ function allNodes(program) {
10
+ const found = [];
11
+ const stack = [program];
12
+ while (stack.length > 0) {
13
+ const node = stack.pop();
14
+ found.push(node);
15
+ pushAll(stack, childrenOf(node));
16
+ }
17
+ return found;
18
+ }
19
+ function importAt(nodes, offset) {
20
+ return nodes.find((node) => {
21
+ const literal = node.type === "CallExpression" ? nodesAt(node, "arguments")[0] : nodeAt(node, "source") ?? nodeAt(nodeAt(node, "moduleReference") ?? node, "expression");
22
+ return literal?.start === offset && node.type !== "Literal";
23
+ });
24
+ }
25
+ function isDeclarationHandedOut(analysis, declaration) {
26
+ const source = staticStringOf(nodeAt(declaration, "source"));
27
+ return analysis.references.filter(({ binding }) => binding?.kind === "import" && binding.source === source).some(({ node }) => {
28
+ const flow = flowOf(analysis, node);
29
+ return flow.isUnbound || flow.names.size > 0;
30
+ });
31
+ }
32
+ function isImportedCxHandedOut(program, offset) {
33
+ const analysis = analyze(program);
34
+ const node = importAt(allNodes(program), offset);
35
+ if (!node) return true;
36
+ if (node.type === "ImportDeclaration") return isDeclarationHandedOut(analysis, node);
37
+ if (node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") return true;
38
+ return !isUsedAsCallsOnly(analysis, node, CX_ONLY);
39
+ }
40
+
41
+ export { isImportedCxHandedOut };
package/dist/css.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {}