@bamboocss/vite 1.45.4 → 1.46.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/chunk.cjs ADDED
@@ -0,0 +1,28 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ Object.defineProperty(exports, "__toESM", {
24
+ enumerable: true,
25
+ get: function() {
26
+ return __toESM;
27
+ }
28
+ });
@@ -0,0 +1,17 @@
1
+ //#region src/class-name.ts
2
+ /**
3
+ * A class name with its CSS escapes removed, which is the only spelling the compiler and
4
+ * stylesheet inventory both agree on.
5
+ *
6
+ * This stays in the eager graph because the output lifecycle uses it for a synchronous safety
7
+ * check. The PostCSS parser which consumes the same spelling belongs to the lazy CSS-output
8
+ * boundary instead.
9
+ */
10
+ const bare = (className) => className.replaceAll("\\", "");
11
+ //#endregion
12
+ Object.defineProperty(exports, "bare", {
13
+ enumerable: true,
14
+ get: function() {
15
+ return bare;
16
+ }
17
+ });
@@ -0,0 +1,12 @@
1
+ //#region src/class-name.ts
2
+ /**
3
+ * A class name with its CSS escapes removed, which is the only spelling the compiler and
4
+ * stylesheet inventory both agree on.
5
+ *
6
+ * This stays in the eager graph because the output lifecycle uses it for a synchronous safety
7
+ * check. The PostCSS parser which consumes the same spelling belongs to the lazy CSS-output
8
+ * boundary instead.
9
+ */
10
+ const bare = (className) => className.replaceAll("\\", "");
11
+ //#endregion
12
+ export { bare as t };
@@ -0,0 +1,9 @@
1
+ var _bamboocss_config = require("@bamboocss/config");
2
+ Object.keys(_bamboocss_config).forEach(function(k) {
3
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
4
+ enumerable: true,
5
+ get: function() {
6
+ return _bamboocss_config[k];
7
+ }
8
+ });
9
+ });
@@ -0,0 +1,2 @@
1
+ export * from "@bamboocss/config";
2
+ export {};
@@ -0,0 +1,218 @@
1
+ const require_chunk = require("./chunk.cjs");
2
+ const require_class_name = require("./class-name.cjs");
3
+ let _bamboocss_shared = require("@bamboocss/shared");
4
+ let _ampproject_remapping = require("@ampproject/remapping");
5
+ _ampproject_remapping = require_chunk.__toESM(_ampproject_remapping);
6
+ let magic_string = require("magic-string");
7
+ magic_string = require_chunk.__toESM(magic_string);
8
+ let postcss = require("postcss");
9
+ postcss = require_chunk.__toESM(postcss);
10
+ let postcss_selector_parser = require("postcss-selector-parser");
11
+ postcss_selector_parser = require_chunk.__toESM(postcss_selector_parser);
12
+ //#region src/prune-static-css.ts
13
+ /** The generated declaration that identifies a Bamboo stylesheet after minification. */
14
+ const SENTINEL = "--made-with-bamboo";
15
+ /**
16
+ * Remove source-graph atoms no transformed module can emit.
17
+ *
18
+ * `prunableClasses` contains only atoms extracted from the source graph. Explicit `staticCss`
19
+ * additions are absent and survive as a safelist; graph atoms are governed by the transformed
20
+ * module reachability set, regardless of whether they originated in `css()` or a recipe.
21
+ */
22
+ const pruneStaticCss = (css, session, { environment, prune = true, requiredClasses } = {}) => {
23
+ if (!css.includes(SENTINEL)) return css;
24
+ const root = postcss.default.parse(css);
25
+ const prunable = new Set([...session.prunableClasses].map(require_class_name.bare));
26
+ const used = new Set([...session.usedClasses].map(require_class_name.bare));
27
+ const isUtilityRule = (rule) => {
28
+ let parent = rule.parent;
29
+ while (parent) {
30
+ if (parent.type === "atrule") {
31
+ const atRule = parent;
32
+ if (atRule.name === "layer" && atRule.params === session.utilityLayer) return true;
33
+ }
34
+ parent = parent.parent;
35
+ }
36
+ return false;
37
+ };
38
+ if (prune) root.walkRules((rule) => {
39
+ if (!isUtilityRule(rule)) return;
40
+ let removedAny = false;
41
+ let selector;
42
+ try {
43
+ selector = (0, postcss_selector_parser.default)((selectors) => {
44
+ selectors.each((candidate) => {
45
+ const classes = /* @__PURE__ */ new Set();
46
+ candidate.walkClasses((classNode) => {
47
+ classes.add(require_class_name.bare(classNode.toString().slice(1)));
48
+ });
49
+ if (classes.size !== 1) return;
50
+ const [className] = classes;
51
+ if (!className || !prunable.has(className) || used.has(className)) return;
52
+ candidate.remove();
53
+ removedAny = true;
54
+ session.prunedClasses.add(className);
55
+ });
56
+ }).processSync(rule.selector);
57
+ } catch {
58
+ return;
59
+ }
60
+ if (!removedAny) return;
61
+ if (!selector.trim()) {
62
+ rule.remove();
63
+ return;
64
+ }
65
+ rule.selector = selector;
66
+ });
67
+ let removed = true;
68
+ while (removed) {
69
+ removed = false;
70
+ root.walkAtRules((rule) => {
71
+ if (rule.nodes?.length !== 0) return;
72
+ rule.remove();
73
+ removed = true;
74
+ });
75
+ }
76
+ const present = /* @__PURE__ */ new Set();
77
+ root.walkRules((rule) => {
78
+ if (!isUtilityRule(rule)) return;
79
+ try {
80
+ (0, postcss_selector_parser.default)((selectors) => {
81
+ selectors.walkClasses((classNode) => {
82
+ present.add(require_class_name.bare(classNode.toString().slice(1)));
83
+ });
84
+ }).processSync(rule.selector);
85
+ } catch {}
86
+ });
87
+ const required = requiredClasses ?? new Set([...session.usedClasses].filter((className) => prunable.has(require_class_name.bare(className))));
88
+ const orphaned = [];
89
+ for (const className of required) {
90
+ if (/\s/.test(className)) {
91
+ orphaned.push(className);
92
+ continue;
93
+ }
94
+ if (present.has(require_class_name.bare(className))) continue;
95
+ orphaned.push(className);
96
+ }
97
+ if (orphaned.length) {
98
+ const describe = (className) => {
99
+ if (/\s/.test(className)) return ` ${className}\n (malformed key: a class name cannot contain whitespace)`;
100
+ const normalized = require_class_name.bare(className);
101
+ const extracted = prunable.has(normalized) ? "in the extracted atoms" : "NOT extracted";
102
+ const near = [...present].filter((candidate) => candidate !== className && candidate.replaceAll("\\", "") === normalized);
103
+ return ` ${className}\n (${extracted}; no rule in the sheet` + (near.length ? `; a rule exists under ${near.map((n) => JSON.stringify(n)).join(", ")}` : "") + `)`;
104
+ };
105
+ const environmentDescription = environment ? ` for the ${JSON.stringify(environment)} environment` : "";
106
+ throw new Error(`bamboocss: ${orphaned.length} compiled class(es) still named by live output have no rule in the candidate stylesheet${environmentDescription}. Elements carrying them would render unstyled.\n\n${(0, _bamboocss_shared.truncateList)(orphaned.map(describe), {
107
+ unit: "class",
108
+ separator: "\n"
109
+ })}\n\nThe current source generation no longer provides every rule required by the JavaScript outputs still on disk. Bamboo refused to replace the prior stylesheet. Finish rebuilding every output which retains an older generation, then rebuild the stylesheet. If every output is already current, report this as a compiler bug with the block above.`);
110
+ }
111
+ return root.toString();
112
+ };
113
+ //#endregion
114
+ //#region src/css-output-module.ts
115
+ const INLINE_SOURCE_MAP = /\n?\/\/# sourceMappingURL=data:application\/json[^\n]*$/;
116
+ /** Rewrite one generated chunk without invalidating all mappings after the changed string. */
117
+ const replaceChunkReference = (chunk, bundle, previous, next, sourcemap) => {
118
+ if (!chunk.code.includes(previous)) return;
119
+ const magic = new magic_string.default(chunk.code);
120
+ let index = chunk.code.indexOf(previous);
121
+ while (index !== -1) {
122
+ magic.overwrite(index, index + previous.length, next);
123
+ index = chunk.code.indexOf(previous, index + previous.length);
124
+ }
125
+ chunk.code = magic.toString();
126
+ if (!chunk.map) return;
127
+ const file = chunk.map.file;
128
+ const debugId = chunk.map.debugId;
129
+ const combined = (0, _ampproject_remapping.default)([magic.generateMap({
130
+ source: chunk.fileName,
131
+ hires: "boundary"
132
+ }), chunk.map], () => null);
133
+ if (file) combined.file = file;
134
+ if (debugId) combined.debugId = debugId;
135
+ const rollupMap = combined;
136
+ rollupMap.toUrl = () => `data:application/json;charset=utf-8;base64,${Buffer.from(combined.toString()).toString("base64")}`;
137
+ chunk.map = rollupMap;
138
+ if (sourcemap === "inline") {
139
+ chunk.code = chunk.code.replace(INLINE_SOURCE_MAP, "");
140
+ chunk.code += `\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(combined.toString()).toString("base64")}`;
141
+ return;
142
+ }
143
+ const mapAsset = bundle[`${chunk.fileName}.map`];
144
+ if (mapAsset?.type === "asset") mapAsset.source = combined.toString();
145
+ };
146
+ /** Replace an emitted filename wherever Vite or Rollup has already recorded it. */
147
+ const replaceAssetReferences = (bundle, previous, next, sourcemap) => {
148
+ const replace = (value) => value.replaceAll(previous, next);
149
+ for (const output of Object.values(bundle)) {
150
+ if (output.type === "asset") {
151
+ if (typeof output.source === "string") output.source = replace(output.source);
152
+ continue;
153
+ }
154
+ replaceChunkReference(output, bundle, previous, next, sourcemap);
155
+ const referencedFiles = output.referencedFiles;
156
+ if (referencedFiles) output.referencedFiles = referencedFiles.map(replace);
157
+ const importedCss = output.viteMetadata?.importedCss;
158
+ if (importedCss?.delete(previous)) importedCss.add(next);
159
+ }
160
+ };
161
+ /**
162
+ * Could this bundle entry be the generated stylesheet?
163
+ *
164
+ * The filename is checked before the bytes because the alternative decodes every asset in the
165
+ * bundle to a UTF-8 string in order to search it — fonts, images and sourcemaps included. On an
166
+ * app with a large asset graph that is seconds of decode and a lot of garbage, twice over, to
167
+ * answer a question the extension already answers. The marker is a CSS custom property, so it
168
+ * cannot occur anywhere but CSS.
169
+ */
170
+ const isCssAsset = (output) => output.type === "asset" && output.fileName.endsWith(".css");
171
+ /** Decode a generated Bamboo stylesheet, or decline any other bundle entry. */
172
+ const generatedCssSource = (output) => {
173
+ if (!isCssAsset(output)) return void 0;
174
+ const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
175
+ return source.includes("--made-with-bamboo") ? source : void 0;
176
+ };
177
+ /** Whether this bundle replaces a previously generated Bamboo stylesheet. */
178
+ const containsGeneratedCssAsset = (bundle) => Object.values(bundle).some((output) => generatedCssSource(output) !== void 0);
179
+ /**
180
+ * Prune compiler-owned CSS, then give any sheet whose bytes changed a hash of those bytes.
181
+ *
182
+ * Rollup has already expanded `[hash]` when `generateBundle` runs. Mutating only `source`
183
+ * would therefore leave two different reachable subsets under one CDN key. The extra final
184
+ * hash is not cosmetic: it makes late graph reachability cache-safe.
185
+ *
186
+ * Renaming is therefore not a choice this takes. Pruned bytes under the unpruned sheet's name
187
+ * is the one outcome that must never be reachable, and a sheet nothing was removed from keeps
188
+ * its name because its bytes are unchanged — so "rename" is a consequence of "the bytes moved",
189
+ * not a second option. `prune` is the only knob.
190
+ */
191
+ const optimizeStaticCssAssets = (bundle, session, options = {}) => {
192
+ const { environment, prune = true, requiredClasses, sourcemap = session.sourcemap } = options;
193
+ /** Assets in this bundle that carry the generated stylesheet, pruned or not. */
194
+ let sheets = 0;
195
+ for (const output of Object.values(bundle)) {
196
+ const source = generatedCssSource(output);
197
+ if (source === void 0) continue;
198
+ sheets++;
199
+ const optimized = pruneStaticCss(source, session, {
200
+ environment,
201
+ prune,
202
+ requiredClasses
203
+ });
204
+ if (!prune) continue;
205
+ output.source = optimized;
206
+ if (optimized === source) continue;
207
+ const nextName = output.fileName.replace(/\.css$/, `.b-${(0, _bamboocss_shared.toHash)(optimized)}.css`);
208
+ if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
209
+ const previous = output.fileName;
210
+ output.fileName = nextName;
211
+ replaceAssetReferences(bundle, previous, nextName, sourcemap);
212
+ }
213
+ return { sheets };
214
+ };
215
+ //#endregion
216
+ exports.containsGeneratedCssAsset = containsGeneratedCssAsset;
217
+ exports.optimizeStaticCssAssets = optimizeStaticCssAssets;
218
+ exports.pruneStaticCss = pruneStaticCss;
@@ -0,0 +1,211 @@
1
+ import { t as bare } from "./class-name.mjs";
2
+ import { toHash, truncateList } from "@bamboocss/shared";
3
+ import remapping from "@ampproject/remapping";
4
+ import MagicString from "magic-string";
5
+ import postcss from "postcss";
6
+ import selectorParser from "postcss-selector-parser";
7
+ //#region src/prune-static-css.ts
8
+ /** The generated declaration that identifies a Bamboo stylesheet after minification. */
9
+ const SENTINEL = "--made-with-bamboo";
10
+ /**
11
+ * Remove source-graph atoms no transformed module can emit.
12
+ *
13
+ * `prunableClasses` contains only atoms extracted from the source graph. Explicit `staticCss`
14
+ * additions are absent and survive as a safelist; graph atoms are governed by the transformed
15
+ * module reachability set, regardless of whether they originated in `css()` or a recipe.
16
+ */
17
+ const pruneStaticCss = (css, session, { environment, prune = true, requiredClasses } = {}) => {
18
+ if (!css.includes(SENTINEL)) return css;
19
+ const root = postcss.parse(css);
20
+ const prunable = new Set([...session.prunableClasses].map(bare));
21
+ const used = new Set([...session.usedClasses].map(bare));
22
+ const isUtilityRule = (rule) => {
23
+ let parent = rule.parent;
24
+ while (parent) {
25
+ if (parent.type === "atrule") {
26
+ const atRule = parent;
27
+ if (atRule.name === "layer" && atRule.params === session.utilityLayer) return true;
28
+ }
29
+ parent = parent.parent;
30
+ }
31
+ return false;
32
+ };
33
+ if (prune) root.walkRules((rule) => {
34
+ if (!isUtilityRule(rule)) return;
35
+ let removedAny = false;
36
+ let selector;
37
+ try {
38
+ selector = selectorParser((selectors) => {
39
+ selectors.each((candidate) => {
40
+ const classes = /* @__PURE__ */ new Set();
41
+ candidate.walkClasses((classNode) => {
42
+ classes.add(bare(classNode.toString().slice(1)));
43
+ });
44
+ if (classes.size !== 1) return;
45
+ const [className] = classes;
46
+ if (!className || !prunable.has(className) || used.has(className)) return;
47
+ candidate.remove();
48
+ removedAny = true;
49
+ session.prunedClasses.add(className);
50
+ });
51
+ }).processSync(rule.selector);
52
+ } catch {
53
+ return;
54
+ }
55
+ if (!removedAny) return;
56
+ if (!selector.trim()) {
57
+ rule.remove();
58
+ return;
59
+ }
60
+ rule.selector = selector;
61
+ });
62
+ let removed = true;
63
+ while (removed) {
64
+ removed = false;
65
+ root.walkAtRules((rule) => {
66
+ if (rule.nodes?.length !== 0) return;
67
+ rule.remove();
68
+ removed = true;
69
+ });
70
+ }
71
+ const present = /* @__PURE__ */ new Set();
72
+ root.walkRules((rule) => {
73
+ if (!isUtilityRule(rule)) return;
74
+ try {
75
+ selectorParser((selectors) => {
76
+ selectors.walkClasses((classNode) => {
77
+ present.add(bare(classNode.toString().slice(1)));
78
+ });
79
+ }).processSync(rule.selector);
80
+ } catch {}
81
+ });
82
+ const required = requiredClasses ?? new Set([...session.usedClasses].filter((className) => prunable.has(bare(className))));
83
+ const orphaned = [];
84
+ for (const className of required) {
85
+ if (/\s/.test(className)) {
86
+ orphaned.push(className);
87
+ continue;
88
+ }
89
+ if (present.has(bare(className))) continue;
90
+ orphaned.push(className);
91
+ }
92
+ if (orphaned.length) {
93
+ const describe = (className) => {
94
+ if (/\s/.test(className)) return ` ${className}\n (malformed key: a class name cannot contain whitespace)`;
95
+ const normalized = bare(className);
96
+ const extracted = prunable.has(normalized) ? "in the extracted atoms" : "NOT extracted";
97
+ const near = [...present].filter((candidate) => candidate !== className && candidate.replaceAll("\\", "") === normalized);
98
+ return ` ${className}\n (${extracted}; no rule in the sheet` + (near.length ? `; a rule exists under ${near.map((n) => JSON.stringify(n)).join(", ")}` : "") + `)`;
99
+ };
100
+ const environmentDescription = environment ? ` for the ${JSON.stringify(environment)} environment` : "";
101
+ throw new Error(`bamboocss: ${orphaned.length} compiled class(es) still named by live output have no rule in the candidate stylesheet${environmentDescription}. Elements carrying them would render unstyled.\n\n${truncateList(orphaned.map(describe), {
102
+ unit: "class",
103
+ separator: "\n"
104
+ })}\n\nThe current source generation no longer provides every rule required by the JavaScript outputs still on disk. Bamboo refused to replace the prior stylesheet. Finish rebuilding every output which retains an older generation, then rebuild the stylesheet. If every output is already current, report this as a compiler bug with the block above.`);
105
+ }
106
+ return root.toString();
107
+ };
108
+ //#endregion
109
+ //#region src/css-output-module.ts
110
+ const INLINE_SOURCE_MAP = /\n?\/\/# sourceMappingURL=data:application\/json[^\n]*$/;
111
+ /** Rewrite one generated chunk without invalidating all mappings after the changed string. */
112
+ const replaceChunkReference = (chunk, bundle, previous, next, sourcemap) => {
113
+ if (!chunk.code.includes(previous)) return;
114
+ const magic = new MagicString(chunk.code);
115
+ let index = chunk.code.indexOf(previous);
116
+ while (index !== -1) {
117
+ magic.overwrite(index, index + previous.length, next);
118
+ index = chunk.code.indexOf(previous, index + previous.length);
119
+ }
120
+ chunk.code = magic.toString();
121
+ if (!chunk.map) return;
122
+ const file = chunk.map.file;
123
+ const debugId = chunk.map.debugId;
124
+ const combined = remapping([magic.generateMap({
125
+ source: chunk.fileName,
126
+ hires: "boundary"
127
+ }), chunk.map], () => null);
128
+ if (file) combined.file = file;
129
+ if (debugId) combined.debugId = debugId;
130
+ const rollupMap = combined;
131
+ rollupMap.toUrl = () => `data:application/json;charset=utf-8;base64,${Buffer.from(combined.toString()).toString("base64")}`;
132
+ chunk.map = rollupMap;
133
+ if (sourcemap === "inline") {
134
+ chunk.code = chunk.code.replace(INLINE_SOURCE_MAP, "");
135
+ chunk.code += `\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(combined.toString()).toString("base64")}`;
136
+ return;
137
+ }
138
+ const mapAsset = bundle[`${chunk.fileName}.map`];
139
+ if (mapAsset?.type === "asset") mapAsset.source = combined.toString();
140
+ };
141
+ /** Replace an emitted filename wherever Vite or Rollup has already recorded it. */
142
+ const replaceAssetReferences = (bundle, previous, next, sourcemap) => {
143
+ const replace = (value) => value.replaceAll(previous, next);
144
+ for (const output of Object.values(bundle)) {
145
+ if (output.type === "asset") {
146
+ if (typeof output.source === "string") output.source = replace(output.source);
147
+ continue;
148
+ }
149
+ replaceChunkReference(output, bundle, previous, next, sourcemap);
150
+ const referencedFiles = output.referencedFiles;
151
+ if (referencedFiles) output.referencedFiles = referencedFiles.map(replace);
152
+ const importedCss = output.viteMetadata?.importedCss;
153
+ if (importedCss?.delete(previous)) importedCss.add(next);
154
+ }
155
+ };
156
+ /**
157
+ * Could this bundle entry be the generated stylesheet?
158
+ *
159
+ * The filename is checked before the bytes because the alternative decodes every asset in the
160
+ * bundle to a UTF-8 string in order to search it — fonts, images and sourcemaps included. On an
161
+ * app with a large asset graph that is seconds of decode and a lot of garbage, twice over, to
162
+ * answer a question the extension already answers. The marker is a CSS custom property, so it
163
+ * cannot occur anywhere but CSS.
164
+ */
165
+ const isCssAsset = (output) => output.type === "asset" && output.fileName.endsWith(".css");
166
+ /** Decode a generated Bamboo stylesheet, or decline any other bundle entry. */
167
+ const generatedCssSource = (output) => {
168
+ if (!isCssAsset(output)) return void 0;
169
+ const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString();
170
+ return source.includes("--made-with-bamboo") ? source : void 0;
171
+ };
172
+ /** Whether this bundle replaces a previously generated Bamboo stylesheet. */
173
+ const containsGeneratedCssAsset = (bundle) => Object.values(bundle).some((output) => generatedCssSource(output) !== void 0);
174
+ /**
175
+ * Prune compiler-owned CSS, then give any sheet whose bytes changed a hash of those bytes.
176
+ *
177
+ * Rollup has already expanded `[hash]` when `generateBundle` runs. Mutating only `source`
178
+ * would therefore leave two different reachable subsets under one CDN key. The extra final
179
+ * hash is not cosmetic: it makes late graph reachability cache-safe.
180
+ *
181
+ * Renaming is therefore not a choice this takes. Pruned bytes under the unpruned sheet's name
182
+ * is the one outcome that must never be reachable, and a sheet nothing was removed from keeps
183
+ * its name because its bytes are unchanged — so "rename" is a consequence of "the bytes moved",
184
+ * not a second option. `prune` is the only knob.
185
+ */
186
+ const optimizeStaticCssAssets = (bundle, session, options = {}) => {
187
+ const { environment, prune = true, requiredClasses, sourcemap = session.sourcemap } = options;
188
+ /** Assets in this bundle that carry the generated stylesheet, pruned or not. */
189
+ let sheets = 0;
190
+ for (const output of Object.values(bundle)) {
191
+ const source = generatedCssSource(output);
192
+ if (source === void 0) continue;
193
+ sheets++;
194
+ const optimized = pruneStaticCss(source, session, {
195
+ environment,
196
+ prune,
197
+ requiredClasses
198
+ });
199
+ if (!prune) continue;
200
+ output.source = optimized;
201
+ if (optimized === source) continue;
202
+ const nextName = output.fileName.replace(/\.css$/, `.b-${toHash(optimized)}.css`);
203
+ if (bundle[nextName] && bundle[nextName] !== output) throw new Error(`bamboocss: final CSS asset name collision at ${JSON.stringify(nextName)}.`);
204
+ const previous = output.fileName;
205
+ output.fileName = nextName;
206
+ replaceAssetReferences(bundle, previous, nextName, sourcemap);
207
+ }
208
+ return { sheets };
209
+ };
210
+ //#endregion
211
+ export { containsGeneratedCssAsset, optimizeStaticCssAssets, pruneStaticCss };