@navecss/core 0.3.0 → 0.5.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 +285 -30
- package/dist/atom-names-B8Ud-7zD.d.ts +28 -0
- package/dist/atoms.d.ts +4 -13
- package/dist/atoms.js +2 -1
- package/dist/bin.js +101 -16
- 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-R6JJZGXC.js → chunk-63H2FLGU.js} +3 -2
- package/dist/chunk-BCUK4M4P.js +2765 -0
- package/dist/{chunk-XQQCDUV6.js → chunk-CTFEYJBE.js} +1 -1
- package/dist/{chunk-LIUB4EES.js → chunk-CUL5PLPI.js} +1 -5
- package/dist/chunk-GZL2VW7C.js +57 -0
- package/dist/{chunk-IZQLFUQU.js → chunk-KKUYU75D.js} +9 -8
- package/dist/chunk-MWHZ26S4.js +4059 -0
- package/dist/chunk-SYNQJNVB.js +302 -0
- package/dist/chunk-UVHGEVMV.js +204 -0
- package/dist/{chunk-UANF3FGO.js → chunk-ZNTNLGEC.js} +2 -1
- package/dist/collect.d.ts +317 -0
- package/dist/collect.js +5 -0
- package/dist/css.d.ts +1 -0
- package/dist/cx.d.ts +1 -1
- package/dist/cx.js +14 -1
- package/dist/lightningcss.d.ts +3 -1
- package/dist/lightningcss.js +10 -5
- package/dist/postcss.d.ts +29 -2
- package/dist/postcss.js +334 -82
- package/dist/standalone.css +4 -0
- package/dist/vite-options-sOCeGn9B.d.ts +87 -0
- package/dist/vite.d.ts +27 -68
- package/dist/vite.js +1344 -3176
- package/package.json +58 -24
- package/skills/navecss/SKILL.md +16 -0
- package/dist/chunk-S7DZUVV3.js +0 -1386
|
@@ -0,0 +1,2765 @@
|
|
|
1
|
+
import { decodeIncomingMap, MappingsBuilder, formatDiagnostic } from './chunk-SYNQJNVB.js';
|
|
2
|
+
import { tokenize } from './chunk-2K5EBBF2.js';
|
|
3
|
+
import { atomClassMap } from './chunk-GZL2VW7C.js';
|
|
4
|
+
|
|
5
|
+
// src/vite-ast.ts
|
|
6
|
+
function isNode(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
8
|
+
}
|
|
9
|
+
function nodeAt(node, key) {
|
|
10
|
+
const value = node[key];
|
|
11
|
+
return isNode(value) ? value : void 0;
|
|
12
|
+
}
|
|
13
|
+
function nodesAt(node, key) {
|
|
14
|
+
const value = node[key];
|
|
15
|
+
return Array.isArray(value) ? value.filter((item) => isNode(item)) : [];
|
|
16
|
+
}
|
|
17
|
+
function stringAt(node, key) {
|
|
18
|
+
const value = node[key];
|
|
19
|
+
return typeof value === "string" ? value : void 0;
|
|
20
|
+
}
|
|
21
|
+
function pushAll(target, items) {
|
|
22
|
+
for (const item of items) target.push(item);
|
|
23
|
+
}
|
|
24
|
+
var NO_KEYS = /* @__PURE__ */ new Set();
|
|
25
|
+
function childrenOf(node, skipping = NO_KEYS) {
|
|
26
|
+
return Object.entries(node).flatMap(([key, value]) => {
|
|
27
|
+
if (skipping.has(key)) return [];
|
|
28
|
+
if (Array.isArray(value)) return value.filter((item) => isNode(item));
|
|
29
|
+
return isNode(value) ? [value] : [];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
var ASSERTIONS = /* @__PURE__ */ new Set([
|
|
33
|
+
"TSAsExpression",
|
|
34
|
+
"TSNonNullExpression",
|
|
35
|
+
"TSSatisfiesExpression",
|
|
36
|
+
"TSTypeAssertion"
|
|
37
|
+
]);
|
|
38
|
+
function assertedBy(node) {
|
|
39
|
+
return ASSERTIONS.has(node.type) ? nodeAt(node, "expression") : void 0;
|
|
40
|
+
}
|
|
41
|
+
function wrappedBy(node) {
|
|
42
|
+
return node.type === "ParenthesizedExpression" ? nodeAt(node, "expression") : assertedBy(node);
|
|
43
|
+
}
|
|
44
|
+
function isTypeOnly(node) {
|
|
45
|
+
return node.importKind === "type" || node.exportKind === "type";
|
|
46
|
+
}
|
|
47
|
+
function valueSpecifiersOf(node) {
|
|
48
|
+
return nodesAt(node, "specifiers").filter((specifier) => !isTypeOnly(specifier));
|
|
49
|
+
}
|
|
50
|
+
function staticStringOf(node) {
|
|
51
|
+
if (!node) return void 0;
|
|
52
|
+
if (node.type === "Literal") {
|
|
53
|
+
return typeof node.value === "string" ? node.value : void 0;
|
|
54
|
+
}
|
|
55
|
+
if (node.type !== "TemplateLiteral" || nodesAt(node, "expressions").length > 0) return void 0;
|
|
56
|
+
const quasi = nodesAt(node, "quasis")[0];
|
|
57
|
+
const value = quasi?.value;
|
|
58
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
59
|
+
const cooked = value.cooked;
|
|
60
|
+
return typeof cooked === "string" ? cooked : void 0;
|
|
61
|
+
}
|
|
62
|
+
function exportNameOf(node) {
|
|
63
|
+
if (!node) return void 0;
|
|
64
|
+
return node.type === "Identifier" ? stringAt(node, "name") : staticStringOf(node);
|
|
65
|
+
}
|
|
66
|
+
function propertyNameOf(key, isComputed) {
|
|
67
|
+
if (!key) return void 0;
|
|
68
|
+
if (!isComputed && key.type === "Identifier") return stringAt(key, "name");
|
|
69
|
+
return staticStringOf(key);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/vite-assertion-text.ts
|
|
73
|
+
function endOfComment(code, at) {
|
|
74
|
+
if (code.startsWith("/*", at)) {
|
|
75
|
+
const close = code.indexOf("*/", at + 2);
|
|
76
|
+
return close === -1 ? code.length : close + 2;
|
|
77
|
+
}
|
|
78
|
+
if (code.startsWith("//", at)) {
|
|
79
|
+
const newline = code.indexOf("\n", at);
|
|
80
|
+
return newline === -1 ? code.length : newline + 1;
|
|
81
|
+
}
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
function skipBlanks(code, from) {
|
|
85
|
+
let at = from;
|
|
86
|
+
for (; ; ) {
|
|
87
|
+
const commentEnd = endOfComment(code, at);
|
|
88
|
+
if (commentEnd !== void 0) at = commentEnd;
|
|
89
|
+
else if (/\s/.test(code.charAt(at))) at += 1;
|
|
90
|
+
else return at;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function skipClosings(code, from) {
|
|
94
|
+
let next = skipBlanks(code, from);
|
|
95
|
+
let closed = from;
|
|
96
|
+
while (code[next] === ")") {
|
|
97
|
+
closed = next + 1;
|
|
98
|
+
next = skipBlanks(code, closed);
|
|
99
|
+
}
|
|
100
|
+
return { next, closed };
|
|
101
|
+
}
|
|
102
|
+
function droppedPartOf(code, node, asserted) {
|
|
103
|
+
if (node.type !== "TSTypeAssertion") return [skipClosings(code, asserted.end).closed, node.end];
|
|
104
|
+
const type = nodeAt(node, "typeAnnotation");
|
|
105
|
+
if (!type) return [node.start, asserted.start];
|
|
106
|
+
return [node.start, skipClosings(code, type.end).next + 1];
|
|
107
|
+
}
|
|
108
|
+
function textWithoutAssertions(code, args) {
|
|
109
|
+
const dropped = [];
|
|
110
|
+
const stack = [...args];
|
|
111
|
+
while (stack.length > 0) {
|
|
112
|
+
const node = stack.pop();
|
|
113
|
+
const asserted = assertedBy(node);
|
|
114
|
+
if (asserted) dropped.push(droppedPartOf(code, node, asserted));
|
|
115
|
+
pushAll(stack, childrenOf(node));
|
|
116
|
+
}
|
|
117
|
+
dropped.sort(([first2], [second]) => first2 - second);
|
|
118
|
+
let text = "";
|
|
119
|
+
let from = args[0].start;
|
|
120
|
+
for (const [start, end] of dropped) {
|
|
121
|
+
text += code.slice(from, start);
|
|
122
|
+
from = end;
|
|
123
|
+
}
|
|
124
|
+
return text + code.slice(from, args.at(-1).end);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/vite-atom-check.ts
|
|
128
|
+
function isBuiltInAtom(name) {
|
|
129
|
+
return Object.hasOwn(atomClassMap, name);
|
|
130
|
+
}
|
|
131
|
+
function hintFor(name) {
|
|
132
|
+
const text = formatDiagnostic({ code: "unknown-atom", name, offset: 0, endOffset: 0 });
|
|
133
|
+
const hint = text.slice(`@nave: unknown atom "${name}". `.length);
|
|
134
|
+
return hint.startsWith("Did you mean") ? hint : void 0;
|
|
135
|
+
}
|
|
136
|
+
function literal(text) {
|
|
137
|
+
return `'${text.replaceAll("\\", "\\\\").replaceAll("'", String.raw`\'`)}'`;
|
|
138
|
+
}
|
|
139
|
+
function whitespaceText(value) {
|
|
140
|
+
const names = value.split(/\s+/).filter(Boolean);
|
|
141
|
+
if (names.length < 2) {
|
|
142
|
+
return `"${value}" has whitespace around the atom name. Write it without: cx(${literal(names[0] ?? "")}).`;
|
|
143
|
+
}
|
|
144
|
+
const count = names.length === 2 ? "two" : String(names.length);
|
|
145
|
+
const call = names.map((name) => literal(name)).join(", ");
|
|
146
|
+
return `"${value}" is ${count} atom names in one string. Pass one per argument: cx(${call}).`;
|
|
147
|
+
}
|
|
148
|
+
function unknownText(name) {
|
|
149
|
+
return `unknown atom "${name}". cx() takes Nave atoms only; for a class of your own, use a CSS Module class or cx.raw(${literal(name)}).`;
|
|
150
|
+
}
|
|
151
|
+
function judgeAtom(value, own) {
|
|
152
|
+
if (/\s/.test(value)) return { kind: "whitespace", text: whitespaceText(value) };
|
|
153
|
+
if (isBuiltInAtom(value)) return { kind: "atom" };
|
|
154
|
+
if (own.has(value)) return { kind: "own" };
|
|
155
|
+
const hint = hintFor(value);
|
|
156
|
+
if (hint) return { kind: "unknown", text: `unknown atom "${value}". ${hint}`, hasHint: true };
|
|
157
|
+
return { kind: "unknown", text: unknownText(value), hasHint: false };
|
|
158
|
+
}
|
|
159
|
+
function availableLine() {
|
|
160
|
+
return `Available: ${Object.keys(atomClassMap).join(", ")}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/vite-setup-member.ts
|
|
164
|
+
function setupMemberName(node) {
|
|
165
|
+
if (node.type !== "MemberExpression") return void 0;
|
|
166
|
+
const object = nodeAt(node, "object");
|
|
167
|
+
if (object?.type !== "Identifier" || stringAt(object, "name") !== "$setup") return void 0;
|
|
168
|
+
return propertyNameOf(nodeAt(node, "property"), node.computed === true);
|
|
169
|
+
}
|
|
170
|
+
var FUNCTION_TYPES = /* @__PURE__ */ new Set([
|
|
171
|
+
"ArrowFunctionExpression",
|
|
172
|
+
"FunctionDeclaration",
|
|
173
|
+
"FunctionExpression"
|
|
174
|
+
]);
|
|
175
|
+
function isOutsideFunctions(node, parentOf) {
|
|
176
|
+
for (let current = parentOf.get(node); current; current = parentOf.get(current)) {
|
|
177
|
+
if (FUNCTION_TYPES.has(current.type)) return false;
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
var SETUP_PARAMETER_POSITIONS = [3, 5];
|
|
182
|
+
function isSetupParameter(analysis, identifier) {
|
|
183
|
+
const binding = analysis.referenceOf(identifier)?.binding;
|
|
184
|
+
const owner = binding?.owner;
|
|
185
|
+
if (!owner || binding.kind !== "param" || binding.name !== "$setup") return false;
|
|
186
|
+
if (!isOutsideFunctions(owner, analysis.parentOf)) return false;
|
|
187
|
+
const params = nodesAt(owner, "params");
|
|
188
|
+
return SETUP_PARAMETER_POSITIONS.some((position) => {
|
|
189
|
+
const parameter = params[position];
|
|
190
|
+
return parameter?.type === "Identifier" && stringAt(parameter, "name") === binding.name;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function isSetupMethod(setup, parentOf) {
|
|
194
|
+
const property = setup && parentOf.get(setup);
|
|
195
|
+
if (setup?.type !== "FunctionExpression" || property?.type !== "Property") return false;
|
|
196
|
+
return propertyNameOf(nodeAt(property, "key"), property.computed === true) === "setup";
|
|
197
|
+
}
|
|
198
|
+
function isSetupReturn(declarator, parentOf) {
|
|
199
|
+
if (declarator?.type !== "VariableDeclarator") return false;
|
|
200
|
+
if (stringAt(nodeAt(declarator, "id") ?? declarator, "name") !== "__returned__") return false;
|
|
201
|
+
const declaration = parentOf.get(declarator);
|
|
202
|
+
const block = declaration && parentOf.get(declaration);
|
|
203
|
+
return block?.type === "BlockStatement" && isSetupMethod(parentOf.get(block), parentOf);
|
|
204
|
+
}
|
|
205
|
+
function mergedExposures(linked, own) {
|
|
206
|
+
if (own.size === 0) return linked;
|
|
207
|
+
return new Map([...own, ...linked ?? []]);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/vite-cx-args.ts
|
|
211
|
+
function literalValue(node) {
|
|
212
|
+
const value = node.value;
|
|
213
|
+
if (value === null && node.raw === "null") return [];
|
|
214
|
+
return value === false ? [] : void 0;
|
|
215
|
+
}
|
|
216
|
+
function unaryValue(node) {
|
|
217
|
+
const argument = nodeAt(node, "argument");
|
|
218
|
+
const isNumber = (value) => argument?.type === "Literal" && argument.value === value;
|
|
219
|
+
const isFalse = node.operator === "!" && isNumber(1);
|
|
220
|
+
const isUndefined = node.operator === "void" && isNumber(0);
|
|
221
|
+
return isFalse || isUndefined ? [] : void 0;
|
|
222
|
+
}
|
|
223
|
+
function soleInitialiserBinding(binding) {
|
|
224
|
+
const isPlain = binding && ["const", "let", "var"].includes(binding.kind);
|
|
225
|
+
return isPlain && binding.init && binding.writes === 0 ? binding : void 0;
|
|
226
|
+
}
|
|
227
|
+
function operandOf(node) {
|
|
228
|
+
if (node?.type !== "Literal") return void 0;
|
|
229
|
+
const { value } = node;
|
|
230
|
+
return { isFalsy: !value, isNullish: value === null };
|
|
231
|
+
}
|
|
232
|
+
function setupValue(node, context) {
|
|
233
|
+
const object = nodeAt(node, "object");
|
|
234
|
+
if (!object || !isSetupParameter(context.analysis, object)) return void 0;
|
|
235
|
+
const name = setupMemberName(node);
|
|
236
|
+
const exposure = name === void 0 ? void 0 : context.setup?.get(name);
|
|
237
|
+
if (exposure?.kind !== "values") return void 0;
|
|
238
|
+
return exposure.values.filter((value) => value !== "").map((value) => ({ value, node }));
|
|
239
|
+
}
|
|
240
|
+
var RESOLVED = /* @__PURE__ */ new WeakMap();
|
|
241
|
+
function resolvedFor(analysis, setup) {
|
|
242
|
+
if (setup) return /* @__PURE__ */ new Map();
|
|
243
|
+
const found = RESOLVED.get(analysis) ?? /* @__PURE__ */ new Map();
|
|
244
|
+
RESOLVED.set(analysis, found);
|
|
245
|
+
return found;
|
|
246
|
+
}
|
|
247
|
+
function unionOf(parts) {
|
|
248
|
+
if (parts.includes(void 0)) return void 0;
|
|
249
|
+
const seen = /* @__PURE__ */ new Map();
|
|
250
|
+
const isNew = (possible) => {
|
|
251
|
+
const values = seen.get(possible.node) ?? /* @__PURE__ */ new Set();
|
|
252
|
+
seen.set(possible.node, values);
|
|
253
|
+
const before = values.size;
|
|
254
|
+
values.add(possible.value);
|
|
255
|
+
return values.size > before;
|
|
256
|
+
};
|
|
257
|
+
return parts.flatMap((part) => part.filter((possible) => isNew(possible)));
|
|
258
|
+
}
|
|
259
|
+
var first = (done) => done[0];
|
|
260
|
+
var leaf = (result) => ({ deps: [], combine: () => result });
|
|
261
|
+
function planOfName(node, context) {
|
|
262
|
+
const reference2 = context.analysis.referenceOf(node);
|
|
263
|
+
if (!reference2?.binding) return leaf(stringAt(node, "name") === "undefined" ? [] : void 0);
|
|
264
|
+
const binding = soleInitialiserBinding(reference2.binding);
|
|
265
|
+
if (!binding) return leaf(void 0);
|
|
266
|
+
if (context.resolved.has(binding)) return leaf(context.resolved.get(binding));
|
|
267
|
+
if (context.resolving.has(binding)) return leaf(void 0);
|
|
268
|
+
context.resolving.add(binding);
|
|
269
|
+
return {
|
|
270
|
+
deps: [binding.init],
|
|
271
|
+
combine: first,
|
|
272
|
+
finish(result) {
|
|
273
|
+
context.resolving.delete(binding);
|
|
274
|
+
context.resolved.set(binding, result);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function operandsRead(node) {
|
|
279
|
+
const left = nodeAt(node, "left");
|
|
280
|
+
const right = nodeAt(node, "right");
|
|
281
|
+
const operand = operandOf(left);
|
|
282
|
+
if (node.operator === "&&") return operand?.isFalsy ? [] : [right];
|
|
283
|
+
const isDecided = node.operator === "||" ? operand?.isFalsy : operand?.isNullish;
|
|
284
|
+
return isDecided === false ? [left] : [left, right];
|
|
285
|
+
}
|
|
286
|
+
function planOfLogical(node) {
|
|
287
|
+
const read = operandsRead(node);
|
|
288
|
+
if (read.length === 0) return leaf([]);
|
|
289
|
+
return { deps: read, combine: read.length === 1 ? first : unionOf };
|
|
290
|
+
}
|
|
291
|
+
function planOf(node, context) {
|
|
292
|
+
const text = staticStringOf(node);
|
|
293
|
+
if (text !== void 0) return leaf(text === "" ? [] : [{ value: text, node }]);
|
|
294
|
+
const inner = wrappedBy(node);
|
|
295
|
+
if (inner) return { deps: [inner], combine: first };
|
|
296
|
+
switch (node.type) {
|
|
297
|
+
case "ConditionalExpression": {
|
|
298
|
+
return {
|
|
299
|
+
deps: [nodeAt(node, "consequent"), nodeAt(node, "alternate")],
|
|
300
|
+
combine: unionOf
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
case "Identifier": {
|
|
304
|
+
return planOfName(node, context);
|
|
305
|
+
}
|
|
306
|
+
case "Literal": {
|
|
307
|
+
return leaf(literalValue(node));
|
|
308
|
+
}
|
|
309
|
+
case "LogicalExpression": {
|
|
310
|
+
return planOfLogical(node);
|
|
311
|
+
}
|
|
312
|
+
case "MemberExpression": {
|
|
313
|
+
return leaf(setupValue(node, context));
|
|
314
|
+
}
|
|
315
|
+
case "UnaryExpression": {
|
|
316
|
+
return leaf(unaryValue(node));
|
|
317
|
+
}
|
|
318
|
+
default: {
|
|
319
|
+
return leaf(void 0);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function possibles(root, context) {
|
|
324
|
+
if (!root) return void 0;
|
|
325
|
+
const stack = [{ plan: planOf(root, context), done: [] }];
|
|
326
|
+
let result;
|
|
327
|
+
while (stack.length > 0) {
|
|
328
|
+
const top = stack.at(-1);
|
|
329
|
+
const next = top.plan.deps[top.done.length];
|
|
330
|
+
if (top.done.length < top.plan.deps.length) {
|
|
331
|
+
if (next) stack.push({ plan: planOf(next, context), done: [] });
|
|
332
|
+
else top.done.push(void 0);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
result = top.plan.combine(top.done);
|
|
336
|
+
top.plan.finish?.(result);
|
|
337
|
+
stack.pop();
|
|
338
|
+
stack.at(-1)?.done.push(result);
|
|
339
|
+
}
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
function isFilteredOut(node, analysis) {
|
|
343
|
+
switch (node.type) {
|
|
344
|
+
case "Identifier": {
|
|
345
|
+
return stringAt(node, "name") === "undefined" && !analysis.referenceOf(node)?.binding;
|
|
346
|
+
}
|
|
347
|
+
case "Literal": {
|
|
348
|
+
return literalValue(node) !== void 0;
|
|
349
|
+
}
|
|
350
|
+
case "UnaryExpression": {
|
|
351
|
+
return unaryValue(node) !== void 0;
|
|
352
|
+
}
|
|
353
|
+
default: {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function constantOf(node, analysis) {
|
|
359
|
+
const text = staticStringOf(node);
|
|
360
|
+
if (text !== void 0) return text;
|
|
361
|
+
return isFilteredOut(node, analysis) ? "" : void 0;
|
|
362
|
+
}
|
|
363
|
+
function resolveArgument(node, analysis, setup) {
|
|
364
|
+
const resolved = resolvedFor(analysis, setup);
|
|
365
|
+
return possibles(node, { analysis, resolving: /* @__PURE__ */ new Set(), resolved, setup });
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/vite-cx-bindings.ts
|
|
369
|
+
function cxBindingsOf(analysis, sources) {
|
|
370
|
+
const found = /* @__PURE__ */ new Map();
|
|
371
|
+
for (const { binding } of analysis.references) {
|
|
372
|
+
if (binding?.kind !== "import" || !binding.source || !sources.has(binding.source)) continue;
|
|
373
|
+
if (binding.imported === "cx") found.set(binding, { binding, isNamespace: false });
|
|
374
|
+
else if (binding.imported === "*") found.set(binding, { binding, isNamespace: true });
|
|
375
|
+
}
|
|
376
|
+
return found;
|
|
377
|
+
}
|
|
378
|
+
function isImportingCx(program, sources) {
|
|
379
|
+
return nodesAt(program, "body").some((node) => {
|
|
380
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
381
|
+
const isImport = node.type === "ImportDeclaration" && !isTypeOnly(node);
|
|
382
|
+
return isImport && source !== void 0 && sources.has(source);
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/vite-cx-refuse.ts
|
|
387
|
+
function textOf(reading, node) {
|
|
388
|
+
return reading.code.slice(node.start, node.end);
|
|
389
|
+
}
|
|
390
|
+
function calleeName(reading, call) {
|
|
391
|
+
const callee = nodeAt(call, "callee");
|
|
392
|
+
if (!callee) return "a function";
|
|
393
|
+
if (callee.type === "Identifier") return stringAt(callee, "name") ?? "a function";
|
|
394
|
+
const isPlainMember = callee.type === "MemberExpression" && callee.computed !== true;
|
|
395
|
+
const property = isPlainMember ? nodeAt(callee, "property") : void 0;
|
|
396
|
+
return stringAt(property ?? callee, "name") ?? textOf(reading, callee);
|
|
397
|
+
}
|
|
398
|
+
var assignedTo = (reading, parent, local) => {
|
|
399
|
+
const target = nodeAt(parent, "id") ?? nodeAt(parent, "left") ?? parent;
|
|
400
|
+
return `${local} is assigned to ${textOf(reading, target)}`;
|
|
401
|
+
};
|
|
402
|
+
var reexported = (reading, parent, local) => `${textOf(reading, parent)}: a re-export of ${local}, which the build follows only from a module listed in cxModules`;
|
|
403
|
+
var PHRASES = {
|
|
404
|
+
VariableDeclarator: assignedTo,
|
|
405
|
+
AssignmentExpression: assignedTo,
|
|
406
|
+
CallExpression: (reading, parent, local) => `${local} is passed to ${calleeName(reading, parent)}() as a value instead of being called`,
|
|
407
|
+
SpreadElement: (_reading, _parent, local) => `${local} is spread`,
|
|
408
|
+
ExportSpecifier: reexported,
|
|
409
|
+
ExportDefaultDeclaration: reexported
|
|
410
|
+
};
|
|
411
|
+
function isWrittenTo(parent, expression) {
|
|
412
|
+
return parent.type === "AssignmentExpression" && nodeAt(parent, "right") !== expression;
|
|
413
|
+
}
|
|
414
|
+
function phraseFor(reading, expression, local) {
|
|
415
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
416
|
+
const phrase = parent && !isWrittenTo(parent, expression) && PHRASES[parent.type];
|
|
417
|
+
return phrase && parent ? phrase(reading, parent, local) : `${local} is used as a value instead of being called`;
|
|
418
|
+
}
|
|
419
|
+
function isReexportOf(reading, expression) {
|
|
420
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
421
|
+
return parent?.type === "ExportSpecifier" || parent?.type === "ExportDefaultDeclaration";
|
|
422
|
+
}
|
|
423
|
+
function reexportNameOf(reading, expression) {
|
|
424
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
425
|
+
if (parent?.type === "ExportDefaultDeclaration") return "default";
|
|
426
|
+
return parent?.type === "ExportSpecifier" ? exportNameOf(nodeAt(parent, "exported")) : void 0;
|
|
427
|
+
}
|
|
428
|
+
function isRenamedReexportOf(reading, expression) {
|
|
429
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
430
|
+
if (parent?.type === "ExportDefaultDeclaration") return true;
|
|
431
|
+
return parent?.type === "ExportSpecifier" && exportNameOf(nodeAt(parent, "exported")) !== "cx";
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// src/vite-cx-reference.ts
|
|
435
|
+
function isCallee(parent, node) {
|
|
436
|
+
return parent?.type === "CallExpression" && nodeAt(parent, "callee") === node;
|
|
437
|
+
}
|
|
438
|
+
function isOnlyRaw(pattern) {
|
|
439
|
+
const properties = nodesAt(pattern, "properties");
|
|
440
|
+
const only = properties[0];
|
|
441
|
+
if (properties.length !== 1 || only?.type !== "Property") return false;
|
|
442
|
+
const name = propertyNameOf(nodeAt(only, "key"), only.computed === true);
|
|
443
|
+
return name === "raw" && nodeAt(only, "value")?.type === "Identifier";
|
|
444
|
+
}
|
|
445
|
+
function refused(node, local, phrase) {
|
|
446
|
+
return { kind: "refused", node, local, phrase };
|
|
447
|
+
}
|
|
448
|
+
function rawMemberUse(parent, member, local) {
|
|
449
|
+
const isAlias = parent?.type === "VariableDeclarator" && nodeAt(parent, "init") === member && nodeAt(parent, "id")?.type === "Identifier";
|
|
450
|
+
if (isAlias || isCallee(parent, member)) return { kind: "raw", node: member, local };
|
|
451
|
+
return refused(member, local, `${local}.raw is used other than by calling it`);
|
|
452
|
+
}
|
|
453
|
+
function memberUse(reading, member, local) {
|
|
454
|
+
const parent = reading.analysis.parentOf.get(member);
|
|
455
|
+
const isComputed = member.computed === true;
|
|
456
|
+
const name = propertyNameOf(nodeAt(member, "property"), isComputed);
|
|
457
|
+
if (name === "raw") return rawMemberUse(parent, member, local);
|
|
458
|
+
if (name === "dynamic" && !isComputed) {
|
|
459
|
+
if (parent && isCallee(parent, member)) return { kind: "dynamic", node: parent, local };
|
|
460
|
+
return refused(member, local, `${local}.dynamic is referenced other than by a direct call`);
|
|
461
|
+
}
|
|
462
|
+
if (name === "call" || name === "apply") {
|
|
463
|
+
return refused(member, local, `${local} is called through .${name}()`);
|
|
464
|
+
}
|
|
465
|
+
if (isComputed) return refused(member, local, `${local} is read with a computed member`);
|
|
466
|
+
return refused(member, local, `${local}.${name ?? "?"} is not a member the build reads`);
|
|
467
|
+
}
|
|
468
|
+
function isVueUnref(reading, callee) {
|
|
469
|
+
if (callee?.type !== "Identifier") return false;
|
|
470
|
+
const binding = reading.analysis.referenceOf(callee)?.binding;
|
|
471
|
+
return binding?.kind === "import" && binding.source === "vue" && binding.imported === "unref";
|
|
472
|
+
}
|
|
473
|
+
function throughUnref(reading, expression) {
|
|
474
|
+
let current = expression;
|
|
475
|
+
for (; ; ) {
|
|
476
|
+
const call = reading.analysis.parentOf.get(current);
|
|
477
|
+
const args = call ? nodesAt(call, "arguments") : [];
|
|
478
|
+
const isUnref = call?.type === "CallExpression" && args.length === 1 && args[0] === current && isVueUnref(reading, nodeAt(call, "callee"));
|
|
479
|
+
if (!isUnref) return current;
|
|
480
|
+
current = call;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function ancestor(reading, node, levels) {
|
|
484
|
+
let current = node;
|
|
485
|
+
for (let level = 0; current && level < levels; level += 1) {
|
|
486
|
+
current = reading.analysis.parentOf.get(current);
|
|
487
|
+
}
|
|
488
|
+
return current;
|
|
489
|
+
}
|
|
490
|
+
function exposureName(reading, expression) {
|
|
491
|
+
if (reading.allowsExposure !== true) return void 0;
|
|
492
|
+
const getter = ancestor(reading, expression, 4);
|
|
493
|
+
const isGetter = getter?.type === "Property" && getter.kind === "get";
|
|
494
|
+
const isReturn = ancestor(reading, expression, 1)?.type === "ReturnStatement";
|
|
495
|
+
if (!isGetter || !isReturn || !isSetupReturn(ancestor(reading, expression, 6), reading.analysis.parentOf))
|
|
496
|
+
return void 0;
|
|
497
|
+
return propertyNameOf(nodeAt(getter, "key"), getter.computed === true);
|
|
498
|
+
}
|
|
499
|
+
function rawDestructuring(parent, expression, local) {
|
|
500
|
+
if (parent.type !== "VariableDeclarator" || nodeAt(parent, "init") !== expression)
|
|
501
|
+
return void 0;
|
|
502
|
+
const id = nodeAt(parent, "id");
|
|
503
|
+
if (id?.type !== "ObjectPattern" || !isOnlyRaw(id)) return void 0;
|
|
504
|
+
return { kind: "raw", node: id, local };
|
|
505
|
+
}
|
|
506
|
+
function readableUse(reading, expression, local) {
|
|
507
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
508
|
+
if (!parent) return void 0;
|
|
509
|
+
if (isCallee(parent, expression)) return { kind: "call", node: parent, local };
|
|
510
|
+
if (parent.type === "MemberExpression" && nodeAt(parent, "object") === expression) {
|
|
511
|
+
return memberUse(reading, parent, local);
|
|
512
|
+
}
|
|
513
|
+
return rawDestructuring(parent, expression, local);
|
|
514
|
+
}
|
|
515
|
+
function useOfExpression(reading, start, local) {
|
|
516
|
+
const expression = throughUnref(reading, start);
|
|
517
|
+
const readable = readableUse(reading, expression, local);
|
|
518
|
+
if (readable) return readable;
|
|
519
|
+
const exposedAs = exposureName(reading, expression);
|
|
520
|
+
if (exposedAs !== void 0) return { kind: "exposure", node: expression, local, exposedAs };
|
|
521
|
+
const phrase = phraseFor(reading, expression, local);
|
|
522
|
+
const isReexport = isReexportOf(reading, expression);
|
|
523
|
+
const isRenamed = isReexport && isRenamedReexportOf(reading, expression);
|
|
524
|
+
const exportedAs = reexportedAs(reading, expression);
|
|
525
|
+
return {
|
|
526
|
+
...refused(expression, local, phrase),
|
|
527
|
+
isReexport,
|
|
528
|
+
...isRenamed && { isRenamed },
|
|
529
|
+
...exportedAs
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function reexportedAs(reading, expression) {
|
|
533
|
+
const name = reexportNameOf(reading, expression);
|
|
534
|
+
return name === void 0 ? void 0 : { exportedAs: [name] };
|
|
535
|
+
}
|
|
536
|
+
function isOtherKey(property) {
|
|
537
|
+
if (property.type !== "Property") return false;
|
|
538
|
+
const name = propertyNameOf(nodeAt(property, "key"), property.computed === true);
|
|
539
|
+
return name !== void 0 && name !== "cx";
|
|
540
|
+
}
|
|
541
|
+
function isPatternAssignment(reading, node) {
|
|
542
|
+
if (node?.type === "AssignmentPattern") return true;
|
|
543
|
+
return node?.type === "AssignmentExpression" && node.operator === "=" && reading.analysis.parentOf.get(node)?.type === "ExpressionStatement";
|
|
544
|
+
}
|
|
545
|
+
function patternDestructuring(reading, expression) {
|
|
546
|
+
const parent = reading.analysis.parentOf.get(expression);
|
|
547
|
+
if (parent?.type === "VariableDeclarator" && nodeAt(parent, "init") === expression) {
|
|
548
|
+
return nodeAt(parent, "id");
|
|
549
|
+
}
|
|
550
|
+
return isPatternAssignment(reading, parent) && nodeAt(parent, "right") === expression ? nodeAt(parent, "left") : void 0;
|
|
551
|
+
}
|
|
552
|
+
function isOtherKeysDestructuring(reading, expression) {
|
|
553
|
+
const pattern = patternDestructuring(reading, expression);
|
|
554
|
+
return pattern?.type === "ObjectPattern" && nodesAt(pattern, "properties").every((p) => isOtherKey(p));
|
|
555
|
+
}
|
|
556
|
+
function memberReadOf(reading, expression) {
|
|
557
|
+
const member = reading.analysis.parentOf.get(expression);
|
|
558
|
+
if (member?.type !== "MemberExpression" || nodeAt(member, "object") !== expression) {
|
|
559
|
+
return void 0;
|
|
560
|
+
}
|
|
561
|
+
return { member, key: propertyNameOf(nodeAt(member, "property"), member.computed === true) };
|
|
562
|
+
}
|
|
563
|
+
function namespaceUse(reading, expression, cx) {
|
|
564
|
+
const local = cx.binding.name;
|
|
565
|
+
const read = memberReadOf(reading, expression);
|
|
566
|
+
if (read?.key === "cx") return useOfExpression(reading, read.member, `${local}.cx`);
|
|
567
|
+
const isListed = reading.declaredSources?.has(cx.binding.source ?? "") === true;
|
|
568
|
+
const isOtherExport = read ? read.key !== void 0 : isOtherKeysDestructuring(reading, expression);
|
|
569
|
+
if (isListed && isOtherExport) return void 0;
|
|
570
|
+
const use = refused(expression, local, `${local} is used other than as ${local}.cx`);
|
|
571
|
+
const exportedAs = reexportedAs(reading, expression);
|
|
572
|
+
return exportedAs ? { ...use, ...exportedAs, isRenamed: true } : use;
|
|
573
|
+
}
|
|
574
|
+
function useOf(reading, reference2, cx) {
|
|
575
|
+
if (cx.isNamespace) return namespaceUse(reading, reference2.node, cx);
|
|
576
|
+
const local = cx.binding.name;
|
|
577
|
+
const use = useOfExpression(reading, reference2.node, local);
|
|
578
|
+
if (!use.isReexport) return use;
|
|
579
|
+
const isDeclaredSource = reading.declaredSources?.has(cx.binding.source ?? "") === true;
|
|
580
|
+
return { ...use, isListable: !isDeclaredSource };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/vite-cx-source-forms.ts
|
|
584
|
+
var REEXPORT_TEXT = "a re-export of cx, which the build follows only from a module listed in cxModules.";
|
|
585
|
+
var SECOND_HOP_TEXT = "a re-export of the cx of a module listed in cxModules, which the build follows one step only.";
|
|
586
|
+
var DYNAMIC_IMPORT_TEXT = "a dynamic import of cx, which the build cannot follow. Import it at the top of the module.";
|
|
587
|
+
function isExportingCx(node) {
|
|
588
|
+
if (node.type === "ExportAllDeclaration") return true;
|
|
589
|
+
return valueSpecifiersOf(node).some((specifier) => {
|
|
590
|
+
const local = nodeAt(specifier, "local");
|
|
591
|
+
return (local?.type === "Identifier" ? stringAt(local, "name") : staticStringOf(local)) === "cx";
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
function isExportingRenamed(node) {
|
|
595
|
+
if (node.type === "ExportAllDeclaration") return nodeAt(node, "exported") !== void 0;
|
|
596
|
+
return valueSpecifiersOf(node).some(
|
|
597
|
+
(specifier) => exportNameOf(nodeAt(specifier, "local")) === "cx" && exportNameOf(nodeAt(specifier, "exported")) !== "cx"
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
function exportedNamesOf(node) {
|
|
601
|
+
if (node.type === "ExportAllDeclaration") {
|
|
602
|
+
return [exportNameOf(nodeAt(node, "exported")) ?? "cx"];
|
|
603
|
+
}
|
|
604
|
+
return valueSpecifiersOf(node).filter((specifier) => exportNameOf(nodeAt(specifier, "local")) === "cx").flatMap((specifier) => exportNameOf(nodeAt(specifier, "exported")) ?? []);
|
|
605
|
+
}
|
|
606
|
+
function reexportProblem(code, node, isListed) {
|
|
607
|
+
if (isListed && !isExportingCx(node)) return void 0;
|
|
608
|
+
return {
|
|
609
|
+
kind: "reexport",
|
|
610
|
+
offset: node.start,
|
|
611
|
+
construct: code.slice(node.start, node.end),
|
|
612
|
+
text: isListed ? SECOND_HOP_TEXT : REEXPORT_TEXT,
|
|
613
|
+
isListable: !isListed,
|
|
614
|
+
...!isListed && isExportingRenamed(node) && { isRenamed: true },
|
|
615
|
+
exportedAs: exportedNamesOf(node)
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
function sourceFormProblem(code, node, options) {
|
|
619
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
620
|
+
if (source === void 0 || !options.cxSources.has(source)) return void 0;
|
|
621
|
+
if (node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") {
|
|
622
|
+
if (isTypeOnly(node) || options.isDeclared === true) return void 0;
|
|
623
|
+
return reexportProblem(code, node, options.declaredSources?.has(source) === true);
|
|
624
|
+
}
|
|
625
|
+
if (node.type !== "ImportExpression") return void 0;
|
|
626
|
+
const construct = code.slice(node.start, node.end);
|
|
627
|
+
return { kind: "reference", offset: node.start, construct, text: DYNAMIC_IMPORT_TEXT };
|
|
628
|
+
}
|
|
629
|
+
function sourceFormProblems(code, program, options) {
|
|
630
|
+
const problems = [];
|
|
631
|
+
const stack = [program];
|
|
632
|
+
while (stack.length > 0) {
|
|
633
|
+
const node = stack.pop();
|
|
634
|
+
const problem2 = sourceFormProblem(code, node, options);
|
|
635
|
+
if (problem2) problems.push(problem2);
|
|
636
|
+
pushAll(stack, childrenOf(node));
|
|
637
|
+
}
|
|
638
|
+
return problems;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// src/vite-declared-exports.ts
|
|
642
|
+
var DECLARED_TEXT = "listed in cxModules, but this export can give it a cx the build does not follow: the build follows a listed module one step, to Nave's cx re-exported from @navecss/core/cx under the name cx.";
|
|
643
|
+
function innerPatterns(pattern) {
|
|
644
|
+
switch (pattern.type) {
|
|
645
|
+
case "ArrayPattern": {
|
|
646
|
+
return nodesAt(pattern, "elements");
|
|
647
|
+
}
|
|
648
|
+
case "AssignmentPattern": {
|
|
649
|
+
return [nodeAt(pattern, "left")].filter((inner) => inner !== void 0);
|
|
650
|
+
}
|
|
651
|
+
case "ObjectPattern": {
|
|
652
|
+
return nodesAt(pattern, "properties").flatMap(
|
|
653
|
+
(property) => [nodeAt(property, property.type === "Property" ? "value" : "argument")].filter(
|
|
654
|
+
(inner) => inner !== void 0
|
|
655
|
+
)
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
case "RestElement": {
|
|
659
|
+
return [nodeAt(pattern, "argument")].filter((inner) => inner !== void 0);
|
|
660
|
+
}
|
|
661
|
+
default: {
|
|
662
|
+
return [];
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
function patternNames(pattern) {
|
|
667
|
+
const names = [];
|
|
668
|
+
const stack = pattern ? [pattern] : [];
|
|
669
|
+
while (stack.length > 0) {
|
|
670
|
+
const next = stack.pop();
|
|
671
|
+
if (next.type === "Identifier") names.push(stringAt(next, "name") ?? "");
|
|
672
|
+
pushAll(stack, innerPatterns(next));
|
|
673
|
+
}
|
|
674
|
+
return names;
|
|
675
|
+
}
|
|
676
|
+
function declaredNames(declaration) {
|
|
677
|
+
if (declaration.type !== "VariableDeclaration") {
|
|
678
|
+
return patternNames(nodeAt(declaration, "id"));
|
|
679
|
+
}
|
|
680
|
+
return nodesAt(declaration, "declarations").flatMap(
|
|
681
|
+
(declarator) => patternNames(nodeAt(declarator, "id"))
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
function problem(node) {
|
|
685
|
+
return { kind: "declared", offset: node.start, construct: "", text: DECLARED_TEXT };
|
|
686
|
+
}
|
|
687
|
+
function isPlainReExport(local, exported) {
|
|
688
|
+
return local === "cx" && exported === "cx";
|
|
689
|
+
}
|
|
690
|
+
function fromSourceProblems(node, source, input) {
|
|
691
|
+
const isNave = input.cxSources.has(source) && !input.declaredSources.has(source);
|
|
692
|
+
const isListed = input.declaredSources.has(source);
|
|
693
|
+
const isBad = valueSpecifiersOf(node).some((specifier) => {
|
|
694
|
+
const local = exportNameOf(nodeAt(specifier, "local"));
|
|
695
|
+
const exported = exportNameOf(nodeAt(specifier, "exported"));
|
|
696
|
+
if (isNave) return !isPlainReExport(local, exported);
|
|
697
|
+
return exported === "cx" || isListed && local === "cx";
|
|
698
|
+
});
|
|
699
|
+
return isBad ? [problem(node)] : [];
|
|
700
|
+
}
|
|
701
|
+
function localProblems(node, input) {
|
|
702
|
+
const isBad = valueSpecifiersOf(node).some((specifier) => {
|
|
703
|
+
const local = nodeAt(specifier, "local");
|
|
704
|
+
const binding = local && input.analysis.referenceOf(local)?.binding;
|
|
705
|
+
const cx = binding ? input.bindings.get(binding) : void 0;
|
|
706
|
+
if (exportNameOf(nodeAt(specifier, "exported")) !== "cx") return cx !== void 0;
|
|
707
|
+
const isNaves = cx !== void 0 && !cx.isNamespace && !input.declaredSources.has(binding?.source ?? "");
|
|
708
|
+
return !isNaves;
|
|
709
|
+
});
|
|
710
|
+
return isBad ? [problem(node)] : [];
|
|
711
|
+
}
|
|
712
|
+
function namedExportProblems(node, input) {
|
|
713
|
+
const declaration = nodeAt(node, "declaration");
|
|
714
|
+
if (declaration) return declaredNames(declaration).includes("cx") ? [problem(node)] : [];
|
|
715
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
716
|
+
return source === void 0 ? localProblems(node, input) : fromSourceProblems(node, source, input);
|
|
717
|
+
}
|
|
718
|
+
function starExportProblems(node, input, hasNaveCx) {
|
|
719
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
720
|
+
if (source === void 0) return [];
|
|
721
|
+
const exported = nodeAt(node, "exported");
|
|
722
|
+
if (!input.cxSources.has(source)) {
|
|
723
|
+
return exportNameOf(exported) === "cx" ? [problem(node)] : [];
|
|
724
|
+
}
|
|
725
|
+
if (exported !== void 0) return [problem(node)];
|
|
726
|
+
return !hasNaveCx && input.declaredSources.has(source) ? [problem(node)] : [];
|
|
727
|
+
}
|
|
728
|
+
function isNaveSource(source, input) {
|
|
729
|
+
return source !== void 0 && input.cxSources.has(source) && !input.declaredSources.has(source);
|
|
730
|
+
}
|
|
731
|
+
function isNaveLocalExport(local, exported, input) {
|
|
732
|
+
const binding = local && input.analysis.referenceOf(local)?.binding;
|
|
733
|
+
const cx = binding ? input.bindings.get(binding) : void 0;
|
|
734
|
+
const isListed = input.declaredSources.has(binding?.source ?? "");
|
|
735
|
+
return exported === "cx" && cx !== void 0 && !cx.isNamespace && !isListed;
|
|
736
|
+
}
|
|
737
|
+
function isNaveSpecifier(specifier, source, input) {
|
|
738
|
+
const local = nodeAt(specifier, "local");
|
|
739
|
+
const exported = exportNameOf(nodeAt(specifier, "exported"));
|
|
740
|
+
if (source === void 0) return isNaveLocalExport(local, exported, input);
|
|
741
|
+
return isNaveSource(source, input) && isPlainReExport(exportNameOf(local), exported);
|
|
742
|
+
}
|
|
743
|
+
function isNaveCxExport(node, input) {
|
|
744
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
745
|
+
if (node.type === "ExportAllDeclaration") {
|
|
746
|
+
return isNaveSource(source, input) && nodeAt(node, "exported") === void 0;
|
|
747
|
+
}
|
|
748
|
+
if (node.type !== "ExportNamedDeclaration" || nodeAt(node, "declaration")) return false;
|
|
749
|
+
return valueSpecifiersOf(node).some((specifier) => isNaveSpecifier(specifier, source, input));
|
|
750
|
+
}
|
|
751
|
+
function unfollowedStarProblems(body, input) {
|
|
752
|
+
if (body.some((node) => isNaveCxExport(node, input))) return [];
|
|
753
|
+
const star = body.find((node) => {
|
|
754
|
+
const source = staticStringOf(nodeAt(node, "source"));
|
|
755
|
+
const isPlainStar = node.type === "ExportAllDeclaration" && nodeAt(node, "exported") === void 0;
|
|
756
|
+
return isPlainStar && source !== void 0 && !input.cxSources.has(source);
|
|
757
|
+
});
|
|
758
|
+
return star ? [problem(star)] : [];
|
|
759
|
+
}
|
|
760
|
+
function defaultExportProblems(node, input) {
|
|
761
|
+
const declaration = nodeAt(node, "declaration");
|
|
762
|
+
const binding = declaration && input.analysis.referenceOf(declaration)?.binding;
|
|
763
|
+
return binding && input.bindings.has(binding) ? [problem(node)] : [];
|
|
764
|
+
}
|
|
765
|
+
var EXPORT_PROBLEMS = {
|
|
766
|
+
ExportDefaultDeclaration: defaultExportProblems,
|
|
767
|
+
ExportNamedDeclaration: namedExportProblems
|
|
768
|
+
};
|
|
769
|
+
function declaredExportProblems(input) {
|
|
770
|
+
const body = nodesAt(input.program, "body").filter((node) => !isTypeOnly(node));
|
|
771
|
+
const hasNaveCx = body.some((node) => isNaveCxExport(node, input));
|
|
772
|
+
const problems = [
|
|
773
|
+
...body.flatMap(
|
|
774
|
+
(node) => node.type === "ExportAllDeclaration" ? starExportProblems(node, input, hasNaveCx) : EXPORT_PROBLEMS[node.type]?.(node, input) ?? []
|
|
775
|
+
),
|
|
776
|
+
...unfollowedStarProblems(body, input)
|
|
777
|
+
];
|
|
778
|
+
return hasNaveCx ? problems.map((found) => ({ ...found, hasNaveCx })) : problems;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/vite-class-pieces.ts
|
|
782
|
+
function isIdentChar(char) {
|
|
783
|
+
if (char === void 0) return false;
|
|
784
|
+
return /[\w-]/.test(char) || char.codePointAt(0) >= 128;
|
|
785
|
+
}
|
|
786
|
+
function pieceOfText(node, text) {
|
|
787
|
+
let start = text.length;
|
|
788
|
+
while (start > 0 && isIdentChar(text[start - 1])) start -= 1;
|
|
789
|
+
return { node, head: text.slice(start, start + 5), isOpen: start === 0 };
|
|
790
|
+
}
|
|
791
|
+
function leafPiece(node) {
|
|
792
|
+
const asserted = assertedBy(node);
|
|
793
|
+
if (asserted) {
|
|
794
|
+
const piece = leafPiece(asserted);
|
|
795
|
+
return piece && { ...piece, node };
|
|
796
|
+
}
|
|
797
|
+
const whole = staticStringOf(node);
|
|
798
|
+
if (whole !== void 0) return pieceOfText(node, whole);
|
|
799
|
+
if (node.type !== "TemplateLiteral") return void 0;
|
|
800
|
+
const cooked = nodesAt(node, "quasis").at(-1)?.value?.cooked;
|
|
801
|
+
return cooked === void 0 ? void 0 : pieceOfText(node, cooked);
|
|
802
|
+
}
|
|
803
|
+
function isPlus(node) {
|
|
804
|
+
return node?.type === "BinaryExpression" && node.operator === "+";
|
|
805
|
+
}
|
|
806
|
+
function edgePiece(start, memo) {
|
|
807
|
+
const path = [];
|
|
808
|
+
let node = start;
|
|
809
|
+
while (isPlus(node) && !memo.edges.has(node)) {
|
|
810
|
+
path.push(node);
|
|
811
|
+
node = nodeAt(node, "right");
|
|
812
|
+
}
|
|
813
|
+
let found;
|
|
814
|
+
if (node !== void 0) found = memo.edges.has(node) ? memo.edges.get(node) : leafPiece(node);
|
|
815
|
+
for (const visited of path) memo.edges.set(visited, found);
|
|
816
|
+
return found;
|
|
817
|
+
}
|
|
818
|
+
function joinPieces(before, last) {
|
|
819
|
+
if (!last.isOpen) return { node: before.node, head: last.head, isOpen: false };
|
|
820
|
+
return {
|
|
821
|
+
node: before.node,
|
|
822
|
+
head: (before.head + last.head).slice(0, 5),
|
|
823
|
+
isOpen: before.isOpen
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
function pieceOfPlus(link, before, last) {
|
|
827
|
+
if (last === void 0) return void 0;
|
|
828
|
+
const isAdjacent = before !== void 0 && nodeAt(link, "right") === last.node;
|
|
829
|
+
return isAdjacent ? joinPieces(before, last) : last;
|
|
830
|
+
}
|
|
831
|
+
function rightmostPiece(start, memo) {
|
|
832
|
+
const spine = [];
|
|
833
|
+
let node = start;
|
|
834
|
+
while (isPlus(node) && !memo.rightmost.has(node)) {
|
|
835
|
+
spine.push(node);
|
|
836
|
+
node = nodeAt(node, "left");
|
|
837
|
+
}
|
|
838
|
+
let before;
|
|
839
|
+
if (node !== void 0) {
|
|
840
|
+
before = memo.rightmost.has(node) ? memo.rightmost.get(node) : edgePiece(node, memo);
|
|
841
|
+
}
|
|
842
|
+
for (const link of spine.toReversed()) {
|
|
843
|
+
before = pieceOfPlus(link, before, edgePiece(link, memo));
|
|
844
|
+
memo.rightmost.set(link, before);
|
|
845
|
+
}
|
|
846
|
+
return before;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// src/vite-string-values.ts
|
|
850
|
+
var none = () => [];
|
|
851
|
+
var leaf2 = (values) => ({ deps: none, combine: () => values });
|
|
852
|
+
function unionOf2(parts) {
|
|
853
|
+
if (parts.includes(void 0)) return void 0;
|
|
854
|
+
return [...new Set(parts.flat())];
|
|
855
|
+
}
|
|
856
|
+
function planOfFallback(node) {
|
|
857
|
+
const left = nodeAt(node, "left");
|
|
858
|
+
const right = nodeAt(node, "right");
|
|
859
|
+
const isOr = node.operator === "||";
|
|
860
|
+
return {
|
|
861
|
+
deps: (done) => {
|
|
862
|
+
if (done.length === 0) return [left];
|
|
863
|
+
const known = done[0];
|
|
864
|
+
return known && isOr && known.includes("") ? [left, right] : [left];
|
|
865
|
+
},
|
|
866
|
+
combine: (done) => {
|
|
867
|
+
const [known, other] = done;
|
|
868
|
+
if (!known || !isOr || !known.includes("")) return known;
|
|
869
|
+
return other && unionOf2([known.filter((value) => value !== ""), other]);
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
function planOfName2(node, analysis) {
|
|
874
|
+
const init = soleInitialiserBinding(analysis.referenceOf(node)?.binding)?.init;
|
|
875
|
+
if (!init) return leaf2(void 0);
|
|
876
|
+
return { deps: () => [init], combine: ([only]) => only };
|
|
877
|
+
}
|
|
878
|
+
function planOf2(node, analysis) {
|
|
879
|
+
const text = staticStringOf(node);
|
|
880
|
+
if (text !== void 0) return leaf2([text]);
|
|
881
|
+
const inner = wrappedBy(node);
|
|
882
|
+
if (inner) return { deps: () => [inner], combine: ([only]) => only };
|
|
883
|
+
switch (node.type) {
|
|
884
|
+
case "ConditionalExpression": {
|
|
885
|
+
const parts = [nodeAt(node, "consequent"), nodeAt(node, "alternate")];
|
|
886
|
+
return { deps: () => parts, combine: unionOf2 };
|
|
887
|
+
}
|
|
888
|
+
case "Identifier": {
|
|
889
|
+
return planOfName2(node, analysis);
|
|
890
|
+
}
|
|
891
|
+
case "LogicalExpression": {
|
|
892
|
+
return node.operator === "&&" ? leaf2(void 0) : planOfFallback(node);
|
|
893
|
+
}
|
|
894
|
+
default: {
|
|
895
|
+
return leaf2(void 0);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function stringValues(root, analysis) {
|
|
900
|
+
if (!root) return void 0;
|
|
901
|
+
const memo = /* @__PURE__ */ new Map();
|
|
902
|
+
const active = /* @__PURE__ */ new Set([root]);
|
|
903
|
+
const stack = [{ node: root, plan: planOf2(root, analysis), done: [] }];
|
|
904
|
+
let result;
|
|
905
|
+
while (stack.length > 0) {
|
|
906
|
+
const top = stack.at(-1);
|
|
907
|
+
const deps = top.plan.deps(top.done);
|
|
908
|
+
if (top.done.length < deps.length) {
|
|
909
|
+
const child = deps[top.done.length];
|
|
910
|
+
if (!child) top.done.push(void 0);
|
|
911
|
+
else if (memo.has(child)) top.done.push(memo.get(child));
|
|
912
|
+
else if (active.has(child)) top.done.push(void 0);
|
|
913
|
+
else {
|
|
914
|
+
active.add(child);
|
|
915
|
+
stack.push({ node: child, plan: planOf2(child, analysis), done: [] });
|
|
916
|
+
}
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
result = top.plan.combine(top.done);
|
|
920
|
+
memo.set(top.node, result);
|
|
921
|
+
active.delete(top.node);
|
|
922
|
+
stack.pop();
|
|
923
|
+
stack.at(-1)?.done.push(result);
|
|
924
|
+
}
|
|
925
|
+
return result;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// src/vite-class-endings.ts
|
|
929
|
+
function isEndingValue(value) {
|
|
930
|
+
return !(isIdentChar(value[0]) || value.startsWith("\\"));
|
|
931
|
+
}
|
|
932
|
+
function operandsOf(element) {
|
|
933
|
+
if (typeof element === "string") return void 0;
|
|
934
|
+
const inner = unwrap(element);
|
|
935
|
+
if (inner.type !== "BinaryExpression" || inner.operator !== "+") return void 0;
|
|
936
|
+
const left = nodeAt(inner, "left");
|
|
937
|
+
const right = nodeAt(inner, "right");
|
|
938
|
+
return left && right ? [left, right] : void 0;
|
|
939
|
+
}
|
|
940
|
+
function* sequenceOf(first2, rest) {
|
|
941
|
+
const pending = first2.toReversed();
|
|
942
|
+
for (; ; ) {
|
|
943
|
+
let element = pending.pop();
|
|
944
|
+
if (element === void 0) return;
|
|
945
|
+
const operands = operandsOf(element);
|
|
946
|
+
if (operands) pending.push(operands[1], operands[0]);
|
|
947
|
+
else yield element;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
function verdictOf(elements, analysis) {
|
|
951
|
+
for (const element of elements) {
|
|
952
|
+
const values = typeof element === "string" ? [element] : stringValues(element, analysis);
|
|
953
|
+
if (!values?.every((value) => value === "" || isEndingValue(value))) return false;
|
|
954
|
+
if (!values.includes("")) return true;
|
|
955
|
+
}
|
|
956
|
+
return void 0;
|
|
957
|
+
}
|
|
958
|
+
function isEndingAfter(start, analysis, memo) {
|
|
959
|
+
const walked = [];
|
|
960
|
+
let link = start;
|
|
961
|
+
let verdict;
|
|
962
|
+
while (verdict === void 0) {
|
|
963
|
+
if (!link) {
|
|
964
|
+
verdict = true;
|
|
965
|
+
} else if (memo.has(link)) {
|
|
966
|
+
verdict = memo.get(link);
|
|
967
|
+
} else {
|
|
968
|
+
walked.push(link);
|
|
969
|
+
verdict = verdictOf(sequenceOf([link.node]), analysis);
|
|
970
|
+
link = link.next;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
for (const walkedLink of walked) memo.set(walkedLink, verdict);
|
|
974
|
+
return verdict;
|
|
975
|
+
}
|
|
976
|
+
function isEndingTheClass(first2, rest, analysis, memo) {
|
|
977
|
+
return verdictOf(sequenceOf(first2), analysis) ?? isEndingAfter(rest, analysis, memo);
|
|
978
|
+
}
|
|
979
|
+
function unwrap(node) {
|
|
980
|
+
let current = node;
|
|
981
|
+
for (let inner = wrappedBy(current); inner; inner = wrappedBy(current)) current = inner;
|
|
982
|
+
return current;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// src/vite-literal-classes.ts
|
|
986
|
+
var ATOM_OF_CLASS = new Map(
|
|
987
|
+
Object.entries(atomClassMap).map(([atom, className]) => [className, atom])
|
|
988
|
+
);
|
|
989
|
+
function atomOfClass(className) {
|
|
990
|
+
return ATOM_OF_CLASS.get(className);
|
|
991
|
+
}
|
|
992
|
+
function isBoundary(code, index) {
|
|
993
|
+
if (index === 0 || !isIdentChar(code[index - 1])) return true;
|
|
994
|
+
return code[index - 2] === "\\" && /[bfnrtv0]/.test(code[index - 1]);
|
|
995
|
+
}
|
|
996
|
+
function identifierAt(code, index) {
|
|
997
|
+
let end = index;
|
|
998
|
+
while (isIdentChar(code[end])) end += 1;
|
|
999
|
+
return code.slice(index, end);
|
|
1000
|
+
}
|
|
1001
|
+
function atomsWrittenIn(code) {
|
|
1002
|
+
const found = /* @__PURE__ */ new Set();
|
|
1003
|
+
let index = code.indexOf("nave-");
|
|
1004
|
+
while (index !== -1) {
|
|
1005
|
+
if (isBoundary(code, index)) {
|
|
1006
|
+
const atom = ATOM_OF_CLASS.get(identifierAt(code, index));
|
|
1007
|
+
if (atom) found.add(atom);
|
|
1008
|
+
}
|
|
1009
|
+
index = code.indexOf("nave-", index + 5);
|
|
1010
|
+
}
|
|
1011
|
+
return found;
|
|
1012
|
+
}
|
|
1013
|
+
function isEndingInNavePrefix(text) {
|
|
1014
|
+
let start = text.length;
|
|
1015
|
+
while (start > 0 && isIdentChar(text[start - 1])) start -= 1;
|
|
1016
|
+
return text.slice(start).startsWith("nave-");
|
|
1017
|
+
}
|
|
1018
|
+
function isBreakingOut(node, analysis, ending) {
|
|
1019
|
+
if (node.type !== "TemplateLiteral") return false;
|
|
1020
|
+
const quasis = nodesAt(node, "quasis");
|
|
1021
|
+
const substitutions = nodesAt(node, "expressions");
|
|
1022
|
+
return quasis.slice(0, -1).some((quasi, index) => {
|
|
1023
|
+
const cooked = quasi.value?.cooked;
|
|
1024
|
+
if (cooked === void 0 || !isEndingInNavePrefix(cooked)) return false;
|
|
1025
|
+
const following = substitutions.slice(index).flatMap((substitution, offset) => {
|
|
1026
|
+
const next = quasis[index + 1 + offset];
|
|
1027
|
+
const text = next?.value?.cooked;
|
|
1028
|
+
return [substitution, ...next ? [text ?? next] : []];
|
|
1029
|
+
});
|
|
1030
|
+
return !isEndingTheClass(following, ending.after, analysis, ending.memo);
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
function concatenatedPiece(node, memo, analysis, ending) {
|
|
1034
|
+
if (!isPlus(node)) return void 0;
|
|
1035
|
+
const piece = rightmostPiece(nodeAt(node, "left"), memo);
|
|
1036
|
+
if (piece?.head !== "nave-") return void 0;
|
|
1037
|
+
const right = nodeAt(node, "right");
|
|
1038
|
+
return isEndingTheClass(right ? [right] : [], ending.after, analysis, ending.memo) ? void 0 : piece;
|
|
1039
|
+
}
|
|
1040
|
+
function escapedText(node) {
|
|
1041
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
1042
|
+
return { raw: String(node.raw), decoded: node.value };
|
|
1043
|
+
}
|
|
1044
|
+
if (node.type !== "TemplateElement") return void 0;
|
|
1045
|
+
const { raw, cooked } = node.value;
|
|
1046
|
+
if (!cooked || !raw?.includes("\\")) return void 0;
|
|
1047
|
+
return { raw, decoded: cooked };
|
|
1048
|
+
}
|
|
1049
|
+
var CHARACTER_REFERENCE = /&#(?:(\d+)|x([\dA-Fa-f]+));/g;
|
|
1050
|
+
function decodeCharacterReferences(text) {
|
|
1051
|
+
return text.replaceAll(CHARACTER_REFERENCE, (reference2, decimal, hex) => {
|
|
1052
|
+
const codePoint = decimal === void 0 ? Number.parseInt(hex, 16) : Number(decimal);
|
|
1053
|
+
const isScalar = codePoint <= 1114111 && (codePoint < 55296 || codePoint > 57343);
|
|
1054
|
+
return isScalar ? String.fromCodePoint(codePoint) : reference2;
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
function jsxAttributeText(node) {
|
|
1058
|
+
if (node.type !== "JSXAttribute") return void 0;
|
|
1059
|
+
const value = nodeAt(node, "value");
|
|
1060
|
+
if (value?.type !== "Literal" || typeof value.value !== "string") return void 0;
|
|
1061
|
+
const written = typeof value.raw === "string" ? value.raw.slice(1, -1) : value.value;
|
|
1062
|
+
return written.includes("&#") ? decodeCharacterReferences(written) : void 0;
|
|
1063
|
+
}
|
|
1064
|
+
var PARENTHESES_KEPT = "readModule reads a syntax tree with no node for a pair of parentheses, as Vite's parser returns it. This tree keeps one (a ParenthesizedExpression): parse with the parentheses dropped, for example oxc-parser with preserveParens: false.";
|
|
1065
|
+
function refuseParenthesesAndFindEscapedAtoms(program) {
|
|
1066
|
+
const found = /* @__PURE__ */ new Set();
|
|
1067
|
+
const stack = [program];
|
|
1068
|
+
while (stack.length > 0) {
|
|
1069
|
+
const node = stack.pop();
|
|
1070
|
+
if (node.type === "ParenthesizedExpression") throw new TypeError(PARENTHESES_KEPT);
|
|
1071
|
+
const text = escapedText(node);
|
|
1072
|
+
const decoded = text?.raw.includes("\\") ? text.decoded : jsxAttributeText(node);
|
|
1073
|
+
if (decoded !== void 0) {
|
|
1074
|
+
for (const atom of atomsWrittenIn(decoded)) found.add(atom);
|
|
1075
|
+
}
|
|
1076
|
+
pushAll(stack, childrenOf(node));
|
|
1077
|
+
}
|
|
1078
|
+
return found;
|
|
1079
|
+
}
|
|
1080
|
+
var SENTENCE = "a Nave class built from pieces is invisible to the build, so its atom would not ship.";
|
|
1081
|
+
function concatenationProblems(program, code, analysis) {
|
|
1082
|
+
const problems = [];
|
|
1083
|
+
const memo = { edges: /* @__PURE__ */ new Map(), rightmost: /* @__PURE__ */ new Map() };
|
|
1084
|
+
const ends = /* @__PURE__ */ new Map();
|
|
1085
|
+
const stack = [{ node: program, after: void 0 }];
|
|
1086
|
+
while (stack.length > 0) {
|
|
1087
|
+
const { node, after } = stack.pop();
|
|
1088
|
+
const offset = concatenatedPiece(node, memo, analysis, { after, memo: ends })?.node.start ?? (isBreakingOut(node, analysis, { after, memo: ends }) ? node.start : -1);
|
|
1089
|
+
if (offset !== -1) {
|
|
1090
|
+
problems.push({
|
|
1091
|
+
kind: "concatenation",
|
|
1092
|
+
offset,
|
|
1093
|
+
construct: code.slice(node.start, node.end),
|
|
1094
|
+
text: SENTENCE
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
pushAll(stack, childrenWithAfter(node, after));
|
|
1098
|
+
}
|
|
1099
|
+
return problems.toSorted((a, b) => a.offset - b.offset);
|
|
1100
|
+
}
|
|
1101
|
+
function childrenWithAfter(node, after) {
|
|
1102
|
+
const isOperands = node.type === "BinaryExpression" && node.operator === "+";
|
|
1103
|
+
if (isOperands) {
|
|
1104
|
+
const left = nodeAt(node, "left");
|
|
1105
|
+
const right = nodeAt(node, "right");
|
|
1106
|
+
return [
|
|
1107
|
+
...left ? [{ node: left, after: right ? { node: right, next: after } : after }] : [],
|
|
1108
|
+
...right ? [{ node: right, after }] : []
|
|
1109
|
+
];
|
|
1110
|
+
}
|
|
1111
|
+
const isWrapper = node.type === "ParenthesizedExpression";
|
|
1112
|
+
return childrenOf(node).map((child) => ({ node: child, after: isWrapper ? after : void 0 }));
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// src/vite-rewrite-class.ts
|
|
1116
|
+
function classOf(name) {
|
|
1117
|
+
return Object.hasOwn(atomClassMap, name) ? atomClassMap[name] : name;
|
|
1118
|
+
}
|
|
1119
|
+
function decode(node, frame, out) {
|
|
1120
|
+
const found = resolveArgument(node, frame.analysis, frame.setup) ?? [];
|
|
1121
|
+
const values = [...new Set(found.map((possible) => possible.value))];
|
|
1122
|
+
if (values.length === 0) return;
|
|
1123
|
+
const text = frame.code.slice(node.start, node.end);
|
|
1124
|
+
const chain = values.map((value) => `${text} === ${JSON.stringify(value)} ? ${JSON.stringify(classOf(value))} : `).join("");
|
|
1125
|
+
out.push({ start: node.start, end: node.end, text: `(${chain}${text})` });
|
|
1126
|
+
}
|
|
1127
|
+
var decodeName = (node, frame, out) => {
|
|
1128
|
+
if (frame.analysis.referenceOf(node)?.binding) decode(node, frame, out);
|
|
1129
|
+
};
|
|
1130
|
+
var collectEach = (keys) => (node, frame, out) => {
|
|
1131
|
+
for (const key of keys) collect(nodeAt(node, key), frame, out);
|
|
1132
|
+
};
|
|
1133
|
+
var COLLECTORS = /* @__PURE__ */ new Map([
|
|
1134
|
+
["ConditionalExpression", collectEach(["consequent", "alternate"])],
|
|
1135
|
+
["Identifier", decodeName],
|
|
1136
|
+
[
|
|
1137
|
+
"LogicalExpression",
|
|
1138
|
+
(node, frame, out) => {
|
|
1139
|
+
for (const operand of operandsRead(node)) collect(operand, frame, out);
|
|
1140
|
+
}
|
|
1141
|
+
],
|
|
1142
|
+
["MemberExpression", decode],
|
|
1143
|
+
["ParenthesizedExpression", collectEach(["expression"])]
|
|
1144
|
+
]);
|
|
1145
|
+
function collect(node, frame, out) {
|
|
1146
|
+
const text = staticStringOf(node);
|
|
1147
|
+
if (text === void 0) {
|
|
1148
|
+
COLLECTORS.get(node.type)?.(node, frame, out);
|
|
1149
|
+
} else if (text !== "") {
|
|
1150
|
+
out.push({ start: node.start, end: node.end, text: JSON.stringify(classOf(text)) });
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
function classEdits(argument, frame) {
|
|
1154
|
+
const out = [];
|
|
1155
|
+
collect(argument, frame, out);
|
|
1156
|
+
return out;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
// src/vite-source-map.ts
|
|
1160
|
+
function toSourceMap(map) {
|
|
1161
|
+
return {
|
|
1162
|
+
version: 3,
|
|
1163
|
+
sources: map.sources,
|
|
1164
|
+
names: map.names ?? [],
|
|
1165
|
+
mappings: map.mappings,
|
|
1166
|
+
...map.sourceRoot !== void 0 && { sourceRoot: map.sourceRoot },
|
|
1167
|
+
...map.sourcesContent !== void 0 && { sourcesContent: map.sourcesContent }
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
function combinedMapOf(ctx) {
|
|
1171
|
+
const map = ctx.getCombinedSourcemap();
|
|
1172
|
+
return map.mappings === "" ? void 0 : decodeIncomingMap(toSourceMap(map));
|
|
1173
|
+
}
|
|
1174
|
+
var LINE_TERMINATOR = /\r\n|[\n\r\u{2028}\u{2029}]/gu;
|
|
1175
|
+
function lineStartsOf(code) {
|
|
1176
|
+
const starts = [0];
|
|
1177
|
+
for (const match of code.matchAll(LINE_TERMINATOR)) starts.push(match.index + match[0].length);
|
|
1178
|
+
return starts;
|
|
1179
|
+
}
|
|
1180
|
+
function lineIndexOf(starts, offset) {
|
|
1181
|
+
let low = 0;
|
|
1182
|
+
let high = starts.length - 1;
|
|
1183
|
+
while (low < high) {
|
|
1184
|
+
const middle = Math.ceil((low + high) / 2);
|
|
1185
|
+
if (starts[middle] <= offset) low = middle;
|
|
1186
|
+
else high = middle - 1;
|
|
1187
|
+
}
|
|
1188
|
+
return low;
|
|
1189
|
+
}
|
|
1190
|
+
function positionIn(code) {
|
|
1191
|
+
let starts;
|
|
1192
|
+
return (offset) => {
|
|
1193
|
+
starts ??= lineStartsOf(code);
|
|
1194
|
+
const index = lineIndexOf(starts, offset);
|
|
1195
|
+
return { line: index + 1, column: offset - starts[index] + 1 };
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
function normalized(text) {
|
|
1199
|
+
return text.replace(/^\u{FEFF}/u, "").replaceAll("\r\n", "\n");
|
|
1200
|
+
}
|
|
1201
|
+
function placerFor(code, map, authored) {
|
|
1202
|
+
const position = positionIn(code);
|
|
1203
|
+
const isAuthored = (index) => {
|
|
1204
|
+
const source = map?.sourcesContent?.[index];
|
|
1205
|
+
return authored === void 0 || typeof source !== "string" ? true : normalized(source) === normalized(authored);
|
|
1206
|
+
};
|
|
1207
|
+
return (offset) => {
|
|
1208
|
+
const generated = position(offset);
|
|
1209
|
+
const origin = map?.originalPositionFor({ line: generated.line, column: generated.column - 1 });
|
|
1210
|
+
return origin && isAuthored(origin.sourceIndex) ? { line: origin.line, column: origin.column + 1 } : void 0;
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// src/vite-rewrite-edit.ts
|
|
1215
|
+
function afterComment(code, at) {
|
|
1216
|
+
if (code.startsWith("/*", at)) {
|
|
1217
|
+
const end2 = code.indexOf("*/", at + 2);
|
|
1218
|
+
return end2 === -1 ? code.length : end2 + 2;
|
|
1219
|
+
}
|
|
1220
|
+
if (!code.startsWith("//", at)) return void 0;
|
|
1221
|
+
const end = code.slice(at).search(/[\n\r\u{2028}\u{2029}]/u);
|
|
1222
|
+
return end === -1 ? code.length : at + end + 1;
|
|
1223
|
+
}
|
|
1224
|
+
function startOfNext(code, from) {
|
|
1225
|
+
let at = from;
|
|
1226
|
+
while (at < code.length) {
|
|
1227
|
+
const comment = afterComment(code, at);
|
|
1228
|
+
if (comment !== void 0) at = comment;
|
|
1229
|
+
else if (/\s/.test(code[at])) at += 1;
|
|
1230
|
+
else break;
|
|
1231
|
+
}
|
|
1232
|
+
return at;
|
|
1233
|
+
}
|
|
1234
|
+
var TOKEN = /\w+|[\s\S]/gu;
|
|
1235
|
+
function countable(text) {
|
|
1236
|
+
return text.replaceAll("\f", " ").replaceAll(/[\u{2028}\u{2029}]/gu, "\n");
|
|
1237
|
+
}
|
|
1238
|
+
function applyEdits(code, id, edits) {
|
|
1239
|
+
const position = positionIn(code);
|
|
1240
|
+
const mappings = new MappingsBuilder();
|
|
1241
|
+
const mark = (offset) => {
|
|
1242
|
+
const { line, column } = position(offset);
|
|
1243
|
+
mappings.mark({ line, column: column - 1 });
|
|
1244
|
+
};
|
|
1245
|
+
let out = "";
|
|
1246
|
+
const keep = (from, to) => {
|
|
1247
|
+
const text = code.slice(from, to);
|
|
1248
|
+
for (const token of text.matchAll(TOKEN)) {
|
|
1249
|
+
if (token[0].trim() !== "") mark(from + token.index);
|
|
1250
|
+
mappings.advance(countable(token[0]));
|
|
1251
|
+
}
|
|
1252
|
+
out += text;
|
|
1253
|
+
};
|
|
1254
|
+
const ordered = edits.toSorted((a, b) => a.start - b.start || a.end - b.end);
|
|
1255
|
+
let cursor = 0;
|
|
1256
|
+
for (const edit of ordered) {
|
|
1257
|
+
keep(cursor, edit.start);
|
|
1258
|
+
if (edit.text !== "") {
|
|
1259
|
+
mark(edit.start);
|
|
1260
|
+
mappings.advance(countable(edit.text));
|
|
1261
|
+
out += edit.text;
|
|
1262
|
+
}
|
|
1263
|
+
cursor = edit.end;
|
|
1264
|
+
}
|
|
1265
|
+
keep(cursor, code.length);
|
|
1266
|
+
const map = { version: 3, sources: [id], names: [], mappings: mappings.toMappings() };
|
|
1267
|
+
return { code: out, map: JSON.stringify(map) };
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
// src/vite-rewrite-call.ts
|
|
1271
|
+
var JOIN = '].filter(Boolean).join(" ")';
|
|
1272
|
+
function argumentsStart(code, call) {
|
|
1273
|
+
let at = nodeAt(call, "callee").end;
|
|
1274
|
+
while (at < code.length) {
|
|
1275
|
+
const char = code[at];
|
|
1276
|
+
if (char === "(") return at + 1;
|
|
1277
|
+
const comment = afterComment(code, at);
|
|
1278
|
+
if (char === ")" || /\s/.test(char)) at += 1;
|
|
1279
|
+
else if (code.startsWith("?.", at)) at += 2;
|
|
1280
|
+
else if (comment === void 0) return void 0;
|
|
1281
|
+
else at = comment;
|
|
1282
|
+
}
|
|
1283
|
+
return void 0;
|
|
1284
|
+
}
|
|
1285
|
+
var STATEMENT_LISTS = /* @__PURE__ */ new Set([
|
|
1286
|
+
"BlockStatement",
|
|
1287
|
+
"Program",
|
|
1288
|
+
"StaticBlock",
|
|
1289
|
+
"SwitchCase"
|
|
1290
|
+
]);
|
|
1291
|
+
function isStatementStart(call, frame) {
|
|
1292
|
+
const { parentOf } = frame.analysis;
|
|
1293
|
+
let node = call;
|
|
1294
|
+
for (let parent = parentOf.get(node); parent?.start === call.start; parent = parentOf.get(node)) {
|
|
1295
|
+
node = parent;
|
|
1296
|
+
}
|
|
1297
|
+
const holder = parentOf.get(node);
|
|
1298
|
+
return node.type === "ExpressionStatement" && holder !== void 0 && STATEMENT_LISTS.has(holder.type);
|
|
1299
|
+
}
|
|
1300
|
+
function lead(call, frame) {
|
|
1301
|
+
return isStatementStart(call, frame) ? ";" : "";
|
|
1302
|
+
}
|
|
1303
|
+
function joined(call, frame, inside) {
|
|
1304
|
+
const open = argumentsStart(frame.code, call);
|
|
1305
|
+
if (open === void 0) return void 0;
|
|
1306
|
+
return [
|
|
1307
|
+
{ start: call.start, end: open, text: `${lead(call, frame)}[` },
|
|
1308
|
+
...inside,
|
|
1309
|
+
{ start: call.end - 1, end: call.end, text: JOIN }
|
|
1310
|
+
];
|
|
1311
|
+
}
|
|
1312
|
+
function literal2(call, frame, text) {
|
|
1313
|
+
return [{ start: call.start, end: call.end, text: `${lead(call, frame)}${JSON.stringify(text)}` }];
|
|
1314
|
+
}
|
|
1315
|
+
function constantsOf(args, frame) {
|
|
1316
|
+
const constants = args.map((arg) => constantOf(arg, frame.analysis));
|
|
1317
|
+
return constants.includes(void 0) ? void 0 : constants;
|
|
1318
|
+
}
|
|
1319
|
+
function cxCallEdits(call, frame) {
|
|
1320
|
+
const args = nodesAt(call, "arguments");
|
|
1321
|
+
const constants = constantsOf(args, frame);
|
|
1322
|
+
if (constants) {
|
|
1323
|
+
return literal2(
|
|
1324
|
+
call,
|
|
1325
|
+
frame,
|
|
1326
|
+
constants.filter(Boolean).map((name) => classOf(name)).join(" ")
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
return joined(
|
|
1330
|
+
call,
|
|
1331
|
+
frame,
|
|
1332
|
+
args.flatMap((arg) => classEdits(arg, frame))
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
function rawCallEdits(call, frame) {
|
|
1336
|
+
const args = nodesAt(call, "arguments");
|
|
1337
|
+
const constants = constantsOf(args, frame);
|
|
1338
|
+
if (constants) return literal2(call, frame, constants.filter(Boolean).join(" "));
|
|
1339
|
+
return joined(call, frame, []);
|
|
1340
|
+
}
|
|
1341
|
+
function rawCallOf(member, frame) {
|
|
1342
|
+
const parent = frame.analysis.parentOf.get(member);
|
|
1343
|
+
return parent?.type === "CallExpression" && nodeAt(parent, "callee") === member ? parent : void 0;
|
|
1344
|
+
}
|
|
1345
|
+
function trailingComma(code, argument, call) {
|
|
1346
|
+
let at = argument.end;
|
|
1347
|
+
const end = call.end - 1;
|
|
1348
|
+
while (at < end) {
|
|
1349
|
+
const char = code[at];
|
|
1350
|
+
if (char === ",") return at;
|
|
1351
|
+
const comment = afterComment(code, at);
|
|
1352
|
+
if (char === ")" || /\s/.test(char)) at += 1;
|
|
1353
|
+
else if (comment === void 0) return void 0;
|
|
1354
|
+
else at = comment;
|
|
1355
|
+
}
|
|
1356
|
+
return void 0;
|
|
1357
|
+
}
|
|
1358
|
+
function dynamicCallEdits(call, frame, map) {
|
|
1359
|
+
const args = nodesAt(call, "arguments");
|
|
1360
|
+
const open = argumentsStart(frame.code, call);
|
|
1361
|
+
if (open === void 0) return void 0;
|
|
1362
|
+
const [argument] = args;
|
|
1363
|
+
const head = `${lead(call, frame)}(${map}[`;
|
|
1364
|
+
const end = { start: call.end - 1, end: call.end };
|
|
1365
|
+
if (args.length !== 1 || argument.type === "SpreadElement") {
|
|
1366
|
+
return [
|
|
1367
|
+
{ start: call.start, end: open, text: `${head}[` },
|
|
1368
|
+
{ ...end, text: '][0]] || "")' }
|
|
1369
|
+
];
|
|
1370
|
+
}
|
|
1371
|
+
const comma = trailingComma(frame.code, argument, call);
|
|
1372
|
+
return [
|
|
1373
|
+
{ start: call.start, end: open, text: head },
|
|
1374
|
+
...comma === void 0 ? [] : [{ start: comma, end: comma + 1, text: "" }],
|
|
1375
|
+
{ ...end, text: '] || "")' }
|
|
1376
|
+
];
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// src/vite-rewrite-module.ts
|
|
1380
|
+
function newRewriting() {
|
|
1381
|
+
return { attempts: 0, done: /* @__PURE__ */ new Set(), kept: /* @__PURE__ */ new Set() };
|
|
1382
|
+
}
|
|
1383
|
+
function addEdits(subject, nodes, build) {
|
|
1384
|
+
const { options, result, rewriting } = subject;
|
|
1385
|
+
if (!options.rewrite || rewriting.done.has(nodes[0])) return;
|
|
1386
|
+
let edits;
|
|
1387
|
+
try {
|
|
1388
|
+
edits = build();
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
if (error instanceof RangeError) return;
|
|
1391
|
+
throw error;
|
|
1392
|
+
}
|
|
1393
|
+
if (!edits) return;
|
|
1394
|
+
for (const node of nodes) rewriting.done.add(node);
|
|
1395
|
+
pushAll(result.edits, edits);
|
|
1396
|
+
}
|
|
1397
|
+
function frameOf(subject, analysis) {
|
|
1398
|
+
return { code: subject.code, analysis, setup: subject.options.setup };
|
|
1399
|
+
}
|
|
1400
|
+
function rewriteCx(subject, call, analysis) {
|
|
1401
|
+
addEdits(subject, [call], () => cxCallEdits(call, frameOf(subject, analysis)));
|
|
1402
|
+
}
|
|
1403
|
+
function rewriteRaw(subject, member, analysis) {
|
|
1404
|
+
const frame = frameOf(subject, analysis);
|
|
1405
|
+
const call = rawCallOf(member, frame);
|
|
1406
|
+
if (call) addEdits(subject, [member, call], () => rawCallEdits(call, frame));
|
|
1407
|
+
}
|
|
1408
|
+
function mapLiteral(keep) {
|
|
1409
|
+
const entries = Object.entries(keep).map(
|
|
1410
|
+
([atom, name]) => `${JSON.stringify(atom)}:${JSON.stringify(name)}`
|
|
1411
|
+
);
|
|
1412
|
+
return `{${["__proto__:null", ...entries].join(",")}}`;
|
|
1413
|
+
}
|
|
1414
|
+
function rewriteDynamic(subject, call, analysis) {
|
|
1415
|
+
const keep = subject.options.rewrite?.keep;
|
|
1416
|
+
if (!keep) return;
|
|
1417
|
+
addEdits(
|
|
1418
|
+
subject,
|
|
1419
|
+
[call],
|
|
1420
|
+
() => dynamicCallEdits(call, frameOf(subject, analysis), mapLiteral(keep))
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
function noteUse(rewriting, cx, use) {
|
|
1424
|
+
if (cx && !(use && rewriting.done.has(use.node))) rewriting.kept.add(cx.binding);
|
|
1425
|
+
}
|
|
1426
|
+
function localNamesOf(declaration) {
|
|
1427
|
+
return nodesAt(declaration, "specifiers").map((specifier) => {
|
|
1428
|
+
const local = nodeAt(specifier, "local");
|
|
1429
|
+
return (local && stringAt(local, "name")) ?? "";
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
var CONTINUING = /[([`+\-/]/;
|
|
1433
|
+
function removeUnusedImports(subject, program, bound) {
|
|
1434
|
+
if (bound.hasDirectEval) return;
|
|
1435
|
+
const unused = new Set(
|
|
1436
|
+
bound.bindings.keys().filter((binding) => !subject.rewriting.kept.has(binding)).map((binding) => binding.name)
|
|
1437
|
+
);
|
|
1438
|
+
const { code } = subject;
|
|
1439
|
+
for (const declaration of nodesAt(program, "body")) {
|
|
1440
|
+
const names = declaration.type === "ImportDeclaration" && staticStringOf(nodeAt(declaration, "source")) === bound.source ? localNamesOf(declaration) : [];
|
|
1441
|
+
if (names.length === 0 || names.some((name) => !unused.has(name))) continue;
|
|
1442
|
+
const line = /^\r?\n/.exec(code.slice(declaration.end));
|
|
1443
|
+
const end = declaration.end + (line?.[0].length ?? 0);
|
|
1444
|
+
const text = CONTINUING.test(code.charAt(startOfNext(code, end))) ? ";" : "";
|
|
1445
|
+
subject.result.edits.push({ start: declaration.start, end, text });
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
function finishRewrite(subject, program, bound) {
|
|
1449
|
+
if (!subject.options.rewrite || subject.result.edits.length === 0) return;
|
|
1450
|
+
removeUnusedImports(subject, program, bound);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
// src/vite-scope-types.ts
|
|
1454
|
+
function newScope(parent, isFunction) {
|
|
1455
|
+
return { parent, isFunction, bindings: /* @__PURE__ */ new Map() };
|
|
1456
|
+
}
|
|
1457
|
+
function functionScopeOf(scope) {
|
|
1458
|
+
let current = scope;
|
|
1459
|
+
while (!current.isFunction && current.parent) current = current.parent;
|
|
1460
|
+
return current;
|
|
1461
|
+
}
|
|
1462
|
+
function declare(scope, binding, isAssigning = true) {
|
|
1463
|
+
const existing = scope.bindings.get(binding.name);
|
|
1464
|
+
if (existing) {
|
|
1465
|
+
if (isAssigning) existing.writes += 1;
|
|
1466
|
+
return existing;
|
|
1467
|
+
}
|
|
1468
|
+
scope.bindings.set(binding.name, binding);
|
|
1469
|
+
return binding;
|
|
1470
|
+
}
|
|
1471
|
+
function reference(walker, node, scope, isWrite = false) {
|
|
1472
|
+
walker.references.push({ node, scope, isWrite, binding: void 0 });
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/vite-scope-enum.ts
|
|
1476
|
+
function visitEnum(node, scope, walker) {
|
|
1477
|
+
const inner = newScope(scope, false);
|
|
1478
|
+
const body = nodeAt(node, "body");
|
|
1479
|
+
const members = body ? nodesAt(body, "members") : [];
|
|
1480
|
+
for (const member of members) {
|
|
1481
|
+
const name = propertyNameOf(nodeAt(member, "id"), false);
|
|
1482
|
+
if (name !== void 0) declare(inner, { name, kind: "const", writes: 0 });
|
|
1483
|
+
}
|
|
1484
|
+
if (!body) return;
|
|
1485
|
+
walker.parentOf.set(body, node);
|
|
1486
|
+
walker.visit(body, inner);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// src/vite-scope-imports.ts
|
|
1490
|
+
function importedName(specifier) {
|
|
1491
|
+
if (specifier.type === "ImportNamespaceSpecifier") return "*";
|
|
1492
|
+
if (specifier.type !== "ImportSpecifier") return "default";
|
|
1493
|
+
const imported = nodeAt(specifier, "imported");
|
|
1494
|
+
return stringAt(imported ?? specifier, "name") ?? String(imported?.value);
|
|
1495
|
+
}
|
|
1496
|
+
function declareImport(node, scope) {
|
|
1497
|
+
if (isTypeOnly(node)) return;
|
|
1498
|
+
const source = String(nodeAt(node, "source")?.value);
|
|
1499
|
+
for (const specifier of nodesAt(node, "specifiers")) {
|
|
1500
|
+
if (isTypeOnly(specifier)) continue;
|
|
1501
|
+
const local = stringAt(nodeAt(specifier, "local") ?? specifier, "name");
|
|
1502
|
+
if (local === void 0) continue;
|
|
1503
|
+
const imported = importedName(specifier);
|
|
1504
|
+
scope.bindings.set(local, { name: local, kind: "import", writes: 0, source, imported });
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// src/vite-scope-pattern.ts
|
|
1509
|
+
function partsOf(pattern) {
|
|
1510
|
+
return nodesAt(pattern, pattern.type === "ArrayPattern" ? "elements" : "properties");
|
|
1511
|
+
}
|
|
1512
|
+
function targetOf(part) {
|
|
1513
|
+
return part.type === "Property" ? nodeAt(part, "value") : part;
|
|
1514
|
+
}
|
|
1515
|
+
function functionScopeOrHere(spec, scope) {
|
|
1516
|
+
return spec.kind === "var" ? functionScopeOf(scope) : scope;
|
|
1517
|
+
}
|
|
1518
|
+
function declarePattern(pattern, spec, scope, walker) {
|
|
1519
|
+
if (!pattern) return;
|
|
1520
|
+
const name = stringAt(pattern, "name");
|
|
1521
|
+
if (name !== void 0 && pattern.type === "Identifier") {
|
|
1522
|
+
const into = functionScopeOrHere(spec, scope);
|
|
1523
|
+
const isAssigning = spec.kind !== "var" || spec.init !== void 0 || spec.isAssigned === true;
|
|
1524
|
+
const binding = { name, kind: spec.kind, writes: 0 };
|
|
1525
|
+
if (spec.owner) binding.owner = spec.owner;
|
|
1526
|
+
const declared = declare(into, binding, isAssigning);
|
|
1527
|
+
if (spec.init) declared.init = spec.init;
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
DECLARE[pattern.type]?.(pattern, spec, scope, walker);
|
|
1531
|
+
}
|
|
1532
|
+
var DECLARE = {
|
|
1533
|
+
TSParameterProperty: (pattern, spec, scope, walker) => {
|
|
1534
|
+
declarePattern(nodeAt(pattern, "parameter"), spec, scope, walker);
|
|
1535
|
+
},
|
|
1536
|
+
AssignmentPattern: (pattern, spec, scope, walker) => {
|
|
1537
|
+
declarePattern(nodeAt(pattern, "left"), spec, scope, walker);
|
|
1538
|
+
const right = nodeAt(pattern, "right");
|
|
1539
|
+
if (right) walker.parentOf.set(right, pattern);
|
|
1540
|
+
walker.visit(right, scope);
|
|
1541
|
+
},
|
|
1542
|
+
RestElement: (pattern, spec, scope, walker) => {
|
|
1543
|
+
declarePattern(nodeAt(pattern, "argument"), spec, scope, walker);
|
|
1544
|
+
},
|
|
1545
|
+
ArrayPattern: (pattern, spec, scope, walker) => {
|
|
1546
|
+
for (const part of partsOf(pattern)) declarePattern(part, spec, scope, walker);
|
|
1547
|
+
},
|
|
1548
|
+
ObjectPattern: (pattern, spec, scope, walker) => {
|
|
1549
|
+
for (const part of partsOf(pattern)) {
|
|
1550
|
+
if (part.computed === true) walker.visit(nodeAt(part, "key"), scope);
|
|
1551
|
+
declarePattern(targetOf(part), spec, scope, walker);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
function writeTargets(target, scope, walker) {
|
|
1556
|
+
if (!target) return;
|
|
1557
|
+
const inner = assertedBy(target);
|
|
1558
|
+
if (inner) {
|
|
1559
|
+
walker.parentOf.set(inner, target);
|
|
1560
|
+
writeTargets(inner, scope, walker);
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (target.type === "Identifier") {
|
|
1564
|
+
reference(walker, target, scope, true);
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
const write = WRITE[target.type];
|
|
1568
|
+
if (write) write(target, void 0, scope, walker);
|
|
1569
|
+
else walker.visit(target, scope);
|
|
1570
|
+
}
|
|
1571
|
+
var WRITE = {
|
|
1572
|
+
ArrayPattern: (target, _result, scope, walker) => {
|
|
1573
|
+
for (const part of partsOf(target)) writeTargets(part, scope, walker);
|
|
1574
|
+
},
|
|
1575
|
+
ObjectPattern: (target, _result, scope, walker) => {
|
|
1576
|
+
for (const part of partsOf(target)) {
|
|
1577
|
+
if (part.computed === true) walker.visit(nodeAt(part, "key"), scope);
|
|
1578
|
+
writeTargets(targetOf(part), scope, walker);
|
|
1579
|
+
}
|
|
1580
|
+
},
|
|
1581
|
+
AssignmentPattern: (target, _result, scope, walker) => {
|
|
1582
|
+
writeTargets(nodeAt(target, "left"), scope, walker);
|
|
1583
|
+
walker.visit(nodeAt(target, "right"), scope);
|
|
1584
|
+
},
|
|
1585
|
+
RestElement: (target, _result, scope, walker) => {
|
|
1586
|
+
writeTargets(nodeAt(target, "argument"), scope, walker);
|
|
1587
|
+
}
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1590
|
+
// src/vite-scope-walk.ts
|
|
1591
|
+
function visit(node, scope, walker) {
|
|
1592
|
+
if (!node) return;
|
|
1593
|
+
const handler = HANDLERS[node.type];
|
|
1594
|
+
if (handler) handler(node, scope, walker);
|
|
1595
|
+
else visitChildren(node, scope, walker);
|
|
1596
|
+
}
|
|
1597
|
+
var TYPE_KEYS = /* @__PURE__ */ new Set(["typeAnnotation", "typeArguments"]);
|
|
1598
|
+
function visitChildren(node, scope, walker) {
|
|
1599
|
+
for (const child of childrenOf(node, TYPE_KEYS)) {
|
|
1600
|
+
walker.parentOf.set(child, node);
|
|
1601
|
+
visit(child, scope, walker);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
function visitKeys(node, keys, scope, walker) {
|
|
1605
|
+
const children = keys.flatMap((key) => {
|
|
1606
|
+
const value = node[key];
|
|
1607
|
+
return (Array.isArray(value) ? value : [value]).filter((child) => isNode(child));
|
|
1608
|
+
});
|
|
1609
|
+
for (const child of children) {
|
|
1610
|
+
walker.parentOf.set(child, node);
|
|
1611
|
+
visit(child, scope, walker);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
function expressionKeys(node, others) {
|
|
1615
|
+
return node.computed === true ? ["key", ...others] : [...others];
|
|
1616
|
+
}
|
|
1617
|
+
function visitLoop(node, scope, walker) {
|
|
1618
|
+
const inner = newScope(scope, false);
|
|
1619
|
+
const left = nodeAt(node, "left");
|
|
1620
|
+
if (left?.type === "VariableDeclaration") {
|
|
1621
|
+
const kind = left.kind === "var" ? "var" : "loop";
|
|
1622
|
+
for (const declarator of nodesAt(left, "declarations")) {
|
|
1623
|
+
declarePattern(nodeAt(declarator, "id"), { kind, isAssigned: true }, inner, walker);
|
|
1624
|
+
}
|
|
1625
|
+
} else {
|
|
1626
|
+
writeTargets(left, inner, walker);
|
|
1627
|
+
}
|
|
1628
|
+
visitKeys(node, ["right"], scope, walker);
|
|
1629
|
+
visitKeys(node, ["body"], inner, walker);
|
|
1630
|
+
}
|
|
1631
|
+
function visitFunction(node, scope, walker) {
|
|
1632
|
+
let outer = scope;
|
|
1633
|
+
const id = nodeAt(node, "id");
|
|
1634
|
+
if (id && node.type === "FunctionExpression") {
|
|
1635
|
+
outer = newScope(scope, false);
|
|
1636
|
+
declare(outer, { name: stringAt(id, "name") ?? "", kind: "function", writes: 0 });
|
|
1637
|
+
}
|
|
1638
|
+
const parameters = newScope(outer, true);
|
|
1639
|
+
for (const param of nodesAt(node, "params")) {
|
|
1640
|
+
visitKeys(param, ["decorators"], scope, walker);
|
|
1641
|
+
declarePattern(param, { kind: "param", owner: node }, parameters, walker);
|
|
1642
|
+
}
|
|
1643
|
+
const body = nodeAt(node, "body");
|
|
1644
|
+
if (body?.type === "BlockStatement") {
|
|
1645
|
+
walker.parentOf.set(body, node);
|
|
1646
|
+
visitChildren(body, newScope(parameters, true), walker);
|
|
1647
|
+
} else {
|
|
1648
|
+
visitKeys(node, ["body"], parameters, walker);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
function visitClass(node, scope, walker) {
|
|
1652
|
+
visitKeys(node, ["decorators"], scope, walker);
|
|
1653
|
+
const inner = newScope(scope, false);
|
|
1654
|
+
const name = stringAt(nodeAt(node, "id") ?? node, "name");
|
|
1655
|
+
if (name !== void 0) declare(inner, { name, kind: "class", writes: 0 });
|
|
1656
|
+
visitKeys(node, ["superClass", "body"], inner, walker);
|
|
1657
|
+
}
|
|
1658
|
+
function visitDeclaration(node, scope, walker) {
|
|
1659
|
+
const kind = node.kind;
|
|
1660
|
+
for (const declarator of nodesAt(node, "declarations")) {
|
|
1661
|
+
walker.parentOf.set(declarator, node);
|
|
1662
|
+
const id = nodeAt(declarator, "id");
|
|
1663
|
+
const init = nodeAt(declarator, "init");
|
|
1664
|
+
const hasPlainInit = id?.type === "Identifier" && init !== void 0;
|
|
1665
|
+
const spec = hasPlainInit ? { kind, init } : { kind, isAssigned: init !== void 0 };
|
|
1666
|
+
declarePattern(id, spec, scope, walker);
|
|
1667
|
+
if (id) walker.parentOf.set(id, declarator);
|
|
1668
|
+
visit(init, scope, walker);
|
|
1669
|
+
if (init) walker.parentOf.set(init, declarator);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
function visitExport(node, scope, walker) {
|
|
1673
|
+
if (node.source || isTypeOnly(node)) return;
|
|
1674
|
+
visitKeys(node, ["declaration"], scope, walker);
|
|
1675
|
+
for (const specifier of nodesAt(node, "specifiers")) {
|
|
1676
|
+
const local = nodeAt(specifier, "local");
|
|
1677
|
+
if (!local || isTypeOnly(specifier)) continue;
|
|
1678
|
+
walker.parentOf.set(specifier, node);
|
|
1679
|
+
walker.parentOf.set(local, specifier);
|
|
1680
|
+
reference(walker, local, scope);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
function leaf3() {
|
|
1684
|
+
}
|
|
1685
|
+
function isDirectEval(node) {
|
|
1686
|
+
let callee = nodeAt(node, "callee");
|
|
1687
|
+
while (callee?.type === "ParenthesizedExpression") callee = nodeAt(callee, "expression");
|
|
1688
|
+
return callee?.type === "Identifier" && stringAt(callee, "name") === "eval";
|
|
1689
|
+
}
|
|
1690
|
+
function writeTarget(node, key, scope, walker) {
|
|
1691
|
+
const target = nodeAt(node, key);
|
|
1692
|
+
if (target) walker.parentOf.set(target, node);
|
|
1693
|
+
writeTargets(target, scope, walker);
|
|
1694
|
+
}
|
|
1695
|
+
function visitChain(node, scope, walker) {
|
|
1696
|
+
const spine = [];
|
|
1697
|
+
let current = node;
|
|
1698
|
+
while (current?.type === "BinaryExpression" || current?.type === "LogicalExpression") {
|
|
1699
|
+
spine.push(current);
|
|
1700
|
+
current = nodeAt(current, "left");
|
|
1701
|
+
}
|
|
1702
|
+
const links = [...spine, ...current ? [current] : []];
|
|
1703
|
+
for (let index = 1; index < links.length; index += 1) {
|
|
1704
|
+
walker.parentOf.set(links[index], links[index - 1]);
|
|
1705
|
+
}
|
|
1706
|
+
visit(current, scope, walker);
|
|
1707
|
+
for (const link of spine.toReversed()) visitKeys(link, ["right"], scope, walker);
|
|
1708
|
+
}
|
|
1709
|
+
var MEMBER_LIKE = (node, scope, walker) => {
|
|
1710
|
+
visitKeys(node, ["decorators", ...expressionKeys(node, ["value"])], scope, walker);
|
|
1711
|
+
};
|
|
1712
|
+
var HANDLERS = {
|
|
1713
|
+
Identifier: (node, scope, walker) => {
|
|
1714
|
+
reference(walker, node, scope);
|
|
1715
|
+
},
|
|
1716
|
+
MemberExpression: (node, scope, walker) => {
|
|
1717
|
+
visitKeys(node, node.computed === true ? ["object", "property"] : ["object"], scope, walker);
|
|
1718
|
+
},
|
|
1719
|
+
Property: MEMBER_LIKE,
|
|
1720
|
+
MethodDefinition: MEMBER_LIKE,
|
|
1721
|
+
PropertyDefinition: MEMBER_LIKE,
|
|
1722
|
+
AccessorProperty: MEMBER_LIKE,
|
|
1723
|
+
LabeledStatement: (node, scope, walker) => {
|
|
1724
|
+
visitKeys(node, ["body"], scope, walker);
|
|
1725
|
+
},
|
|
1726
|
+
BreakStatement: leaf3,
|
|
1727
|
+
ContinueStatement: leaf3,
|
|
1728
|
+
MetaProperty: leaf3,
|
|
1729
|
+
ExportAllDeclaration: leaf3,
|
|
1730
|
+
TSEnumDeclaration: visitEnum,
|
|
1731
|
+
TSEnumMember: (node, scope, walker) => {
|
|
1732
|
+
visitKeys(node, ["initializer"], scope, walker);
|
|
1733
|
+
},
|
|
1734
|
+
TSInterfaceDeclaration: leaf3,
|
|
1735
|
+
TSTypeAliasDeclaration: leaf3,
|
|
1736
|
+
TSDeclareFunction: leaf3,
|
|
1737
|
+
TSEmptyBodyFunctionExpression: leaf3,
|
|
1738
|
+
TSAbstractMethodDefinition: leaf3,
|
|
1739
|
+
TSAbstractPropertyDefinition: leaf3,
|
|
1740
|
+
TSAbstractAccessorProperty: leaf3,
|
|
1741
|
+
TSIndexSignature: leaf3,
|
|
1742
|
+
TSModuleDeclaration: (node, scope, walker) => {
|
|
1743
|
+
visitKeys(node, ["body"], newScope(scope, true), walker);
|
|
1744
|
+
},
|
|
1745
|
+
CallExpression: (node, scope, walker) => {
|
|
1746
|
+
if (isDirectEval(node)) walker.evalScopes.push(scope);
|
|
1747
|
+
visitChildren(node, scope, walker);
|
|
1748
|
+
},
|
|
1749
|
+
BinaryExpression: visitChain,
|
|
1750
|
+
LogicalExpression: visitChain,
|
|
1751
|
+
AssignmentExpression: (node, scope, walker) => {
|
|
1752
|
+
writeTarget(node, "left", scope, walker);
|
|
1753
|
+
visitKeys(node, ["right"], scope, walker);
|
|
1754
|
+
},
|
|
1755
|
+
UpdateExpression: (node, scope, walker) => {
|
|
1756
|
+
writeTarget(node, "argument", scope, walker);
|
|
1757
|
+
},
|
|
1758
|
+
ImportDeclaration: (node, scope) => {
|
|
1759
|
+
declareImport(node, scope);
|
|
1760
|
+
},
|
|
1761
|
+
ExportNamedDeclaration: visitExport,
|
|
1762
|
+
VariableDeclaration: visitDeclaration,
|
|
1763
|
+
FunctionDeclaration: (node, scope, walker) => {
|
|
1764
|
+
const name = stringAt(nodeAt(node, "id") ?? node, "name");
|
|
1765
|
+
if (name !== void 0) declare(scope, { name, kind: "function", writes: 0 });
|
|
1766
|
+
visitFunction(node, scope, walker);
|
|
1767
|
+
},
|
|
1768
|
+
FunctionExpression: visitFunction,
|
|
1769
|
+
ArrowFunctionExpression: visitFunction,
|
|
1770
|
+
ClassDeclaration: (node, scope, walker) => {
|
|
1771
|
+
const name = stringAt(nodeAt(node, "id") ?? node, "name");
|
|
1772
|
+
if (name !== void 0) declare(scope, { name, kind: "class", writes: 0 });
|
|
1773
|
+
visitClass(node, scope, walker);
|
|
1774
|
+
},
|
|
1775
|
+
ClassExpression: visitClass,
|
|
1776
|
+
StaticBlock: (node, scope, walker) => {
|
|
1777
|
+
visitChildren(node, newScope(scope, true), walker);
|
|
1778
|
+
},
|
|
1779
|
+
BlockStatement: (node, scope, walker) => {
|
|
1780
|
+
visitChildren(node, newScope(scope, false), walker);
|
|
1781
|
+
},
|
|
1782
|
+
SwitchStatement: (node, scope, walker) => {
|
|
1783
|
+
visitKeys(node, ["discriminant"], scope, walker);
|
|
1784
|
+
visitKeys(node, ["cases"], newScope(scope, false), walker);
|
|
1785
|
+
},
|
|
1786
|
+
CatchClause: (node, scope, walker) => {
|
|
1787
|
+
const inner = newScope(scope, false);
|
|
1788
|
+
declarePattern(nodeAt(node, "param"), { kind: "catch" }, inner, walker);
|
|
1789
|
+
visitKeys(node, ["body"], inner, walker);
|
|
1790
|
+
},
|
|
1791
|
+
ForStatement: (node, scope, walker) => {
|
|
1792
|
+
visitChildren(node, newScope(scope, false), walker);
|
|
1793
|
+
},
|
|
1794
|
+
ForInStatement: visitLoop,
|
|
1795
|
+
ForOfStatement: visitLoop
|
|
1796
|
+
};
|
|
1797
|
+
|
|
1798
|
+
// src/vite-scope.ts
|
|
1799
|
+
function lookup(scope, name) {
|
|
1800
|
+
for (let current = scope; current; current = current.parent) {
|
|
1801
|
+
const found = current.bindings.get(name);
|
|
1802
|
+
if (found) return found;
|
|
1803
|
+
}
|
|
1804
|
+
return void 0;
|
|
1805
|
+
}
|
|
1806
|
+
function resolve(reference2) {
|
|
1807
|
+
const name = stringAt(reference2.node, "name");
|
|
1808
|
+
reference2.binding = name === void 0 ? void 0 : lookup(reference2.scope, name);
|
|
1809
|
+
if (reference2.binding && reference2.isWrite) reference2.binding.writes += 1;
|
|
1810
|
+
}
|
|
1811
|
+
var ASSIGNABLE = /* @__PURE__ */ new Set([
|
|
1812
|
+
"catch",
|
|
1813
|
+
"class",
|
|
1814
|
+
"function",
|
|
1815
|
+
"let",
|
|
1816
|
+
"loop",
|
|
1817
|
+
"param",
|
|
1818
|
+
"var"
|
|
1819
|
+
]);
|
|
1820
|
+
function assignable(scope) {
|
|
1821
|
+
return scope.bindings.values().filter((binding) => ASSIGNABLE.has(binding.kind)).toArray();
|
|
1822
|
+
}
|
|
1823
|
+
function markEvalWrites(scopes) {
|
|
1824
|
+
const marked = /* @__PURE__ */ new Set();
|
|
1825
|
+
for (const start of scopes) {
|
|
1826
|
+
for (let scope = start; scope && !marked.has(scope); scope = scope.parent) {
|
|
1827
|
+
marked.add(scope);
|
|
1828
|
+
for (const binding of assignable(scope)) binding.writes += 1;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
function analyze(program) {
|
|
1833
|
+
const walker = {
|
|
1834
|
+
references: [],
|
|
1835
|
+
parentOf: /* @__PURE__ */ new Map(),
|
|
1836
|
+
evalScopes: [],
|
|
1837
|
+
visit: (node, scope) => {
|
|
1838
|
+
visit(node, scope, walker);
|
|
1839
|
+
}
|
|
1840
|
+
};
|
|
1841
|
+
const module = newScope(void 0, true);
|
|
1842
|
+
for (const statement of nodesAt(program, "body")) {
|
|
1843
|
+
walker.parentOf.set(statement, program);
|
|
1844
|
+
visit(statement, module, walker);
|
|
1845
|
+
}
|
|
1846
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
1847
|
+
for (const reference2 of walker.references) {
|
|
1848
|
+
resolve(reference2);
|
|
1849
|
+
byNode.set(reference2.node, reference2);
|
|
1850
|
+
}
|
|
1851
|
+
const evalScopes = walker.evalScopes.filter((scope) => !lookup(scope, "eval"));
|
|
1852
|
+
markEvalWrites(evalScopes);
|
|
1853
|
+
return {
|
|
1854
|
+
hasDirectEval: evalScopes.length > 0,
|
|
1855
|
+
references: walker.references,
|
|
1856
|
+
parentOf: walker.parentOf,
|
|
1857
|
+
referenceOf: (node) => byNode.get(node)
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
// src/vite-vue-setup.ts
|
|
1862
|
+
function returnedObject(analysis) {
|
|
1863
|
+
for (const [node] of analysis.parentOf) {
|
|
1864
|
+
if (!isSetupReturn(node, analysis.parentOf)) continue;
|
|
1865
|
+
const init = nodeAt(node, "init");
|
|
1866
|
+
if (init?.type === "ObjectExpression") return init;
|
|
1867
|
+
}
|
|
1868
|
+
return void 0;
|
|
1869
|
+
}
|
|
1870
|
+
function stringExposures(analysis) {
|
|
1871
|
+
const exposures = /* @__PURE__ */ new Map();
|
|
1872
|
+
const object = returnedObject(analysis);
|
|
1873
|
+
const properties = object ? nodesAt(object, "properties") : [];
|
|
1874
|
+
for (const property of properties) {
|
|
1875
|
+
const value = nodeAt(property, "value");
|
|
1876
|
+
const name = propertyNameOf(nodeAt(property, "key"), property.computed === true);
|
|
1877
|
+
if (name === void 0 || value?.type !== "Identifier" || property.kind === "get") continue;
|
|
1878
|
+
const possibles2 = resolveArgument(value, analysis);
|
|
1879
|
+
if (possibles2) exposures.set(name, { kind: "values", values: possibles2.map((p) => p.value) });
|
|
1880
|
+
}
|
|
1881
|
+
return exposures;
|
|
1882
|
+
}
|
|
1883
|
+
function cxReadsOnSetup(analysis, exposures) {
|
|
1884
|
+
const reads = [];
|
|
1885
|
+
for (const reference2 of analysis.references) {
|
|
1886
|
+
if (!isSetupParameter(analysis, reference2.node)) continue;
|
|
1887
|
+
const member = analysis.parentOf.get(reference2.node);
|
|
1888
|
+
const name = member && setupMemberName(member);
|
|
1889
|
+
if (member && name !== void 0 && exposures.get(name)?.kind === "cx") reads.push(member);
|
|
1890
|
+
}
|
|
1891
|
+
return reads;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// src/vite-collect.ts
|
|
1895
|
+
var CX_SOURCE = "@navecss/core/cx";
|
|
1896
|
+
function report(reading, problem2) {
|
|
1897
|
+
reading.rewriting.attempts += 1;
|
|
1898
|
+
const key = `${problem2.kind}:${problem2.offset}`;
|
|
1899
|
+
if (reading.seen.has(key)) return;
|
|
1900
|
+
reading.seen.add(key);
|
|
1901
|
+
reading.result.problems.push(problem2);
|
|
1902
|
+
}
|
|
1903
|
+
var COMPILER_PREFIX = /\$setup\.|\$\$props\./g;
|
|
1904
|
+
function quoteCall(reading, use, args, callee = use.local) {
|
|
1905
|
+
const inner = args.length > 0 ? textWithoutAssertions(reading.code, args) : "";
|
|
1906
|
+
return `${callee}(${inner.replaceAll(COMPILER_PREFIX, "")})`;
|
|
1907
|
+
}
|
|
1908
|
+
function judgeString(reading, use, value, node) {
|
|
1909
|
+
const verdict = judgeAtom(value, reading.options.ownAtoms);
|
|
1910
|
+
switch (verdict.kind) {
|
|
1911
|
+
case "atom": {
|
|
1912
|
+
reading.result.atoms.add(value);
|
|
1913
|
+
break;
|
|
1914
|
+
}
|
|
1915
|
+
case "own": {
|
|
1916
|
+
report(reading, {
|
|
1917
|
+
kind: "own",
|
|
1918
|
+
offset: node.start,
|
|
1919
|
+
construct: `${use.local}()`,
|
|
1920
|
+
text: `"${value}" is an atom of your own, which has no class. Use @nave ${value} in a CSS rule instead.`
|
|
1921
|
+
});
|
|
1922
|
+
break;
|
|
1923
|
+
}
|
|
1924
|
+
case "whitespace": {
|
|
1925
|
+
report(reading, {
|
|
1926
|
+
kind: "argument",
|
|
1927
|
+
offset: node.start,
|
|
1928
|
+
construct: `${use.local}()`,
|
|
1929
|
+
text: verdict.text
|
|
1930
|
+
});
|
|
1931
|
+
break;
|
|
1932
|
+
}
|
|
1933
|
+
default: {
|
|
1934
|
+
report(reading, {
|
|
1935
|
+
kind: "unknown",
|
|
1936
|
+
offset: node.start,
|
|
1937
|
+
construct: `${use.local}()`,
|
|
1938
|
+
text: verdict.text,
|
|
1939
|
+
needsAvailable: !verdict.hasHint
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
function readCall(reading, use, analysis) {
|
|
1945
|
+
const args = nodesAt(use.node, "arguments");
|
|
1946
|
+
let quote;
|
|
1947
|
+
const quoted = () => quote ??= quoteCall(reading, use, args);
|
|
1948
|
+
for (const arg of args) {
|
|
1949
|
+
if (arg.type === "SpreadElement") {
|
|
1950
|
+
report(reading, {
|
|
1951
|
+
kind: "argument",
|
|
1952
|
+
offset: arg.start,
|
|
1953
|
+
construct: quoted(),
|
|
1954
|
+
text: "a spread argument."
|
|
1955
|
+
});
|
|
1956
|
+
continue;
|
|
1957
|
+
}
|
|
1958
|
+
const possibles2 = resolveArgument(arg, analysis, reading.options.setup);
|
|
1959
|
+
if (!possibles2) {
|
|
1960
|
+
report(reading, {
|
|
1961
|
+
kind: "argument",
|
|
1962
|
+
offset: arg.start,
|
|
1963
|
+
construct: quoted(),
|
|
1964
|
+
text: "the argument is not a literal atom name."
|
|
1965
|
+
});
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1968
|
+
for (const { value, node } of possibles2) judgeString(reading, use, value, node);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
function refusedProblem(reading, use) {
|
|
1972
|
+
if (use.isReexport && reading.options.isDeclared === true) return void 0;
|
|
1973
|
+
return {
|
|
1974
|
+
kind: use.isReexport ? "reexport" : "reference",
|
|
1975
|
+
offset: use.node.start,
|
|
1976
|
+
construct: "",
|
|
1977
|
+
text: `${use.phrase ?? ""}.`,
|
|
1978
|
+
...use.isReexport && { isListable: use.isListable },
|
|
1979
|
+
...use.isRenamed === true && { isRenamed: true },
|
|
1980
|
+
...use.exportedAs && { exportedAs: use.exportedAs }
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
function readUse(reading, use, analysis) {
|
|
1984
|
+
switch (use.kind) {
|
|
1985
|
+
case "call": {
|
|
1986
|
+
const before = reading.rewriting.attempts;
|
|
1987
|
+
readCall(reading, use, analysis);
|
|
1988
|
+
if (reading.rewriting.attempts === before) rewriteCx(reading, use.node, analysis);
|
|
1989
|
+
break;
|
|
1990
|
+
}
|
|
1991
|
+
case "dynamic": {
|
|
1992
|
+
const args = nodesAt(use.node, "arguments");
|
|
1993
|
+
const construct = quoteCall(reading, use, args, `${use.local}.dynamic`);
|
|
1994
|
+
reading.result.dynamicCalls.push({ offset: use.node.start, construct });
|
|
1995
|
+
rewriteDynamic(reading, use.node, analysis);
|
|
1996
|
+
break;
|
|
1997
|
+
}
|
|
1998
|
+
case "exposure": {
|
|
1999
|
+
reading.result.exposes.set(use.exposedAs ?? use.local, { kind: "cx" });
|
|
2000
|
+
break;
|
|
2001
|
+
}
|
|
2002
|
+
case "raw": {
|
|
2003
|
+
rewriteRaw(reading, use.node, analysis);
|
|
2004
|
+
break;
|
|
2005
|
+
}
|
|
2006
|
+
case "refused": {
|
|
2007
|
+
const problem2 = refusedProblem(reading, use);
|
|
2008
|
+
if (problem2) report(reading, problem2);
|
|
2009
|
+
break;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
function readUses(reading, program) {
|
|
2014
|
+
const { code, options, result } = reading;
|
|
2015
|
+
const analysis = analyze(program);
|
|
2016
|
+
const bindings = cxBindingsOf(analysis, options.cxSources);
|
|
2017
|
+
const frame = {
|
|
2018
|
+
analysis,
|
|
2019
|
+
code,
|
|
2020
|
+
allowsExposure: options.isVueScript === true,
|
|
2021
|
+
declaredSources: options.declaredSources
|
|
2022
|
+
};
|
|
2023
|
+
for (const reference2 of analysis.references) {
|
|
2024
|
+
const cx = reference2.binding && bindings.get(reference2.binding);
|
|
2025
|
+
const use = cx && useOf(frame, reference2, cx);
|
|
2026
|
+
if (use) readUse(reading, use, analysis);
|
|
2027
|
+
noteUse(reading.rewriting, cx, use);
|
|
2028
|
+
}
|
|
2029
|
+
for (const [name, exposure] of stringExposures(analysis)) result.exposes.set(name, exposure);
|
|
2030
|
+
const setup = mergedExposures(options.setup, result.exposes);
|
|
2031
|
+
const members = setup ? cxReadsOnSetup(analysis, setup) : [];
|
|
2032
|
+
const withSetup = { ...reading, options: { ...options, setup } };
|
|
2033
|
+
for (const member of members) {
|
|
2034
|
+
readUse(withSetup, useOfExpression(frame, member, setupMemberName(member) ?? "cx"), analysis);
|
|
2035
|
+
}
|
|
2036
|
+
return { analysis, bindings };
|
|
2037
|
+
}
|
|
2038
|
+
function readModule(code, program, options) {
|
|
2039
|
+
const escapedAtoms = refuseParenthesesAndFindEscapedAtoms(program);
|
|
2040
|
+
const result = {
|
|
2041
|
+
atoms: /* @__PURE__ */ new Set(),
|
|
2042
|
+
classes: /* @__PURE__ */ new Set(),
|
|
2043
|
+
problems: [],
|
|
2044
|
+
dynamicCalls: [],
|
|
2045
|
+
exposes: /* @__PURE__ */ new Map(),
|
|
2046
|
+
usesCx: isImportingCx(program, options.cxSources),
|
|
2047
|
+
edits: []
|
|
2048
|
+
};
|
|
2049
|
+
const reading = { code, options, result, seen: /* @__PURE__ */ new Set(), rewriting: newRewriting() };
|
|
2050
|
+
const { analysis, bindings } = readUses(reading, program);
|
|
2051
|
+
finishRewrite(reading, program, {
|
|
2052
|
+
bindings,
|
|
2053
|
+
hasDirectEval: analysis.hasDirectEval,
|
|
2054
|
+
source: CX_SOURCE
|
|
2055
|
+
});
|
|
2056
|
+
const listed = options.isDeclared === true ? declaredExportProblems({
|
|
2057
|
+
program,
|
|
2058
|
+
analysis,
|
|
2059
|
+
bindings,
|
|
2060
|
+
cxSources: options.cxSources,
|
|
2061
|
+
declaredSources: options.declaredSources ?? /* @__PURE__ */ new Set()
|
|
2062
|
+
}) : [];
|
|
2063
|
+
for (const problem2 of [...sourceFormProblems(code, program, options), ...listed]) {
|
|
2064
|
+
report(reading, problem2);
|
|
2065
|
+
}
|
|
2066
|
+
for (const atom of atomsWrittenIn(code)) result.classes.add(atom);
|
|
2067
|
+
for (const atom of escapedAtoms) result.classes.add(atom);
|
|
2068
|
+
if (result.usesCx || !options.isDependency) {
|
|
2069
|
+
for (const problem2 of concatenationProblems(program, code, analysis)) report(reading, problem2);
|
|
2070
|
+
}
|
|
2071
|
+
return result;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
// src/vite-options.ts
|
|
2075
|
+
function unknownAtomText(name) {
|
|
2076
|
+
const hint = hintFor(name);
|
|
2077
|
+
return hint ? ` ${hint}` : "";
|
|
2078
|
+
}
|
|
2079
|
+
function problemWithName(where, name, own) {
|
|
2080
|
+
if (typeof name === "string" && isBuiltInAtom(name)) return void 0;
|
|
2081
|
+
if (typeof name === "string" && own === void 0) return void 0;
|
|
2082
|
+
if (typeof name === "string" && own?.has(name)) {
|
|
2083
|
+
return `navePlugin(): ${where} names "${name}", an atom of your own; those have no class, so there is nothing to keep.`;
|
|
2084
|
+
}
|
|
2085
|
+
const spelled = typeof name === "string" ? name : String(name);
|
|
2086
|
+
return `navePlugin(): ${where} names an unknown atom "${spelled}".${unknownAtomText(spelled)}`;
|
|
2087
|
+
}
|
|
2088
|
+
function problemsInList(where, list, own) {
|
|
2089
|
+
if (!Array.isArray(list)) return [`navePlugin(): ${where} must be an array of atom names.`];
|
|
2090
|
+
return Array.from(list, (name) => problemWithName(where, name, own) ?? []).flat();
|
|
2091
|
+
}
|
|
2092
|
+
function problemsInKeepFor(keepFor, own) {
|
|
2093
|
+
if (typeof keepFor !== "object" || keepFor === null || Array.isArray(keepFor)) {
|
|
2094
|
+
return ["navePlugin(): keepFor must be an object from package names to arrays of atom names."];
|
|
2095
|
+
}
|
|
2096
|
+
const problems = [];
|
|
2097
|
+
for (const [pkg, list] of Object.entries(keepFor)) {
|
|
2098
|
+
problems.push(...problemsInList(`keepFor["${pkg}"]`, list, own));
|
|
2099
|
+
}
|
|
2100
|
+
return problems;
|
|
2101
|
+
}
|
|
2102
|
+
function problemsInCxModules(cxModules) {
|
|
2103
|
+
if (!Array.isArray(cxModules)) {
|
|
2104
|
+
return ["navePlugin(): cxModules must be an array of module paths or specifiers."];
|
|
2105
|
+
}
|
|
2106
|
+
return Array.from(
|
|
2107
|
+
cxModules,
|
|
2108
|
+
(entry, index) => typeof entry === "string" ? [] : `navePlugin(): cxModules[${index}] must be a string: a module path or a specifier.`
|
|
2109
|
+
).flat();
|
|
2110
|
+
}
|
|
2111
|
+
function problemsInOptions(options, own) {
|
|
2112
|
+
const problems = [];
|
|
2113
|
+
const { atomic, keep, keepFor, cxModules } = options;
|
|
2114
|
+
if (atomic !== void 0 && atomic !== "all" && atomic !== "used") {
|
|
2115
|
+
problems.push("navePlugin(): atomic must be 'used' or 'all'.");
|
|
2116
|
+
}
|
|
2117
|
+
if (keep !== void 0) problems.push(...problemsInList("keep", keep, own));
|
|
2118
|
+
if (keepFor !== void 0) problems.push(...problemsInKeepFor(keepFor, own));
|
|
2119
|
+
if (cxModules !== void 0) problems.push(...problemsInCxModules(cxModules));
|
|
2120
|
+
return problems;
|
|
2121
|
+
}
|
|
2122
|
+
function assertOptions(options, own) {
|
|
2123
|
+
const [first2] = problemsInOptions(options, own);
|
|
2124
|
+
if (first2 !== void 0) throw new Error(first2);
|
|
2125
|
+
}
|
|
2126
|
+
function resolveUsedOptions(options) {
|
|
2127
|
+
return {
|
|
2128
|
+
atomic: options.atomic ?? "used",
|
|
2129
|
+
keep: [...options.keep ?? []],
|
|
2130
|
+
keepFor: Object.fromEntries(
|
|
2131
|
+
Object.entries(options.keepFor ?? {}).map(([pkg, list]) => [pkg, [...list]])
|
|
2132
|
+
),
|
|
2133
|
+
cxModules: [...options.cxModules ?? []]
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
function keptAtoms(options) {
|
|
2137
|
+
return [.../* @__PURE__ */ new Set([...options.keep, ...Object.values(options.keepFor).flat()])];
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
// src/vite-css-blocks.ts
|
|
2141
|
+
function matchBraces(tokens) {
|
|
2142
|
+
const matches = /* @__PURE__ */ new Map();
|
|
2143
|
+
const open = [];
|
|
2144
|
+
for (const [index, token] of tokens.entries()) {
|
|
2145
|
+
if (token.type === "{-token") open.push(index);
|
|
2146
|
+
else if (token.type === "}-token" && open.length > 0) matches.set(open.pop(), index);
|
|
2147
|
+
}
|
|
2148
|
+
return matches;
|
|
2149
|
+
}
|
|
2150
|
+
function isBlank(tokens, from, to) {
|
|
2151
|
+
for (let index = from; index < to; index += 1) {
|
|
2152
|
+
const type = tokens[index].type;
|
|
2153
|
+
if (type !== "whitespace-token" && type !== "comment") return false;
|
|
2154
|
+
}
|
|
2155
|
+
return true;
|
|
2156
|
+
}
|
|
2157
|
+
var OPENERS = /* @__PURE__ */ new Set(["(-token", "[-token", "function-token"]);
|
|
2158
|
+
var CLOSERS = /* @__PURE__ */ new Set([")-token", "]-token"]);
|
|
2159
|
+
function readSheet(css) {
|
|
2160
|
+
const tokens = tokenize(css);
|
|
2161
|
+
const matches = matchBraces(tokens);
|
|
2162
|
+
return {
|
|
2163
|
+
tokens,
|
|
2164
|
+
slice: (from, to) => css.slice(tokens[from]?.startIndex ?? css.length, tokens[to - 1]?.endIndex ?? 0),
|
|
2165
|
+
statements(from, to) {
|
|
2166
|
+
const found = [];
|
|
2167
|
+
let start = from;
|
|
2168
|
+
let index = from;
|
|
2169
|
+
let depth = 0;
|
|
2170
|
+
while (index < to) {
|
|
2171
|
+
const type = tokens[index].type;
|
|
2172
|
+
if (OPENERS.has(type)) depth += 1;
|
|
2173
|
+
else if (CLOSERS.has(type)) depth = Math.max(0, depth - 1);
|
|
2174
|
+
const close = type === "{-token" && depth === 0 ? matches.get(index) : void 0;
|
|
2175
|
+
if (close !== void 0 && close < to) {
|
|
2176
|
+
found.push({ from: start, to: close + 1, open: index, close });
|
|
2177
|
+
index = close + 1;
|
|
2178
|
+
start = index;
|
|
2179
|
+
} else if (type === "semicolon-token") {
|
|
2180
|
+
found.push({ from: start, to: index + 1 });
|
|
2181
|
+
index += 1;
|
|
2182
|
+
start = index;
|
|
2183
|
+
} else {
|
|
2184
|
+
index += 1;
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
if (!isBlank(tokens, start, to)) found.push({ from: start, to });
|
|
2188
|
+
return found;
|
|
2189
|
+
}
|
|
2190
|
+
};
|
|
2191
|
+
}
|
|
2192
|
+
function firstSignificant(tokens, from, to) {
|
|
2193
|
+
let index = from;
|
|
2194
|
+
while (index < to && isBlank(tokens, index, index + 1)) index += 1;
|
|
2195
|
+
return index;
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
// src/vite-selector-atoms.ts
|
|
2199
|
+
var OPENERS2 = /* @__PURE__ */ new Set(["(-token", "[-token", "function-token"]);
|
|
2200
|
+
var CLOSERS2 = /* @__PURE__ */ new Set([")-token", "]-token"]);
|
|
2201
|
+
function membersOf(sheet, from, to) {
|
|
2202
|
+
const members = [];
|
|
2203
|
+
let start = from;
|
|
2204
|
+
let depth = 0;
|
|
2205
|
+
for (let index = from; index < to; index += 1) {
|
|
2206
|
+
const type = sheet.tokens[index].type;
|
|
2207
|
+
if (OPENERS2.has(type)) depth += 1;
|
|
2208
|
+
else if (CLOSERS2.has(type)) depth -= 1;
|
|
2209
|
+
else if (type === "comma-token" && depth === 0) {
|
|
2210
|
+
members.push([start, index]);
|
|
2211
|
+
start = index + 1;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
members.push([start, to]);
|
|
2215
|
+
return members;
|
|
2216
|
+
}
|
|
2217
|
+
var closings = /* @__PURE__ */ new WeakMap();
|
|
2218
|
+
function closesOf(sheet) {
|
|
2219
|
+
const known = closings.get(sheet);
|
|
2220
|
+
if (known) return known;
|
|
2221
|
+
const closes = /* @__PURE__ */ new Map();
|
|
2222
|
+
const open = [];
|
|
2223
|
+
for (const [index, token] of sheet.tokens.entries()) {
|
|
2224
|
+
if (OPENERS2.has(token.type)) open.push(index);
|
|
2225
|
+
else if (CLOSERS2.has(token.type) && open.length > 0) closes.set(open.pop(), index);
|
|
2226
|
+
}
|
|
2227
|
+
closings.set(sheet, closes);
|
|
2228
|
+
return closes;
|
|
2229
|
+
}
|
|
2230
|
+
function afterGroup(sheet, index, to) {
|
|
2231
|
+
return Math.min((closesOf(sheet).get(index) ?? to - 1) + 1, to);
|
|
2232
|
+
}
|
|
2233
|
+
function isTransparentList(sheet, index) {
|
|
2234
|
+
const token = sheet.tokens[index];
|
|
2235
|
+
if (token.type !== "function-token" || sheet.tokens[index - 1]?.type !== "colon-token") {
|
|
2236
|
+
return false;
|
|
2237
|
+
}
|
|
2238
|
+
const name = token.structured.value.toLowerCase();
|
|
2239
|
+
return name === "is" || name === "where";
|
|
2240
|
+
}
|
|
2241
|
+
function atomAt(sheet, index, to) {
|
|
2242
|
+
const name = sheet.tokens[index + 1];
|
|
2243
|
+
if (index + 1 >= to || name?.type !== "ident-token") return void 0;
|
|
2244
|
+
const dot = sheet.tokens[index];
|
|
2245
|
+
if (dot.type !== "delim-token" || dot.raw !== ".") return void 0;
|
|
2246
|
+
return atomOfClass(name.structured.value);
|
|
2247
|
+
}
|
|
2248
|
+
function atomsNamedBy(sheet, from, to) {
|
|
2249
|
+
const atoms = [];
|
|
2250
|
+
let index = from;
|
|
2251
|
+
while (index < to) {
|
|
2252
|
+
const isGroup = OPENERS2.has(sheet.tokens[index].type);
|
|
2253
|
+
if (isGroup && !isTransparentList(sheet, index)) {
|
|
2254
|
+
index = afterGroup(sheet, index, to);
|
|
2255
|
+
continue;
|
|
2256
|
+
}
|
|
2257
|
+
const atom = isGroup ? void 0 : atomAt(sheet, index, to);
|
|
2258
|
+
if (atom) atoms.push(atom);
|
|
2259
|
+
index += 1;
|
|
2260
|
+
}
|
|
2261
|
+
return atoms;
|
|
2262
|
+
}
|
|
2263
|
+
var newNeeds = () => ({ parts: [], size: 0 });
|
|
2264
|
+
var newList = () => ({ finished: [], current: newNeeds() });
|
|
2265
|
+
function closeList(done, parent) {
|
|
2266
|
+
const all = [...done.finished, done.current];
|
|
2267
|
+
if (all.some((needs) => needs.size === 0)) return;
|
|
2268
|
+
for (const needs of all) {
|
|
2269
|
+
parent.current.parts.push(needs.parts);
|
|
2270
|
+
parent.current.size += needs.size;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
function flatten(parts) {
|
|
2274
|
+
const atoms = [];
|
|
2275
|
+
const stack = [parts];
|
|
2276
|
+
while (stack.length > 0) {
|
|
2277
|
+
const part = stack.pop();
|
|
2278
|
+
if (typeof part === "string") atoms.push(part);
|
|
2279
|
+
else for (let index = part.length - 1; index >= 0; index -= 1) stack.push(part[index]);
|
|
2280
|
+
}
|
|
2281
|
+
return atoms;
|
|
2282
|
+
}
|
|
2283
|
+
function readToken(sheet, index, limit, lists) {
|
|
2284
|
+
const type = sheet.tokens[index].type;
|
|
2285
|
+
const list = lists.at(-1);
|
|
2286
|
+
const isNested = lists.length > 1;
|
|
2287
|
+
if (OPENERS2.has(type)) {
|
|
2288
|
+
if (!isTransparentList(sheet, index)) return afterGroup(sheet, index, limit.to);
|
|
2289
|
+
lists.push(newList());
|
|
2290
|
+
} else if (isNested && type === ")-token") {
|
|
2291
|
+
closeList(lists.pop(), lists.at(-1));
|
|
2292
|
+
} else if (isNested && type === "comma-token") {
|
|
2293
|
+
list.finished.push(list.current);
|
|
2294
|
+
list.current = newNeeds();
|
|
2295
|
+
} else {
|
|
2296
|
+
const atom = atomAt(sheet, index, limit.to);
|
|
2297
|
+
if (atom && !limit.emitted.has(atom)) {
|
|
2298
|
+
list.current.parts.push(atom);
|
|
2299
|
+
list.current.size += 1;
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
return index + 1;
|
|
2303
|
+
}
|
|
2304
|
+
function blockersOf(sheet, from, to, emitted) {
|
|
2305
|
+
const lists = [newList()];
|
|
2306
|
+
let index = from;
|
|
2307
|
+
while (index < to) index = readToken(sheet, index, { emitted, to }, lists);
|
|
2308
|
+
while (lists.length > 1) closeList(lists.pop(), lists.at(-1));
|
|
2309
|
+
return flatten(lists[0].current.parts);
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
// src/vite-prune.ts
|
|
2313
|
+
var GROUPS = /* @__PURE__ */ new Set([
|
|
2314
|
+
"container",
|
|
2315
|
+
"document",
|
|
2316
|
+
"layer",
|
|
2317
|
+
"media",
|
|
2318
|
+
"scope",
|
|
2319
|
+
"starting-style",
|
|
2320
|
+
"supports"
|
|
2321
|
+
]);
|
|
2322
|
+
function atKeywordAt(sheet, index) {
|
|
2323
|
+
const token = sheet.tokens[index];
|
|
2324
|
+
if (token?.type !== "at-keyword-token") return void 0;
|
|
2325
|
+
return token.structured.value.toLowerCase();
|
|
2326
|
+
}
|
|
2327
|
+
function isAtomicLayer(sheet, statement) {
|
|
2328
|
+
if (statement.open === void 0) return false;
|
|
2329
|
+
const significant = [];
|
|
2330
|
+
for (let index = statement.from; index < statement.open; index += 1) {
|
|
2331
|
+
const type = sheet.tokens[index].type;
|
|
2332
|
+
if (type !== "whitespace-token" && type !== "comment") significant.push(index);
|
|
2333
|
+
}
|
|
2334
|
+
const name = sheet.tokens[significant[1] ?? -1];
|
|
2335
|
+
return significant.length === 2 && atKeywordAt(sheet, significant[0]) === "layer" && name?.type === "ident-token" && name.structured.value === "atomic";
|
|
2336
|
+
}
|
|
2337
|
+
var CONDITIONALS = /* @__PURE__ */ new Set(["container", "document", "media", "scope", "supports"]);
|
|
2338
|
+
function layerBlocks(sheet, from, to) {
|
|
2339
|
+
const found = [];
|
|
2340
|
+
for (const statement of sheet.statements(from, to)) {
|
|
2341
|
+
const { open, close } = statement;
|
|
2342
|
+
if (open === void 0 || close === void 0) continue;
|
|
2343
|
+
if (isAtomicLayer(sheet, statement)) found.push(statement);
|
|
2344
|
+
else {
|
|
2345
|
+
const keyword = atKeywordAt(sheet, firstSignificant(sheet.tokens, statement.from, open));
|
|
2346
|
+
if (keyword !== void 0 && CONDITIONALS.has(keyword)) {
|
|
2347
|
+
found.push(...layerBlocks(sheet, open + 1, close));
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
return found;
|
|
2352
|
+
}
|
|
2353
|
+
function isEmptyRegion(sheet, from, to) {
|
|
2354
|
+
return sheet.statements(from, to).length === 0;
|
|
2355
|
+
}
|
|
2356
|
+
function pruneRule(sheet, statement, emitted) {
|
|
2357
|
+
const { from, open, close } = statement;
|
|
2358
|
+
const first2 = firstSignificant(sheet.tokens, from, open);
|
|
2359
|
+
const members = membersOf(sheet, first2, open);
|
|
2360
|
+
const kept = members.filter(([start, end]) => blockersOf(sheet, start, end, emitted).length === 0);
|
|
2361
|
+
if (kept.length === members.length) return sheet.slice(from, close + 1);
|
|
2362
|
+
if (kept.length === 0) return "";
|
|
2363
|
+
let trailing = open;
|
|
2364
|
+
while (trailing > first2 && firstSignificant(sheet.tokens, trailing - 1, trailing) === trailing) {
|
|
2365
|
+
trailing -= 1;
|
|
2366
|
+
}
|
|
2367
|
+
const list = sheet.slice(first2, trailing);
|
|
2368
|
+
const separator = /,\s/.test(list) ? ", " : ",";
|
|
2369
|
+
const text = kept.map(([start, end]) => sheet.slice(start, end).trim()).join(separator);
|
|
2370
|
+
return `${sheet.slice(from, first2)}${text}${sheet.slice(trailing, open)}${sheet.slice(open, close + 1)}`;
|
|
2371
|
+
}
|
|
2372
|
+
function pruneRegion(sheet, from, to, emitted) {
|
|
2373
|
+
const statements = sheet.statements(from, to);
|
|
2374
|
+
let out = "";
|
|
2375
|
+
for (const statement of statements) out += pruneStatement(sheet, statement, emitted);
|
|
2376
|
+
const last = statements.at(-1);
|
|
2377
|
+
return last ? out + sheet.slice(last.to, to) : sheet.slice(from, to);
|
|
2378
|
+
}
|
|
2379
|
+
function pruneStatement(sheet, statement, emitted) {
|
|
2380
|
+
const { open, close } = statement;
|
|
2381
|
+
if (open === void 0 || close === void 0) return sheet.slice(statement.from, statement.to);
|
|
2382
|
+
const first2 = firstSignificant(sheet.tokens, statement.from, open);
|
|
2383
|
+
const keyword = atKeywordAt(sheet, first2);
|
|
2384
|
+
if (keyword === void 0) return pruneRule(sheet, statement, emitted);
|
|
2385
|
+
if (!GROUPS.has(keyword)) return sheet.slice(statement.from, close + 1);
|
|
2386
|
+
if (isEmptyRegion(sheet, open + 1, close)) return sheet.slice(statement.from, close + 1);
|
|
2387
|
+
const inner = pruneRegion(sheet, open + 1, close, emitted);
|
|
2388
|
+
if (inner.trim() === "") return "";
|
|
2389
|
+
return `${sheet.slice(statement.from, open + 1)}${inner}}`;
|
|
2390
|
+
}
|
|
2391
|
+
function pruneAtomicLayer(css, emitted) {
|
|
2392
|
+
if (!css.includes("@")) return css;
|
|
2393
|
+
const sheet = readSheet(css);
|
|
2394
|
+
let out = "";
|
|
2395
|
+
let cursor = 0;
|
|
2396
|
+
for (const statement of layerBlocks(sheet, 0, sheet.tokens.length)) {
|
|
2397
|
+
const { open, close } = statement;
|
|
2398
|
+
out += sheet.slice(cursor, open + 1) + pruneRegion(sheet, open + 1, close, emitted);
|
|
2399
|
+
cursor = close;
|
|
2400
|
+
}
|
|
2401
|
+
return cursor === 0 ? css : out + sheet.slice(cursor, sheet.tokens.length);
|
|
2402
|
+
}
|
|
2403
|
+
function visitMembers(sheet, from, to, visit2) {
|
|
2404
|
+
for (const statement of sheet.statements(from, to)) {
|
|
2405
|
+
const { open, close } = statement;
|
|
2406
|
+
if (open === void 0 || close === void 0) continue;
|
|
2407
|
+
const first2 = firstSignificant(sheet.tokens, statement.from, open);
|
|
2408
|
+
const keyword = atKeywordAt(sheet, first2);
|
|
2409
|
+
if (keyword === void 0) {
|
|
2410
|
+
for (const [start, end] of membersOf(sheet, first2, open)) visit2(start, end);
|
|
2411
|
+
} else if (GROUPS.has(keyword)) {
|
|
2412
|
+
visitMembers(sheet, open + 1, close, visit2);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
function inspectAtomicLayer(css) {
|
|
2417
|
+
const atoms = /* @__PURE__ */ new Set();
|
|
2418
|
+
if (!css.includes("@")) return { hasLayer: false, atoms };
|
|
2419
|
+
const sheet = readSheet(css);
|
|
2420
|
+
const blocks = layerBlocks(sheet, 0, sheet.tokens.length);
|
|
2421
|
+
for (const { open, close } of blocks) {
|
|
2422
|
+
visitMembers(sheet, open + 1, close, (start, end) => {
|
|
2423
|
+
for (const atom of atomsNamedBy(sheet, start, end)) atoms.add(atom);
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2426
|
+
return { hasLayer: blocks.length > 0, atoms };
|
|
2427
|
+
}
|
|
2428
|
+
function unprunedAtoms(css, emitted) {
|
|
2429
|
+
if (!css.includes("@")) return [];
|
|
2430
|
+
const atoms = /* @__PURE__ */ new Set();
|
|
2431
|
+
const sheet = readSheet(css);
|
|
2432
|
+
for (const { open, close } of layerBlocks(sheet, 0, sheet.tokens.length)) {
|
|
2433
|
+
visitMembers(sheet, open + 1, close, (start, end) => {
|
|
2434
|
+
for (const atom of blockersOf(sheet, start, end, emitted)) atoms.add(atom);
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
return [...atoms].toSorted((a, b) => a.localeCompare(b));
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
// src/vite-restorers.ts
|
|
2441
|
+
function withRestorers(atoms) {
|
|
2442
|
+
if (atoms.has("srOnly")) atoms.add("srOnlyFocusable");
|
|
2443
|
+
return atoms;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
// src/vite-problems.ts
|
|
2447
|
+
var PROBLEM_KINDS = [
|
|
2448
|
+
"argument",
|
|
2449
|
+
"reference",
|
|
2450
|
+
"reexport",
|
|
2451
|
+
"declared",
|
|
2452
|
+
"concatenation",
|
|
2453
|
+
"dynamic",
|
|
2454
|
+
"unknown",
|
|
2455
|
+
"own",
|
|
2456
|
+
"unreadable"
|
|
2457
|
+
];
|
|
2458
|
+
function compareText(a, b) {
|
|
2459
|
+
if (a === b) return 0;
|
|
2460
|
+
return a < b ? -1 : 1;
|
|
2461
|
+
}
|
|
2462
|
+
function cxModulesArray(configured, added) {
|
|
2463
|
+
const extra = [...new Set(added)].filter((entry) => !configured.includes(entry)).toSorted(compareText);
|
|
2464
|
+
if (extra.length === 0) return void 0;
|
|
2465
|
+
return `[${[...configured, ...extra].map((entry) => `'${entry}'`).join(", ")}]`;
|
|
2466
|
+
}
|
|
2467
|
+
function cut(text, limit = 40) {
|
|
2468
|
+
const oneLine = text.replaceAll(/\s+/g, " ");
|
|
2469
|
+
return oneLine.length > limit ? `${oneLine.slice(0, limit)}...` : oneLine;
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
// src/vite-class-map-message.ts
|
|
2473
|
+
var CLASS_MAP_NOT_PARSED = "the module could not be read, so the atoms it names would not ship: it is a CSS Module, and the JavaScript Vite wrote for its class map did not parse. A plugin that runs after Vite's CSS step has changed that JavaScript: have that plugin leave a CSS Module's JavaScript valid.";
|
|
2474
|
+
|
|
2475
|
+
// src/vite-used-take-lines.ts
|
|
2476
|
+
var IDENTIFIER = /^[$\p{ID_Start}_][$\p{ID_Continue}]*$/u;
|
|
2477
|
+
function takenName(name) {
|
|
2478
|
+
if (name === "default") return "the default export";
|
|
2479
|
+
if (IDENTIFIER.test(name)) return name;
|
|
2480
|
+
return `'${name.replaceAll("\\", String.raw`\\`).replaceAll("'", String.raw`\'`)}'`;
|
|
2481
|
+
}
|
|
2482
|
+
function takeWhat(take) {
|
|
2483
|
+
const names = take.names.map((name) => takenName(name)).join(", ");
|
|
2484
|
+
switch (take.shape) {
|
|
2485
|
+
case "dynamic-import": {
|
|
2486
|
+
return names === "" ? "import()" : `import() reading ${names}`;
|
|
2487
|
+
}
|
|
2488
|
+
case "names": {
|
|
2489
|
+
return names;
|
|
2490
|
+
}
|
|
2491
|
+
case "namespace": {
|
|
2492
|
+
return names === "" ? "a namespace import" : `a namespace import reading ${names}`;
|
|
2493
|
+
}
|
|
2494
|
+
case "star": {
|
|
2495
|
+
return "export *";
|
|
2496
|
+
}
|
|
2497
|
+
case "unreadable": {
|
|
2498
|
+
return "a require() or other import the build cannot read";
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
var FIX = " The lasting fix is upstream: import cx from @navecss/core/cx where it is called, and re-export it from there, only under the name cx, in each module that gives it out.";
|
|
2503
|
+
function clausesOf(takes) {
|
|
2504
|
+
const entries = takes.map((take) => ({
|
|
2505
|
+
taker: take.taker,
|
|
2506
|
+
text: `${take.taker} (${takeWhat(take)})`,
|
|
2507
|
+
shape: take.shape
|
|
2508
|
+
})).toSorted((a, b) => compareText(a.taker, b.taker) || compareText(a.text, b.text));
|
|
2509
|
+
const listed = [...new Set(entries.map((entry) => entry.text))].join(", ");
|
|
2510
|
+
const files = new Set(entries.map((entry) => entry.taker)).size === 1 ? "in that file" : "in each of those files";
|
|
2511
|
+
const isWhole = entries.some((entry) => entry.shape !== "names");
|
|
2512
|
+
const wholeClause = isWhole ? "; where a file takes a module whole (a namespace import, export *, import() or an import the build cannot read), import by name what it uses from that module, and cx from @navecss/core/cx" : "";
|
|
2513
|
+
const passedOn = takes.some((take) => take.isPassedOn === true) ? "; where a file re-exports what it takes, import cx from @navecss/core/cx in the files that call it, call cx there in its place, and drop the re-export" : "";
|
|
2514
|
+
return { files, listed, whole: `${wholeClause}${passedOn}` };
|
|
2515
|
+
}
|
|
2516
|
+
function takenLine(pkg, takes, hasPackageFix) {
|
|
2517
|
+
const { files, listed, whole } = clausesOf(takes);
|
|
2518
|
+
const fix = hasPackageFix ? FIX : "";
|
|
2519
|
+
return `${pkg} re-exports cx, and your code takes that cx, from the package or through another package that re-exports it, in ${listed}. The build does not read calls made through what your code takes there, and the keepFor entry stands in only for the package's own calls: ${files}, import cx from @navecss/core/cx instead and call cx in its place${whole}. The build prints no cxModules entry for this, since it found none of these takes made, by an import it can read and a specifier that resolves from Vite's root, from a module that re-exports cx from @navecss/core/cx itself and only under the name cx. Once your code makes none of these takes, the keepFor entry clears this.${fix}`;
|
|
2520
|
+
}
|
|
2521
|
+
function forwardLine(pkg, takes) {
|
|
2522
|
+
const { files, listed, whole } = clausesOf(takes);
|
|
2523
|
+
return `${pkg} re-exports the cx of a module listed in cxModules, and your code takes that cx, from ${pkg} or through another package that re-exports it, in ${listed}. The build follows a listed module one step, so it does not read calls made through what your code takes there: ${files}, import cx from @navecss/core/cx instead and call cx in its place${whole}.${FIX}`;
|
|
2524
|
+
}
|
|
2525
|
+
function callsThroughLine(pkg, callers, home) {
|
|
2526
|
+
const [make, owner, its] = callers.length === 1 ? ["makes", "a dependency's", "its"] : ["make", "dependencies'", "their"];
|
|
2527
|
+
return `${pkg} re-exports the cx of a module listed in cxModules, and the build follows a listed module one step, so it does not read the calls that ${callers.join(", ")} ${make} through that re-export. That code is ${owner}, not yours to change: list the atoms those calls can produce, from ${its} documentation, under the name of ${pkg}, which holds the re-export, in ${home}: keepFor: { '${pkg}': ['<atom>'] }. The lasting fix is upstream: ${pkg} can re-export cx from @navecss/core/cx itself, or the code that calls through it can import cx from there.`;
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
// src/vite-used-package-lines.ts
|
|
2531
|
+
function isListableReexport(problem2) {
|
|
2532
|
+
return problem2.kind === "reexport" && problem2.isListable !== false;
|
|
2533
|
+
}
|
|
2534
|
+
function isRenamedOrReached(problem2) {
|
|
2535
|
+
return problem2.isRenamed === true || problem2.kind === "reexport" && !isListableReexport(problem2);
|
|
2536
|
+
}
|
|
2537
|
+
function isSecondHop(problem2) {
|
|
2538
|
+
return problem2.kind === "reexport" && problem2.isListable === false && problem2.pkg !== void 0;
|
|
2539
|
+
}
|
|
2540
|
+
function callsLine(pkg, problems, entry) {
|
|
2541
|
+
if (problems.every((problem2) => problem2.kind === "own")) {
|
|
2542
|
+
return `${pkg} names atoms of your own, which have no class, so a keepFor entry cannot make its calls produce a Nave class. The fix is the package's: it must name atoms Nave ships.`;
|
|
2543
|
+
}
|
|
2544
|
+
const isOnlyDynamic = problems.every((problem2) => problem2.kind === "dynamic");
|
|
2545
|
+
if (isOnlyDynamic) {
|
|
2546
|
+
const count = problems.length;
|
|
2547
|
+
const places = count === 1 ? "1 place" : `${count} places`;
|
|
2548
|
+
return `${pkg} calls cx.dynamic() in ${places}, and keepFor lists no atoms for it, so none of them applies a class. List the atoms those calls can take, from its documentation, under its name in ${entry}.`;
|
|
2549
|
+
}
|
|
2550
|
+
return `${pkg} is a dependency, so its code is not yours to change. List the atoms its calls can produce, from its documentation, under its name in ${entry}. The lasting fix is the package's: names chosen at run time go through cx.dynamic().`;
|
|
2551
|
+
}
|
|
2552
|
+
var LASTING_FIX = "The lasting fix is the package's: import cx from @navecss/core/cx where it is called, or re-export it from the package's entry.";
|
|
2553
|
+
function listedLine(pkg, specifiers, configured, home) {
|
|
2554
|
+
const array = cxModulesArray(configured, specifiers);
|
|
2555
|
+
const named = specifiers.map((specifier) => `'${specifier}'`).join(", ");
|
|
2556
|
+
const it = specifiers.length === 1 ? "it" : "them";
|
|
2557
|
+
return array === void 0 ? void 0 : `${pkg} re-exports cx in ${named}. List ${it} in ${home}: cxModules: ${array}.`;
|
|
2558
|
+
}
|
|
2559
|
+
function internalLine(pkg, count, entry, hasKeepFor) {
|
|
2560
|
+
if (hasKeepFor) {
|
|
2561
|
+
return `${pkg} also re-exports cx in a file that only the package itself imports; the keepFor entry above clears that too. The build does not read calls made through that cx: where your code imports cx from ${pkg} or one of its subpaths, import it from @navecss/core/cx instead. The lasting fix there is the package's: import cx from @navecss/core/cx where it is called, or re-export it from the package's entry.`;
|
|
2562
|
+
}
|
|
2563
|
+
const [file, them] = count === 1 ? ["a file that only", "it"] : ["files that only", "them"];
|
|
2564
|
+
return `${pkg} re-exports cx in ${file} the package itself imports, so your code has no specifier for ${them} to list in cxModules, and the build does not read calls made through that cx. Where your code imports cx from ${pkg} or one of its subpaths, import it from @navecss/core/cx instead. For the package's own calls, list the atoms they can produce, from its documentation, under its name in ${entry}. ${LASTING_FIX}`;
|
|
2565
|
+
}
|
|
2566
|
+
var RENAMED_FIX = "import cx from @navecss/core/cx where it is called, and re-export it only under the name cx.";
|
|
2567
|
+
var RENAMED_FORM = "other than under the name cx (renamed, as a default or inside a namespace)";
|
|
2568
|
+
function renamedLine(pkg, count, entry, hasKeepFor) {
|
|
2569
|
+
const [those, them, its] = count === 1 ? ["that export", "it", "its"] : ["those exports", "them", "their"];
|
|
2570
|
+
const act = `import cx from @navecss/core/cx instead and call cx in ${its} place`;
|
|
2571
|
+
if (hasKeepFor) {
|
|
2572
|
+
return `${pkg} also re-exports cx ${RENAMED_FORM}, and no cxModules entry clears an export of cx from a module that does, under the name cx or another; the keepFor entry above clears ${those} too. The build does not read calls made through ${them}: where your code imports ${them} from ${pkg} or one of its subpaths, ${act}. The lasting fix there is the package's: ${RENAMED_FIX}`;
|
|
2573
|
+
}
|
|
2574
|
+
return `${pkg} re-exports cx ${RENAMED_FORM}, which the build does not follow even from a module listed in cxModules. Listing a module that does fails the build, so no entry there clears an export of cx from it, under the name cx or another, and the build does not read calls made through ${those}. Where your code imports ${those} from ${pkg} or one of its subpaths, ${act}. For the package's own calls, list the atoms they can produce, from its documentation, under its name in ${entry}. The lasting fix is the package's: ${RENAMED_FIX}`;
|
|
2575
|
+
}
|
|
2576
|
+
function declaredLine(pkg, entries, hasInternal, home) {
|
|
2577
|
+
const named = entries.map((entry) => `'${entry}'`).join(", ");
|
|
2578
|
+
const [is, it, module] = entries.length === 1 ? ["is", "it", "the module"] : ["are", "them", "each module"];
|
|
2579
|
+
const reader = hasInternal ? "" : `, and where your code imports cx from ${it}, import cx from @navecss/core/cx instead`;
|
|
2580
|
+
return `${pkg} exports a cx the build does not follow from ${named}, which ${is} listed in cxModules. Remove ${it} from cxModules in ${home}${reader}. The lasting fix is the package's: make export { cx } from '@navecss/core/cx' the only export of cx in ${module} you list.`;
|
|
2581
|
+
}
|
|
2582
|
+
function withoutRemoved(problems, configured) {
|
|
2583
|
+
const removed = new Set(
|
|
2584
|
+
problems.flatMap(
|
|
2585
|
+
(problem2) => problem2.pkg !== void 0 && problem2.kind === "declared" ? problem2.entries ?? [] : []
|
|
2586
|
+
)
|
|
2587
|
+
);
|
|
2588
|
+
return configured.filter((entry) => !removed.has(entry));
|
|
2589
|
+
}
|
|
2590
|
+
function takeLines(pkg, all, home) {
|
|
2591
|
+
const isTaken = (problem2) => (problem2.takes?.length ?? 0) > 0;
|
|
2592
|
+
const taken = all.filter((problem2) => isTaken(problem2));
|
|
2593
|
+
const plain = taken.filter((problem2) => !isSecondHop(problem2));
|
|
2594
|
+
const hops = taken.filter((problem2) => isSecondHop(problem2));
|
|
2595
|
+
const takes = plain.flatMap((problem2) => problem2.takes);
|
|
2596
|
+
const lines = [];
|
|
2597
|
+
if (takes.length > 0) {
|
|
2598
|
+
const hasPackageFix = plain.some((problem2) => isRenamedOrReached(problem2)) || takes.some((take) => take.isReached);
|
|
2599
|
+
lines.push(takenLine(pkg, takes, hasPackageFix));
|
|
2600
|
+
}
|
|
2601
|
+
if (hops.length > 0)
|
|
2602
|
+
lines.push(
|
|
2603
|
+
forwardLine(
|
|
2604
|
+
pkg,
|
|
2605
|
+
hops.flatMap((problem2) => problem2.takes)
|
|
2606
|
+
)
|
|
2607
|
+
);
|
|
2608
|
+
const callers = all.flatMap((problem2) => problem2.callers ?? []);
|
|
2609
|
+
if (callers.length > 0)
|
|
2610
|
+
lines.push(callsThroughLine(pkg, [...new Set(callers)].toSorted(compareText), home));
|
|
2611
|
+
return lines;
|
|
2612
|
+
}
|
|
2613
|
+
function packageLines(pkg, all, configured, home) {
|
|
2614
|
+
const isTaken = (problem2) => (problem2.takes?.length ?? 0) > 0;
|
|
2615
|
+
const problems = all.filter((problem2) => !isTaken(problem2) && problem2.callers === void 0);
|
|
2616
|
+
const entry = `${home}: keepFor: { '${pkg}': ['<atom>'] }`;
|
|
2617
|
+
const reexports = problems.filter((problem2) => isListableReexport(problem2));
|
|
2618
|
+
const internal = reexports.filter(
|
|
2619
|
+
(problem2) => problem2.specifier === void 0 && problem2.isRenamed !== true
|
|
2620
|
+
);
|
|
2621
|
+
const renamed = reexports.filter((problem2) => problem2.isRenamed === true);
|
|
2622
|
+
const declared = problems.filter((problem2) => problem2.kind === "declared");
|
|
2623
|
+
const rest = problems.filter(
|
|
2624
|
+
(problem2) => !isListableReexport(problem2) && problem2.kind !== "declared" && problem2.text !== CLASS_MAP_NOT_PARSED
|
|
2625
|
+
);
|
|
2626
|
+
const named = [...new Set(reexports.flatMap((problem2) => problem2.specifier ?? []))].toSorted(
|
|
2627
|
+
compareText
|
|
2628
|
+
);
|
|
2629
|
+
const lines = [];
|
|
2630
|
+
if (declared.length > 0) {
|
|
2631
|
+
const entries = [...new Set(declared.flatMap((problem2) => problem2.entries ?? []))];
|
|
2632
|
+
lines.push(declaredLine(pkg, entries.toSorted(compareText), internal.length > 0, home));
|
|
2633
|
+
}
|
|
2634
|
+
if (rest.length > 0) lines.push(callsLine(pkg, rest, entry));
|
|
2635
|
+
const listed = named.length > 0 ? listedLine(pkg, named, configured, home) : void 0;
|
|
2636
|
+
if (listed !== void 0) lines.push(listed);
|
|
2637
|
+
if (internal.length > 0) {
|
|
2638
|
+
const files = new Set(internal.map((problem2) => problem2.file)).size;
|
|
2639
|
+
const hasKeepFor = rest.some((problem2) => problem2.kind !== "own");
|
|
2640
|
+
lines.push(internalLine(pkg, files, entry, hasKeepFor));
|
|
2641
|
+
}
|
|
2642
|
+
if (renamed.length > 0) {
|
|
2643
|
+
const hasKeepFor = rest.some((problem2) => problem2.kind !== "own") || internal.length > 0;
|
|
2644
|
+
lines.push(renamedLine(pkg, renamed.length, entry, hasKeepFor));
|
|
2645
|
+
}
|
|
2646
|
+
lines.push(...takeLines(pkg, all, home));
|
|
2647
|
+
return lines;
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
// src/vite-used-report.ts
|
|
2651
|
+
var LINE_UNKNOWN_WITHOUT_MAP = " (line unknown: this file's compiled code has no source map in this build; with build.sourcemap set in the Vite config, the report gives the line if the source maps then lead back to it)";
|
|
2652
|
+
var LINE_UNKNOWN_UNMAPPED = " (line unknown: no source map leads from the compiled code to this file)";
|
|
2653
|
+
var REPORT_CAUSE = "the build cannot tell which atoms these apply, and it ships only the atoms it can read.";
|
|
2654
|
+
var remedies = (home) => ({
|
|
2655
|
+
argument: [
|
|
2656
|
+
"Name the atoms at the call: a string literal, a const in the same file, or a condition choosing between them, as in cx(on ? 'flex' : 'grid').",
|
|
2657
|
+
"To choose by a value, call cx() once per case and pick between the results: ({ row: cx('flex'), grid: cx('grid') })[variant].",
|
|
2658
|
+
`If the name comes from data the build never sees, write cx.dynamic(name) and list every atom it can take in keep in ${home}.`
|
|
2659
|
+
],
|
|
2660
|
+
reference: [
|
|
2661
|
+
"Call cx() where the classes are applied, with the atom names as its arguments: the build reads calls, not a cx that is assigned, passed or spread."
|
|
2662
|
+
],
|
|
2663
|
+
// Printed by `reexportRemedy`, which names the modules a `cxModules` entry would clear.
|
|
2664
|
+
reexport: [],
|
|
2665
|
+
declared: [
|
|
2666
|
+
"In a module listed in cxModules, make export { cx } from '@navecss/core/cx' its only export of cx, or remove the module from cxModules and import cx from @navecss/core/cx where it is called."
|
|
2667
|
+
],
|
|
2668
|
+
concatenation: [
|
|
2669
|
+
"Write cx() with the atom name, or cx.dynamic() with keep for a name chosen at run time."
|
|
2670
|
+
],
|
|
2671
|
+
dynamic: [`List the atoms those calls can take in keep in ${home}.`],
|
|
2672
|
+
unknown: [],
|
|
2673
|
+
own: [],
|
|
2674
|
+
unreadable: []
|
|
2675
|
+
});
|
|
2676
|
+
function problemLine(problem2) {
|
|
2677
|
+
const where = problem2.unknownLine === void 0 ? `${problem2.file}:${problem2.line}:${problem2.column}: ` : `${problem2.file}: `;
|
|
2678
|
+
const ending = problem2.unknownLine ?? "";
|
|
2679
|
+
if (problem2.construct === "") return `${where}${problem2.text}${ending}`;
|
|
2680
|
+
const construct = cut(problem2.construct);
|
|
2681
|
+
return problem2.text === "" ? `${where}${construct}${ending}` : `${where}${construct}: ${problem2.text}${ending}`;
|
|
2682
|
+
}
|
|
2683
|
+
function reexportRemedy(problems, configured, home) {
|
|
2684
|
+
const modules = problems.filter((problem2) => isListableReexport(problem2)).map((problem2) => problem2.file.startsWith(".") ? problem2.file : `./${problem2.file}`);
|
|
2685
|
+
const array = cxModulesArray(configured, modules);
|
|
2686
|
+
const lines = array === void 0 ? [] : [
|
|
2687
|
+
`To keep a module that re-exports cx, list it in ${home} by its path from the project root: cxModules: ${array}. Files that import cx from it are then read as if they imported it from @navecss/core/cx. Or import cx from @navecss/core/cx directly where it is called.`
|
|
2688
|
+
];
|
|
2689
|
+
if (problems.some((problem2) => problem2.kind === "reexport" && !isListableReexport(problem2))) {
|
|
2690
|
+
lines.push(
|
|
2691
|
+
"Import cx where it is called, from @navecss/core/cx or from a module listed in cxModules, instead of re-exporting the cx of a listed module."
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
return lines;
|
|
2695
|
+
}
|
|
2696
|
+
function applicationLines(application, configured, home) {
|
|
2697
|
+
const fixed = remedies(home);
|
|
2698
|
+
const lines = [];
|
|
2699
|
+
for (const kind of PROBLEM_KINDS) {
|
|
2700
|
+
if (application.every((problem2) => problem2.kind !== kind)) continue;
|
|
2701
|
+
lines.push(
|
|
2702
|
+
...kind === "reexport" ? reexportRemedy(application, configured, home) : fixed[kind]
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
return lines;
|
|
2706
|
+
}
|
|
2707
|
+
function remedyBlock(problems, listed, home, hostRemedies) {
|
|
2708
|
+
const configured = withoutRemoved(problems, listed);
|
|
2709
|
+
const application = problems.filter((problem2) => problem2.pkg === void 0);
|
|
2710
|
+
const lines = [
|
|
2711
|
+
...applicationLines(application, configured, home),
|
|
2712
|
+
...hostRemedies?.(application) ?? []
|
|
2713
|
+
];
|
|
2714
|
+
const byPackage = /* @__PURE__ */ new Map();
|
|
2715
|
+
for (const problem2 of problems) {
|
|
2716
|
+
if (problem2.pkg !== void 0)
|
|
2717
|
+
byPackage.set(problem2.pkg, [...byPackage.get(problem2.pkg) ?? [], problem2]);
|
|
2718
|
+
}
|
|
2719
|
+
for (const pkg of byPackage.keys().toArray().toSorted(compareText)) {
|
|
2720
|
+
lines.push(...packageLines(pkg, byPackage.get(pkg), configured, home));
|
|
2721
|
+
}
|
|
2722
|
+
if (application.some((problem2) => problem2.needsAvailable)) lines.push(availableLine());
|
|
2723
|
+
return lines;
|
|
2724
|
+
}
|
|
2725
|
+
function inReportOrder(problems) {
|
|
2726
|
+
const rank = (problem2) => problem2.pkg === void 0 ? 0 : 1;
|
|
2727
|
+
return problems.toSorted(
|
|
2728
|
+
(a, b) => rank(a) - rank(b) || compareText(a.file, b.file) || Number(a.unknownLine !== void 0) - Number(b.unknownLine !== void 0) || a.line - b.line || a.column - b.column
|
|
2729
|
+
);
|
|
2730
|
+
}
|
|
2731
|
+
function problemLines(problems) {
|
|
2732
|
+
const ordered = inReportOrder(problems);
|
|
2733
|
+
const isApplicationDynamic = (problem2) => problem2.kind === "dynamic" && problem2.pkg === void 0;
|
|
2734
|
+
const application = ordered.filter(
|
|
2735
|
+
(problem2) => problem2.pkg === void 0 && !isApplicationDynamic(problem2)
|
|
2736
|
+
);
|
|
2737
|
+
const dynamic = ordered.filter((problem2) => isApplicationDynamic(problem2));
|
|
2738
|
+
const dependencies = ordered.filter((problem2) => problem2.pkg !== void 0);
|
|
2739
|
+
const lines = application.map((problem2) => problemLine(problem2));
|
|
2740
|
+
if (dynamic.length > 0) {
|
|
2741
|
+
const places = dynamic.length === 1 ? "1 place" : `${dynamic.length} places`;
|
|
2742
|
+
lines.push(
|
|
2743
|
+
`cx.dynamic() is called in ${places} in your code, but keep is empty, so none of them applies a class.`,
|
|
2744
|
+
...dynamic.map((problem2) => problemLine(problem2))
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
return [...lines, ...dependencies.map((problem2) => problemLine(problem2))];
|
|
2748
|
+
}
|
|
2749
|
+
function noun(count, word) {
|
|
2750
|
+
return `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
2751
|
+
}
|
|
2752
|
+
function buildReport(problems, configured, home, hostRemedies) {
|
|
2753
|
+
const files = new Set(problems.map((problem2) => problem2.file)).size;
|
|
2754
|
+
const first2 = `${noun(problems.length, "problem")} in ${noun(files, "file")}: ${REPORT_CAUSE}`;
|
|
2755
|
+
return [
|
|
2756
|
+
first2,
|
|
2757
|
+
...problemLines(problems),
|
|
2758
|
+
...remedyBlock(problems, configured, home, hostRemedies)
|
|
2759
|
+
].join("\n");
|
|
2760
|
+
}
|
|
2761
|
+
function moduleReport(problems, configured, home) {
|
|
2762
|
+
return [...problemLines(problems), ...remedyBlock(problems, configured, home)].join("\n");
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
export { CLASS_MAP_NOT_PARSED, CX_SOURCE, LINE_UNKNOWN_UNMAPPED, LINE_UNKNOWN_WITHOUT_MAP, REPORT_CAUSE, analyze, applyEdits, assertOptions, atomOfClass, atomsWrittenIn, buildReport, childrenOf, combinedMapOf, compareText, cxModulesArray, exportNameOf, inspectAtomicLayer, isListableReexport, isNode, isSecondHop, keptAtoms, memberReadOf, moduleReport, nodeAt, nodesAt, patternDestructuring, placerFor, propertyNameOf, pruneAtomicLayer, pushAll, readModule, resolveUsedOptions, staticStringOf, stringAt, toSourceMap, unprunedAtoms, withRestorers, withoutRemoved };
|