@astryxdesign/cli 0.6.3-canary.45a9bf5 → 0.6.3-canary.54be197

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.
@@ -12,10 +12,9 @@
12
12
  * - A .d.ts (plus an optional .variants.d.ts for custom prop values)
13
13
  *
14
14
  * It performs the writes and returns a `theme.build` receipt — its `warnings`
15
- * carry override problems, every declaration core's generator dropped because
16
- * its value could not stay one CSS declaration, and any fonts the theme names
17
- * but does not load (font-warning.mjs) — or `null` when the theme produced no
18
- * CSS (nothing to build). Errors throw AstryxError (with
15
+ * carry override problems and any fonts the theme names but does not load
16
+ * (font-warning.mjs) — or `null` when the theme produced no CSS (nothing to
17
+ * build). Errors throw AstryxError (with
19
18
  * a stable code). Human progress is emitted through the shared `logger`
20
19
  * (silent by default), so the CLI keeps its exact output while a programmatic
21
20
  * caller stays quiet.
@@ -2304,15 +2303,7 @@ async function themeBuildInternal(
2304
2303
  const scopeSelector = themeScopeStart(themeDef.name);
2305
2304
  const scopeTo = THEME_SCOPE_TO;
2306
2305
 
2307
- // Older cores ignore this optional collector. Current core writes the same
2308
- // warning text here that runtime callers receive on the console.
2309
- /** @type {string[]} */
2310
- const droppedDeclarations = [];
2311
-
2312
- const {component, prose} = _generateThemeRulesSplit(
2313
- resolvedTheme,
2314
- droppedDeclarations,
2315
- );
2306
+ const {component, prose} = _generateThemeRulesSplit(resolvedTheme);
2316
2307
  const cssParts = [];
2317
2308
  // Prose element defaults always ship — the `<Theme>` runtime
2318
2309
  // (generateThemeCSS) always emits them, so the build must too, or the
@@ -2331,7 +2322,7 @@ async function themeBuildInternal(
2331
2322
  let adaptationCss;
2332
2323
  try {
2333
2324
  adaptationCss = _generateAdaptationCSS
2334
- ? _generateAdaptationCSS(resolvedTheme, droppedDeclarations)
2325
+ ? _generateAdaptationCSS(resolvedTheme)
2335
2326
  : {component: '', prose: ''};
2336
2327
  } catch (error) {
2337
2328
  const message =
@@ -2377,16 +2368,11 @@ async function themeBuildInternal(
2377
2368
  // adaptations on the same resolved leaf.
2378
2369
  let onMediaCss = '';
2379
2370
  if (_generateOnMediaCSS) {
2380
- onMediaCss = _generateOnMediaCSS(resolvedTheme, droppedDeclarations);
2371
+ onMediaCss = _generateOnMediaCSS(resolvedTheme);
2381
2372
  if (onMediaCss) {
2382
2373
  cssParts.push(`@layer astryx-theme {\n${onMediaCss}\n}`);
2383
2374
  }
2384
2375
  }
2385
- for (const message of droppedDeclarations) {
2386
- const w = `Declaration ${message}. The generated CSS omits it; fix the value in the theme source.`;
2387
- warningMessages.push(w);
2388
- logger.warn(` ⚠ ${w}`);
2389
- }
2390
2376
  if (cssParts.length === 0) {
2391
2377
  logger.log('No overrides found — nothing to build.');
2392
2378
  return null;
@@ -206,133 +206,6 @@ describe('themeBuild() — receipt', () => {
206
206
  });
207
207
  });
208
208
 
209
- describe('themeBuild() — dropped declarations reach the receipt', () => {
210
- // Core's generator refuses a declaration whose value would end it early
211
- // (an unquoted `;` or brace, an unclosed string/comment/url). The runtime
212
- // says so on the console; a build has a receipt, so every drop must land in
213
- // `warnings` — a programmatic caller otherwise sees `warnings: []` while the
214
- // CSS silently omits a value the generated JS still carries.
215
- it('reports every dropped declaration, from every generator path, in warnings', async () => {
216
- const themeFile = path.join(tmpDir, 'dropped.mjs');
217
- fs.writeFileSync(
218
- themeFile,
219
- `export default {
220
- name: 'dropped',
221
- tokens: {
222
- '--color-bg': '#0a0a0a } body { background: url(https://example.com/token) ',
223
- },
224
- components: {
225
- button: {
226
- 'variant:secondary': {
227
- backgroundColor: 'red; background-image: url(https://example.com/component)',
228
- ':hover': {color: '"https://example.com/pseudo'},
229
- },
230
- },
231
- },
232
- onDark: {
233
- tokens: {'--color-bg': 'url(https://example.com/dark'},
234
- },
235
- adaptations: {
236
- rules: [
237
- {
238
- when: {pointer: 'coarse'},
239
- value: {tokens: {'--color-bg': 'red /* https://example.com/adaptation'}},
240
- },
241
- ],
242
- },
243
- };\n`,
244
- );
245
-
246
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
247
- let result;
248
- try {
249
- result = await themeBuild('dropped.mjs', {}, {cwd: tmpDir});
250
- // Drops are collected, not printed: the programmatic API stays silent.
251
- expect(warnSpy).not.toHaveBeenCalled();
252
- } finally {
253
- warnSpy.mockRestore();
254
- }
255
-
256
- const css = fs.readFileSync(path.join(tmpDir, 'dropped.css'), 'utf8');
257
- expect(css).not.toContain('example.com');
258
-
259
- const warnings = result?.data.warnings ?? [];
260
- expect(warnings).toHaveLength(5);
261
- expect(warnings).toEqual(
262
- expect.arrayContaining([
263
- expect.stringMatching(
264
- /^Declaration dropped "--color-bg" in tokens: an unquoted "}" would close the rule/,
265
- ),
266
- expect.stringMatching(
267
- /^Declaration dropped "background-color" in components\.button\["variant:secondary"\]: an unquoted ";" would end the declaration/,
268
- ),
269
- expect.stringMatching(
270
- /^Declaration dropped "color" in components\.button\["variant:secondary"\]\[":hover"\]: an unclosed " string/,
271
- ),
272
- expect.stringMatching(
273
- /^Declaration dropped "--color-bg" in onDark\.tokens: an unclosed url\(/,
274
- ),
275
- expect.stringMatching(
276
- /^Declaration dropped "--color-bg" in adaptations\[0\]\.tokens: an unclosed \/\* comment/,
277
- ),
278
- ]),
279
- );
280
- for (const w of warnings) {
281
- expect(w).toContain('The generated CSS omits it');
282
- }
283
- });
284
-
285
- it('generates CSS for legacy null tokens without losing neighboring declarations', async () => {
286
- fs.writeFileSync(
287
- path.join(tmpDir, 'legacy.mjs'),
288
- `export default {
289
- name: 'legacy',
290
- tokens: {'--color-background-body': null, '--spacing-4': 12},
291
- onDark: {tokens: {'--color-background-body': null}},
292
- components: {button: {base: {borderRadius: '4px'}}},
293
- };\n`,
294
- );
295
-
296
- const result = await themeBuild('legacy.mjs', {}, {cwd: tmpDir});
297
- const css = fs.readFileSync(path.join(tmpDir, 'legacy.css'), 'utf8');
298
- expect(css).toContain('--color-background-body: null;');
299
- expect(css).toContain('--spacing-4: 12;');
300
- expect(css).toContain('border-radius: 4px;');
301
- expect(result?.data.warnings).toEqual([]);
302
- });
303
-
304
- it('keeps valid CSS that carries semicolons, and reports nothing', async () => {
305
- const themeFile = path.join(tmpDir, 'kept.mjs');
306
- fs.writeFileSync(
307
- themeFile,
308
- `export default {
309
- name: 'kept',
310
- tokens: {'--font-family-body': 'Gill\\\\ Sans, "Segoe;UI", serif /* ; */'},
311
- components: {
312
- button: {
313
- 'variant:secondary': {
314
- backgroundImage: 'URL(data:image/svg+xml;base64,PHN2Zz4=)',
315
- WebkitLineClamp: '2',
316
- },
317
- },
318
- },
319
- };\n`,
320
- );
321
-
322
- const result = await themeBuild('kept.mjs', {}, {cwd: tmpDir});
323
- const css = fs.readFileSync(path.join(tmpDir, 'kept.css'), 'utf8');
324
-
325
- expect(css).toContain(
326
- '--font-family-body: Gill\\ Sans, "Segoe;UI", serif /* ; */;',
327
- );
328
- expect(css).toContain(
329
- 'background-image: URL(data:image/svg+xml;base64,PHN2Zz4=);',
330
- );
331
- expect(css).toContain('-webkit-line-clamp: 2;');
332
- expect(result?.data.warnings).toEqual([]);
333
- });
334
- });
335
-
336
209
  describe('themeBuild() — nothing to build', () => {
337
210
  it('returns null and writes nothing when the generator yields no CSS', async () => {
338
211
  const themeFile = path.join(tmpDir, 'empty.mjs');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/cli",
3
- "version": "0.6.3-canary.45a9bf5",
3
+ "version": "0.6.3-canary.54be197",
4
4
  "displayName": "CLI",
5
5
  "description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
6
6
  "author": "Meta Open Source",
@@ -100,10 +100,10 @@
100
100
  "zod": "^4.4.3"
101
101
  },
102
102
  "peerDependencies": {
103
- "@astryxdesign/charts": "0.6.3-canary.45a9bf5",
104
- "@astryxdesign/core": "0.6.3-canary.45a9bf5",
105
- "@astryxdesign/lab": "0.6.3-canary.45a9bf5",
106
- "@astryxdesign/theme-neutral": "0.6.3-canary.45a9bf5",
103
+ "@astryxdesign/charts": "0.6.3-canary.54be197",
104
+ "@astryxdesign/core": "0.6.3-canary.54be197",
105
+ "@astryxdesign/lab": "0.6.3-canary.54be197",
106
+ "@astryxdesign/theme-neutral": "0.6.3-canary.54be197",
107
107
  "gpt-tokenizer": "^3.4.0"
108
108
  },
109
109
  "peerDependenciesMeta": {
@@ -121,10 +121,10 @@
121
121
  }
122
122
  },
123
123
  "devDependencies": {
124
- "@astryxdesign/charts": "0.6.3-canary.45a9bf5",
125
- "@astryxdesign/core": "0.6.3-canary.45a9bf5",
126
- "@astryxdesign/lab": "0.6.3-canary.45a9bf5",
127
- "@astryxdesign/theme-neutral": "0.6.3-canary.45a9bf5",
124
+ "@astryxdesign/charts": "0.6.3-canary.54be197",
125
+ "@astryxdesign/core": "0.6.3-canary.54be197",
126
+ "@astryxdesign/lab": "0.6.3-canary.54be197",
127
+ "@astryxdesign/theme-neutral": "0.6.3-canary.54be197",
128
128
  "@heroicons/react": "^2.2.0",
129
129
  "@stylexjs/stylex": "^0.19.0",
130
130
  "@types/babel__core": "^7.20.5",