@bamboocss/parser 1.53.0 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +54 -8
- package/dist/index.d.cts +65 -2
- package/dist/index.d.mts +65 -2
- package/dist/index.mjs +54 -8
- package/package.json +11 -11
package/dist/index.cjs
CHANGED
|
@@ -939,6 +939,13 @@ var ParserResult = class {
|
|
|
939
939
|
* `assertNoDeadCalls` rather than warned about, for that reason.
|
|
940
940
|
*/
|
|
941
941
|
deadCalls = [];
|
|
942
|
+
/**
|
|
943
|
+
* Whether each result item is attributed to its call site, for a source map.
|
|
944
|
+
*
|
|
945
|
+
* Off for a source a `parser:before` hook rewrote: its positions are the hook's output's,
|
|
946
|
+
* not the file's, and a wrong line is worse than none.
|
|
947
|
+
*/
|
|
948
|
+
origins = true;
|
|
942
949
|
constructor(context, encoder) {
|
|
943
950
|
this.context = context;
|
|
944
951
|
this.encoder = encoder ?? context.encoder;
|
|
@@ -971,13 +978,26 @@ var ParserResult = class {
|
|
|
971
978
|
const data = result.data;
|
|
972
979
|
const unresolved = findUnresolvedStyles(result, "atomic").filter((entry) => entry.reason === "unenumerable-keys");
|
|
973
980
|
if (unresolved.length) this.unresolved.push(...unresolved);
|
|
974
|
-
data.forEach((obj) => encoder.processAtomic(obj));
|
|
981
|
+
encoder.withOrigin(this.originOf(result), () => data.forEach((obj) => encoder.processAtomic(obj)));
|
|
975
982
|
}
|
|
983
|
+
/** The call site of `result`, when the encoder is recording them. */
|
|
984
|
+
originOf = (result) => {
|
|
985
|
+
if (!this.origins || !this.encoder.recordOrigins) return void 0;
|
|
986
|
+
const node = result.box?.getNode();
|
|
987
|
+
const sourceFile = node?.getSourceFile();
|
|
988
|
+
if (!node || !sourceFile) return void 0;
|
|
989
|
+
const { line, column } = (0, _bamboocss_ts_ast.getLineAndColumnAtPos)(sourceFile, node.getStart());
|
|
990
|
+
return {
|
|
991
|
+
filePath: (0, _bamboocss_ts_ast.pathOf)(sourceFile),
|
|
992
|
+
line,
|
|
993
|
+
column
|
|
994
|
+
};
|
|
995
|
+
};
|
|
976
996
|
setCva(result) {
|
|
977
997
|
this.cva.add(this.append(Object.assign({ type: "cva" }, result)));
|
|
978
998
|
this.reportUnresolvedRecipe(result);
|
|
979
999
|
const encoder = this.encoder;
|
|
980
|
-
result.data.forEach((data) => encoder.processAtomicRecipe(data));
|
|
1000
|
+
encoder.withOrigin(this.originOf(result), () => result.data.forEach((data) => encoder.processAtomicRecipe(data)));
|
|
981
1001
|
}
|
|
982
1002
|
/**
|
|
983
1003
|
* A call of a locally-bound inline recipe -- `const badge = cva(...)`, then `badge({...})`.
|
|
@@ -997,7 +1017,7 @@ var ParserResult = class {
|
|
|
997
1017
|
this.sva.add(this.append(Object.assign({ type: "sva" }, result)));
|
|
998
1018
|
this.reportUnresolvedRecipe(result);
|
|
999
1019
|
const encoder = this.encoder;
|
|
1000
|
-
result.data.forEach((data) => encoder.processAtomicSlotRecipe(data));
|
|
1020
|
+
encoder.withOrigin(this.originOf(result), () => result.data.forEach((data) => encoder.processAtomicSlotRecipe(data)));
|
|
1001
1021
|
}
|
|
1002
1022
|
/**
|
|
1003
1023
|
* Record a recipe config the build could not fully read.
|
|
@@ -1038,7 +1058,7 @@ var ParserResult = class {
|
|
|
1038
1058
|
type: "pattern",
|
|
1039
1059
|
name
|
|
1040
1060
|
}, result)));
|
|
1041
|
-
result.data.forEach((obj) => this.encoder.processPattern(name, obj));
|
|
1061
|
+
this.encoder.withOrigin(this.originOf(result), () => result.data.forEach((obj) => this.encoder.processPattern(name, obj)));
|
|
1042
1062
|
}
|
|
1043
1063
|
/**
|
|
1044
1064
|
* The variant axes a call site passed and the build could not read.
|
|
@@ -1181,13 +1201,14 @@ const fallbackImpl = (...values) => values.some((value) => value === void 0) ? v
|
|
|
1181
1201
|
const evaluateOptions = { environment: defaultEnv };
|
|
1182
1202
|
function createParser(context) {
|
|
1183
1203
|
const { jsx, imports, recipes } = context;
|
|
1184
|
-
return function parse(sourceFile, encoder, options, resolveModule) {
|
|
1204
|
+
return function parse(sourceFile, encoder, options, resolveModule, origins = true) {
|
|
1185
1205
|
if (!sourceFile) return;
|
|
1186
1206
|
const importDeclarations = getImportDeclarations$1(context, sourceFile);
|
|
1187
1207
|
const file = imports.file(importDeclarations);
|
|
1188
1208
|
const filePath = (0, _bamboocss_ts_ast.pathOf)(sourceFile);
|
|
1189
1209
|
_bamboocss_logger.logger.debug("ast:import", !file.isEmpty() ? `Found import { ${file.toString()} } in ${filePath}` : `No import found in ${filePath}`);
|
|
1190
1210
|
const parserResult = new ParserResult(context, encoder);
|
|
1211
|
+
parserResult.origins = origins;
|
|
1191
1212
|
const importedRecipes = resolveModule ? importedRecipeBindings(sourceFile, imports, resolveModule) : /* @__PURE__ */ new Map();
|
|
1192
1213
|
if (file.isEmpty() && !jsx.isEnabled && importedRecipes.size === 0) return parserResult;
|
|
1193
1214
|
parserResult.importedRecipes = importedRecipes;
|
|
@@ -2123,9 +2144,11 @@ var Project = class {
|
|
|
2123
2144
|
for (const { kind, ordinal, plan, specifier } of planned) {
|
|
2124
2145
|
const resolved = this.#completeResolution(plan);
|
|
2125
2146
|
if (!resolved.local) continue;
|
|
2147
|
+
const target = resolved.sourceFile ? this.normalizePath((0, _bamboocss_ts_ast.pathOf)(resolved.sourceFile)) : null;
|
|
2148
|
+
if (target && !specifier.startsWith(".") && !specifier.startsWith("/")) this.#bareSpecifierTargets.set(specifier, target);
|
|
2126
2149
|
facts.push(Object.freeze({
|
|
2127
2150
|
importer,
|
|
2128
|
-
target
|
|
2151
|
+
target,
|
|
2129
2152
|
specifier,
|
|
2130
2153
|
kind,
|
|
2131
2154
|
ordinal
|
|
@@ -2453,6 +2476,29 @@ var Project = class {
|
|
|
2453
2476
|
this.project.addSourceFiles(installed);
|
|
2454
2477
|
this.invalidate(true);
|
|
2455
2478
|
};
|
|
2479
|
+
/**
|
|
2480
|
+
* Whether the project holds this exact path, without reading anything from the compiler.
|
|
2481
|
+
*
|
|
2482
|
+
* Membership is answered from what was installed, so it costs no round trip — which is what
|
|
2483
|
+
* lets the Vite compiler ask it once per module it is handed.
|
|
2484
|
+
*/
|
|
2485
|
+
hasSourceFile = (filePath) => {
|
|
2486
|
+
this.#ensureSourceFiles();
|
|
2487
|
+
return this.project.has(filePath);
|
|
2488
|
+
};
|
|
2489
|
+
/**
|
|
2490
|
+
* Where a bare specifier — a package name — resolved to, the last time any importer asked.
|
|
2491
|
+
*
|
|
2492
|
+
* One answer per specifier rather than per importer, which is an approximation a nested
|
|
2493
|
+
* `node_modules` could defeat; it exists for the Vite compiler to ask, of a module it has
|
|
2494
|
+
* not parsed, whether a package it imports is one the project holds a source of.
|
|
2495
|
+
*/
|
|
2496
|
+
bareSpecifierTarget = (specifier) => this.#bareSpecifierTargets.get(specifier);
|
|
2497
|
+
/** @internal The revision every importer's cached resolution facts are checked against. */
|
|
2498
|
+
get fileTreeRevision() {
|
|
2499
|
+
return this.#fileTreeRevision;
|
|
2500
|
+
}
|
|
2501
|
+
#bareSpecifierTargets = /* @__PURE__ */ new Map();
|
|
2456
2502
|
addSourceFile = (filePath, content, options = {}) => {
|
|
2457
2503
|
this.#assertNotLoading();
|
|
2458
2504
|
this.#ensureSourceFiles();
|
|
@@ -2485,7 +2531,7 @@ var Project = class {
|
|
|
2485
2531
|
}
|
|
2486
2532
|
this.invalidateSourcePreparation(filePath, existing);
|
|
2487
2533
|
this.removedSourcePaths.delete(this.normalizePath(filePath));
|
|
2488
|
-
this.invalidate(!existing, (0, _bamboocss_ts_ast.pathOf)(existing));
|
|
2534
|
+
this.invalidate(!existing && !options.auxiliary, existing ? (0, _bamboocss_ts_ast.pathOf)(existing) : options.auxiliary ? filePath : void 0);
|
|
2489
2535
|
const sourceFile = this.project.createSourceFile(filePath, content, { scriptKind: scriptKindFor(filePath) });
|
|
2490
2536
|
if (!sourceFile) throw new Error(`bamboo: could not add ${filePath} to the project`);
|
|
2491
2537
|
this.markAuxiliary((0, _bamboocss_ts_ast.pathOf)(sourceFile), options.auxiliary);
|
|
@@ -2587,7 +2633,7 @@ var Project = class {
|
|
|
2587
2633
|
const prepared = this.prepareEffectiveSource(filePath, sourceFile, hookFilePath);
|
|
2588
2634
|
const parserOptions = prepared.options;
|
|
2589
2635
|
sourceFile = prepared.sourceFile ?? sourceFile;
|
|
2590
|
-
const result = (encoder ?? this.options.parserOptions.encoder).withOwner("parse", (0, _bamboocss_ts_ast.pathOf)(sourceFile), () => this.parser(sourceFile, encoder, parserOptions, this.resolveModule))?.setFilePath(filePath);
|
|
2636
|
+
const result = (encoder ?? this.options.parserOptions.encoder).withOwner("parse", (0, _bamboocss_ts_ast.pathOf)(sourceFile), () => this.parser(sourceFile, encoder, parserOptions, this.resolveModule, prepared.effectiveText === prepared.inputText))?.setFilePath(filePath);
|
|
2591
2637
|
hooks["parser:after"]?.({
|
|
2592
2638
|
filePath: hookFilePath,
|
|
2593
2639
|
result
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, DeadImport, ParserOptions, StyleDecoder, Stylesheet } from "@bamboocss/core";
|
|
1
|
+
import { AtomOrigin, Context, DeadImport, ParserOptions, StyleDecoder, Stylesheet } from "@bamboocss/core";
|
|
2
2
|
import { ArtifactId, BambooHooks, ConfigTsOptions, CssArtifactType, LoadConfigResult, ParserResultConfigureOptions, ParserResultInterface, ResultItem, Runtime, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
|
|
3
3
|
import { CompilerOptions, Project as Project$1, ProjectOptions as ProjectOptions$1, SourceFile } from "@bamboocss/ts-ast";
|
|
4
4
|
import { ResolveModule } from "@bamboocss/extractor";
|
|
@@ -134,6 +134,13 @@ declare class Generator extends Context {
|
|
|
134
134
|
*/
|
|
135
135
|
private getAlwaysKeptTokenVars;
|
|
136
136
|
getParserCss: (decoder: StyleDecoder) => string;
|
|
137
|
+
/**
|
|
138
|
+
* Each atom's first call site, by the class name the sheet writes it under.
|
|
139
|
+
*
|
|
140
|
+
* Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
|
|
141
|
+
* integration asked for origins. Several hashes can decode to one class; the first wins.
|
|
142
|
+
*/
|
|
143
|
+
getAtomOrigins: () => Map<string, AtomOrigin>;
|
|
137
144
|
getCss: (stylesheet?: Stylesheet) => string;
|
|
138
145
|
/**
|
|
139
146
|
* Fail on a style value shaped like a token path that names no token.
|
|
@@ -195,6 +202,34 @@ declare class Generator extends Context {
|
|
|
195
202
|
*/
|
|
196
203
|
reportRawValues: () => void;
|
|
197
204
|
assertNoUnresolvedTokens: () => void;
|
|
205
|
+
/**
|
|
206
|
+
* The findings `warn` has already printed, keyed `property:value`.
|
|
207
|
+
*
|
|
208
|
+
* A dev server emits the sheet on every edit, and extraction is additive within a watch, so
|
|
209
|
+
* a finding that warned on every rebuild would bury the edit that introduced the next one.
|
|
210
|
+
* Per process, like the sheet it describes.
|
|
211
|
+
*/
|
|
212
|
+
private reportedInvalidDeclarations;
|
|
213
|
+
/**
|
|
214
|
+
* Report every declaration in the sheet just emitted that its property's grammar rejects.
|
|
215
|
+
*
|
|
216
|
+
* The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
|
|
217
|
+
* for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
|
|
218
|
+
* has had its say — which is the only place a transform that handed a value through
|
|
219
|
+
* unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
|
|
220
|
+
* `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
|
|
221
|
+
* emitted.
|
|
222
|
+
*
|
|
223
|
+
* A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
|
|
224
|
+
* one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
|
|
225
|
+
* value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
|
|
226
|
+
* would otherwise be rejected again here as the declaration it became. Keyed on the
|
|
227
|
+
* property the utility *emits*, because that is how the sheet spells it.
|
|
228
|
+
*
|
|
229
|
+
* `warn` reports each distinct declaration once per process. `error` lists everything the
|
|
230
|
+
* sheet holds each time, because each time the build is failing on it.
|
|
231
|
+
*/
|
|
232
|
+
reportInvalidDeclarations: (sheet: Stylesheet) => void;
|
|
198
233
|
/**
|
|
199
234
|
* Get CSS for a specific layer from the stylesheet
|
|
200
235
|
*/
|
|
@@ -298,10 +333,19 @@ declare class ParserResult implements ParserResultInterface {
|
|
|
298
333
|
* `assertNoDeadCalls` rather than warned about, for that reason.
|
|
299
334
|
*/
|
|
300
335
|
deadCalls: DeadImport[];
|
|
336
|
+
/**
|
|
337
|
+
* Whether each result item is attributed to its call site, for a source map.
|
|
338
|
+
*
|
|
339
|
+
* Off for a source a `parser:before` hook rewrote: its positions are the hook's output's,
|
|
340
|
+
* not the file's, and a wrong line is worse than none.
|
|
341
|
+
*/
|
|
342
|
+
origins: boolean;
|
|
301
343
|
constructor(context: ParserOptions, encoder?: ParserOptions['encoder']);
|
|
302
344
|
append(result: ResultItem): ResultItem;
|
|
303
345
|
set(name: 'cva' | 'css' | 'sva' | 'token', result: ResultItem): void;
|
|
304
346
|
setCss(result: ResultItem): void;
|
|
347
|
+
/** The call site of `result`, when the encoder is recording them. */
|
|
348
|
+
private originOf;
|
|
305
349
|
setCva(result: ResultItem): void;
|
|
306
350
|
/**
|
|
307
351
|
* A call of a locally-bound inline recipe -- `const badge = cva(...)`, then `badge({...})`.
|
|
@@ -400,7 +444,9 @@ declare function createParser(context: ParserOptions): (sourceFile: SourceFile |
|
|
|
400
444
|
* recipe declared in another module stays invisible exactly as before.
|
|
401
445
|
*/
|
|
402
446
|
|
|
403
|
-
resolveModule?: ResolveModule
|
|
447
|
+
resolveModule?: ResolveModule, /** Whether result items may be attributed to their call site. @see `ParserResult.origins` */
|
|
448
|
+
|
|
449
|
+
origins?: boolean) => ParserResult | undefined;
|
|
404
450
|
//#endregion
|
|
405
451
|
//#region src/project.d.ts
|
|
406
452
|
interface ProjectOptions extends ProjectOptions$1 {
|
|
@@ -654,6 +700,23 @@ declare class Project {
|
|
|
654
700
|
* that, and a caller that wants a file *extracted* puts it in `include`.
|
|
655
701
|
*/
|
|
656
702
|
addSourceFiles: (entries: Iterable<readonly [string, string]>) => void;
|
|
703
|
+
/**
|
|
704
|
+
* Whether the project holds this exact path, without reading anything from the compiler.
|
|
705
|
+
*
|
|
706
|
+
* Membership is answered from what was installed, so it costs no round trip — which is what
|
|
707
|
+
* lets the Vite compiler ask it once per module it is handed.
|
|
708
|
+
*/
|
|
709
|
+
hasSourceFile: (filePath: string) => boolean;
|
|
710
|
+
/**
|
|
711
|
+
* Where a bare specifier — a package name — resolved to, the last time any importer asked.
|
|
712
|
+
*
|
|
713
|
+
* One answer per specifier rather than per importer, which is an approximation a nested
|
|
714
|
+
* `node_modules` could defeat; it exists for the Vite compiler to ask, of a module it has
|
|
715
|
+
* not parsed, whether a package it imports is one the project holds a source of.
|
|
716
|
+
*/
|
|
717
|
+
bareSpecifierTarget: (specifier: string) => string | undefined;
|
|
718
|
+
/** @internal The revision every importer's cached resolution facts are checked against. */
|
|
719
|
+
get fileTreeRevision(): number;
|
|
657
720
|
addSourceFile: (filePath: string, content: string, options?: AddSourceFileOptions) => SourceFile;
|
|
658
721
|
/** Claim or release compiler ownership of one source, in the ledger's own spelling. */
|
|
659
722
|
private markAuxiliary;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CompilerOptions, Project as Project$1, ProjectOptions as ProjectOptions$1, SourceFile } from "@bamboocss/ts-ast";
|
|
2
2
|
import { ResolveModule } from "@bamboocss/extractor";
|
|
3
|
-
import { Context, DeadImport, ParserOptions, StyleDecoder, Stylesheet } from "@bamboocss/core";
|
|
3
|
+
import { AtomOrigin, Context, DeadImport, ParserOptions, StyleDecoder, Stylesheet } from "@bamboocss/core";
|
|
4
4
|
import { ArtifactId, BambooHooks, ConfigTsOptions, CssArtifactType, LoadConfigResult, ParserResultConfigureOptions, ParserResultInterface, ResultItem, Runtime, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
|
|
5
5
|
|
|
6
6
|
//#region ../generator/dist/index.d.cts
|
|
@@ -134,6 +134,13 @@ declare class Generator extends Context {
|
|
|
134
134
|
*/
|
|
135
135
|
private getAlwaysKeptTokenVars;
|
|
136
136
|
getParserCss: (decoder: StyleDecoder) => string;
|
|
137
|
+
/**
|
|
138
|
+
* Each atom's first call site, by the class name the sheet writes it under.
|
|
139
|
+
*
|
|
140
|
+
* Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
|
|
141
|
+
* integration asked for origins. Several hashes can decode to one class; the first wins.
|
|
142
|
+
*/
|
|
143
|
+
getAtomOrigins: () => Map<string, AtomOrigin>;
|
|
137
144
|
getCss: (stylesheet?: Stylesheet) => string;
|
|
138
145
|
/**
|
|
139
146
|
* Fail on a style value shaped like a token path that names no token.
|
|
@@ -195,6 +202,34 @@ declare class Generator extends Context {
|
|
|
195
202
|
*/
|
|
196
203
|
reportRawValues: () => void;
|
|
197
204
|
assertNoUnresolvedTokens: () => void;
|
|
205
|
+
/**
|
|
206
|
+
* The findings `warn` has already printed, keyed `property:value`.
|
|
207
|
+
*
|
|
208
|
+
* A dev server emits the sheet on every edit, and extraction is additive within a watch, so
|
|
209
|
+
* a finding that warned on every rebuild would bury the edit that introduced the next one.
|
|
210
|
+
* Per process, like the sheet it describes.
|
|
211
|
+
*/
|
|
212
|
+
private reportedInvalidDeclarations;
|
|
213
|
+
/**
|
|
214
|
+
* Report every declaration in the sheet just emitted that its property's grammar rejects.
|
|
215
|
+
*
|
|
216
|
+
* The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
|
|
217
|
+
* for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
|
|
218
|
+
* has had its say — which is the only place a transform that handed a value through
|
|
219
|
+
* unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
|
|
220
|
+
* `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
|
|
221
|
+
* emitted.
|
|
222
|
+
*
|
|
223
|
+
* A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
|
|
224
|
+
* one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
|
|
225
|
+
* value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
|
|
226
|
+
* would otherwise be rejected again here as the declaration it became. Keyed on the
|
|
227
|
+
* property the utility *emits*, because that is how the sheet spells it.
|
|
228
|
+
*
|
|
229
|
+
* `warn` reports each distinct declaration once per process. `error` lists everything the
|
|
230
|
+
* sheet holds each time, because each time the build is failing on it.
|
|
231
|
+
*/
|
|
232
|
+
reportInvalidDeclarations: (sheet: Stylesheet) => void;
|
|
198
233
|
/**
|
|
199
234
|
* Get CSS for a specific layer from the stylesheet
|
|
200
235
|
*/
|
|
@@ -298,10 +333,19 @@ declare class ParserResult implements ParserResultInterface {
|
|
|
298
333
|
* `assertNoDeadCalls` rather than warned about, for that reason.
|
|
299
334
|
*/
|
|
300
335
|
deadCalls: DeadImport[];
|
|
336
|
+
/**
|
|
337
|
+
* Whether each result item is attributed to its call site, for a source map.
|
|
338
|
+
*
|
|
339
|
+
* Off for a source a `parser:before` hook rewrote: its positions are the hook's output's,
|
|
340
|
+
* not the file's, and a wrong line is worse than none.
|
|
341
|
+
*/
|
|
342
|
+
origins: boolean;
|
|
301
343
|
constructor(context: ParserOptions, encoder?: ParserOptions['encoder']);
|
|
302
344
|
append(result: ResultItem): ResultItem;
|
|
303
345
|
set(name: 'cva' | 'css' | 'sva' | 'token', result: ResultItem): void;
|
|
304
346
|
setCss(result: ResultItem): void;
|
|
347
|
+
/** The call site of `result`, when the encoder is recording them. */
|
|
348
|
+
private originOf;
|
|
305
349
|
setCva(result: ResultItem): void;
|
|
306
350
|
/**
|
|
307
351
|
* A call of a locally-bound inline recipe -- `const badge = cva(...)`, then `badge({...})`.
|
|
@@ -400,7 +444,9 @@ declare function createParser(context: ParserOptions): (sourceFile: SourceFile |
|
|
|
400
444
|
* recipe declared in another module stays invisible exactly as before.
|
|
401
445
|
*/
|
|
402
446
|
|
|
403
|
-
resolveModule?: ResolveModule
|
|
447
|
+
resolveModule?: ResolveModule, /** Whether result items may be attributed to their call site. @see `ParserResult.origins` */
|
|
448
|
+
|
|
449
|
+
origins?: boolean) => ParserResult | undefined;
|
|
404
450
|
//#endregion
|
|
405
451
|
//#region src/project.d.ts
|
|
406
452
|
interface ProjectOptions extends ProjectOptions$1 {
|
|
@@ -654,6 +700,23 @@ declare class Project {
|
|
|
654
700
|
* that, and a caller that wants a file *extracted* puts it in `include`.
|
|
655
701
|
*/
|
|
656
702
|
addSourceFiles: (entries: Iterable<readonly [string, string]>) => void;
|
|
703
|
+
/**
|
|
704
|
+
* Whether the project holds this exact path, without reading anything from the compiler.
|
|
705
|
+
*
|
|
706
|
+
* Membership is answered from what was installed, so it costs no round trip — which is what
|
|
707
|
+
* lets the Vite compiler ask it once per module it is handed.
|
|
708
|
+
*/
|
|
709
|
+
hasSourceFile: (filePath: string) => boolean;
|
|
710
|
+
/**
|
|
711
|
+
* Where a bare specifier — a package name — resolved to, the last time any importer asked.
|
|
712
|
+
*
|
|
713
|
+
* One answer per specifier rather than per importer, which is an approximation a nested
|
|
714
|
+
* `node_modules` could defeat; it exists for the Vite compiler to ask, of a module it has
|
|
715
|
+
* not parsed, whether a package it imports is one the project holds a source of.
|
|
716
|
+
*/
|
|
717
|
+
bareSpecifierTarget: (specifier: string) => string | undefined;
|
|
718
|
+
/** @internal The revision every importer's cached resolution facts are checked against. */
|
|
719
|
+
get fileTreeRevision(): number;
|
|
657
720
|
addSourceFile: (filePath: string, content: string, options?: AddSourceFileOptions) => SourceFile;
|
|
658
721
|
/** Claim or release compiler ownership of one source, in the ledger's own spelling. */
|
|
659
722
|
private markAuxiliary;
|
package/dist/index.mjs
CHANGED
|
@@ -938,6 +938,13 @@ var ParserResult = class {
|
|
|
938
938
|
* `assertNoDeadCalls` rather than warned about, for that reason.
|
|
939
939
|
*/
|
|
940
940
|
deadCalls = [];
|
|
941
|
+
/**
|
|
942
|
+
* Whether each result item is attributed to its call site, for a source map.
|
|
943
|
+
*
|
|
944
|
+
* Off for a source a `parser:before` hook rewrote: its positions are the hook's output's,
|
|
945
|
+
* not the file's, and a wrong line is worse than none.
|
|
946
|
+
*/
|
|
947
|
+
origins = true;
|
|
941
948
|
constructor(context, encoder) {
|
|
942
949
|
this.context = context;
|
|
943
950
|
this.encoder = encoder ?? context.encoder;
|
|
@@ -970,13 +977,26 @@ var ParserResult = class {
|
|
|
970
977
|
const data = result.data;
|
|
971
978
|
const unresolved = findUnresolvedStyles(result, "atomic").filter((entry) => entry.reason === "unenumerable-keys");
|
|
972
979
|
if (unresolved.length) this.unresolved.push(...unresolved);
|
|
973
|
-
data.forEach((obj) => encoder.processAtomic(obj));
|
|
980
|
+
encoder.withOrigin(this.originOf(result), () => data.forEach((obj) => encoder.processAtomic(obj)));
|
|
974
981
|
}
|
|
982
|
+
/** The call site of `result`, when the encoder is recording them. */
|
|
983
|
+
originOf = (result) => {
|
|
984
|
+
if (!this.origins || !this.encoder.recordOrigins) return void 0;
|
|
985
|
+
const node = result.box?.getNode();
|
|
986
|
+
const sourceFile = node?.getSourceFile();
|
|
987
|
+
if (!node || !sourceFile) return void 0;
|
|
988
|
+
const { line, column } = getLineAndColumnAtPos(sourceFile, node.getStart());
|
|
989
|
+
return {
|
|
990
|
+
filePath: pathOf(sourceFile),
|
|
991
|
+
line,
|
|
992
|
+
column
|
|
993
|
+
};
|
|
994
|
+
};
|
|
975
995
|
setCva(result) {
|
|
976
996
|
this.cva.add(this.append(Object.assign({ type: "cva" }, result)));
|
|
977
997
|
this.reportUnresolvedRecipe(result);
|
|
978
998
|
const encoder = this.encoder;
|
|
979
|
-
result.data.forEach((data) => encoder.processAtomicRecipe(data));
|
|
999
|
+
encoder.withOrigin(this.originOf(result), () => result.data.forEach((data) => encoder.processAtomicRecipe(data)));
|
|
980
1000
|
}
|
|
981
1001
|
/**
|
|
982
1002
|
* A call of a locally-bound inline recipe -- `const badge = cva(...)`, then `badge({...})`.
|
|
@@ -996,7 +1016,7 @@ var ParserResult = class {
|
|
|
996
1016
|
this.sva.add(this.append(Object.assign({ type: "sva" }, result)));
|
|
997
1017
|
this.reportUnresolvedRecipe(result);
|
|
998
1018
|
const encoder = this.encoder;
|
|
999
|
-
result.data.forEach((data) => encoder.processAtomicSlotRecipe(data));
|
|
1019
|
+
encoder.withOrigin(this.originOf(result), () => result.data.forEach((data) => encoder.processAtomicSlotRecipe(data)));
|
|
1000
1020
|
}
|
|
1001
1021
|
/**
|
|
1002
1022
|
* Record a recipe config the build could not fully read.
|
|
@@ -1037,7 +1057,7 @@ var ParserResult = class {
|
|
|
1037
1057
|
type: "pattern",
|
|
1038
1058
|
name
|
|
1039
1059
|
}, result)));
|
|
1040
|
-
result.data.forEach((obj) => this.encoder.processPattern(name, obj));
|
|
1060
|
+
this.encoder.withOrigin(this.originOf(result), () => result.data.forEach((obj) => this.encoder.processPattern(name, obj)));
|
|
1041
1061
|
}
|
|
1042
1062
|
/**
|
|
1043
1063
|
* The variant axes a call site passed and the build could not read.
|
|
@@ -1180,13 +1200,14 @@ const fallbackImpl = (...values) => values.some((value) => value === void 0) ? v
|
|
|
1180
1200
|
const evaluateOptions = { environment: defaultEnv };
|
|
1181
1201
|
function createParser(context) {
|
|
1182
1202
|
const { jsx, imports, recipes } = context;
|
|
1183
|
-
return function parse(sourceFile, encoder, options, resolveModule) {
|
|
1203
|
+
return function parse(sourceFile, encoder, options, resolveModule, origins = true) {
|
|
1184
1204
|
if (!sourceFile) return;
|
|
1185
1205
|
const importDeclarations = getImportDeclarations$1(context, sourceFile);
|
|
1186
1206
|
const file = imports.file(importDeclarations);
|
|
1187
1207
|
const filePath = pathOf(sourceFile);
|
|
1188
1208
|
logger.debug("ast:import", !file.isEmpty() ? `Found import { ${file.toString()} } in ${filePath}` : `No import found in ${filePath}`);
|
|
1189
1209
|
const parserResult = new ParserResult(context, encoder);
|
|
1210
|
+
parserResult.origins = origins;
|
|
1190
1211
|
const importedRecipes = resolveModule ? importedRecipeBindings(sourceFile, imports, resolveModule) : /* @__PURE__ */ new Map();
|
|
1191
1212
|
if (file.isEmpty() && !jsx.isEnabled && importedRecipes.size === 0) return parserResult;
|
|
1192
1213
|
parserResult.importedRecipes = importedRecipes;
|
|
@@ -2122,9 +2143,11 @@ var Project = class {
|
|
|
2122
2143
|
for (const { kind, ordinal, plan, specifier } of planned) {
|
|
2123
2144
|
const resolved = this.#completeResolution(plan);
|
|
2124
2145
|
if (!resolved.local) continue;
|
|
2146
|
+
const target = resolved.sourceFile ? this.normalizePath(pathOf(resolved.sourceFile)) : null;
|
|
2147
|
+
if (target && !specifier.startsWith(".") && !specifier.startsWith("/")) this.#bareSpecifierTargets.set(specifier, target);
|
|
2125
2148
|
facts.push(Object.freeze({
|
|
2126
2149
|
importer,
|
|
2127
|
-
target
|
|
2150
|
+
target,
|
|
2128
2151
|
specifier,
|
|
2129
2152
|
kind,
|
|
2130
2153
|
ordinal
|
|
@@ -2452,6 +2475,29 @@ var Project = class {
|
|
|
2452
2475
|
this.project.addSourceFiles(installed);
|
|
2453
2476
|
this.invalidate(true);
|
|
2454
2477
|
};
|
|
2478
|
+
/**
|
|
2479
|
+
* Whether the project holds this exact path, without reading anything from the compiler.
|
|
2480
|
+
*
|
|
2481
|
+
* Membership is answered from what was installed, so it costs no round trip — which is what
|
|
2482
|
+
* lets the Vite compiler ask it once per module it is handed.
|
|
2483
|
+
*/
|
|
2484
|
+
hasSourceFile = (filePath) => {
|
|
2485
|
+
this.#ensureSourceFiles();
|
|
2486
|
+
return this.project.has(filePath);
|
|
2487
|
+
};
|
|
2488
|
+
/**
|
|
2489
|
+
* Where a bare specifier — a package name — resolved to, the last time any importer asked.
|
|
2490
|
+
*
|
|
2491
|
+
* One answer per specifier rather than per importer, which is an approximation a nested
|
|
2492
|
+
* `node_modules` could defeat; it exists for the Vite compiler to ask, of a module it has
|
|
2493
|
+
* not parsed, whether a package it imports is one the project holds a source of.
|
|
2494
|
+
*/
|
|
2495
|
+
bareSpecifierTarget = (specifier) => this.#bareSpecifierTargets.get(specifier);
|
|
2496
|
+
/** @internal The revision every importer's cached resolution facts are checked against. */
|
|
2497
|
+
get fileTreeRevision() {
|
|
2498
|
+
return this.#fileTreeRevision;
|
|
2499
|
+
}
|
|
2500
|
+
#bareSpecifierTargets = /* @__PURE__ */ new Map();
|
|
2455
2501
|
addSourceFile = (filePath, content, options = {}) => {
|
|
2456
2502
|
this.#assertNotLoading();
|
|
2457
2503
|
this.#ensureSourceFiles();
|
|
@@ -2484,7 +2530,7 @@ var Project = class {
|
|
|
2484
2530
|
}
|
|
2485
2531
|
this.invalidateSourcePreparation(filePath, existing);
|
|
2486
2532
|
this.removedSourcePaths.delete(this.normalizePath(filePath));
|
|
2487
|
-
this.invalidate(!existing, pathOf(existing));
|
|
2533
|
+
this.invalidate(!existing && !options.auxiliary, existing ? pathOf(existing) : options.auxiliary ? filePath : void 0);
|
|
2488
2534
|
const sourceFile = this.project.createSourceFile(filePath, content, { scriptKind: scriptKindFor(filePath) });
|
|
2489
2535
|
if (!sourceFile) throw new Error(`bamboo: could not add ${filePath} to the project`);
|
|
2490
2536
|
this.markAuxiliary(pathOf(sourceFile), options.auxiliary);
|
|
@@ -2586,7 +2632,7 @@ var Project = class {
|
|
|
2586
2632
|
const prepared = this.prepareEffectiveSource(filePath, sourceFile, hookFilePath);
|
|
2587
2633
|
const parserOptions = prepared.options;
|
|
2588
2634
|
sourceFile = prepared.sourceFile ?? sourceFile;
|
|
2589
|
-
const result = (encoder ?? this.options.parserOptions.encoder).withOwner("parse", pathOf(sourceFile), () => this.parser(sourceFile, encoder, parserOptions, this.resolveModule))?.setFilePath(filePath);
|
|
2635
|
+
const result = (encoder ?? this.options.parserOptions.encoder).withOwner("parse", pathOf(sourceFile), () => this.parser(sourceFile, encoder, parserOptions, this.resolveModule, prepared.effectiveText === prepared.inputText))?.setFilePath(filePath);
|
|
2590
2636
|
hooks["parser:after"]?.({
|
|
2591
2637
|
filePath: hookFilePath,
|
|
2592
2638
|
result
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/parser",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.54.0",
|
|
4
4
|
"description": "The static parser for bamboo css",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,20 +33,20 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"ts-pattern": "5.9.0",
|
|
36
|
-
"@bamboocss/config": "^1.
|
|
37
|
-
"@bamboocss/core": "^1.
|
|
38
|
-
"@bamboocss/extractor": "1.
|
|
39
|
-
"@bamboocss/logger": "1.
|
|
40
|
-
"@bamboocss/shared": "1.
|
|
41
|
-
"@bamboocss/ts-ast": "1.
|
|
42
|
-
"@bamboocss/types": "1.
|
|
36
|
+
"@bamboocss/config": "^1.54.0",
|
|
37
|
+
"@bamboocss/core": "^1.54.0",
|
|
38
|
+
"@bamboocss/extractor": "1.54.0",
|
|
39
|
+
"@bamboocss/logger": "1.54.0",
|
|
40
|
+
"@bamboocss/shared": "1.54.0",
|
|
41
|
+
"@bamboocss/ts-ast": "1.54.0",
|
|
42
|
+
"@bamboocss/types": "1.54.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@typescript/api": "npm:typescript@7.1.0-dev.20260826.1",
|
|
46
46
|
"ts-morph": "28.0.0",
|
|
47
|
-
"@bamboocss/generator": "1.
|
|
48
|
-
"@bamboocss/plugin-svelte": "1.
|
|
49
|
-
"@bamboocss/plugin-vue": "1.
|
|
47
|
+
"@bamboocss/generator": "1.54.0",
|
|
48
|
+
"@bamboocss/plugin-svelte": "1.54.0",
|
|
49
|
+
"@bamboocss/plugin-vue": "1.54.0"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsdown src/index.ts --format=esm,cjs --dts",
|