@bamboocss/vite 1.36.5 → 1.37.1

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 CHANGED
@@ -116,23 +116,6 @@ const pruneStaticCss = (css, session, { prune = true } = {}) => {
116
116
  separator: "\n"
117
117
  })}\n\nThis is a compiler bug rather than anything to fix in your source — please report it with the class names above.`);
118
118
  }
119
- if (session.denseClassNames) root.walkRules((rule) => {
120
- if (!isUtilityRule(rule)) return;
121
- const transitionClasses = /* @__PURE__ */ new Set();
122
- try {
123
- rule.selector = (0, postcss_selector_parser.default)((selectors) => {
124
- selectors.walkClasses((classNode) => {
125
- if (!session.prunableClasses.has(classNode.toString().slice(1))) return;
126
- if (session.viewTransitionClasses.has(classNode.value)) transitionClasses.add(classNode.value);
127
- classNode.value = session.allocateClassString(classNode.value);
128
- });
129
- }).processSync(rule.selector);
130
- } catch {}
131
- if (transitionClasses.size) rule.walkDecls("view-transition-class", (declaration) => {
132
- if (!transitionClasses.has(declaration.value)) return;
133
- declaration.value = session.allocateClassString(declaration.value);
134
- });
135
- });
136
119
  return root.toString();
137
120
  };
138
121
  //#endregion
@@ -228,22 +211,23 @@ const carriesGeneratedCss = (output) => output.type === "asset" && output.fileNa
228
211
  */
229
212
  const optimizeStaticCssAssets = (bundle, session, options = {}) => {
230
213
  const { rename = true } = options;
231
- for (const [bundleName, output] of Object.entries(bundle)) {
214
+ for (const output of Object.values(bundle)) {
232
215
  if (!carriesGeneratedCss(output)) continue;
233
216
  const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
234
217
  if (!source.includes("--made-with-bamboo")) continue;
235
218
  const optimized = pruneStaticCss(source, session);
236
219
  output.source = optimized;
237
220
  if (optimized === source) continue;
238
- if (!rename) continue;
221
+ if (!rename) {
222
+ output.source = source;
223
+ continue;
224
+ }
239
225
  const nextName = output.fileName.replace(/\.css$/, `.b-${(0, _bamboocss_shared.toHash)(optimized)}.css`);
240
226
  if (nextName === output.fileName) continue;
241
227
  if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
242
228
  const previous = output.fileName;
243
229
  output.fileName = nextName;
244
230
  replaceAssetReferences(bundle, previous, nextName, session.sourcemap);
245
- delete bundle[bundleName];
246
- bundle[nextName] = output;
247
231
  }
248
232
  };
249
233
  /**
@@ -349,8 +333,7 @@ const bamboocssCss = (options) => {
349
333
  generateBundle: {
350
334
  order: "post",
351
335
  handler(_, bundle) {
352
- const rolldown = Boolean(this.meta?.rolldownVersion);
353
- optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset && !rolldown });
336
+ optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset });
354
337
  if (!session.transformedFiles.size) return;
355
338
  if (!Object.values(bundle).some((output) => {
356
339
  if (!carriesGeneratedCss(output)) return false;
@@ -2699,18 +2682,7 @@ const createStaticStyleSetCompiler = (ctx, runtimeCss, allocateClassString = (cl
2699
2682
  };
2700
2683
  //#endregion
2701
2684
  //#region src/static-session.ts
2702
- const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2703
- const denseName = (index) => {
2704
- let value = index;
2705
- let result = "";
2706
- do {
2707
- result = ALPHABET[value % 52] + result;
2708
- value = Math.floor(value / 52) - 1;
2709
- } while (value >= 0);
2710
- return `_${result}`;
2711
- };
2712
- const createStaticCompilationSession = (denseClassNames = true) => {
2713
- const mode = denseClassNames === true ? "stable" : denseClassNames;
2685
+ const createStaticCompilationSession = () => {
2714
2686
  const session = {
2715
2687
  utilityLayer: "utilities",
2716
2688
  sourcemap: false,
@@ -2720,28 +2692,10 @@ const createStaticCompilationSession = (denseClassNames = true) => {
2720
2692
  prunableClasses: /* @__PURE__ */ new Set(),
2721
2693
  viewTransitionClasses: /* @__PURE__ */ new Set(),
2722
2694
  usedClasses: /* @__PURE__ */ new Set(),
2723
- denseClasses: /* @__PURE__ */ new Map(),
2724
- semanticClasses: /* @__PURE__ */ new Map(),
2725
- denseClassNames: Boolean(mode),
2726
- allocateClassString(className) {
2727
- if (!mode) return className;
2728
- return className.split(" ").filter(Boolean).map((semantic) => {
2729
- let dense = session.denseClasses.get(semantic);
2730
- if (!dense) {
2731
- dense = mode === "local" ? denseName(session.denseClasses.size) : `_${(0, _bamboocss_shared.toHash)(semantic)}`;
2732
- const collision = session.semanticClasses.get(dense);
2733
- if (collision && collision !== semantic) throw new Error(`Bamboo compact class collision between ${JSON.stringify(collision)} and ${JSON.stringify(semantic)}. Disable \`denseClassNames\` for this build.`);
2734
- session.denseClasses.set(semantic, dense);
2735
- session.semanticClasses.set(dense, semantic);
2736
- }
2737
- return dense;
2738
- }).join(" ");
2739
- },
2740
2695
  markClassUsed(className) {
2741
2696
  for (const token of className.split(" ")) {
2742
2697
  if (!token) continue;
2743
- const semantic = session.semanticClasses.get(token) ?? token;
2744
- session.usedClasses.add((0, _bamboocss_shared.esc)(semantic));
2698
+ session.usedClasses.add((0, _bamboocss_shared.esc)(token));
2745
2699
  }
2746
2700
  }
2747
2701
  };
@@ -2754,8 +2708,6 @@ const resetStaticCompilationSession = (session) => {
2754
2708
  session.prunableClasses.clear();
2755
2709
  session.viewTransitionClasses.clear();
2756
2710
  session.usedClasses.clear();
2757
- session.denseClasses.clear();
2758
- session.semanticClasses.clear();
2759
2711
  };
2760
2712
  //#endregion
2761
2713
  //#region src/plugin.ts
@@ -2809,7 +2761,7 @@ const formatSkipped = (id, skipped) => {
2809
2761
  * with no matching rule.
2810
2762
  */
2811
2763
  const bamboocss = (options = {}) => {
2812
- const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates, renameCssAsset = true } = options;
2764
+ const { configPath, cwd, reportSkipped = false, reportSummary = true, maxRecipeStates, renameCssAsset = true } = options;
2813
2765
  if (maxRecipeStates !== void 0 && (!Number.isSafeInteger(maxRecipeStates) || maxRecipeStates < 1)) throw new Error("bamboocss: `maxRecipeStates` must be a positive safe integer.");
2814
2766
  /** Totals across the build, for the summary. */
2815
2767
  const totals = {
@@ -2818,7 +2770,7 @@ const bamboocss = (options = {}) => {
2818
2770
  filesWithFolds: 0,
2819
2771
  skipped: /* @__PURE__ */ new Map()
2820
2772
  };
2821
- const staticSession = createStaticCompilationSession(denseClassNames);
2773
+ const staticSession = createStaticCompilationSession();
2822
2774
  const survivors = [];
2823
2775
  const survivorKeys = /* @__PURE__ */ new Set();
2824
2776
  const addSurvivor = (entry) => {
@@ -2865,9 +2817,8 @@ const bamboocss = (options = {}) => {
2865
2817
  cwd
2866
2818
  }).then((loaded) => {
2867
2819
  ctx = loaded;
2868
- const semanticCss = createRuntimeCss(loaded);
2869
- runtimeCss = (...styles) => staticSession.allocateClassString(semanticCss(...styles));
2870
- styleCompiler = createStaticStyleSetCompiler(loaded, runtimeCss, staticSession.allocateClassString);
2820
+ runtimeCss = createRuntimeCss(loaded);
2821
+ styleCompiler = createStaticStyleSetCompiler(loaded, runtimeCss);
2871
2822
  });
2872
2823
  await setup;
2873
2824
  };
package/dist/index.d.cts CHANGED
@@ -1,8 +1,5 @@
1
1
  import { Plugin } from "vite";
2
2
 
3
- //#region src/static-session.d.ts
4
- type DenseClassNameMode = boolean | 'stable' | 'local';
5
- //#endregion
6
3
  //#region src/css.d.ts
7
4
  /**
8
5
  * What a project imports to get the stylesheet.
@@ -34,12 +31,6 @@ interface BambooVitePluginOptions {
34
31
  * @default true
35
32
  */
36
33
  reportSummary?: boolean;
37
- /**
38
- * Compact atom names. `true`/`stable` is deterministic across
39
- * client and SSR builds. `local` uses the shortest names and is safe only when one build
40
- * produces both HTML and CSS. @default true
41
- */
42
- denseClassNames?: DenseClassNameMode;
43
34
  /**
44
35
  * Maximum complete selections compiled for one runtime `cva`/`sva` call. This bounds
45
36
  * build time and memory for the exact compound-variant decision table. @default 65536
@@ -48,17 +39,15 @@ interface BambooVitePluginOptions {
48
39
  /**
49
40
  * Give the pruned stylesheet a final name derived from its own bytes.
50
41
  *
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.
42
+ * Rollup and Rolldown both expand `[hash]` before `generateBundle`, so pruning after it can
43
+ * leave two different reachable subsets under one CDN key. Renaming the pruned stylesheet to
44
+ * a hash of its own bytes closes that.
57
45
  *
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.
46
+ * Turning it off does not merely skip the rename it skips the pruning with it. The two are
47
+ * one operation: pruned bytes under a name describing the unpruned ones is how a stale
48
+ * stylesheet outlives a deploy, which is worse than shipping a larger sheet. Reach for this
49
+ * only when something downstream cannot follow a renamed asset, and expect the full
50
+ * extracted stylesheet when you do.
62
51
  *
63
52
  * @default true
64
53
  */
package/dist/index.d.mts CHANGED
@@ -1,8 +1,5 @@
1
1
  import { Plugin } from "vite";
2
2
 
3
- //#region src/static-session.d.ts
4
- type DenseClassNameMode = boolean | 'stable' | 'local';
5
- //#endregion
6
3
  //#region src/css.d.ts
7
4
  /**
8
5
  * What a project imports to get the stylesheet.
@@ -34,12 +31,6 @@ interface BambooVitePluginOptions {
34
31
  * @default true
35
32
  */
36
33
  reportSummary?: boolean;
37
- /**
38
- * Compact atom names. `true`/`stable` is deterministic across
39
- * client and SSR builds. `local` uses the shortest names and is safe only when one build
40
- * produces both HTML and CSS. @default true
41
- */
42
- denseClassNames?: DenseClassNameMode;
43
34
  /**
44
35
  * Maximum complete selections compiled for one runtime `cva`/`sva` call. This bounds
45
36
  * build time and memory for the exact compound-variant decision table. @default 65536
@@ -48,17 +39,15 @@ interface BambooVitePluginOptions {
48
39
  /**
49
40
  * Give the pruned stylesheet a final name derived from its own bytes.
50
41
  *
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.
42
+ * Rollup and Rolldown both expand `[hash]` before `generateBundle`, so pruning after it can
43
+ * leave two different reachable subsets under one CDN key. Renaming the pruned stylesheet to
44
+ * a hash of its own bytes closes that.
57
45
  *
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.
46
+ * Turning it off does not merely skip the rename it skips the pruning with it. The two are
47
+ * one operation: pruned bytes under a name describing the unpruned ones is how a stale
48
+ * stylesheet outlives a deploy, which is worse than shipping a larger sheet. Reach for this
49
+ * only when something downstream cannot follow a renamed asset, and expect the full
50
+ * extracted stylesheet when you do.
62
51
  *
63
52
  * @default true
64
53
  */
package/dist/index.mjs CHANGED
@@ -86,23 +86,6 @@ const pruneStaticCss = (css, session, { prune = true } = {}) => {
86
86
  separator: "\n"
87
87
  })}\n\nThis is a compiler bug rather than anything to fix in your source — please report it with the class names above.`);
88
88
  }
89
- if (session.denseClassNames) root.walkRules((rule) => {
90
- if (!isUtilityRule(rule)) return;
91
- const transitionClasses = /* @__PURE__ */ new Set();
92
- try {
93
- rule.selector = selectorParser((selectors) => {
94
- selectors.walkClasses((classNode) => {
95
- if (!session.prunableClasses.has(classNode.toString().slice(1))) return;
96
- if (session.viewTransitionClasses.has(classNode.value)) transitionClasses.add(classNode.value);
97
- classNode.value = session.allocateClassString(classNode.value);
98
- });
99
- }).processSync(rule.selector);
100
- } catch {}
101
- if (transitionClasses.size) rule.walkDecls("view-transition-class", (declaration) => {
102
- if (!transitionClasses.has(declaration.value)) return;
103
- declaration.value = session.allocateClassString(declaration.value);
104
- });
105
- });
106
89
  return root.toString();
107
90
  };
108
91
  //#endregion
@@ -198,22 +181,23 @@ const carriesGeneratedCss = (output) => output.type === "asset" && output.fileNa
198
181
  */
199
182
  const optimizeStaticCssAssets = (bundle, session, options = {}) => {
200
183
  const { rename = true } = options;
201
- for (const [bundleName, output] of Object.entries(bundle)) {
184
+ for (const output of Object.values(bundle)) {
202
185
  if (!carriesGeneratedCss(output)) continue;
203
186
  const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
204
187
  if (!source.includes("--made-with-bamboo")) continue;
205
188
  const optimized = pruneStaticCss(source, session);
206
189
  output.source = optimized;
207
190
  if (optimized === source) continue;
208
- if (!rename) continue;
191
+ if (!rename) {
192
+ output.source = source;
193
+ continue;
194
+ }
209
195
  const nextName = output.fileName.replace(/\.css$/, `.b-${toHash(optimized)}.css`);
210
196
  if (nextName === output.fileName) continue;
211
197
  if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
212
198
  const previous = output.fileName;
213
199
  output.fileName = nextName;
214
200
  replaceAssetReferences(bundle, previous, nextName, session.sourcemap);
215
- delete bundle[bundleName];
216
- bundle[nextName] = output;
217
201
  }
218
202
  };
219
203
  /**
@@ -319,8 +303,7 @@ const bamboocssCss = (options) => {
319
303
  generateBundle: {
320
304
  order: "post",
321
305
  handler(_, bundle) {
322
- const rolldown = Boolean(this.meta?.rolldownVersion);
323
- optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset && !rolldown });
306
+ optimizeStaticCssAssets(bundle, session, { rename: renameCssAsset });
324
307
  if (!session.transformedFiles.size) return;
325
308
  if (!Object.values(bundle).some((output) => {
326
309
  if (!carriesGeneratedCss(output)) return false;
@@ -2669,18 +2652,7 @@ const createStaticStyleSetCompiler = (ctx, runtimeCss, allocateClassString = (cl
2669
2652
  };
2670
2653
  //#endregion
2671
2654
  //#region src/static-session.ts
2672
- const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2673
- const denseName = (index) => {
2674
- let value = index;
2675
- let result = "";
2676
- do {
2677
- result = ALPHABET[value % 52] + result;
2678
- value = Math.floor(value / 52) - 1;
2679
- } while (value >= 0);
2680
- return `_${result}`;
2681
- };
2682
- const createStaticCompilationSession = (denseClassNames = true) => {
2683
- const mode = denseClassNames === true ? "stable" : denseClassNames;
2655
+ const createStaticCompilationSession = () => {
2684
2656
  const session = {
2685
2657
  utilityLayer: "utilities",
2686
2658
  sourcemap: false,
@@ -2690,28 +2662,10 @@ const createStaticCompilationSession = (denseClassNames = true) => {
2690
2662
  prunableClasses: /* @__PURE__ */ new Set(),
2691
2663
  viewTransitionClasses: /* @__PURE__ */ new Set(),
2692
2664
  usedClasses: /* @__PURE__ */ new Set(),
2693
- denseClasses: /* @__PURE__ */ new Map(),
2694
- semanticClasses: /* @__PURE__ */ new Map(),
2695
- denseClassNames: Boolean(mode),
2696
- allocateClassString(className) {
2697
- if (!mode) return className;
2698
- return className.split(" ").filter(Boolean).map((semantic) => {
2699
- let dense = session.denseClasses.get(semantic);
2700
- if (!dense) {
2701
- dense = mode === "local" ? denseName(session.denseClasses.size) : `_${toHash(semantic)}`;
2702
- const collision = session.semanticClasses.get(dense);
2703
- if (collision && collision !== semantic) throw new Error(`Bamboo compact class collision between ${JSON.stringify(collision)} and ${JSON.stringify(semantic)}. Disable \`denseClassNames\` for this build.`);
2704
- session.denseClasses.set(semantic, dense);
2705
- session.semanticClasses.set(dense, semantic);
2706
- }
2707
- return dense;
2708
- }).join(" ");
2709
- },
2710
2665
  markClassUsed(className) {
2711
2666
  for (const token of className.split(" ")) {
2712
2667
  if (!token) continue;
2713
- const semantic = session.semanticClasses.get(token) ?? token;
2714
- session.usedClasses.add(esc(semantic));
2668
+ session.usedClasses.add(esc(token));
2715
2669
  }
2716
2670
  }
2717
2671
  };
@@ -2724,8 +2678,6 @@ const resetStaticCompilationSession = (session) => {
2724
2678
  session.prunableClasses.clear();
2725
2679
  session.viewTransitionClasses.clear();
2726
2680
  session.usedClasses.clear();
2727
- session.denseClasses.clear();
2728
- session.semanticClasses.clear();
2729
2681
  };
2730
2682
  //#endregion
2731
2683
  //#region src/plugin.ts
@@ -2779,7 +2731,7 @@ const formatSkipped = (id, skipped) => {
2779
2731
  * with no matching rule.
2780
2732
  */
2781
2733
  const bamboocss = (options = {}) => {
2782
- const { configPath, cwd, reportSkipped = false, reportSummary = true, denseClassNames = true, maxRecipeStates, renameCssAsset = true } = options;
2734
+ const { configPath, cwd, reportSkipped = false, reportSummary = true, maxRecipeStates, renameCssAsset = true } = options;
2783
2735
  if (maxRecipeStates !== void 0 && (!Number.isSafeInteger(maxRecipeStates) || maxRecipeStates < 1)) throw new Error("bamboocss: `maxRecipeStates` must be a positive safe integer.");
2784
2736
  /** Totals across the build, for the summary. */
2785
2737
  const totals = {
@@ -2788,7 +2740,7 @@ const bamboocss = (options = {}) => {
2788
2740
  filesWithFolds: 0,
2789
2741
  skipped: /* @__PURE__ */ new Map()
2790
2742
  };
2791
- const staticSession = createStaticCompilationSession(denseClassNames);
2743
+ const staticSession = createStaticCompilationSession();
2792
2744
  const survivors = [];
2793
2745
  const survivorKeys = /* @__PURE__ */ new Set();
2794
2746
  const addSurvivor = (entry) => {
@@ -2835,9 +2787,8 @@ const bamboocss = (options = {}) => {
2835
2787
  cwd
2836
2788
  }).then((loaded) => {
2837
2789
  ctx = loaded;
2838
- const semanticCss = createRuntimeCss(loaded);
2839
- runtimeCss = (...styles) => staticSession.allocateClassString(semanticCss(...styles));
2840
- styleCompiler = createStaticStyleSetCompiler(loaded, runtimeCss, staticSession.allocateClassString);
2790
+ runtimeCss = createRuntimeCss(loaded);
2791
+ styleCompiler = createStaticStyleSetCompiler(loaded, runtimeCss);
2841
2792
  });
2842
2793
  await setup;
2843
2794
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bamboocss/vite",
3
- "version": "1.36.5",
3
+ "version": "1.37.1",
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.36.5",
44
- "@bamboocss/extractor": "1.36.5",
45
- "@bamboocss/core": "1.36.5",
46
- "@bamboocss/node": "1.36.5",
47
- "@bamboocss/logger": "1.36.5",
48
- "@bamboocss/shared": "1.36.5",
49
- "@bamboocss/types": "1.36.5"
43
+ "@bamboocss/config": "1.37.1",
44
+ "@bamboocss/extractor": "1.37.1",
45
+ "@bamboocss/logger": "1.37.1",
46
+ "@bamboocss/node": "1.37.1",
47
+ "@bamboocss/core": "1.37.1",
48
+ "@bamboocss/shared": "1.37.1",
49
+ "@bamboocss/types": "1.37.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@jridgewell/trace-mapping": "^0.3.31",
53
53
  "vite": "7.2.6",
54
- "@bamboocss/fixture": "1.36.5"
54
+ "@bamboocss/fixture": "1.37.1"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "vite": ">=5"