@bamboocss/generator 1.53.1 → 1.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4073,14 +4073,32 @@ var Generator = class extends _bamboocss_core.Context {
4073
4073
  getParserCss = (decoder) => {
4074
4074
  return generateParserCss(this, decoder);
4075
4075
  };
4076
+ /**
4077
+ * Each atom's first call site, by the class name the sheet writes it under.
4078
+ *
4079
+ * Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
4080
+ * integration asked for origins. Several hashes can decode to one class; the first wins.
4081
+ */
4082
+ getAtomOrigins = () => {
4083
+ const byHash = this.encoder.atomOrigins();
4084
+ const origins = /* @__PURE__ */ new Map();
4085
+ if (!byHash.size) return origins;
4086
+ for (const atom of this.decoder.collect(this.encoder).atomic) {
4087
+ const origin = byHash.get(atom.hash);
4088
+ if (origin && !origins.has(atom.className)) origins.set(atom.className, origin);
4089
+ }
4090
+ return origins;
4091
+ };
4076
4092
  getCss = (stylesheet) => {
4077
- let css = (stylesheet ?? this.createSheet()).toCss({ minify: this.config.minify });
4093
+ const sheet = stylesheet ?? this.createSheet();
4094
+ let css = sheet.toCss({ minify: this.config.minify });
4078
4095
  if (this.hooks["cssgen:done"]) css = this.hooks["cssgen:done"]({
4079
4096
  artifact: "styles.css",
4080
4097
  content: css
4081
4098
  }) ?? css;
4082
4099
  this.assertNoUnresolvedTokens();
4083
4100
  this.reportRawValues();
4101
+ this.reportInvalidDeclarations(sheet);
4084
4102
  return css;
4085
4103
  };
4086
4104
  /**
@@ -4187,6 +4205,63 @@ var Generator = class extends _bamboocss_core.Context {
4187
4205
  throw new _bamboocss_shared.BambooError("UNRESOLVED_TOKEN", `${found.size} style value(s) name a token that does not exist:\n\n${detail}\n\nEach is emitted as written, which parses — so the stylesheet is valid and nothing downstream objects. The browser drops the declaration at compute time and the style is simply absent from the element, which surfaces as "this never applied" a long way from the typo that caused it. Write \`[value]\` to mark one as a literal, or set \`unresolvedToken: 'warn'\` to report these without failing.`);
4188
4206
  };
4189
4207
  /**
4208
+ * The findings `warn` has already printed, keyed `property:value`.
4209
+ *
4210
+ * A dev server emits the sheet on every edit, and extraction is additive within a watch, so
4211
+ * a finding that warned on every rebuild would bury the edit that introduced the next one.
4212
+ * Per process, like the sheet it describes.
4213
+ */
4214
+ reportedInvalidDeclarations = /* @__PURE__ */ new Set();
4215
+ /**
4216
+ * Report every declaration in the sheet just emitted that its property's grammar rejects.
4217
+ *
4218
+ * The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
4219
+ * for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
4220
+ * has had its say — which is the only place a transform that handed a value through
4221
+ * unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
4222
+ * `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
4223
+ * emitted.
4224
+ *
4225
+ * A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
4226
+ * one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
4227
+ * value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
4228
+ * would otherwise be rejected again here as the declaration it became. Keyed on the
4229
+ * property the utility *emits*, because that is how the sheet spells it.
4230
+ *
4231
+ * `warn` reports each distinct declaration once per process. `error` lists everything the
4232
+ * sheet holds each time, because each time the build is failing on it.
4233
+ */
4234
+ reportInvalidDeclarations = (sheet) => {
4235
+ const severity = this.utility.invalidDeclaration;
4236
+ if (severity === "off") return;
4237
+ const owned = /* @__PURE__ */ new Set();
4238
+ for (const ref of this.utility.unresolvedTokens.values()) owned.add(`${this.utility.cssPropertyOf(ref.prop)}:${ref.value}`);
4239
+ const id = (finding) => `${finding.prop}:${finding.value}`;
4240
+ const findings = sheet.invalidDeclarations.filter((finding) => !owned.has(id(finding)));
4241
+ if (!findings.length) return;
4242
+ const describe = ({ prop, value, selector, layer, count }) => {
4243
+ return `- \`${prop}: ${value}\`${selector ? ` in \`${selector}\`` : ""}${layer ? `, \`@layer ${layer}\`` : ""}${count > 1 ? ` (${count} rules)` : ""}`;
4244
+ };
4245
+ const dropped = "Each parses, so the stylesheet is valid and nothing downstream objects. The browser drops the declaration at compute time and the style is simply absent from the element.";
4246
+ if (severity === "error") {
4247
+ const detail = (0, _bamboocss_shared.truncateList)(findings.map(describe), {
4248
+ limit: 25,
4249
+ unit: "declaration",
4250
+ separator: "\n"
4251
+ });
4252
+ throw new _bamboocss_shared.BambooError("INVALID_DECLARATION", `${findings.length} declaration(s) in the stylesheet are not valid CSS for their property:\n\n${detail}\n\n${dropped} Fix the value, or set \`invalidDeclaration: 'warn'\` to report these without failing.`);
4253
+ }
4254
+ const fresh = findings.filter((finding) => !this.reportedInvalidDeclarations.has(id(finding)));
4255
+ if (!fresh.length) return;
4256
+ for (const finding of fresh) this.reportedInvalidDeclarations.add(id(finding));
4257
+ const detail = (0, _bamboocss_shared.truncateList)(fresh.map(describe), {
4258
+ limit: 25,
4259
+ unit: "declaration",
4260
+ separator: "\n"
4261
+ });
4262
+ _bamboocss_logger.logger.warn("sheet", `${fresh.length} declaration(s) in the stylesheet are not valid CSS for their property:\n\n${detail}\n\n${dropped} Set \`invalidDeclaration: 'error'\` to fail the build on these, or \`'off'\` to stop reporting them.`);
4263
+ };
4264
+ /**
4190
4265
  * Get CSS for a specific layer from the stylesheet
4191
4266
  */
4192
4267
  getLayerCss = (sheet, layer) => {
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Context, StyleDecoder, Stylesheet } from "@bamboocss/core";
1
+ import { AtomOrigin, Context, StyleDecoder, Stylesheet } from "@bamboocss/core";
2
2
  import { ArtifactId, CssArtifactType, LoadConfigResult, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
3
3
 
4
4
  //#region src/generator.d.ts
@@ -131,6 +131,13 @@ declare class Generator extends Context {
131
131
  */
132
132
  private getAlwaysKeptTokenVars;
133
133
  getParserCss: (decoder: StyleDecoder) => string;
134
+ /**
135
+ * Each atom's first call site, by the class name the sheet writes it under.
136
+ *
137
+ * Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
138
+ * integration asked for origins. Several hashes can decode to one class; the first wins.
139
+ */
140
+ getAtomOrigins: () => Map<string, AtomOrigin>;
134
141
  getCss: (stylesheet?: Stylesheet) => string;
135
142
  /**
136
143
  * Fail on a style value shaped like a token path that names no token.
@@ -192,6 +199,34 @@ declare class Generator extends Context {
192
199
  */
193
200
  reportRawValues: () => void;
194
201
  assertNoUnresolvedTokens: () => void;
202
+ /**
203
+ * The findings `warn` has already printed, keyed `property:value`.
204
+ *
205
+ * A dev server emits the sheet on every edit, and extraction is additive within a watch, so
206
+ * a finding that warned on every rebuild would bury the edit that introduced the next one.
207
+ * Per process, like the sheet it describes.
208
+ */
209
+ private reportedInvalidDeclarations;
210
+ /**
211
+ * Report every declaration in the sheet just emitted that its property's grammar rejects.
212
+ *
213
+ * The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
214
+ * for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
215
+ * has had its say — which is the only place a transform that handed a value through
216
+ * unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
217
+ * `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
218
+ * emitted.
219
+ *
220
+ * A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
221
+ * one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
222
+ * value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
223
+ * would otherwise be rejected again here as the declaration it became. Keyed on the
224
+ * property the utility *emits*, because that is how the sheet spells it.
225
+ *
226
+ * `warn` reports each distinct declaration once per process. `error` lists everything the
227
+ * sheet holds each time, because each time the build is failing on it.
228
+ */
229
+ reportInvalidDeclarations: (sheet: Stylesheet) => void;
195
230
  /**
196
231
  * Get CSS for a specific layer from the stylesheet
197
232
  */
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Context, StyleDecoder, Stylesheet } from "@bamboocss/core";
1
+ import { AtomOrigin, Context, StyleDecoder, Stylesheet } from "@bamboocss/core";
2
2
  import { ArtifactId, CssArtifactType, LoadConfigResult, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
3
3
 
4
4
  //#region src/generator.d.ts
@@ -131,6 +131,13 @@ declare class Generator extends Context {
131
131
  */
132
132
  private getAlwaysKeptTokenVars;
133
133
  getParserCss: (decoder: StyleDecoder) => string;
134
+ /**
135
+ * Each atom's first call site, by the class name the sheet writes it under.
136
+ *
137
+ * Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
138
+ * integration asked for origins. Several hashes can decode to one class; the first wins.
139
+ */
140
+ getAtomOrigins: () => Map<string, AtomOrigin>;
134
141
  getCss: (stylesheet?: Stylesheet) => string;
135
142
  /**
136
143
  * Fail on a style value shaped like a token path that names no token.
@@ -192,6 +199,34 @@ declare class Generator extends Context {
192
199
  */
193
200
  reportRawValues: () => void;
194
201
  assertNoUnresolvedTokens: () => void;
202
+ /**
203
+ * The findings `warn` has already printed, keyed `property:value`.
204
+ *
205
+ * A dev server emits the sheet on every edit, and extraction is additive within a watch, so
206
+ * a finding that warned on every rebuild would bury the edit that introduced the next one.
207
+ * Per process, like the sheet it describes.
208
+ */
209
+ private reportedInvalidDeclarations;
210
+ /**
211
+ * Report every declaration in the sheet just emitted that its property's grammar rejects.
212
+ *
213
+ * The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
214
+ * for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
215
+ * has had its say — which is the only place a transform that handed a value through
216
+ * unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
217
+ * `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
218
+ * emitted.
219
+ *
220
+ * A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
221
+ * one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
222
+ * value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
223
+ * would otherwise be rejected again here as the declaration it became. Keyed on the
224
+ * property the utility *emits*, because that is how the sheet spells it.
225
+ *
226
+ * `warn` reports each distinct declaration once per process. `error` lists everything the
227
+ * sheet holds each time, because each time the build is failing on it.
228
+ */
229
+ reportInvalidDeclarations: (sheet: Stylesheet) => void;
195
230
  /**
196
231
  * Get CSS for a specific layer from the stylesheet
197
232
  */
package/dist/index.mjs CHANGED
@@ -4047,14 +4047,32 @@ var Generator = class extends Context {
4047
4047
  getParserCss = (decoder) => {
4048
4048
  return generateParserCss(this, decoder);
4049
4049
  };
4050
+ /**
4051
+ * Each atom's first call site, by the class name the sheet writes it under.
4052
+ *
4053
+ * Only what the encoder recorded — see `StyleEncoder.recordOrigins` — so empty unless an
4054
+ * integration asked for origins. Several hashes can decode to one class; the first wins.
4055
+ */
4056
+ getAtomOrigins = () => {
4057
+ const byHash = this.encoder.atomOrigins();
4058
+ const origins = /* @__PURE__ */ new Map();
4059
+ if (!byHash.size) return origins;
4060
+ for (const atom of this.decoder.collect(this.encoder).atomic) {
4061
+ const origin = byHash.get(atom.hash);
4062
+ if (origin && !origins.has(atom.className)) origins.set(atom.className, origin);
4063
+ }
4064
+ return origins;
4065
+ };
4050
4066
  getCss = (stylesheet) => {
4051
- let css = (stylesheet ?? this.createSheet()).toCss({ minify: this.config.minify });
4067
+ const sheet = stylesheet ?? this.createSheet();
4068
+ let css = sheet.toCss({ minify: this.config.minify });
4052
4069
  if (this.hooks["cssgen:done"]) css = this.hooks["cssgen:done"]({
4053
4070
  artifact: "styles.css",
4054
4071
  content: css
4055
4072
  }) ?? css;
4056
4073
  this.assertNoUnresolvedTokens();
4057
4074
  this.reportRawValues();
4075
+ this.reportInvalidDeclarations(sheet);
4058
4076
  return css;
4059
4077
  };
4060
4078
  /**
@@ -4161,6 +4179,63 @@ var Generator = class extends Context {
4161
4179
  throw new BambooError("UNRESOLVED_TOKEN", `${found.size} style value(s) name a token that does not exist:\n\n${detail}\n\nEach is emitted as written, which parses — so the stylesheet is valid and nothing downstream objects. The browser drops the declaration at compute time and the style is simply absent from the element, which surfaces as "this never applied" a long way from the typo that caused it. Write \`[value]\` to mark one as a literal, or set \`unresolvedToken: 'warn'\` to report these without failing.`);
4162
4180
  };
4163
4181
  /**
4182
+ * The findings `warn` has already printed, keyed `property:value`.
4183
+ *
4184
+ * A dev server emits the sheet on every edit, and extraction is additive within a watch, so
4185
+ * a finding that warned on every rebuild would bury the edit that introduced the next one.
4186
+ * Per process, like the sheet it describes.
4187
+ */
4188
+ reportedInvalidDeclarations = /* @__PURE__ */ new Set();
4189
+ /**
4190
+ * Report every declaration in the sheet just emitted that its property's grammar rejects.
4191
+ *
4192
+ * The other side of `assertNoUnresolvedTokens`. That one reads the *values* the source asked
4193
+ * for; this reads what the sheet *contains*, after every utility transform, mixin and recipe
4194
+ * has had its say — which is the only place a transform that handed a value through
4195
+ * unchanged, or a `[…]` literal that was never valid CSS, can be seen at all. Collected by
4196
+ * `Stylesheet.toCss`, where the finished tree exists; graded here, where the sheet is
4197
+ * emitted.
4198
+ *
4199
+ * A finding the unresolved-token pass owns is left to it, whatever that pass is set to, so
4200
+ * one mistake is one report and `unresolvedToken: 'off'` means silence rather than the same
4201
+ * value reported in this check's voice: `display: 'flexx'` is that pass's grammar half, and
4202
+ * would otherwise be rejected again here as the declaration it became. Keyed on the
4203
+ * property the utility *emits*, because that is how the sheet spells it.
4204
+ *
4205
+ * `warn` reports each distinct declaration once per process. `error` lists everything the
4206
+ * sheet holds each time, because each time the build is failing on it.
4207
+ */
4208
+ reportInvalidDeclarations = (sheet) => {
4209
+ const severity = this.utility.invalidDeclaration;
4210
+ if (severity === "off") return;
4211
+ const owned = /* @__PURE__ */ new Set();
4212
+ for (const ref of this.utility.unresolvedTokens.values()) owned.add(`${this.utility.cssPropertyOf(ref.prop)}:${ref.value}`);
4213
+ const id = (finding) => `${finding.prop}:${finding.value}`;
4214
+ const findings = sheet.invalidDeclarations.filter((finding) => !owned.has(id(finding)));
4215
+ if (!findings.length) return;
4216
+ const describe = ({ prop, value, selector, layer, count }) => {
4217
+ return `- \`${prop}: ${value}\`${selector ? ` in \`${selector}\`` : ""}${layer ? `, \`@layer ${layer}\`` : ""}${count > 1 ? ` (${count} rules)` : ""}`;
4218
+ };
4219
+ const dropped = "Each parses, so the stylesheet is valid and nothing downstream objects. The browser drops the declaration at compute time and the style is simply absent from the element.";
4220
+ if (severity === "error") {
4221
+ const detail = truncateList(findings.map(describe), {
4222
+ limit: 25,
4223
+ unit: "declaration",
4224
+ separator: "\n"
4225
+ });
4226
+ throw new BambooError("INVALID_DECLARATION", `${findings.length} declaration(s) in the stylesheet are not valid CSS for their property:\n\n${detail}\n\n${dropped} Fix the value, or set \`invalidDeclaration: 'warn'\` to report these without failing.`);
4227
+ }
4228
+ const fresh = findings.filter((finding) => !this.reportedInvalidDeclarations.has(id(finding)));
4229
+ if (!fresh.length) return;
4230
+ for (const finding of fresh) this.reportedInvalidDeclarations.add(id(finding));
4231
+ const detail = truncateList(fresh.map(describe), {
4232
+ limit: 25,
4233
+ unit: "declaration",
4234
+ separator: "\n"
4235
+ });
4236
+ logger.warn("sheet", `${fresh.length} declaration(s) in the stylesheet are not valid CSS for their property:\n\n${detail}\n\n${dropped} Set \`invalidDeclaration: 'error'\` to fail the build on these, or \`'off'\` to stop reporting them.`);
4237
+ };
4238
+ /**
4164
4239
  * Get CSS for a specific layer from the stylesheet
4165
4240
  */
4166
4241
  getLayerCss = (sheet, layer) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bamboocss/generator",
3
- "version": "1.53.1",
3
+ "version": "1.54.0",
4
4
  "description": "The css generator for css bamboo",
5
5
  "homepage": "https://bamboocss.com",
6
6
  "license": "MIT",
@@ -38,12 +38,12 @@
38
38
  "pluralize": "8.0.0",
39
39
  "postcss": "8.5.26",
40
40
  "ts-pattern": "5.9.0",
41
- "@bamboocss/core": "1.53.1",
42
- "@bamboocss/is-valid-prop": "^1.53.1",
43
- "@bamboocss/logger": "1.53.1",
44
- "@bamboocss/shared": "1.53.1",
45
- "@bamboocss/token-dictionary": "1.53.1",
46
- "@bamboocss/types": "1.53.1"
41
+ "@bamboocss/core": "1.54.0",
42
+ "@bamboocss/is-valid-prop": "^1.54.0",
43
+ "@bamboocss/logger": "1.54.0",
44
+ "@bamboocss/shared": "1.54.0",
45
+ "@bamboocss/token-dictionary": "1.54.0",
46
+ "@bamboocss/types": "1.54.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/pluralize": "0.0.33"