@bamboocss/vite 1.35.2 → 1.35.4
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 +61 -13
- package/dist/index.d.cts +18 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.mjs +61 -13
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -170,20 +170,32 @@ const replaceAssetReferences = (bundle, previous, next, sourcemap) => {
|
|
|
170
170
|
}
|
|
171
171
|
};
|
|
172
172
|
/**
|
|
173
|
+
* Could this bundle entry be the generated stylesheet?
|
|
174
|
+
*
|
|
175
|
+
* The filename is checked before the bytes because the alternative decodes every asset in the
|
|
176
|
+
* bundle to a UTF-8 string in order to search it — fonts, images and sourcemaps included. On an
|
|
177
|
+
* app with a large asset graph that is seconds of decode and a lot of garbage, twice over, to
|
|
178
|
+
* answer a question the extension already answers. The marker is a CSS custom property, so it
|
|
179
|
+
* cannot occur anywhere but CSS.
|
|
180
|
+
*/
|
|
181
|
+
const carriesGeneratedCss = (output) => output.type === "asset" && output.fileName.endsWith(".css");
|
|
182
|
+
/**
|
|
173
183
|
* Prune and rename compiler-owned CSS, then give changed assets a hash of their final bytes.
|
|
174
184
|
*
|
|
175
185
|
* Rollup has already expanded `[hash]` when `generateBundle` runs. Mutating only `source`
|
|
176
186
|
* would therefore leave two different reachable subsets under one CDN key. The extra final
|
|
177
187
|
* hash is not cosmetic: it makes late graph reachability cache-safe.
|
|
178
188
|
*/
|
|
179
|
-
const optimizeStaticCssAssets = (bundle, session) => {
|
|
189
|
+
const optimizeStaticCssAssets = (bundle, session, options = {}) => {
|
|
190
|
+
const { rename = true } = options;
|
|
180
191
|
for (const [bundleName, output] of Object.entries(bundle)) {
|
|
181
|
-
if (output
|
|
192
|
+
if (!carriesGeneratedCss(output)) continue;
|
|
182
193
|
const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
|
|
183
194
|
if (!source.includes("--made-with-bamboo")) continue;
|
|
184
195
|
const optimized = pruneStaticCss(source, session);
|
|
185
196
|
output.source = optimized;
|
|
186
197
|
if (optimized === source) continue;
|
|
198
|
+
if (!rename) continue;
|
|
187
199
|
const nextName = output.fileName.replace(/\.css$/, `.b-${(0, _bamboocss_shared.toHash)(optimized)}.css`);
|
|
188
200
|
if (nextName === output.fileName) continue;
|
|
189
201
|
if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
|
|
@@ -208,7 +220,7 @@ const optimizeStaticCssAssets = (bundle, session) => {
|
|
|
208
220
|
* process just wrote, which is a race on any watch rebuild.
|
|
209
221
|
*/
|
|
210
222
|
const bamboocssCss = (options) => {
|
|
211
|
-
const { configPath, cwd, session } = options;
|
|
223
|
+
const { configPath, cwd, session, renameCssAsset = true } = options;
|
|
212
224
|
const builder = new _bamboocss_node.Builder();
|
|
213
225
|
let server;
|
|
214
226
|
let command = "build";
|
|
@@ -292,7 +304,13 @@ const bamboocssCss = (options) => {
|
|
|
292
304
|
generateBundle: {
|
|
293
305
|
order: "post",
|
|
294
306
|
handler(_, bundle) {
|
|
295
|
-
|
|
307
|
+
const rolldown = Boolean(this.meta?.rolldownVersion);
|
|
308
|
+
optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset && !rolldown });
|
|
309
|
+
if (!session.transformedFiles.size) return;
|
|
310
|
+
if (!Object.values(bundle).some((output) => {
|
|
311
|
+
if (!carriesGeneratedCss(output)) return false;
|
|
312
|
+
return (typeof output.source === "string" ? output.source : Buffer.from(output.source).toString()).includes("--made-with-bamboo");
|
|
313
|
+
})) throw new Error(`bamboocss: ${session.transformedFiles.size} module(s) were compiled to Bamboo class values, but no emitted asset carries the generated stylesheet. The build would ship unstyled.\n\nThis happens when another plugin, or the bundler itself, drops or replaces the CSS asset after it is emitted. If you are on Rolldown, report this — the rename that used to cause it is already disabled there. Otherwise look for a plugin running in \`generateBundle\` that rewrites CSS assets.`);
|
|
296
314
|
}
|
|
297
315
|
}
|
|
298
316
|
};
|
|
@@ -709,9 +727,10 @@ const propertyKey = (nameNode) => {
|
|
|
709
727
|
* there is nothing to match — the host here is any import of the generated css module, which
|
|
710
728
|
* a file defining a recipe necessarily has, since `cva` came from it.
|
|
711
729
|
*/
|
|
712
|
-
const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGeneratedCssModule, isShadowed, newImportModule) => {
|
|
730
|
+
const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGeneratedCssModule, isShadowed, newImportModule, helperModuleFromSubpath) => {
|
|
713
731
|
const sourceFile = call.getSourceFile();
|
|
714
732
|
let host;
|
|
733
|
+
let subpathModule;
|
|
715
734
|
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
716
735
|
const mod = declaration.getModuleSpecifierValue();
|
|
717
736
|
if (declaration.isTypeOnly()) continue;
|
|
@@ -724,8 +743,10 @@ const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGenerated
|
|
|
724
743
|
}
|
|
725
744
|
}
|
|
726
745
|
if (!host && isGeneratedCssModule(mod) && declaration.getNamedImports().length > 0) host = declaration;
|
|
746
|
+
if (!subpathModule) subpathModule = helperModuleFromSubpath?.(mod);
|
|
727
747
|
}
|
|
728
|
-
|
|
748
|
+
const fallbackModule = newImportModule ?? subpathModule;
|
|
749
|
+
if (!host && !fallbackModule) return void 0;
|
|
729
750
|
if (declaredAtModuleScope(sourceFile).has(imported)) return void 0;
|
|
730
751
|
if (isShadowed(call, imported)) return void 0;
|
|
731
752
|
if (!host) {
|
|
@@ -736,7 +757,7 @@ const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGenerated
|
|
|
736
757
|
insert: {
|
|
737
758
|
pos: anchor.getEnd(),
|
|
738
759
|
names: [imported],
|
|
739
|
-
module:
|
|
760
|
+
module: fallbackModule
|
|
740
761
|
}
|
|
741
762
|
};
|
|
742
763
|
}
|
|
@@ -1512,6 +1533,32 @@ const foldSource = (options) => {
|
|
|
1512
1533
|
const isBambooCssModule = (mod) => matchesModule(mod, cssModules);
|
|
1513
1534
|
const isGeneratedCssModule = (mod) => matchesModule(mod, [generatedCssModule]);
|
|
1514
1535
|
/**
|
|
1536
|
+
* Where the compiler's helpers can be imported from, for a file that imports the generated
|
|
1537
|
+
* css module by *subpath* rather than through its barrel.
|
|
1538
|
+
*
|
|
1539
|
+
* `styled-system/css/cva.js` is a real spelling, and it cannot host the helper: that module
|
|
1540
|
+
* exports `cva`, not `cvaMap`. Matching only the barrel meant no host was found and every
|
|
1541
|
+
* runtime recipe selection in the file declined — a failure whose reported reason said
|
|
1542
|
+
* nothing about import spelling, and whose suggested remedies all pointed elsewhere.
|
|
1543
|
+
*
|
|
1544
|
+
* The sibling `cx` module is what actually exports them. The prefix is verified against the
|
|
1545
|
+
* configured output before anything is derived, so an unrelated `foo/css/bar.js` is left
|
|
1546
|
+
* alone, and the caller's extension is preserved rather than guessed at.
|
|
1547
|
+
*/
|
|
1548
|
+
const helperModuleFromSubpath = (mod) => {
|
|
1549
|
+
const normalized = mod.replaceAll("\\", "/");
|
|
1550
|
+
const at = normalized.lastIndexOf("/css/");
|
|
1551
|
+
if (at < 0) return void 0;
|
|
1552
|
+
const prefix = normalized.slice(0, at + 5 - 1);
|
|
1553
|
+
if (!isGeneratedCssModule(prefix)) return void 0;
|
|
1554
|
+
const rest = normalized.slice(at + 5);
|
|
1555
|
+
if (!rest || rest.includes("/")) return void 0;
|
|
1556
|
+
const dot = rest.lastIndexOf(".");
|
|
1557
|
+
const extension = dot > 0 ? rest.slice(dot) : "";
|
|
1558
|
+
if (rest === `cx${extension}`) return void 0;
|
|
1559
|
+
return `${prefix}/cx${extension}`;
|
|
1560
|
+
};
|
|
1561
|
+
/**
|
|
1515
1562
|
* The generated css entry as spelled beside an imported config recipe.
|
|
1516
1563
|
*
|
|
1517
1564
|
* A decision table needs only `cvaMap`, but a module importing a config recipe often has
|
|
@@ -1822,7 +1869,7 @@ const foldSource = (options) => {
|
|
|
1822
1869
|
}
|
|
1823
1870
|
const lowered = lowerRecipeCall(call, entry, styleCompiler, isInertExpression, resolvedSelection, inlineSlot, maxRecipeStates);
|
|
1824
1871
|
if (lowered.kind === "dynamic-style") {
|
|
1825
|
-
const helper = ensureRecipeHelperImport(RECIPE_MAP_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name));
|
|
1872
|
+
const helper = ensureRecipeHelperImport(RECIPE_MAP_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name), helperModuleFromSubpath);
|
|
1826
1873
|
if (helper) {
|
|
1827
1874
|
candidates.push({
|
|
1828
1875
|
item,
|
|
@@ -1849,7 +1896,7 @@ const foldSource = (options) => {
|
|
|
1849
1896
|
continue;
|
|
1850
1897
|
}
|
|
1851
1898
|
if (lowered.kind === "slots") {
|
|
1852
|
-
const helper = lowered.helper ? ensureRecipeHelperImport(lowered.helper, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name)) : void 0;
|
|
1899
|
+
const helper = lowered.helper ? ensureRecipeHelperImport(lowered.helper, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name), helperModuleFromSubpath) : void 0;
|
|
1853
1900
|
if (!lowered.helper || helper) {
|
|
1854
1901
|
const replacement = lowered.helper && helper && helper.name !== lowered.helper ? lowered.expression.replaceAll(`${lowered.helper}(`, `${helper.name}(`) : lowered.expression;
|
|
1855
1902
|
candidates.push({
|
|
@@ -2302,7 +2349,7 @@ const foldSource = (options) => {
|
|
|
2302
2349
|
const end = call.getEnd();
|
|
2303
2350
|
if (code.slice(start, end) !== call.getText()) continue;
|
|
2304
2351
|
if (collides([[start, end]])) continue;
|
|
2305
|
-
const helper = ensureRecipeHelperImport(SPLIT_PROPS_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(target.getText()));
|
|
2352
|
+
const helper = ensureRecipeHelperImport(SPLIT_PROPS_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(target.getText()), helperModuleFromSubpath);
|
|
2306
2353
|
if (!helper) continue;
|
|
2307
2354
|
const keys = Object.keys(entry.config.variants ?? {});
|
|
2308
2355
|
magic.overwrite(start, end, `${helper.name}(${args[0].getText()}, ${JSON.stringify(keys)})`);
|
|
@@ -2659,7 +2706,7 @@ const formatSkipped = (id, skipped) => {
|
|
|
2659
2706
|
* with no matching rule.
|
|
2660
2707
|
*/
|
|
2661
2708
|
const bamboocss = (options = {}) => {
|
|
2662
|
-
const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates } = options;
|
|
2709
|
+
const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates, renameCssAsset = true } = options;
|
|
2663
2710
|
if (maxRecipeStates !== void 0 && (!Number.isSafeInteger(maxRecipeStates) || maxRecipeStates < 1)) throw new Error("bamboocss: `maxRecipeStates` must be a positive safe integer.");
|
|
2664
2711
|
/** Totals across the build, for the summary. */
|
|
2665
2712
|
const totals = {
|
|
@@ -2695,7 +2742,7 @@ const bamboocss = (options = {}) => {
|
|
|
2695
2742
|
separator: "\n"
|
|
2696
2743
|
});
|
|
2697
2744
|
const threw = entries.some((entry) => entry.reason === "compile-failed");
|
|
2698
|
-
return /* @__PURE__ */ new Error(`bamboocss: ${entries.length} call(s) could not be compiled.\n\n${detail}\n\n` + (threw ? "`compile-failed` is a module the compiler threw on — see the error logged for it above. Nothing was established about its calls either way.\n\n" : "") + "Bamboo emits no runtime styling fallback or recipe layer. Make the values finite and statically analyzable, move variation into declared recipe variants, or safelist intentional dynamic classes with `staticCss
|
|
2745
|
+
return /* @__PURE__ */ new Error(`bamboocss: ${entries.length} call(s) could not be compiled.\n\n${detail}\n\n` + (threw ? "`compile-failed` is a module the compiler threw on — see the error logged for it above. Nothing was established about its calls either way.\n\n" : "") + (entries.some((entry) => entry.reason === "runtime-binding") ? "`runtime-binding` is a Bamboo value read outside a call the compiler rewrote — most often an inline `cva`/`sva` imported by another module. Its declaration is erased where it is declared, so the import receives `undefined`; a recipe used in more than one file has to be a config recipe under `theme.extend.recipes`. The location given is the reference to change, not the declaration.\n\n" : "") + "Bamboo emits no runtime styling fallback or recipe layer. Make the values finite and statically analyzable, move variation into declared recipe variants, or safelist intentional dynamic classes with `staticCss`.\n\nSet `BAMBOO_DIAGNOSTIC_LIMIT=all` to list every finding rather than the first few.");
|
|
2699
2746
|
};
|
|
2700
2747
|
/**
|
|
2701
2748
|
* Recipe configs read out of modules other than the one being transformed.
|
|
@@ -2724,7 +2771,8 @@ const bamboocss = (options = {}) => {
|
|
|
2724
2771
|
return [bamboocssCss({
|
|
2725
2772
|
configPath,
|
|
2726
2773
|
cwd,
|
|
2727
|
-
session: staticSession
|
|
2774
|
+
session: staticSession,
|
|
2775
|
+
renameCssAsset
|
|
2728
2776
|
}), {
|
|
2729
2777
|
name: "bamboocss:compiler",
|
|
2730
2778
|
enforce: "pre",
|
package/dist/index.d.cts
CHANGED
|
@@ -45,6 +45,24 @@ interface BambooVitePluginOptions {
|
|
|
45
45
|
* build time and memory for the exact compound-variant decision table. @default 65536
|
|
46
46
|
*/
|
|
47
47
|
maxRecipeStates?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Give the pruned stylesheet a final name derived from its own bytes.
|
|
50
|
+
*
|
|
51
|
+
* Rollup expands `[hash]` before `generateBundle`, so pruning after it can leave two
|
|
52
|
+
* different reachable subsets under one CDN key. Renaming closes that, at the cost of
|
|
53
|
+
* replacing an entry in the output bundle — which not every consumer of the bundle
|
|
54
|
+
* tolerates. Rolldown drops the asset outright (detected automatically, no flag needed),
|
|
55
|
+
* and a framework that relocates assets itself, such as react-router's SSR build, can
|
|
56
|
+
* lose track of the new name.
|
|
57
|
+
*
|
|
58
|
+
* Turning it off keeps the pruned bytes and Vite's own content hash. That hash is computed
|
|
59
|
+
* before pruning, so it stops describing the file exactly; in practice it still changes
|
|
60
|
+
* whenever the extracted CSS does, and only a change that alters *reachability alone*
|
|
61
|
+
* can now reuse a key. Prefer that over an asset your framework cannot find.
|
|
62
|
+
*
|
|
63
|
+
* @default true
|
|
64
|
+
*/
|
|
65
|
+
renameCssAsset?: boolean;
|
|
48
66
|
}
|
|
49
67
|
/**
|
|
50
68
|
* Vite integration for Bamboo CSS.
|
package/dist/index.d.mts
CHANGED
|
@@ -45,6 +45,24 @@ interface BambooVitePluginOptions {
|
|
|
45
45
|
* build time and memory for the exact compound-variant decision table. @default 65536
|
|
46
46
|
*/
|
|
47
47
|
maxRecipeStates?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Give the pruned stylesheet a final name derived from its own bytes.
|
|
50
|
+
*
|
|
51
|
+
* Rollup expands `[hash]` before `generateBundle`, so pruning after it can leave two
|
|
52
|
+
* different reachable subsets under one CDN key. Renaming closes that, at the cost of
|
|
53
|
+
* replacing an entry in the output bundle — which not every consumer of the bundle
|
|
54
|
+
* tolerates. Rolldown drops the asset outright (detected automatically, no flag needed),
|
|
55
|
+
* and a framework that relocates assets itself, such as react-router's SSR build, can
|
|
56
|
+
* lose track of the new name.
|
|
57
|
+
*
|
|
58
|
+
* Turning it off keeps the pruned bytes and Vite's own content hash. That hash is computed
|
|
59
|
+
* before pruning, so it stops describing the file exactly; in practice it still changes
|
|
60
|
+
* whenever the extracted CSS does, and only a change that alters *reachability alone*
|
|
61
|
+
* can now reuse a key. Prefer that over an asset your framework cannot find.
|
|
62
|
+
*
|
|
63
|
+
* @default true
|
|
64
|
+
*/
|
|
65
|
+
renameCssAsset?: boolean;
|
|
48
66
|
}
|
|
49
67
|
/**
|
|
50
68
|
* Vite integration for Bamboo CSS.
|
package/dist/index.mjs
CHANGED
|
@@ -140,20 +140,32 @@ const replaceAssetReferences = (bundle, previous, next, sourcemap) => {
|
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
142
|
/**
|
|
143
|
+
* Could this bundle entry be the generated stylesheet?
|
|
144
|
+
*
|
|
145
|
+
* The filename is checked before the bytes because the alternative decodes every asset in the
|
|
146
|
+
* bundle to a UTF-8 string in order to search it — fonts, images and sourcemaps included. On an
|
|
147
|
+
* app with a large asset graph that is seconds of decode and a lot of garbage, twice over, to
|
|
148
|
+
* answer a question the extension already answers. The marker is a CSS custom property, so it
|
|
149
|
+
* cannot occur anywhere but CSS.
|
|
150
|
+
*/
|
|
151
|
+
const carriesGeneratedCss = (output) => output.type === "asset" && output.fileName.endsWith(".css");
|
|
152
|
+
/**
|
|
143
153
|
* Prune and rename compiler-owned CSS, then give changed assets a hash of their final bytes.
|
|
144
154
|
*
|
|
145
155
|
* Rollup has already expanded `[hash]` when `generateBundle` runs. Mutating only `source`
|
|
146
156
|
* would therefore leave two different reachable subsets under one CDN key. The extra final
|
|
147
157
|
* hash is not cosmetic: it makes late graph reachability cache-safe.
|
|
148
158
|
*/
|
|
149
|
-
const optimizeStaticCssAssets = (bundle, session) => {
|
|
159
|
+
const optimizeStaticCssAssets = (bundle, session, options = {}) => {
|
|
160
|
+
const { rename = true } = options;
|
|
150
161
|
for (const [bundleName, output] of Object.entries(bundle)) {
|
|
151
|
-
if (output
|
|
162
|
+
if (!carriesGeneratedCss(output)) continue;
|
|
152
163
|
const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
|
|
153
164
|
if (!source.includes("--made-with-bamboo")) continue;
|
|
154
165
|
const optimized = pruneStaticCss(source, session);
|
|
155
166
|
output.source = optimized;
|
|
156
167
|
if (optimized === source) continue;
|
|
168
|
+
if (!rename) continue;
|
|
157
169
|
const nextName = output.fileName.replace(/\.css$/, `.b-${toHash(optimized)}.css`);
|
|
158
170
|
if (nextName === output.fileName) continue;
|
|
159
171
|
if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
|
|
@@ -178,7 +190,7 @@ const optimizeStaticCssAssets = (bundle, session) => {
|
|
|
178
190
|
* process just wrote, which is a race on any watch rebuild.
|
|
179
191
|
*/
|
|
180
192
|
const bamboocssCss = (options) => {
|
|
181
|
-
const { configPath, cwd, session } = options;
|
|
193
|
+
const { configPath, cwd, session, renameCssAsset = true } = options;
|
|
182
194
|
const builder = new Builder();
|
|
183
195
|
let server;
|
|
184
196
|
let command = "build";
|
|
@@ -262,7 +274,13 @@ const bamboocssCss = (options) => {
|
|
|
262
274
|
generateBundle: {
|
|
263
275
|
order: "post",
|
|
264
276
|
handler(_, bundle) {
|
|
265
|
-
|
|
277
|
+
const rolldown = Boolean(this.meta?.rolldownVersion);
|
|
278
|
+
optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset && !rolldown });
|
|
279
|
+
if (!session.transformedFiles.size) return;
|
|
280
|
+
if (!Object.values(bundle).some((output) => {
|
|
281
|
+
if (!carriesGeneratedCss(output)) return false;
|
|
282
|
+
return (typeof output.source === "string" ? output.source : Buffer.from(output.source).toString()).includes("--made-with-bamboo");
|
|
283
|
+
})) throw new Error(`bamboocss: ${session.transformedFiles.size} module(s) were compiled to Bamboo class values, but no emitted asset carries the generated stylesheet. The build would ship unstyled.\n\nThis happens when another plugin, or the bundler itself, drops or replaces the CSS asset after it is emitted. If you are on Rolldown, report this — the rename that used to cause it is already disabled there. Otherwise look for a plugin running in \`generateBundle\` that rewrites CSS assets.`);
|
|
266
284
|
}
|
|
267
285
|
}
|
|
268
286
|
};
|
|
@@ -679,9 +697,10 @@ const propertyKey = (nameNode) => {
|
|
|
679
697
|
* there is nothing to match — the host here is any import of the generated css module, which
|
|
680
698
|
* a file defining a recipe necessarily has, since `cva` came from it.
|
|
681
699
|
*/
|
|
682
|
-
const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGeneratedCssModule, isShadowed, newImportModule) => {
|
|
700
|
+
const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGeneratedCssModule, isShadowed, newImportModule, helperModuleFromSubpath) => {
|
|
683
701
|
const sourceFile = call.getSourceFile();
|
|
684
702
|
let host;
|
|
703
|
+
let subpathModule;
|
|
685
704
|
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
686
705
|
const mod = declaration.getModuleSpecifierValue();
|
|
687
706
|
if (declaration.isTypeOnly()) continue;
|
|
@@ -694,8 +713,10 @@ const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGenerated
|
|
|
694
713
|
}
|
|
695
714
|
}
|
|
696
715
|
if (!host && isGeneratedCssModule(mod) && declaration.getNamedImports().length > 0) host = declaration;
|
|
716
|
+
if (!subpathModule) subpathModule = helperModuleFromSubpath?.(mod);
|
|
697
717
|
}
|
|
698
|
-
|
|
718
|
+
const fallbackModule = newImportModule ?? subpathModule;
|
|
719
|
+
if (!host && !fallbackModule) return void 0;
|
|
699
720
|
if (declaredAtModuleScope(sourceFile).has(imported)) return void 0;
|
|
700
721
|
if (isShadowed(call, imported)) return void 0;
|
|
701
722
|
if (!host) {
|
|
@@ -706,7 +727,7 @@ const ensureRecipeHelperImport = (imported, call, isBambooCssModule, isGenerated
|
|
|
706
727
|
insert: {
|
|
707
728
|
pos: anchor.getEnd(),
|
|
708
729
|
names: [imported],
|
|
709
|
-
module:
|
|
730
|
+
module: fallbackModule
|
|
710
731
|
}
|
|
711
732
|
};
|
|
712
733
|
}
|
|
@@ -1482,6 +1503,32 @@ const foldSource = (options) => {
|
|
|
1482
1503
|
const isBambooCssModule = (mod) => matchesModule(mod, cssModules);
|
|
1483
1504
|
const isGeneratedCssModule = (mod) => matchesModule(mod, [generatedCssModule]);
|
|
1484
1505
|
/**
|
|
1506
|
+
* Where the compiler's helpers can be imported from, for a file that imports the generated
|
|
1507
|
+
* css module by *subpath* rather than through its barrel.
|
|
1508
|
+
*
|
|
1509
|
+
* `styled-system/css/cva.js` is a real spelling, and it cannot host the helper: that module
|
|
1510
|
+
* exports `cva`, not `cvaMap`. Matching only the barrel meant no host was found and every
|
|
1511
|
+
* runtime recipe selection in the file declined — a failure whose reported reason said
|
|
1512
|
+
* nothing about import spelling, and whose suggested remedies all pointed elsewhere.
|
|
1513
|
+
*
|
|
1514
|
+
* The sibling `cx` module is what actually exports them. The prefix is verified against the
|
|
1515
|
+
* configured output before anything is derived, so an unrelated `foo/css/bar.js` is left
|
|
1516
|
+
* alone, and the caller's extension is preserved rather than guessed at.
|
|
1517
|
+
*/
|
|
1518
|
+
const helperModuleFromSubpath = (mod) => {
|
|
1519
|
+
const normalized = mod.replaceAll("\\", "/");
|
|
1520
|
+
const at = normalized.lastIndexOf("/css/");
|
|
1521
|
+
if (at < 0) return void 0;
|
|
1522
|
+
const prefix = normalized.slice(0, at + 5 - 1);
|
|
1523
|
+
if (!isGeneratedCssModule(prefix)) return void 0;
|
|
1524
|
+
const rest = normalized.slice(at + 5);
|
|
1525
|
+
if (!rest || rest.includes("/")) return void 0;
|
|
1526
|
+
const dot = rest.lastIndexOf(".");
|
|
1527
|
+
const extension = dot > 0 ? rest.slice(dot) : "";
|
|
1528
|
+
if (rest === `cx${extension}`) return void 0;
|
|
1529
|
+
return `${prefix}/cx${extension}`;
|
|
1530
|
+
};
|
|
1531
|
+
/**
|
|
1485
1532
|
* The generated css entry as spelled beside an imported config recipe.
|
|
1486
1533
|
*
|
|
1487
1534
|
* A decision table needs only `cvaMap`, but a module importing a config recipe often has
|
|
@@ -1792,7 +1839,7 @@ const foldSource = (options) => {
|
|
|
1792
1839
|
}
|
|
1793
1840
|
const lowered = lowerRecipeCall(call, entry, styleCompiler, isInertExpression, resolvedSelection, inlineSlot, maxRecipeStates);
|
|
1794
1841
|
if (lowered.kind === "dynamic-style") {
|
|
1795
|
-
const helper = ensureRecipeHelperImport(RECIPE_MAP_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name));
|
|
1842
|
+
const helper = ensureRecipeHelperImport(RECIPE_MAP_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name), helperModuleFromSubpath);
|
|
1796
1843
|
if (helper) {
|
|
1797
1844
|
candidates.push({
|
|
1798
1845
|
item,
|
|
@@ -1819,7 +1866,7 @@ const foldSource = (options) => {
|
|
|
1819
1866
|
continue;
|
|
1820
1867
|
}
|
|
1821
1868
|
if (lowered.kind === "slots") {
|
|
1822
|
-
const helper = lowered.helper ? ensureRecipeHelperImport(lowered.helper, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name)) : void 0;
|
|
1869
|
+
const helper = lowered.helper ? ensureRecipeHelperImport(lowered.helper, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(name), helperModuleFromSubpath) : void 0;
|
|
1823
1870
|
if (!lowered.helper || helper) {
|
|
1824
1871
|
const replacement = lowered.helper && helper && helper.name !== lowered.helper ? lowered.expression.replaceAll(`${lowered.helper}(`, `${helper.name}(`) : lowered.expression;
|
|
1825
1872
|
candidates.push({
|
|
@@ -2272,7 +2319,7 @@ const foldSource = (options) => {
|
|
|
2272
2319
|
const end = call.getEnd();
|
|
2273
2320
|
if (code.slice(start, end) !== call.getText()) continue;
|
|
2274
2321
|
if (collides([[start, end]])) continue;
|
|
2275
|
-
const helper = ensureRecipeHelperImport(SPLIT_PROPS_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(target.getText()));
|
|
2322
|
+
const helper = ensureRecipeHelperImport(SPLIT_PROPS_HELPER, call, isBambooCssModule, isGeneratedCssModule, isShadowed, helperModules.get(target.getText()), helperModuleFromSubpath);
|
|
2276
2323
|
if (!helper) continue;
|
|
2277
2324
|
const keys = Object.keys(entry.config.variants ?? {});
|
|
2278
2325
|
magic.overwrite(start, end, `${helper.name}(${args[0].getText()}, ${JSON.stringify(keys)})`);
|
|
@@ -2629,7 +2676,7 @@ const formatSkipped = (id, skipped) => {
|
|
|
2629
2676
|
* with no matching rule.
|
|
2630
2677
|
*/
|
|
2631
2678
|
const bamboocss = (options = {}) => {
|
|
2632
|
-
const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates } = options;
|
|
2679
|
+
const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates, renameCssAsset = true } = options;
|
|
2633
2680
|
if (maxRecipeStates !== void 0 && (!Number.isSafeInteger(maxRecipeStates) || maxRecipeStates < 1)) throw new Error("bamboocss: `maxRecipeStates` must be a positive safe integer.");
|
|
2634
2681
|
/** Totals across the build, for the summary. */
|
|
2635
2682
|
const totals = {
|
|
@@ -2665,7 +2712,7 @@ const bamboocss = (options = {}) => {
|
|
|
2665
2712
|
separator: "\n"
|
|
2666
2713
|
});
|
|
2667
2714
|
const threw = entries.some((entry) => entry.reason === "compile-failed");
|
|
2668
|
-
return /* @__PURE__ */ new Error(`bamboocss: ${entries.length} call(s) could not be compiled.\n\n${detail}\n\n` + (threw ? "`compile-failed` is a module the compiler threw on — see the error logged for it above. Nothing was established about its calls either way.\n\n" : "") + "Bamboo emits no runtime styling fallback or recipe layer. Make the values finite and statically analyzable, move variation into declared recipe variants, or safelist intentional dynamic classes with `staticCss
|
|
2715
|
+
return /* @__PURE__ */ new Error(`bamboocss: ${entries.length} call(s) could not be compiled.\n\n${detail}\n\n` + (threw ? "`compile-failed` is a module the compiler threw on — see the error logged for it above. Nothing was established about its calls either way.\n\n" : "") + (entries.some((entry) => entry.reason === "runtime-binding") ? "`runtime-binding` is a Bamboo value read outside a call the compiler rewrote — most often an inline `cva`/`sva` imported by another module. Its declaration is erased where it is declared, so the import receives `undefined`; a recipe used in more than one file has to be a config recipe under `theme.extend.recipes`. The location given is the reference to change, not the declaration.\n\n" : "") + "Bamboo emits no runtime styling fallback or recipe layer. Make the values finite and statically analyzable, move variation into declared recipe variants, or safelist intentional dynamic classes with `staticCss`.\n\nSet `BAMBOO_DIAGNOSTIC_LIMIT=all` to list every finding rather than the first few.");
|
|
2669
2716
|
};
|
|
2670
2717
|
/**
|
|
2671
2718
|
* Recipe configs read out of modules other than the one being transformed.
|
|
@@ -2694,7 +2741,8 @@ const bamboocss = (options = {}) => {
|
|
|
2694
2741
|
return [bamboocssCss({
|
|
2695
2742
|
configPath,
|
|
2696
2743
|
cwd,
|
|
2697
|
-
session: staticSession
|
|
2744
|
+
session: staticSession,
|
|
2745
|
+
renameCssAsset
|
|
2698
2746
|
}), {
|
|
2699
2747
|
name: "bamboocss:compiler",
|
|
2700
2748
|
enforce: "pre",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/vite",
|
|
3
|
-
"version": "1.35.
|
|
3
|
+
"version": "1.35.4",
|
|
4
4
|
"description": "Vite integration for Bamboo CSS",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
"postcss": "8.5.26",
|
|
41
41
|
"postcss-selector-parser": "7.1.5",
|
|
42
42
|
"ts-morph": "28.0.0",
|
|
43
|
-
"@bamboocss/config": "1.35.
|
|
44
|
-
"@bamboocss/core": "1.35.
|
|
45
|
-
"@bamboocss/
|
|
46
|
-
"@bamboocss/
|
|
47
|
-
"@bamboocss/
|
|
48
|
-
"@bamboocss/
|
|
49
|
-
"@bamboocss/
|
|
43
|
+
"@bamboocss/config": "1.35.4",
|
|
44
|
+
"@bamboocss/core": "1.35.4",
|
|
45
|
+
"@bamboocss/extractor": "1.35.4",
|
|
46
|
+
"@bamboocss/logger": "1.35.4",
|
|
47
|
+
"@bamboocss/node": "1.35.4",
|
|
48
|
+
"@bamboocss/types": "1.35.4",
|
|
49
|
+
"@bamboocss/shared": "1.35.4"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
53
53
|
"vite": "7.2.6",
|
|
54
|
-
"@bamboocss/fixture": "1.35.
|
|
54
|
+
"@bamboocss/fixture": "1.35.4"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"vite": ">=5"
|