@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.
- package/CONSUMER-ATOMS.md +15 -11
- package/LICENSE +22 -0
- package/README.md +300 -33
- package/dist/{atom-names-2OreuBx9.d.ts → atom-names-B8Ud-7zD.d.ts} +2 -1
- package/dist/atoms.d.ts +3 -2
- package/dist/bin.js +98 -15
- package/dist/check.d.ts +2 -1
- package/dist/check.js +4 -3
- package/dist/{chunk-NFS2REPQ.js → chunk-2K5EBBF2.js} +1 -191
- package/dist/chunk-2TNTYI4L.js +7 -0
- package/dist/{chunk-LQSGQ2OA.js → chunk-B5CWZIBK.js} +3 -2
- package/dist/{chunk-XQQCDUV6.js → chunk-CTFEYJBE.js} +1 -1
- package/dist/{chunk-E5F6YF7A.js → chunk-EYMFWE3A.js} +2273 -126
- package/dist/chunk-KDLLTOAM.js +4031 -0
- package/dist/{chunk-2A7IUZBH.js → chunk-R6R5DSTT.js} +8 -8
- package/dist/chunk-UVHGEVMV.js +204 -0
- package/dist/{chunk-UANF3FGO.js → chunk-ZNTNLGEC.js} +2 -1
- package/dist/collect.d.ts +340 -6
- package/dist/collect.js +38 -1
- package/dist/css.d.ts +1 -0
- package/dist/cx.d.ts +1 -1
- package/dist/lightningcss.d.ts +3 -2
- package/dist/lightningcss.js +7 -4
- package/dist/postcss.d.ts +29 -3
- package/dist/postcss.js +331 -81
- package/dist/standalone.css +2 -0
- package/dist/{vite-options-D1-hGA9L.d.ts → vite-options-sOCeGn9B.d.ts} +3 -2
- package/dist/vite.d.ts +24 -3
- package/dist/vite.js +1541 -2284
- package/package.json +53 -24
- package/skills/navecss/SKILL.md +15 -1
- package/dist/chunk-LADFXRWQ.js +0 -1089
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { foldLocated } from './chunk-
|
|
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,
|
|
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,
|
|
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-
|
|
2
|
-
import './atom-names-
|
|
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
|
|
610
|
+
declare function withRestorers(atoms: Set<string>): Set<string>;
|
|
278
611
|
|
|
279
|
-
export {
|
|
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
|
-
|
|
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 {}
|