dispersa 0.4.2 → 1.0.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.
Files changed (62) hide show
  1. package/README.md +73 -39
  2. package/dist/android-CRDfSB3_.d.cts +126 -0
  3. package/dist/android-DANJjjPO.d.ts +126 -0
  4. package/dist/builders.cjs +220 -64
  5. package/dist/builders.cjs.map +1 -1
  6. package/dist/builders.d.cts +15 -13
  7. package/dist/builders.d.ts +15 -13
  8. package/dist/builders.js +220 -64
  9. package/dist/builders.js.map +1 -1
  10. package/dist/cli/cli.js +120 -7
  11. package/dist/cli/cli.js.map +1 -1
  12. package/dist/cli/config.d.ts +321 -0
  13. package/dist/cli/config.js.map +1 -1
  14. package/dist/cli/index.js +119 -7
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/dispersa-BC1kDF5u.d.ts +118 -0
  17. package/dist/dispersa-DL3J_Pmz.d.cts +118 -0
  18. package/dist/errors-qT4sJgSA.d.cts +104 -0
  19. package/dist/errors-qT4sJgSA.d.ts +104 -0
  20. package/dist/errors.cjs.map +1 -1
  21. package/dist/errors.d.cts +1 -83
  22. package/dist/errors.d.ts +1 -83
  23. package/dist/errors.js.map +1 -1
  24. package/dist/filters.cjs.map +1 -1
  25. package/dist/filters.d.cts +2 -2
  26. package/dist/filters.d.ts +2 -2
  27. package/dist/filters.js.map +1 -1
  28. package/dist/{index-CNT2Meyf.d.cts → index-Dajm5rvM.d.ts} +311 -132
  29. package/dist/{index-CqdaN3X0.d.ts → index-De6SjZYH.d.cts} +311 -132
  30. package/dist/index.cjs +813 -355
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +8 -329
  33. package/dist/index.d.ts +8 -329
  34. package/dist/index.js +807 -355
  35. package/dist/index.js.map +1 -1
  36. package/dist/lint.cjs +1017 -0
  37. package/dist/lint.cjs.map +1 -0
  38. package/dist/lint.d.cts +463 -0
  39. package/dist/lint.d.ts +463 -0
  40. package/dist/lint.js +997 -0
  41. package/dist/lint.js.map +1 -0
  42. package/dist/preprocessors.d.cts +2 -2
  43. package/dist/preprocessors.d.ts +2 -2
  44. package/dist/renderers.cjs.map +1 -1
  45. package/dist/renderers.d.cts +7 -6
  46. package/dist/renderers.d.ts +7 -6
  47. package/dist/renderers.js.map +1 -1
  48. package/dist/transforms.cjs +0 -12
  49. package/dist/transforms.cjs.map +1 -1
  50. package/dist/transforms.d.cts +3 -7
  51. package/dist/transforms.d.ts +3 -7
  52. package/dist/transforms.js +1 -12
  53. package/dist/transforms.js.map +1 -1
  54. package/dist/{types-CZb19kiq.d.ts → types-8MLtztK3.d.ts} +56 -1
  55. package/dist/{types-CussyWwe.d.cts → types-BHBHRm0a.d.cts} +56 -1
  56. package/dist/{types-BAv39mum.d.cts → types-BltzwVYK.d.cts} +1 -1
  57. package/dist/{types-DWKq-eJj.d.cts → types-CAdUV-fa.d.cts} +1 -1
  58. package/dist/{types-CzHa7YkW.d.ts → types-DztXKlka.d.ts} +1 -1
  59. package/dist/{types-Bc0kA7De.d.ts → types-TQHV1MrY.d.cts} +19 -1
  60. package/dist/{types-Bc0kA7De.d.cts → types-TQHV1MrY.d.ts} +19 -1
  61. package/dist/{types-BzNcG-rI.d.ts → types-ebxDimRz.d.ts} +1 -1
  62. package/package.json +11 -1
@@ -1,8 +1,9 @@
1
- import { F as FileFunction, L as LifecycleHooks, C as CssRendererOptions, O as OutputConfig, T as TailwindRendererOptions, I as IosRendererOptions, A as AndroidRendererOptions } from './index-CNT2Meyf.cjs';
2
- import { F as Filter } from './types-DWKq-eJj.cjs';
3
- import { T as Transform } from './types-BAv39mum.cjs';
4
- import { a as JsonRendererOptions, J as JsModuleRendererOptions } from './types-CussyWwe.cjs';
5
- import './types-Bc0kA7De.cjs';
1
+ import { F as FileFunction, L as LifecycleHooks, C as CssRendererOptions, O as OutputConfig } from './index-De6SjZYH.cjs';
2
+ import { F as Filter } from './types-CAdUV-fa.cjs';
3
+ import { T as Transform } from './types-BltzwVYK.cjs';
4
+ import { a as JsonRendererOptions, J as JsModuleRendererOptions } from './types-BHBHRm0a.cjs';
5
+ import { T as TailwindRendererOptions, I as IosRendererOptions, A as AndroidRendererOptions } from './android-CRDfSB3_.cjs';
6
+ import './types-TQHV1MrY.cjs';
6
7
  import 'json-schema-to-ts';
7
8
 
8
9
  /**
@@ -52,19 +53,20 @@ type CssBuilderConfig = BuilderConfigBase & CssRendererOptions;
52
53
  *
53
54
  * The `file` property is optional. When omitted, content is returned in-memory instead
54
55
  * of being written to disk. The `file` property is required when `buildPath` is provided
55
- * to `dispersa.build()`.
56
+ * to `build()`.
56
57
  *
57
58
  * @example Basic CSS bundle with transforms
58
59
  * ```typescript
59
60
  * import { css } from 'dispersa'
60
- * import { nameKebabCase } from 'dispersa/transforms'
61
+ * import { colorToHex } from 'dispersa/transforms'
61
62
  *
63
+ * // nameKebabCase() is applied automatically before your transforms
62
64
  * const config = css({
63
65
  * name: 'css',
64
66
  * file: 'tokens.css',
65
67
  * preset: 'bundle',
66
68
  * selector: ':root',
67
- * transforms: [nameKebabCase()]
69
+ * transforms: [colorToHex()]
68
70
  * })
69
71
  * ```
70
72
  *
@@ -92,7 +94,7 @@ type CssBuilderConfig = BuilderConfigBase & CssRendererOptions;
92
94
  * selector: ':root'
93
95
  * })
94
96
  * // Use without buildPath to get content in-memory
95
- * const result = await dispersa.build({ outputs: [config] })
97
+ * const result = await build({ outputs: [config] })
96
98
  * console.log(result.outputs[0].content)
97
99
  * ```
98
100
  */
@@ -117,7 +119,7 @@ type JsonBuilderConfig = BuilderConfigBase & JsonRendererOptions;
117
119
  *
118
120
  * The `file` property is optional. When omitted, content is returned in-memory instead
119
121
  * of being written to disk. The `file` property is required when `buildPath` is provided
120
- * to `dispersa.build()`.
122
+ * to `build()`.
121
123
  *
122
124
  * @example Standalone JSON with flat structure
123
125
  * ```typescript
@@ -154,7 +156,7 @@ type JsonBuilderConfig = BuilderConfigBase & JsonRendererOptions;
154
156
  * structure: 'flat'
155
157
  * })
156
158
  * // Use without buildPath to get content in-memory
157
- * const result = await dispersa.build({ outputs: [config] })
159
+ * const result = await build({ outputs: [config] })
158
160
  * console.log(result.outputs[0].content)
159
161
  * ```
160
162
  */
@@ -180,7 +182,7 @@ type JsBuilderConfig = BuilderConfigBase & JsModuleRendererOptions;
180
182
  *
181
183
  * The `file` property is optional. When omitted, content is returned in-memory instead
182
184
  * of being written to disk. The `file` property is required when `buildPath` is provided
183
- * to `dispersa.build()`.
185
+ * to `build()`.
184
186
  *
185
187
  * @example Bundle JS with helper function
186
188
  * ```typescript
@@ -219,7 +221,7 @@ type JsBuilderConfig = BuilderConfigBase & JsModuleRendererOptions;
219
221
  * structure: 'flat'
220
222
  * })
221
223
  * // Use without buildPath to get content in-memory
222
- * const result = await dispersa.build({ outputs: [config] })
224
+ * const result = await build({ outputs: [config] })
223
225
  * console.log(result.outputs[0].content)
224
226
  * ```
225
227
  */
@@ -1,8 +1,9 @@
1
- import { F as FileFunction, L as LifecycleHooks, C as CssRendererOptions, O as OutputConfig, T as TailwindRendererOptions, I as IosRendererOptions, A as AndroidRendererOptions } from './index-CqdaN3X0.js';
2
- import { F as Filter } from './types-BzNcG-rI.js';
3
- import { T as Transform } from './types-CzHa7YkW.js';
4
- import { a as JsonRendererOptions, J as JsModuleRendererOptions } from './types-CZb19kiq.js';
5
- import './types-Bc0kA7De.js';
1
+ import { F as FileFunction, L as LifecycleHooks, C as CssRendererOptions, O as OutputConfig } from './index-Dajm5rvM.js';
2
+ import { F as Filter } from './types-ebxDimRz.js';
3
+ import { T as Transform } from './types-DztXKlka.js';
4
+ import { a as JsonRendererOptions, J as JsModuleRendererOptions } from './types-8MLtztK3.js';
5
+ import { T as TailwindRendererOptions, I as IosRendererOptions, A as AndroidRendererOptions } from './android-DANJjjPO.js';
6
+ import './types-TQHV1MrY.js';
6
7
  import 'json-schema-to-ts';
7
8
 
8
9
  /**
@@ -52,19 +53,20 @@ type CssBuilderConfig = BuilderConfigBase & CssRendererOptions;
52
53
  *
53
54
  * The `file` property is optional. When omitted, content is returned in-memory instead
54
55
  * of being written to disk. The `file` property is required when `buildPath` is provided
55
- * to `dispersa.build()`.
56
+ * to `build()`.
56
57
  *
57
58
  * @example Basic CSS bundle with transforms
58
59
  * ```typescript
59
60
  * import { css } from 'dispersa'
60
- * import { nameKebabCase } from 'dispersa/transforms'
61
+ * import { colorToHex } from 'dispersa/transforms'
61
62
  *
63
+ * // nameKebabCase() is applied automatically before your transforms
62
64
  * const config = css({
63
65
  * name: 'css',
64
66
  * file: 'tokens.css',
65
67
  * preset: 'bundle',
66
68
  * selector: ':root',
67
- * transforms: [nameKebabCase()]
69
+ * transforms: [colorToHex()]
68
70
  * })
69
71
  * ```
70
72
  *
@@ -92,7 +94,7 @@ type CssBuilderConfig = BuilderConfigBase & CssRendererOptions;
92
94
  * selector: ':root'
93
95
  * })
94
96
  * // Use without buildPath to get content in-memory
95
- * const result = await dispersa.build({ outputs: [config] })
97
+ * const result = await build({ outputs: [config] })
96
98
  * console.log(result.outputs[0].content)
97
99
  * ```
98
100
  */
@@ -117,7 +119,7 @@ type JsonBuilderConfig = BuilderConfigBase & JsonRendererOptions;
117
119
  *
118
120
  * The `file` property is optional. When omitted, content is returned in-memory instead
119
121
  * of being written to disk. The `file` property is required when `buildPath` is provided
120
- * to `dispersa.build()`.
122
+ * to `build()`.
121
123
  *
122
124
  * @example Standalone JSON with flat structure
123
125
  * ```typescript
@@ -154,7 +156,7 @@ type JsonBuilderConfig = BuilderConfigBase & JsonRendererOptions;
154
156
  * structure: 'flat'
155
157
  * })
156
158
  * // Use without buildPath to get content in-memory
157
- * const result = await dispersa.build({ outputs: [config] })
159
+ * const result = await build({ outputs: [config] })
158
160
  * console.log(result.outputs[0].content)
159
161
  * ```
160
162
  */
@@ -180,7 +182,7 @@ type JsBuilderConfig = BuilderConfigBase & JsModuleRendererOptions;
180
182
  *
181
183
  * The `file` property is optional. When omitted, content is returned in-memory instead
182
184
  * of being written to disk. The `file` property is required when `buildPath` is provided
183
- * to `dispersa.build()`.
185
+ * to `build()`.
184
186
  *
185
187
  * @example Bundle JS with helper function
186
188
  * ```typescript
@@ -219,7 +221,7 @@ type JsBuilderConfig = BuilderConfigBase & JsModuleRendererOptions;
219
221
  * structure: 'flat'
220
222
  * })
221
223
  * // Use without buildPath to get content in-memory
222
- * const result = await dispersa.build({ outputs: [config] })
224
+ * const result = await build({ outputs: [config] })
223
225
  * console.log(result.outputs[0].content)
224
226
  * ```
225
227
  */
package/dist/builders.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { kebabCase } from 'change-case';
1
2
  import { converter, formatHex8, formatHex } from 'culori';
2
3
  import prettier from 'prettier';
3
4
 
@@ -40,19 +41,6 @@ var init_errors = __esm({
40
41
  });
41
42
 
42
43
  // src/shared/utils/token-utils.ts
43
- function formatDeprecationMessage(token, description = "", format = "bracket") {
44
- if (token.$deprecated == null || token.$deprecated === false) {
45
- return description;
46
- }
47
- const deprecationMsg = typeof token.$deprecated === "string" ? token.$deprecated : "";
48
- if (format === "comment") {
49
- const msg2 = deprecationMsg ? ` ${deprecationMsg}` : "";
50
- return `DEPRECATED${msg2}`;
51
- }
52
- const msg = deprecationMsg ? `: ${deprecationMsg}` : "";
53
- const prefix = `[DEPRECATED${msg}]`;
54
- return description ? `${prefix} ${description}` : prefix;
55
- }
56
44
  function stripInternalTokenMetadata(tokens) {
57
45
  const cleaned = {};
58
46
  for (const [name, token] of Object.entries(tokens)) {
@@ -126,7 +114,7 @@ function indentStr(width, level) {
126
114
  function buildGeneratedFileHeader() {
127
115
  return [
128
116
  "// Generated by Dispersa - do not edit manually",
129
- "// https://github.com/timges/dispersa"
117
+ "// https://github.com/dispersa-core/dispersa"
130
118
  ].join("\n");
131
119
  }
132
120
  function toSafeIdentifier(name, keywords, capitalize) {
@@ -330,6 +318,94 @@ var init_utils = __esm({
330
318
  }
331
319
  });
332
320
 
321
+ // src/renderers/metadata.ts
322
+ function sanitizeText(text, format) {
323
+ switch (format) {
324
+ case "css":
325
+ case "tailwind":
326
+ return text.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ").trim();
327
+ case "kotlin":
328
+ return text.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
329
+ case "js":
330
+ case "swift":
331
+ return text.replace(/\r?\n/g, " ").trim();
332
+ default:
333
+ return text.trim();
334
+ }
335
+ }
336
+ function buildDeprecationText(token) {
337
+ if (token.$deprecated == null || token.$deprecated === false) {
338
+ return "";
339
+ }
340
+ const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
341
+ return msg ? `DEPRECATED: ${msg}` : "DEPRECATED";
342
+ }
343
+ function buildTokenDescriptionComment(token, format) {
344
+ if (!token.$description || token.$description === "") {
345
+ return void 0;
346
+ }
347
+ const text = sanitizeText(token.$description, format);
348
+ switch (format) {
349
+ case "css":
350
+ case "tailwind":
351
+ return `/* ${text} */`;
352
+ case "js":
353
+ return `// ${text}`;
354
+ case "swift":
355
+ return `/// ${text}`;
356
+ case "kotlin":
357
+ return `/** ${text} */`;
358
+ default:
359
+ return void 0;
360
+ }
361
+ }
362
+ function buildTokenDeprecationComment(token, format) {
363
+ const text = buildDeprecationText(token);
364
+ if (!text) {
365
+ return void 0;
366
+ }
367
+ switch (format) {
368
+ case "css":
369
+ case "tailwind":
370
+ return `/* ${text} */`;
371
+ case "js":
372
+ return `// ${text}`;
373
+ case "swift":
374
+ return `/// ${text}`;
375
+ case "kotlin":
376
+ return `/** ${text} */`;
377
+ default:
378
+ return void 0;
379
+ }
380
+ }
381
+ function buildModifierComment(modifier, context) {
382
+ return `/* Modifier: ${modifier}=${context} */`;
383
+ }
384
+ function buildSwiftDeprecationAttribute(token) {
385
+ if (token.$deprecated == null || token.$deprecated === false) {
386
+ return void 0;
387
+ }
388
+ const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
389
+ if (msg) {
390
+ return `@available(*, deprecated, message: "${sanitizeText(msg, "swift")}")`;
391
+ }
392
+ return "@available(*, deprecated)";
393
+ }
394
+ function buildKotlinDeprecationAnnotation(token) {
395
+ if (token.$deprecated == null || token.$deprecated === false) {
396
+ return void 0;
397
+ }
398
+ const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
399
+ if (msg) {
400
+ return `@Deprecated(message = "${sanitizeText(msg, "kotlin")}")`;
401
+ }
402
+ return "@Deprecated";
403
+ }
404
+ var init_metadata = __esm({
405
+ "src/renderers/metadata.ts"() {
406
+ }
407
+ });
408
+
333
409
  // src/renderers/bundlers/js.ts
334
410
  var js_exports = {};
335
411
  __export(js_exports, {
@@ -434,7 +510,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
434
510
  }
435
511
  const metadata = buildMetadata(resolver);
436
512
  const jsBlocks = [];
437
- for (const { tokens, modifierInputs } of bundleData) {
513
+ for (const { tokens, modifierInputs, isBase } of bundleData) {
438
514
  const cleanTokens = stripInternalMetadata(tokens);
439
515
  const key = buildStableDashKey({
440
516
  modifierInputs,
@@ -442,10 +518,30 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
442
518
  defaults: metadata.defaults
443
519
  });
444
520
  const camelKey = toCamelKey(key);
521
+ const normalizedInputs = normalizeModifierInputs(modifierInputs);
522
+ const modifierParts = [];
523
+ for (const dim of metadata.dimensions) {
524
+ const value = normalizedInputs[dim.toLowerCase()];
525
+ if (value) {
526
+ modifierParts.push(`${dim}=${value}`);
527
+ }
528
+ }
445
529
  const formattedJs = await formatTokens(cleanTokens);
446
530
  const tokenObject = extractObjectFromJsModule(formattedJs);
447
531
  const indentedObject = tokenObject.replace(/\n/g, "\n ");
448
- jsBlocks.push(` // ${key}
532
+ let comment;
533
+ if (modifierParts.length > 0) {
534
+ const modifierPart = modifierParts[0];
535
+ const eqIndex = modifierPart.indexOf("=");
536
+ const modifier = modifierPart.slice(0, eqIndex);
537
+ const context = modifierPart.slice(eqIndex + 1);
538
+ comment = buildModifierComment(modifier, context);
539
+ } else if (isBase) {
540
+ comment = "// Base permutation";
541
+ } else {
542
+ comment = `// ${key}`;
543
+ }
544
+ jsBlocks.push(` ${comment}
449
545
  ${JSON.stringify(camelKey)}: ${indentedObject}`);
450
546
  }
451
547
  return assembleJsBundle(metadata, jsBlocks, options?.generateHelper ?? false);
@@ -453,6 +549,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
453
549
  var init_js = __esm({
454
550
  "src/renderers/bundlers/js.ts"() {
455
551
  init_errors();
552
+ init_metadata();
456
553
  init_utils();
457
554
  }
458
555
  });
@@ -484,6 +581,17 @@ var init_json = __esm({
484
581
  init_utils();
485
582
  }
486
583
  });
584
+ function nameKebabCase() {
585
+ return {
586
+ transform: (token) => {
587
+ const name = kebabCase(token.path.join(" "));
588
+ return {
589
+ ...token,
590
+ name
591
+ };
592
+ }
593
+ };
594
+ }
487
595
  function isColorObject(value) {
488
596
  return typeof value === "object" && value !== null && "colorSpace" in value && "components" in value;
489
597
  }
@@ -561,6 +669,7 @@ function durationObjectToString(duration) {
561
669
  init_errors();
562
670
  init_token_utils();
563
671
  init_utils();
672
+ init_metadata();
564
673
 
565
674
  // src/renderers/output-tree.ts
566
675
  var outputTree = (files) => {
@@ -621,9 +730,6 @@ function resolveColorFormat(format) {
621
730
  function escapeKotlinString(str) {
622
731
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
623
732
  }
624
- function escapeKDoc(str) {
625
- return str.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
626
- }
627
733
  function formatKotlinNumber(value) {
628
734
  return Number.isInteger(value) ? `${value}.0` : String(value);
629
735
  }
@@ -755,8 +861,13 @@ var AndroidRenderer = class {
755
861
  const kotlinName = this.buildFlatKotlinName(token);
756
862
  const kotlinValue = this.formatKotlinValue(token, options, baseDepth + 1);
757
863
  const annotation = this.typeAnnotationSuffix(token);
758
- if (token.$description) {
759
- lines.push(`${valIndent}/** ${escapeKDoc(token.$description)} */`);
864
+ const descriptionComment = buildTokenDescriptionComment(token, "kotlin");
865
+ if (descriptionComment) {
866
+ lines.push(`${valIndent}${descriptionComment}`);
867
+ }
868
+ const deprecation = buildKotlinDeprecationAnnotation(token);
869
+ if (deprecation) {
870
+ lines.push(`${valIndent}${deprecation}`);
760
871
  }
761
872
  lines.push(
762
873
  `${valIndent}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`
@@ -792,8 +903,13 @@ var AndroidRenderer = class {
792
903
  const kotlinName = toSafeIdentifier(key, KOTLIN_KEYWORDS, false);
793
904
  const kotlinValue = this.formatKotlinValue(token, options, depth);
794
905
  const annotation = this.typeAnnotationSuffix(token);
795
- if (token.$description) {
796
- lines.push(`${pad}/** ${escapeKDoc(token.$description)} */`);
906
+ const descriptionComment = buildTokenDescriptionComment(token, "kotlin");
907
+ if (descriptionComment) {
908
+ lines.push(`${pad}${descriptionComment}`);
909
+ }
910
+ const deprecation = buildKotlinDeprecationAnnotation(token);
911
+ if (deprecation) {
912
+ lines.push(`${pad}${deprecation}`);
797
913
  }
798
914
  lines.push(`${pad}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`);
799
915
  }
@@ -1570,10 +1686,8 @@ function stableInputsKey(modifierInputs) {
1570
1686
 
1571
1687
  // src/renderers/css.ts
1572
1688
  init_utils();
1689
+ init_metadata();
1573
1690
  var CssRenderer = class _CssRenderer {
1574
- sanitizeCssCommentText(text) {
1575
- return text.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ").trim();
1576
- }
1577
1691
  async format(context, options) {
1578
1692
  const opts = {
1579
1693
  preset: options?.preset ?? "bundle",
@@ -1653,12 +1767,13 @@ var CssRenderer = class _CssRenderer {
1653
1767
  }
1654
1768
  pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent, newline, space) {
1655
1769
  const entries = this.buildCssEntries(token, tokens, referenceTokens, preserveReferences);
1656
- if (token.$deprecated != null && token.$deprecated !== false) {
1657
- const deprecationMsg = formatDeprecationMessage(token, "", "comment");
1658
- lines.push(`${indent}/* ${this.sanitizeCssCommentText(deprecationMsg)} */${newline}`);
1770
+ const deprecationComment = buildTokenDeprecationComment(token, "css");
1771
+ if (deprecationComment) {
1772
+ lines.push(`${indent}${deprecationComment}${newline}`);
1659
1773
  }
1660
- if (token.$description && token.$description !== "") {
1661
- lines.push(`${indent}/* ${this.sanitizeCssCommentText(token.$description)} */${newline}`);
1774
+ const descriptionComment = buildTokenDescriptionComment(token, "css");
1775
+ if (descriptionComment) {
1776
+ lines.push(`${indent}${descriptionComment}${newline}`);
1662
1777
  }
1663
1778
  for (const entry of entries) {
1664
1779
  lines.push(`${indent}--${entry.name}:${space}${entry.value};${newline}`);
@@ -2309,6 +2424,7 @@ function isBorderToken(token) {
2309
2424
 
2310
2425
  // src/renderers/ios.ts
2311
2426
  init_utils();
2427
+ init_metadata();
2312
2428
  var toSRGB2 = converter("rgb");
2313
2429
  var toP32 = converter("p3");
2314
2430
  var SWIFT_TYPE_GROUP_MAP = {
@@ -2452,9 +2568,13 @@ var IosRenderer = class {
2452
2568
  const swiftValue = this.formatSwiftValue(token, options);
2453
2569
  const typeAnnotation = this.getTypeAnnotation(token);
2454
2570
  const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
2455
- const docComment = this.buildDocComment(token, indent);
2571
+ const docComment = buildTokenDescriptionComment(token, "swift");
2456
2572
  if (docComment) {
2457
- lines.push(docComment);
2573
+ lines.push(`${indent}${docComment}`);
2574
+ }
2575
+ const deprecationAttr = buildSwiftDeprecationAttribute(token);
2576
+ if (deprecationAttr) {
2577
+ lines.push(`${indent}${deprecationAttr}`);
2458
2578
  }
2459
2579
  lines.push(`${indent}${access} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
2460
2580
  }
@@ -2469,15 +2589,6 @@ var IosRenderer = class {
2469
2589
  }
2470
2590
  return Array.from(imports).sort();
2471
2591
  }
2472
- /**
2473
- * Builds a `///` doc comment from a token's `$description`, if present.
2474
- */
2475
- buildDocComment(token, indent) {
2476
- if (!token.$description) {
2477
- return void 0;
2478
- }
2479
- return `${indent}/// ${token.$description}`;
2480
- }
2481
2592
  /**
2482
2593
  * Builds a qualified Swift name from a token's path, preserving parent
2483
2594
  * hierarchy segments to avoid duplicate identifiers.
@@ -2868,6 +2979,7 @@ function iosRenderer() {
2868
2979
  // src/renderers/js-module.ts
2869
2980
  init_utils();
2870
2981
  init_token_utils();
2982
+ init_metadata();
2871
2983
  var JsModuleRenderer = class {
2872
2984
  async format(context, options) {
2873
2985
  const opts = {
@@ -2905,17 +3017,10 @@ var JsModuleRenderer = class {
2905
3017
  return outputTree(files);
2906
3018
  }
2907
3019
  async formatTokens(tokens, options) {
2908
- const opts = {
2909
- preset: options.preset ?? "standalone",
2910
- structure: options.structure ?? "nested",
2911
- minify: options.minify ?? false,
2912
- moduleName: options.moduleName ?? "tokens",
2913
- generateHelper: options.generateHelper ?? false
2914
- };
2915
3020
  const lines = [];
2916
- lines.push(...this.formatAsObject(tokens, opts));
3021
+ lines.push(...this.formatAsObject(tokens, options));
2917
3022
  const code = lines.join("\n");
2918
- if (opts.minify) {
3023
+ if (options.minify) {
2919
3024
  return code;
2920
3025
  }
2921
3026
  return await prettier.format(code, {
@@ -2928,20 +3033,53 @@ var JsModuleRenderer = class {
2928
3033
  trailingComma: "es5"
2929
3034
  });
2930
3035
  }
2931
- /**
2932
- * Format as default export object
2933
- */
2934
3036
  formatAsObject(tokens, options) {
2935
3037
  const lines = [];
2936
- const tokenObj = this.tokensToPlainObject(tokens, options.structure);
3038
+ const tokenMap = this.buildTokenMap(tokens);
2937
3039
  const varName = options.moduleName !== "" ? options.moduleName : "tokens";
2938
- lines.push(`const ${varName} = {`);
2939
- this.addObjectProperties(lines, tokenObj, 1);
2940
- lines.push("}");
3040
+ if (options.structure === "flat") {
3041
+ lines.push(`const ${varName} = {`);
3042
+ this.addFlatProperties(lines, tokens, 1);
3043
+ lines.push("}");
3044
+ } else {
3045
+ lines.push(`const ${varName} = {`);
3046
+ const tokenObj = this.tokensToPlainObject(tokens, "nested");
3047
+ this.addNestedProperties(lines, tokenObj, tokenMap, 1);
3048
+ lines.push("}");
3049
+ }
2941
3050
  lines.push("");
2942
3051
  lines.push(`export default ${varName}`);
2943
3052
  return lines;
2944
3053
  }
3054
+ buildTokenMap(tokens) {
3055
+ const map = /* @__PURE__ */ new Map();
3056
+ for (const [name, token] of Object.entries(tokens)) {
3057
+ map.set(name, token);
3058
+ }
3059
+ return map;
3060
+ }
3061
+ addFlatProperties(lines, tokens, indent) {
3062
+ const indentStr2 = " ".repeat(indent);
3063
+ const sortedEntries = getSortedTokenEntries(tokens);
3064
+ for (let i = 0; i < sortedEntries.length; i++) {
3065
+ const [name, token] = sortedEntries[i];
3066
+ const isLast = i === sortedEntries.length - 1;
3067
+ this.pushTokenComments(lines, token, indentStr2);
3068
+ lines.push(
3069
+ `${indentStr2}${this.quoteKey(name)}: ${JSON.stringify(token.$value)}${isLast ? "" : ","}`
3070
+ );
3071
+ }
3072
+ }
3073
+ pushTokenComments(lines, token, indent) {
3074
+ const deprecationComment = buildTokenDeprecationComment(token, "js");
3075
+ if (deprecationComment) {
3076
+ lines.push(`${indent}${deprecationComment}`);
3077
+ }
3078
+ const descriptionComment = buildTokenDescriptionComment(token, "js");
3079
+ if (descriptionComment) {
3080
+ lines.push(`${indent}${descriptionComment}`);
3081
+ }
3082
+ }
2945
3083
  tokensToPlainObject(tokens, structure) {
2946
3084
  if (structure === "nested") {
2947
3085
  return buildNestedTokenObject(tokens, (token) => token.$value);
@@ -2952,7 +3090,7 @@ var JsModuleRenderer = class {
2952
3090
  }
2953
3091
  return result;
2954
3092
  }
2955
- addObjectProperties(lines, obj, indent) {
3093
+ addNestedProperties(lines, obj, tokenMap, indent) {
2956
3094
  const indentStr2 = " ".repeat(indent);
2957
3095
  const entries = Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
2958
3096
  for (let i = 0; i < entries.length; i++) {
@@ -2964,19 +3102,20 @@ var JsModuleRenderer = class {
2964
3102
  const isLast = i === entries.length - 1;
2965
3103
  const isNestedObject = typeof value === "object" && value !== null && !Array.isArray(value);
2966
3104
  if (!isNestedObject) {
3105
+ const token = tokenMap.get(key);
3106
+ if (token) {
3107
+ this.pushTokenComments(lines, token, indentStr2);
3108
+ }
2967
3109
  lines.push(
2968
3110
  `${indentStr2}${this.quoteKey(key)}: ${JSON.stringify(value)}${isLast ? "" : ","}`
2969
3111
  );
2970
3112
  continue;
2971
3113
  }
2972
3114
  lines.push(`${indentStr2}${this.quoteKey(key)}: {`);
2973
- this.addObjectProperties(lines, value, indent + 1);
3115
+ this.addNestedProperties(lines, value, tokenMap, indent + 1);
2974
3116
  lines.push(`${indentStr2}}${isLast ? "" : ","}`);
2975
3117
  }
2976
3118
  }
2977
- /**
2978
- * Quote key if necessary
2979
- */
2980
3119
  quoteKey(key) {
2981
3120
  if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
2982
3121
  return key;
@@ -3212,6 +3351,7 @@ function resolveOptions(options) {
3212
3351
 
3213
3352
  // src/renderers/tailwind.ts
3214
3353
  init_utils();
3354
+ init_metadata();
3215
3355
  var TAILWIND_NAMESPACE_MAP = {
3216
3356
  color: "color",
3217
3357
  dimension: "spacing",
@@ -3265,6 +3405,14 @@ var TailwindRenderer = class {
3265
3405
  for (const [, token] of getSortedTokenEntries(tokens)) {
3266
3406
  const varName = this.buildVariableName(token);
3267
3407
  const varValue = this.formatValue(token);
3408
+ const deprecationComment = buildTokenDeprecationComment(token, "tailwind");
3409
+ if (deprecationComment) {
3410
+ lines.push(`${indent}${deprecationComment}${newline}`);
3411
+ }
3412
+ const descriptionComment = buildTokenDescriptionComment(token, "tailwind");
3413
+ if (descriptionComment) {
3414
+ lines.push(`${indent}${descriptionComment}${newline}`);
3415
+ }
3268
3416
  lines.push(`${indent}--${varName}:${space}${varValue};${newline}`);
3269
3417
  }
3270
3418
  lines.push(`}${newline}`);
@@ -3291,6 +3439,14 @@ var TailwindRenderer = class {
3291
3439
  for (const [, token] of getSortedTokenEntries(tokens)) {
3292
3440
  const varName = this.buildVariableName(token);
3293
3441
  const varValue = this.formatValue(token);
3442
+ const deprecationComment = buildTokenDeprecationComment(token, "tailwind");
3443
+ if (deprecationComment) {
3444
+ lines.push(`${tokenIndent}${deprecationComment}${newline}`);
3445
+ }
3446
+ const descriptionComment = buildTokenDescriptionComment(token, "tailwind");
3447
+ if (descriptionComment) {
3448
+ lines.push(`${tokenIndent}${descriptionComment}${newline}`);
3449
+ }
3294
3450
  lines.push(`${tokenIndent}--${varName}:${space}${varValue};${newline}`);
3295
3451
  }
3296
3452
  if (hasMediaQuery) {
@@ -3451,7 +3607,7 @@ function css(config) {
3451
3607
  file,
3452
3608
  renderer: cssRenderer(),
3453
3609
  options: { preset, ...rendererOptions },
3454
- transforms,
3610
+ transforms: [nameKebabCase(), ...transforms ?? []],
3455
3611
  filters,
3456
3612
  hooks
3457
3613
  };