@bamboocss/vite 1.25.0 → 1.28.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 +382 -42
- package/dist/index.d.cts +102 -2
- package/dist/index.d.mts +101 -3
- package/dist/index.mjs +382 -42
- package/package.json +9 -9
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
2
|
import { Context } from "@bamboocss/core";
|
|
3
|
-
import { Dict, ParserResultInterface } from "@bamboocss/types";
|
|
3
|
+
import { Dict, ParserResultInterface, ResultItem } from "@bamboocss/types";
|
|
4
4
|
import MagicString from "magic-string";
|
|
5
|
+
import { SourceFile } from "ts-morph";
|
|
6
|
+
|
|
5
7
|
//#region src/css.d.ts
|
|
6
8
|
/**
|
|
7
9
|
* What a project imports to get the stylesheet.
|
|
@@ -30,6 +32,49 @@ interface BambooCssPluginOptions {
|
|
|
30
32
|
*/
|
|
31
33
|
declare const bamboocssCss: (options?: BambooCssPluginOptions) => Plugin;
|
|
32
34
|
//#endregion
|
|
35
|
+
//#region src/fold-recipe.d.ts
|
|
36
|
+
/**
|
|
37
|
+
* Lowering a call of an inline recipe to the class string it produces.
|
|
38
|
+
*
|
|
39
|
+
* The prize is not the `cva` runtime, which is small. It is the *config*: `cva({ base, variants })`
|
|
40
|
+
* ships the whole style object to the browser purely so the runtime can hash it into a name and
|
|
41
|
+
* pick classes off it. Those styles are already in the stylesheet. Once every call of a binding
|
|
42
|
+
* is lowered, the binding is unreferenced and a bundler drops the config with it — measured at
|
|
43
|
+
* 81 kB gzipped across one application's 1,297 inline recipes, against 4.5 kB for the runtime.
|
|
44
|
+
*
|
|
45
|
+
* Correct by construction rather than by a matching reimplementation: the class names come from
|
|
46
|
+
* `getRecipeIdentity` and `getRecipeClassNames`, the same functions the browser runs, and the
|
|
47
|
+
* prefixing and hashing from `classFormatter`, which is what the encoder emitted rules under.
|
|
48
|
+
*/
|
|
49
|
+
type Dict$1 = Record<string, unknown>;
|
|
50
|
+
/** A recipe's config, as the extractor resolved it. */
|
|
51
|
+
interface RecipeConfig {
|
|
52
|
+
className?: string;
|
|
53
|
+
base?: Dict$1;
|
|
54
|
+
variants?: Record<string, Record<string, unknown>>;
|
|
55
|
+
defaultVariants?: Record<string, unknown>;
|
|
56
|
+
compoundVariants?: unknown[];
|
|
57
|
+
/** Present on a slot recipe, which resolves to one class per slot rather than a string. */
|
|
58
|
+
slots?: unknown;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A recipe the fold can lower against.
|
|
62
|
+
*
|
|
63
|
+
* `name` is hashed once here rather than per call site: `getRecipeIdentity` serialises the
|
|
64
|
+
* whole config to hash it, which measured as 91% of the per-call work when it sat inside
|
|
65
|
+
* `lowerRecipeCall`. The runtime does it once per `cva()` for the same reason.
|
|
66
|
+
*
|
|
67
|
+
* `box` is the *definition's* node, carried so the fold can register the module the config
|
|
68
|
+
* came from as a watch dependency. Without it, editing a config in another module leaves
|
|
69
|
+
* every literal folded against it stale — the stylesheet gets a new identity and the element
|
|
70
|
+
* keeps the old class.
|
|
71
|
+
*/
|
|
72
|
+
interface RecipeEntry {
|
|
73
|
+
config: RecipeConfig;
|
|
74
|
+
name: string;
|
|
75
|
+
box: ResultItem['box'];
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
33
78
|
//#region src/runtime-css.d.ts
|
|
34
79
|
/**
|
|
35
80
|
* The generated runtime's `css`, rebuilt in-process from a resolved context.
|
|
@@ -60,7 +105,7 @@ declare const createRuntimeCss: (ctx: Context) => RuntimeCss;
|
|
|
60
105
|
* Why a call site was left alone. Surfaced through `panda`-style diagnostics so a
|
|
61
106
|
* user can tell the difference between "this folded" and "this silently didn't".
|
|
62
107
|
*/
|
|
63
|
-
type SkipReason = 'dynamic' | 'raw-call' | 'not-foldable' | 'recipe-call' | 'unsupported-kind' | 'not-imported' | 'no-call-expression' | 'overlapping' | 'empty' | 'unresolved-token';
|
|
108
|
+
type SkipReason = 'dynamic' | 'raw-call' | 'not-foldable' | 'recipe-call' | 'unsupported-kind' | 'not-imported' | 'no-call-expression' | 'overlapping' | 'empty' | 'unresolved-token' | 'runtime-binding';
|
|
64
109
|
interface FoldedCall {
|
|
65
110
|
name: string;
|
|
66
111
|
/**
|
|
@@ -119,6 +164,61 @@ interface FoldOptions {
|
|
|
119
164
|
* On by default.
|
|
120
165
|
*/
|
|
121
166
|
partial?: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Parse another module, for a recipe whose `cva` config lives outside this one.
|
|
169
|
+
*
|
|
170
|
+
* Threaded in rather than read off `ctx`, because the project belongs to the node
|
|
171
|
+
* context and this signature takes the core one. Its absence is a supported state:
|
|
172
|
+
* without it a cross-module recipe call is still *reported*, which is the half that
|
|
173
|
+
* used to be missing entirely — it simply cannot be lowered.
|
|
174
|
+
*
|
|
175
|
+
* Pulling the module on demand is also what makes the fold order-independent. A
|
|
176
|
+
* bundler transforms a consumer before the module it imports, so a registry built
|
|
177
|
+
* from what has been transformed so far would fold or decline the same file
|
|
178
|
+
* depending on discovery order.
|
|
179
|
+
*/
|
|
180
|
+
parseModule?: (filePath: string) => ParserResultInterface | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Configs of modules other than this one, shared across a build.
|
|
183
|
+
*
|
|
184
|
+
* Owned by the caller because it has to outlive one call: the declaring module would
|
|
185
|
+
* otherwise be re-parsed once per module that imports it, which is `consumers x module
|
|
186
|
+
* size` on the transform path — measured at 909ms against 8.3ms for fifty consumers of a
|
|
187
|
+
* hundred-recipe module. The caller clears an entry when the file changes, which is the
|
|
188
|
+
* only place that knows.
|
|
189
|
+
*/
|
|
190
|
+
recipeConfigCache?: Map<string, ForeignRecipes>;
|
|
191
|
+
/**
|
|
192
|
+
* Also report bamboo bindings the rewrite left behind, whatever the skip ledger says.
|
|
193
|
+
*
|
|
194
|
+
* The ledger holds only calls something recognised, so it answers "of the calls I looked
|
|
195
|
+
* at, which survived" — and a guarantee built on it is worth exactly what the recogniser
|
|
196
|
+
* is. A cross-module recipe call used to appear in neither column, so a build could report
|
|
197
|
+
* a clean sweep while shipping hundreds of them.
|
|
198
|
+
*
|
|
199
|
+
* This asks what the guarantee actually claims: after the rewrite, is anything from a
|
|
200
|
+
* bamboo module still referenced? Off by default because it costs an identifier walk, and
|
|
201
|
+
* only `strict` needs an answer it can fail a build on.
|
|
202
|
+
*/
|
|
203
|
+
reportSurvivors?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* The module's own AST, when the caller already holds it.
|
|
206
|
+
*
|
|
207
|
+
* Only `reportSurvivors` needs it, and only for the case it exists to catch: a module whose
|
|
208
|
+
* bamboo usage produced no parser result at all has no call to reach the AST through.
|
|
209
|
+
*/
|
|
210
|
+
sourceFile?: SourceFile;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* What one foreign module contributes, in a form that outlives it.
|
|
214
|
+
*
|
|
215
|
+
* Plain data only. Anything holding a ts-morph node would be read after the next
|
|
216
|
+
* `addSourceFile` forgets that module's tree.
|
|
217
|
+
*/
|
|
218
|
+
interface ForeignRecipes {
|
|
219
|
+
configs: Map<string, RecipeEntry>;
|
|
220
|
+
/** How that module spelled the css module, for a helper import written into a consumer. */
|
|
221
|
+
cssSpecifier?: string;
|
|
122
222
|
}
|
|
123
223
|
declare const foldSource: (options: FoldOptions) => FoldResult;
|
|
124
224
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import MagicString from "magic-string";
|
|
2
|
-
import { Node } from "ts-morph";
|
|
2
|
+
import { Node, SourceFile } from "ts-morph";
|
|
3
3
|
import { Context } from "@bamboocss/core";
|
|
4
4
|
import { Plugin } from "vite";
|
|
5
|
-
import { Dict, ParserResultInterface } from "@bamboocss/types";
|
|
5
|
+
import { Dict, ParserResultInterface, ResultItem } from "@bamboocss/types";
|
|
6
6
|
|
|
7
7
|
//#region src/css.d.ts
|
|
8
8
|
/**
|
|
@@ -32,6 +32,49 @@ interface BambooCssPluginOptions {
|
|
|
32
32
|
*/
|
|
33
33
|
declare const bamboocssCss: (options?: BambooCssPluginOptions) => Plugin;
|
|
34
34
|
//#endregion
|
|
35
|
+
//#region src/fold-recipe.d.ts
|
|
36
|
+
/**
|
|
37
|
+
* Lowering a call of an inline recipe to the class string it produces.
|
|
38
|
+
*
|
|
39
|
+
* The prize is not the `cva` runtime, which is small. It is the *config*: `cva({ base, variants })`
|
|
40
|
+
* ships the whole style object to the browser purely so the runtime can hash it into a name and
|
|
41
|
+
* pick classes off it. Those styles are already in the stylesheet. Once every call of a binding
|
|
42
|
+
* is lowered, the binding is unreferenced and a bundler drops the config with it — measured at
|
|
43
|
+
* 81 kB gzipped across one application's 1,297 inline recipes, against 4.5 kB for the runtime.
|
|
44
|
+
*
|
|
45
|
+
* Correct by construction rather than by a matching reimplementation: the class names come from
|
|
46
|
+
* `getRecipeIdentity` and `getRecipeClassNames`, the same functions the browser runs, and the
|
|
47
|
+
* prefixing and hashing from `classFormatter`, which is what the encoder emitted rules under.
|
|
48
|
+
*/
|
|
49
|
+
type Dict$1 = Record<string, unknown>;
|
|
50
|
+
/** A recipe's config, as the extractor resolved it. */
|
|
51
|
+
interface RecipeConfig {
|
|
52
|
+
className?: string;
|
|
53
|
+
base?: Dict$1;
|
|
54
|
+
variants?: Record<string, Record<string, unknown>>;
|
|
55
|
+
defaultVariants?: Record<string, unknown>;
|
|
56
|
+
compoundVariants?: unknown[];
|
|
57
|
+
/** Present on a slot recipe, which resolves to one class per slot rather than a string. */
|
|
58
|
+
slots?: unknown;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A recipe the fold can lower against.
|
|
62
|
+
*
|
|
63
|
+
* `name` is hashed once here rather than per call site: `getRecipeIdentity` serialises the
|
|
64
|
+
* whole config to hash it, which measured as 91% of the per-call work when it sat inside
|
|
65
|
+
* `lowerRecipeCall`. The runtime does it once per `cva()` for the same reason.
|
|
66
|
+
*
|
|
67
|
+
* `box` is the *definition's* node, carried so the fold can register the module the config
|
|
68
|
+
* came from as a watch dependency. Without it, editing a config in another module leaves
|
|
69
|
+
* every literal folded against it stale — the stylesheet gets a new identity and the element
|
|
70
|
+
* keeps the old class.
|
|
71
|
+
*/
|
|
72
|
+
interface RecipeEntry {
|
|
73
|
+
config: RecipeConfig;
|
|
74
|
+
name: string;
|
|
75
|
+
box: ResultItem['box'];
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
35
78
|
//#region src/runtime-css.d.ts
|
|
36
79
|
/**
|
|
37
80
|
* The generated runtime's `css`, rebuilt in-process from a resolved context.
|
|
@@ -62,7 +105,7 @@ declare const createRuntimeCss: (ctx: Context) => RuntimeCss;
|
|
|
62
105
|
* Why a call site was left alone. Surfaced through `panda`-style diagnostics so a
|
|
63
106
|
* user can tell the difference between "this folded" and "this silently didn't".
|
|
64
107
|
*/
|
|
65
|
-
type SkipReason = 'dynamic' | 'raw-call' | 'not-foldable' | 'recipe-call' | 'unsupported-kind' | 'not-imported' | 'no-call-expression' | 'overlapping' | 'empty' | 'unresolved-token';
|
|
108
|
+
type SkipReason = 'dynamic' | 'raw-call' | 'not-foldable' | 'recipe-call' | 'unsupported-kind' | 'not-imported' | 'no-call-expression' | 'overlapping' | 'empty' | 'unresolved-token' | 'runtime-binding';
|
|
66
109
|
interface FoldedCall {
|
|
67
110
|
name: string;
|
|
68
111
|
/**
|
|
@@ -121,6 +164,61 @@ interface FoldOptions {
|
|
|
121
164
|
* On by default.
|
|
122
165
|
*/
|
|
123
166
|
partial?: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Parse another module, for a recipe whose `cva` config lives outside this one.
|
|
169
|
+
*
|
|
170
|
+
* Threaded in rather than read off `ctx`, because the project belongs to the node
|
|
171
|
+
* context and this signature takes the core one. Its absence is a supported state:
|
|
172
|
+
* without it a cross-module recipe call is still *reported*, which is the half that
|
|
173
|
+
* used to be missing entirely — it simply cannot be lowered.
|
|
174
|
+
*
|
|
175
|
+
* Pulling the module on demand is also what makes the fold order-independent. A
|
|
176
|
+
* bundler transforms a consumer before the module it imports, so a registry built
|
|
177
|
+
* from what has been transformed so far would fold or decline the same file
|
|
178
|
+
* depending on discovery order.
|
|
179
|
+
*/
|
|
180
|
+
parseModule?: (filePath: string) => ParserResultInterface | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Configs of modules other than this one, shared across a build.
|
|
183
|
+
*
|
|
184
|
+
* Owned by the caller because it has to outlive one call: the declaring module would
|
|
185
|
+
* otherwise be re-parsed once per module that imports it, which is `consumers x module
|
|
186
|
+
* size` on the transform path — measured at 909ms against 8.3ms for fifty consumers of a
|
|
187
|
+
* hundred-recipe module. The caller clears an entry when the file changes, which is the
|
|
188
|
+
* only place that knows.
|
|
189
|
+
*/
|
|
190
|
+
recipeConfigCache?: Map<string, ForeignRecipes>;
|
|
191
|
+
/**
|
|
192
|
+
* Also report bamboo bindings the rewrite left behind, whatever the skip ledger says.
|
|
193
|
+
*
|
|
194
|
+
* The ledger holds only calls something recognised, so it answers "of the calls I looked
|
|
195
|
+
* at, which survived" — and a guarantee built on it is worth exactly what the recogniser
|
|
196
|
+
* is. A cross-module recipe call used to appear in neither column, so a build could report
|
|
197
|
+
* a clean sweep while shipping hundreds of them.
|
|
198
|
+
*
|
|
199
|
+
* This asks what the guarantee actually claims: after the rewrite, is anything from a
|
|
200
|
+
* bamboo module still referenced? Off by default because it costs an identifier walk, and
|
|
201
|
+
* only `strict` needs an answer it can fail a build on.
|
|
202
|
+
*/
|
|
203
|
+
reportSurvivors?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* The module's own AST, when the caller already holds it.
|
|
206
|
+
*
|
|
207
|
+
* Only `reportSurvivors` needs it, and only for the case it exists to catch: a module whose
|
|
208
|
+
* bamboo usage produced no parser result at all has no call to reach the AST through.
|
|
209
|
+
*/
|
|
210
|
+
sourceFile?: SourceFile;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* What one foreign module contributes, in a form that outlives it.
|
|
214
|
+
*
|
|
215
|
+
* Plain data only. Anything holding a ts-morph node would be read after the next
|
|
216
|
+
* `addSourceFile` forgets that module's tree.
|
|
217
|
+
*/
|
|
218
|
+
interface ForeignRecipes {
|
|
219
|
+
configs: Map<string, RecipeEntry>;
|
|
220
|
+
/** How that module spelled the css module, for a helper import written into a consumer. */
|
|
221
|
+
cssSpecifier?: string;
|
|
124
222
|
}
|
|
125
223
|
declare const foldSource: (options: FoldOptions) => FoldResult;
|
|
126
224
|
//#endregion
|