@sugarcube-org/core 0.0.1-alpha.2 → 0.0.1-alpha.3

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.d.ts CHANGED
@@ -1,79 +1,180 @@
1
- type Files = Record<string, string>;
2
- type CollectionMode = {
3
- name: string;
4
- files: string[];
1
+ type ColorFormat = "hex" | "rgb" | "rgba" | "hsl" | "hsla" | "oklch" | "p3";
2
+ type ColorConfig = {
3
+ format?: ColorFormat;
5
4
  };
6
- type Collection = {
7
- name: string;
8
- modes?: CollectionMode[];
9
- files?: string[];
5
+ type FluidConfig = {
6
+ min: number;
7
+ max: number;
10
8
  };
11
- type ColorFormat = StandardColorFormat | FeatureDependentColorFormat;
12
- type StandardColorFormat = {
13
- name: "hex" | "rgb" | "hsl";
9
+ type TokenCollection = {
10
+ source: string[];
11
+ type: "starter-kit" | "custom";
12
+ themes?: Record<string, string[]>;
14
13
  };
15
- type FeatureDependentColorFormat = {
16
- name: "p3";
17
- featureQuery: string;
14
+ type TokenCollections = Record<string, TokenCollection>;
15
+ type OptionsConfig = {
16
+ fluid?: FluidConfig;
17
+ prefix?: string;
18
+ color?: ColorFormat;
18
19
  };
19
- type ColorFormatConverter = {
20
- type: "standard" | "conditional";
21
- convert: (r: number, g: number, b: number, a: number) => string;
22
- featureQuery?: string;
20
+ type DirectoriesConfig = {
21
+ tokens: string;
22
+ components?: string;
23
+ css: string;
23
24
  };
24
- type ColorConfig = {
25
- format: ColorFormat;
26
- converter?: ColorFormatConverter;
25
+ type CSSOutputConfig = {
26
+ separate: boolean;
27
+ manageIndex?: boolean;
28
+ format?: "css" | "scss" | "less";
27
29
  };
28
- type ViewportDimension = {
29
- value: number;
30
- unit: "px" | "rem";
30
+ type OutputConfig = {
31
+ directories: DirectoriesConfig;
32
+ css: CSSOutputConfig;
33
+ };
34
+ interface SugarcubeConfig {
35
+ tokens: TokenCollection | TokenCollections;
36
+ options?: OptionsConfig;
37
+ output: OutputConfig;
38
+ }
39
+
40
+ /**
41
+ * Represents a single CSS file output with its name and content
42
+ */
43
+ type CSSFile = {
44
+ name: string;
45
+ content: string;
31
46
  };
32
- type FluidConfig = {
33
- viewports: {
34
- min: ViewportDimension;
35
- max: ViewportDimension;
47
+ /**
48
+ * Represents the output from generateCSS which always returns exactly one file
49
+ */
50
+ type SingleFileOutput = [CSSFile];
51
+ /**
52
+ * Represents multiple CSS file outputs from generateSeparateFiles or generateSingleFile
53
+ */
54
+ type CSSFileOutput = CSSFile[];
55
+ /**
56
+ * Result of the CSS generation process
57
+ * For generateCSS: Contains exactly one file
58
+ * For generate: Contains one or more files
59
+ */
60
+ type CSSGenerationResult = {
61
+ output: SingleFileOutput | CSSFileOutput;
62
+ };
63
+
64
+ /**
65
+ * A token value that can either be a raw value or a reference
66
+ */
67
+ type TokenValue<T extends TokenType> = RawTokenValue<T> | Reference<T>;
68
+ /**
69
+ * The actual value of a token without references
70
+ */
71
+ type RawTokenValue<T extends TokenType> = T extends SimpleTokenType ? SimpleTokenValue<T> : T extends CompositeTokenType ? CompositeTokenValue<T> : never;
72
+ /**
73
+ * A reference to another token, with optional type checking
74
+ */
75
+ type Reference<T extends TokenType = TokenType> = string & {
76
+ __tokenType?: T;
77
+ };
78
+ /**
79
+ * Metadata that can be attached to any node in the token tree
80
+ */
81
+ type NodeMetadata = {
82
+ $description?: string;
83
+ $extensions?: {
84
+ [key: string]: unknown;
36
85
  };
37
86
  };
38
- type OutputConfig = {
39
- directory?: string;
40
- separate?: boolean;
87
+ /**
88
+ * A single token with its value and metadata
89
+ */
90
+ type Token = NodeMetadata & {
91
+ $value: TokenValue<TokenType>;
92
+ $type?: TokenType;
41
93
  };
42
- type SugarcubeConfig = {
43
- files: Files;
44
- collections?: Collection[];
45
- fluid?: FluidConfig;
46
- color?: ColorConfig;
47
- output?: OutputConfig;
94
+ /**
95
+ * A group of tokens that can be nested
96
+ */
97
+ type TokenGroup = {
98
+ [key: string]: Token | TokenGroup;
99
+ } & NodeMetadata & {
100
+ $type?: TokenType;
48
101
  };
49
-
102
+ /**
103
+ * All possible token types, either simple or composite
104
+ */
105
+ type TokenType = SimpleTokenType | CompositeTokenType;
106
+ /**
107
+ * Token types that contain a single value
108
+ */
109
+ type SimpleTokenType = "color" | "dimension" | "fluidDimension" | "duration" | "cubicBezier" | "fontFamily" | "fontWeight" | "number";
110
+ /**
111
+ * Values for simple token types
112
+ */
113
+ type SimpleTokenValue<T extends SimpleTokenType = SimpleTokenType> = T extends "color" ? Color : T extends "dimension" ? Dimension : T extends "fluidDimension" ? FluidDimension : T extends "duration" ? Duration : T extends "cubicBezier" ? CubicBezier : T extends "fontFamily" ? FontFamily : T extends "fontWeight" ? FontWeight : T extends "number" ? number : never;
114
+ /**
115
+ * Token types that contain multiple values or are structurally complex
116
+ */
117
+ type CompositeTokenType = AlwaysDecomposedType | "border" | "shadow" | "gradient" | "transition" | StructuralCompositeType;
118
+ /**
119
+ * Token types that must always be broken down into their constituent parts
120
+ */
121
+ type AlwaysDecomposedType = "typography";
122
+ /**
123
+ * Token types that define structural patterns
124
+ */
125
+ type StructuralCompositeType = "strokeStyle";
126
+ /**
127
+ * Values for composite token types
128
+ */
129
+ type CompositeTokenValue<T extends CompositeTokenType = CompositeTokenType> = T extends "typography" ? Typography : T extends "border" ? Border : T extends "shadow" ? Shadow : T extends "gradient" ? Gradient : T extends "transition" ? Transition : T extends "strokeStyle" ? StrokeStyle : never;
130
+ /**
131
+ * A color value in any valid CSS color format
132
+ */
50
133
  type Color = string;
134
+ /**
135
+ * A dimensional value with a numeric value and unit
136
+ */
51
137
  type Dimension = {
52
138
  value: number;
53
139
  unit: "px" | "rem";
54
140
  };
141
+ /**
142
+ * A fluid dimension that scales between min and max values
143
+ */
55
144
  type FluidDimension = {
56
145
  min: Dimension;
57
146
  max: Dimension;
58
147
  };
59
- type Duration = string;
148
+ /**
149
+ * A duration value with a numeric value and time unit
150
+ */
151
+ type Duration = {
152
+ value: number;
153
+ unit: "ms" | "s";
154
+ };
155
+ /**
156
+ * A cubic bezier curve defined by four control points
157
+ */
60
158
  type CubicBezier = [number, number, number, number];
159
+ /**
160
+ * A font family name or list of fallback fonts
161
+ */
61
162
  type FontFamily = string | string[];
163
+ /**
164
+ * A font weight value as either a number or semantic string
165
+ */
62
166
  type FontWeight = number | FontWeightString;
167
+ /**
168
+ * Semantic font weight names
169
+ */
63
170
  type FontWeightString = "thin" | "hairline" | "extra-light" | "ultra-light" | "light" | "normal" | "regular" | "book" | "medium" | "semi-bold" | "demi-bold" | "bold" | "extra-bold" | "ultra-bold" | "black" | "heavy" | "extra-black" | "ultra-black";
171
+ /**
172
+ * Line cap style for strokes
173
+ */
64
174
  type LineCap = "round" | "butt" | "square";
65
- type TokenType = SimpleTokenType | CompositeTokenType;
66
- type SimpleTokenType = "color" | "dimension" | "fluidDimension" | "duration" | "cubicBezier" | "fontFamily" | "fontWeight" | "number";
67
- type CompositeTokenType = AlwaysDecomposedType | "border" | "shadow" | "gradient" | "transition" | StructuralCompositeType;
68
- type AlwaysDecomposedType = "typography";
69
- type StructuralCompositeType = "strokeStyle";
70
- type Reference<T extends TokenType = TokenType> = string & {
71
- __tokenType?: T;
72
- };
73
- type TokenValue<T extends TokenType> = RawTokenValue<T> | Reference<T>;
74
- type RawTokenValue<T extends TokenType> = T extends SimpleTokenType ? SimpleTokenValue<T> : T extends CompositeTokenType ? CompositeTokenValue<T> : never;
75
- type SimpleTokenValue<T extends SimpleTokenType = SimpleTokenType> = T extends "color" ? Color : T extends "dimension" ? Dimension : T extends "fluidDimension" ? FluidDimension : T extends "duration" ? Duration : T extends "cubicBezier" ? CubicBezier : T extends "fontFamily" ? FontFamily : T extends "fontWeight" ? FontWeight : T extends "number" ? number : never;
76
- type CompositeTokenValue<T extends CompositeTokenType = CompositeTokenType> = T extends "typography" ? Typography : T extends "border" ? Border : T extends "shadow" ? Shadow : T extends "gradient" ? Gradient : T extends "transition" ? Transition : T extends "strokeStyle" ? StrokeStyle : never;
175
+ /**
176
+ * Typography token combining font properties
177
+ */
77
178
  type Typography = {
78
179
  fontFamily: TokenValue<"fontFamily">;
79
180
  fontSize: TokenValue<"dimension">;
@@ -81,22 +182,40 @@ type Typography = {
81
182
  letterSpacing?: TokenValue<"dimension">;
82
183
  lineHeight?: TokenValue<"number">;
83
184
  };
185
+ /**
186
+ * Transition token defining animation properties
187
+ */
84
188
  type Transition = {
85
189
  duration: TokenValue<"duration">;
86
190
  delay?: TokenValue<"duration">;
87
191
  timingFunction: TokenValue<"cubicBezier">;
88
192
  };
193
+ /**
194
+ * Predefined stroke style keywords
195
+ */
89
196
  type StrokeStyleKeyword = "solid" | "dashed" | "dotted" | "double" | "groove" | "ridge" | "outset" | "inset";
197
+ /**
198
+ * Custom stroke style definition
199
+ */
90
200
  type StrokeStyleCustom = {
91
201
  dashArray: Array<TokenValue<"dimension">>;
92
202
  lineCap: LineCap;
93
203
  };
204
+ /**
205
+ * A stroke style that can be either a keyword or custom definition
206
+ */
94
207
  type StrokeStyle = StrokeStyleKeyword | StrokeStyleCustom;
208
+ /**
209
+ * Border token combining color, width, and style
210
+ */
95
211
  type Border = {
96
212
  color: TokenValue<"color">;
97
213
  width: TokenValue<"dimension">;
98
214
  style: StrokeStyle | Reference<"strokeStyle">;
99
215
  };
216
+ /**
217
+ * Individual shadow definition
218
+ */
100
219
  type ShadowObject = {
101
220
  color: TokenValue<"color">;
102
221
  offsetX: TokenValue<"dimension">;
@@ -105,43 +224,51 @@ type ShadowObject = {
105
224
  spread: TokenValue<"dimension">;
106
225
  inset?: boolean;
107
226
  };
227
+ /**
228
+ * Shadow token that can be single or multiple shadows
229
+ */
108
230
  type Shadow = ShadowObject | ShadowObject[];
231
+ /**
232
+ * Color stop in a gradient
233
+ */
109
234
  type GradientStop = {
110
235
  color: TokenValue<"color">;
111
- position: number;
236
+ position: number | Reference<"number">;
112
237
  };
238
+ /**
239
+ * Gradient defined as a list of color stops
240
+ */
113
241
  type Gradient = GradientStop[];
114
- type CSSProperties<T extends TokenType> = T extends SimpleTokenType ? SimpleCSSProperties : T extends AlwaysDecomposedType ? AlwaysDecomposedProperties : T extends StructuralCompositeType ? SimpleCSSProperties : never;
115
- type SimpleCSSProperties = {
116
- value: string;
117
- featureValues?: Array<{
118
- query: string;
119
- value: string;
120
- }>;
121
- };
122
- type AlwaysDecomposedProperties = CSSTypographyProperties;
123
- type CSSTypographyProperties = {
124
- "font-family": string;
125
- "font-size": string;
126
- "font-weight"?: number | string;
127
- "letter-spacing"?: string;
128
- "line-height"?: number | string;
129
- };
130
- type NodeMetadata = {
131
- $description?: string;
132
- $extensions?: {
133
- [key: string]: unknown;
134
- };
242
+
243
+ /**
244
+ * Source information for a token, tracking its collection and theme
245
+ */
246
+ type TokenSource = {
247
+ collection: string;
248
+ theme?: string;
249
+ sourcePath: string;
135
250
  };
136
- type Token = NodeMetadata & {
137
- $value: TokenValue<TokenType>;
138
- $type?: TokenType;
251
+ /**
252
+ * A complete token tree with collection and theme information
253
+ */
254
+ type TokenTree = {
255
+ collection: string;
256
+ theme?: string;
257
+ tokens: TokenGroup;
258
+ sourcePath: string;
139
259
  };
140
- type TokenGroup = {
141
- [key: string]: Token | TokenGroup;
142
- } & NodeMetadata & {
143
- $type?: TokenType;
260
+
261
+ /**
262
+ * Base error type that all other error types extend from.
263
+ * Used as the foundation for all error types in the system.
264
+ */
265
+ type BaseError = {
266
+ message: string;
144
267
  };
268
+
269
+ /**
270
+ * A flattened token with its source information and path
271
+ */
145
272
  type FlattenedToken<T extends TokenType = TokenType> = NodeMetadata & {
146
273
  $type: T;
147
274
  $value: TokenValue<T>;
@@ -149,189 +276,286 @@ type FlattenedToken<T extends TokenType = TokenType> = NodeMetadata & {
149
276
  $source: TokenSource;
150
277
  $originalPath: string;
151
278
  };
279
+ /**
280
+ * A map of flattened tokens and metadata by their lookup path
281
+ */
152
282
  type FlattenedTokens = {
153
- [lookupKey: TokenLookupKey]: FlattenedToken | NodeMetadata;
154
- };
155
- type ValidatedToken<T extends TokenType = TokenType> = FlattenedToken<T>;
156
- type ResolvedToken<T extends TokenType = TokenType> = ValidatedToken<T> & {
157
- $resolvedValue: RawTokenValue<T>;
158
- };
159
- type ResolvedTokens = {
160
- [lookupKey: TokenLookupKey]: ResolvedToken | NodeMetadata;
161
- };
162
- type ConvertedToken<T extends TokenType = TokenType> = ResolvedToken<T> & {
163
- $cssProperties: CSSProperties<T>;
164
- };
165
- type ConvertedTokens = {
166
- [lookupKey: TokenLookupKey]: ConvertedToken | NodeMetadata;
167
- };
168
- type TokenSource = {
169
- file: string;
170
- };
171
- type DesignTokens = TokenGroup;
172
- type TokenTree = {
173
- name: string;
174
- tokens: TokenGroup;
175
- };
176
- type BaseError = {
177
- message: string;
178
- };
179
- type LoadError = BaseError & {
180
- file: string;
283
+ [lookupKey: string]: FlattenedToken | NodeMetadata;
181
284
  };
285
+ /**
286
+ * An error that occurred during token flattening
287
+ */
182
288
  type FlattenError = BaseError & {
183
289
  path: string;
184
290
  source: TokenSource;
185
291
  };
292
+
293
+ /**
294
+ * An error that occurred during token validation
295
+ */
186
296
  type ValidationError = BaseError & {
187
297
  path: string;
188
298
  source: TokenSource;
189
299
  };
190
- type ResolutionError = BaseError & {
191
- type: "circular" | "missing" | "type-mismatch";
192
- path: string;
193
- source: TokenSource;
194
- };
195
- type NormalizedConvertedTokens = {
196
- [collection: string]: {
197
- [mode: string]: ConvertedTokens;
198
- };
199
- };
200
-
201
- type LoadResult = {
202
- trees: TokenTree[];
203
- errors: LoadError[];
204
- };
205
- declare function loadTreesFromConfig(files: SugarcubeConfig["files"]): Promise<LoadResult>;
206
300
 
207
- declare function flatten(trees: Array<{
208
- name: string;
209
- tokens: TokenGroup;
210
- }>): {
211
- tokens: FlattenedTokens;
212
- errors: FlattenError[];
301
+ /**
302
+ * A resolved token with its final value
303
+ */
304
+ type ResolvedToken<T extends TokenType = TokenType> = NodeMetadata & {
305
+ $type: T;
306
+ $value: RawTokenValue<T>;
307
+ $path: string;
308
+ $source: TokenSource;
309
+ $originalPath: string;
310
+ $resolvedValue: RawTokenValue<T>;
213
311
  };
214
-
215
- declare function resolve(tokens: FlattenedTokens): {
216
- resolved: ResolvedTokens;
217
- errors: ResolutionError[];
312
+ /**
313
+ * A map of resolved tokens by their lookup path
314
+ */
315
+ type ResolvedTokens = {
316
+ [lookupKey: string]: ResolvedToken | NodeMetadata;
218
317
  };
219
-
220
- declare function convert(tokens: {
221
- [collection: string]: {
222
- [mode: string]: ResolvedTokens;
223
- };
224
- }, config: SugarcubeConfig): NormalizedConvertedTokens;
225
-
226
318
  /**
227
- * This function takes a JSON string representation of a token tree and converts it
228
- * into a DesignTokens object.
229
- *
230
- * @param {string} json - A JSON string representing a token tree structure.
231
- * @returns {DesignTokens} A DesignTokens object representing the parsed token structure.
232
- * @throws {SyntaxError} If the provided JSON string is not valid JSON.
233
- * @throws {TypeError} If the JSON structure doesn't match the expected DesignTokens format.
319
+ * Type of resolution error that occurred
234
320
  */
235
- declare function parseJson(json: string): DesignTokens;
236
-
237
- declare function validate(tokens: FlattenedTokens, config: SugarcubeConfig): ValidationError[];
238
-
239
- type ProcessedTree = {
240
- name: string;
241
- tokens: ResolvedTokens;
321
+ type ResolutionErrorType = "circular" | "missing" | "type-mismatch";
322
+ /**
323
+ * An error that occurred during token resolution
324
+ */
325
+ type ResolutionError = BaseError & {
326
+ type: ResolutionErrorType;
327
+ path: string;
328
+ source: TokenSource;
242
329
  };
243
- declare function processTrees(trees: Pick<TokenTree, "name">[], resolved: ResolvedTokens): ProcessedTree[];
244
330
 
245
- type CollectionModes = {
246
- [mode: string]: ResolvedTokens;
247
- };
248
- type NormalizedTokens = {
249
- default: CollectionModes;
250
- [collection: string]: CollectionModes;
251
- };
252
- type NormalizationError = ValidationError & {
253
- collection: string;
254
- mode: string;
255
- };
331
+ /**
332
+ * A warning that occurred during token normalization
333
+ */
256
334
  type NormalizationWarning = {
257
335
  type: "warning";
258
336
  message: string;
259
337
  file: string;
260
338
  collection: string;
261
- mode?: string;
339
+ theme?: string;
340
+ };
341
+ /**
342
+ * An error that occurred during token normalization
343
+ */
344
+ type NormalizationError = ValidationError & {
345
+ collection: string;
346
+ theme: string;
347
+ };
348
+ /**
349
+ * A set of tokens for a theme, including metadata nodes
350
+ */
351
+ type ThemeTokenSet = {
352
+ default: ResolvedTokens;
353
+ [theme: string]: ResolvedTokens;
354
+ };
355
+ /**
356
+ * Normalized tokens organized by collection and theme
357
+ */
358
+ type NormalizedTokens = {
359
+ [collection: string]: ThemeTokenSet;
262
360
  };
361
+ /**
362
+ * Result of the normalization process
363
+ */
263
364
  type NormalizeResult = {
264
365
  tokens: NormalizedTokens;
265
366
  errors: NormalizationError[];
266
367
  warnings: NormalizationWarning[];
267
368
  };
268
- declare function normalizeTokens(trees: ProcessedTree[], collections?: SugarcubeConfig["collections"]): NormalizeResult;
269
369
 
270
- type GenerationError = {
271
- path: string;
272
- message: string;
370
+ /**
371
+ * Result of loading token trees from files or memory
372
+ */
373
+ type LoadResult = {
374
+ trees: TokenTree[];
375
+ errors: LoadError[];
273
376
  };
274
- type GeneratedOutput = Array<{
275
- name: string;
377
+ /**
378
+ * Data structure for loading tokens from memory
379
+ */
380
+ type TokenMemoryData = Record<string, {
381
+ collection: string;
382
+ theme?: string;
276
383
  content: string;
277
384
  }>;
278
- type GenerationResult = {
279
- output: GeneratedOutput;
280
- errors: GenerationError[];
385
+ /**
386
+ * An error that occurred during token loading
387
+ */
388
+ type LoadError = BaseError & {
389
+ file: string;
281
390
  };
282
- declare function generate(tokens: NormalizedConvertedTokens, config?: OutputConfig): Promise<GenerationResult>;
283
391
 
392
+ /**
393
+ * Result of running the tokens-to-CSS pipeline
394
+ */
284
395
  type TokensToCSSPipelineResult = {
285
- output: GeneratedOutput;
396
+ output: CSSFileOutput;
286
397
  trees: TokenTree[];
287
- errors: {
288
- load: LoadError[];
289
- flatten: FlattenError[];
290
- validation: ValidationError[];
291
- resolution: ResolutionError[];
292
- generation: GenerationError[];
293
- };
294
- warnings: {
295
- normalization: Array<{
296
- type: "warning";
297
- message: string;
298
- file: string;
299
- collection: string;
300
- mode?: string;
301
- }>;
302
- };
398
+ errors: PipelineErrors;
399
+ warnings: PipelineWarnings;
303
400
  };
304
- declare function tokensToCSSPipeline(config: SugarcubeConfig): Promise<TokensToCSSPipelineResult>;
305
-
306
- type ValidationPipelineErrors = {
401
+ /**
402
+ * Common error types that can occur during pipeline execution
403
+ */
404
+ type PipelineErrors = {
307
405
  load: LoadError[];
308
406
  flatten: FlattenError[];
309
407
  validation: ValidationError[];
310
408
  resolution: ResolutionError[];
311
409
  };
410
+ /**
411
+ * Common warning types that can occur during pipeline execution
412
+ */
413
+ type PipelineWarnings = {
414
+ normalization: NormalizationWarning[];
415
+ };
416
+ /**
417
+ * Result of running the validation pipeline
418
+ */
312
419
  type ValidationPipelineResult = {
313
420
  trees: TokenTree[];
314
421
  flattenedTokens: FlattenedTokens;
315
422
  resolved: ResolvedTokens;
316
- errors: ValidationPipelineErrors;
423
+ errors: PipelineErrors;
317
424
  };
318
- declare function validationPipeline(config: SugarcubeConfig): Promise<ValidationPipelineResult>;
319
-
425
+ /**
426
+ * Options for loading tokens in the validation pipeline
427
+ */
428
+ type TokenLoader = {
429
+ type: "files";
430
+ paths: SugarcubeConfig;
431
+ } | {
432
+ type: "memory";
433
+ data: TokenMemoryData;
434
+ };
435
+ /**
436
+ * Options for configuring the validation pipeline
437
+ */
438
+ type ValidationPipelineOptions = {
439
+ loader: TokenLoader;
440
+ };
441
+ /**
442
+ * Result of running the generation pipeline
443
+ */
320
444
  type GenerationPipelineResult = {
321
- output: GeneratedOutput;
322
- errors: {
323
- generation: GenerationError[];
324
- };
325
- warnings: {
326
- normalization: Array<{
327
- type: "warning";
328
- message: string;
329
- file: string;
330
- collection: string;
331
- mode?: string;
332
- }>;
333
- };
445
+ output: CSSFileOutput;
446
+ warnings: PipelineWarnings;
447
+ };
448
+
449
+ declare function tokensToCSSPipeline(config: SugarcubeConfig): Promise<TokensToCSSPipelineResult>;
450
+
451
+ declare function validationPipeline(config: SugarcubeConfig, options: ValidationPipelineOptions): Promise<ValidationPipelineResult>;
452
+
453
+ declare function generationPipeline(trees: TokenTree[], resolved: ResolvedTokens, configState: SugarcubeConfig): Promise<GenerationPipelineResult>;
454
+
455
+ declare function loadTreesFromConfig(config: SugarcubeConfig): Promise<LoadResult>;
456
+ declare function loadTreesFromMemory(data: TokenMemoryData): Promise<LoadResult>;
457
+
458
+ declare function validate(tokens: FlattenedTokens): ValidationError[];
459
+
460
+ declare function flatten(trees: TokenTree[]): {
461
+ tokens: FlattenedTokens;
462
+ errors: FlattenError[];
463
+ };
464
+
465
+ declare function resolve(tokens: FlattenedTokens): {
466
+ resolved: ResolvedTokens;
467
+ errors: ResolutionError[];
468
+ };
469
+
470
+ /**
471
+ * A processed token tree that has been filtered to only include tokens
472
+ * from its specific collection and theme, with resolved values
473
+ */
474
+ type ProcessedTree = {
475
+ collection: string;
476
+ theme?: string;
477
+ tokens: ResolvedTokens;
478
+ };
479
+
480
+ declare function processTrees(trees: TokenTree[], resolved: ResolvedTokens): ProcessedTree[];
481
+
482
+ /**
483
+ * A token that has been converted to CSS properties
484
+ */
485
+ type ConvertedToken<T extends TokenType = TokenType> = ResolvedToken<T> & {
486
+ $cssProperties: CSSProperties<T>;
334
487
  };
335
- declare function generationPipeline(trees: TokenTree[], resolved: ResolvedTokens, configState: any): Promise<GenerationPipelineResult>;
488
+ /**
489
+ * A collection of converted tokens
490
+ */
491
+ type ConvertedTokens = {
492
+ [lookupKey: string]: ConvertedToken | NodeMetadata;
493
+ };
494
+ /**
495
+ * A collection of converted tokens organized by theme
496
+ */
497
+ type ConvertedThemeTokenSet = {
498
+ default: ConvertedTokens;
499
+ [theme: string]: ConvertedTokens;
500
+ };
501
+ /**
502
+ * A collection of converted tokens organized by collection and theme
503
+ */
504
+ type NormalizedConvertedTokens = {
505
+ [collection: string]: ConvertedThemeTokenSet;
506
+ };
507
+ /**
508
+ * CSS property types for different token types
509
+ */
510
+ type CSSProperties<T extends TokenType> = T extends SimpleTokenType ? SimpleCSSProperties : T extends AlwaysDecomposedType ? AlwaysDecomposedProperties : T extends "border" ? CSSBorderProperties : T extends "shadow" ? CSSShadowProperties : T extends "gradient" ? CSSGradientProperties : T extends "transition" ? CSSTransitionProperties : T extends StructuralCompositeType ? SimpleCSSProperties : never;
511
+ /**
512
+ * Simple CSS properties with a single value
513
+ */
514
+ type SimpleCSSProperties = {
515
+ value: string | number;
516
+ featureValues?: Array<{
517
+ query: string;
518
+ value: string;
519
+ }>;
520
+ };
521
+ /**
522
+ * CSS properties that are always broken down into multiple properties
523
+ */
524
+ type AlwaysDecomposedProperties = CSSTypographyProperties;
525
+ /**
526
+ * CSS properties specific to typography tokens
527
+ */
528
+ type CSSTypographyProperties = {
529
+ "font-family": string;
530
+ "font-size": string;
531
+ "font-weight"?: number | string;
532
+ "letter-spacing"?: string;
533
+ "line-height"?: number | string;
534
+ };
535
+ /**
536
+ * CSS properties for specific token types
537
+ */
538
+ type CSSBorderProperties = {
539
+ value: string;
540
+ };
541
+ type CSSShadowProperties = {
542
+ value: string;
543
+ };
544
+ type CSSGradientProperties = {
545
+ value: string;
546
+ };
547
+ type CSSTransitionProperties = {
548
+ value: string;
549
+ };
550
+
551
+ declare function convert(tokens: NormalizedTokens, config: SugarcubeConfig): NormalizedConvertedTokens;
552
+
553
+ declare function normalizeTokens(trees: ProcessedTree[]): NormalizeResult;
554
+
555
+ /**
556
+ * Generates CSS variable files from normalized and converted design tokens.
557
+ * Can output either a single combined file or separate files based on configuration.
558
+ */
559
+ declare function generate(tokens: NormalizedConvertedTokens, config: SugarcubeConfig): Promise<CSSGenerationResult>;
336
560
 
337
- export { type GeneratedOutput, type GenerationResult, type ResolutionError, type ResolvedTokens, type TokenTree, type ValidationError, convert, flatten, generate, generationPipeline, loadTreesFromConfig, normalizeTokens, parseJson, processTrees, resolve, tokensToCSSPipeline, validate, validationPipeline };
561
+ export { type CSSFileOutput, type CSSGenerationResult, type CSSOutputConfig, type ColorConfig, type ColorFormat, type DirectoriesConfig, type FluidConfig, type LoadError, type LoadResult, type OptionsConfig, type OutputConfig, type ResolutionError, type ResolvedToken, type ResolvedTokens, type SugarcubeConfig, type TokenCollection, type TokenCollections, type TokenLoader, type TokenMemoryData, type TokenSource, type TokenTree, type ValidationError, convert, flatten, generate, generationPipeline, loadTreesFromConfig, loadTreesFromMemory, normalizeTokens, processTrees, resolve, tokensToCSSPipeline, validate, validationPipeline };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- var Q=Object.defineProperty;var n=(e,t)=>Q(e,"name",{value:t,configurable:!0});import{readFile as ee}from"fs/promises";import te from"fast-glob";import re from"node:path";const u={LOAD:{FILE_NOT_FOUND:n(e=>`File not found: ${e}`,"FILE_NOT_FOUND"),INVALID_JSON:n((e,t)=>`Invalid JSON in file ${e}: ${t}`,"INVALID_JSON"),READ_ERROR:n((e,t)=>`Error reading file ${e}: ${t}`,"READ_ERROR"),INVALID_SOURCE:n(e=>`Invalid source: expected string or array of file descriptors, got ${typeof e}`,"INVALID_SOURCE"),NO_FILES_FOUND:n(e=>`No files found matching pattern: ${e}.`,"NO_FILES_FOUND"),GLOB_ERROR:n((e,t)=>`Error resolving glob pattern ${e}: ${t}`,"GLOB_ERROR"),EMPTY_CONFIG:n(()=>"No token files specified in sugarcube.config.json","EMPTY_CONFIG")},PARSE:{INVALID_INPUT_TYPE:n(e=>`Invalid input: expected string, got ${e}`,"INVALID_INPUT_TYPE"),JSON_PARSE_ERROR:n(e=>`JSON parsing error: ${e}`,"JSON_PARSE_ERROR"),UNEXPECTED_ERROR:n(e=>`Unexpected error during parsing: ${e}`,"UNEXPECTED_ERROR")},FLATTEN:{INVALID_TOKEN_NAME:n(e=>`Invalid token name '${e}': cannot contain '.', '{', or '}'`,"INVALID_TOKEN_NAME"),INVALID_NODE_STRUCTURE:n(e=>`Invalid node structure at '${e}': expected object`,"INVALID_NODE_STRUCTURE"),MISSING_INHERITED_TYPE:n(e=>`Token at '${e}' has no type (neither explicit nor inherited)`,"MISSING_INHERITED_TYPE")},METADATA:{COLLECTION_ERROR:n(e=>`Error collecting metadata: ${e}`,"COLLECTION_ERROR"),INVALID_EXTENSIONS:n(e=>`Invalid extensions at '${e}': expected object, got ${typeof e}`,"INVALID_EXTENSIONS"),INVALID_DESCRIPTION:n(e=>`Invalid description at '${e}': expected string, got ${typeof e}`,"INVALID_DESCRIPTION")},VALIDATE:{MISSING_TYPE:n(e=>`Token at '${e}' is missing the "$type" property`,"MISSING_TYPE"),MISSING_VALUE:n(e=>`Token at '${e}' is missing the "$value" property`,"MISSING_VALUE"),UNKNOWN_TOKEN_TYPE:n((e,t)=>`Unknown token type '${e}' at '${t}'. Valid types are: color, dimension, fontFamily, fontWeight, duration, cubicBezier, strokeStyle, border, transition, shadow, gradient, typography`,"UNKNOWN_TOKEN_TYPE"),INVALID_COLOR:n((e,t)=>`Invalid color at '${t}': '${e}'. Color should be a valid hex value`,"INVALID_COLOR"),INVALID_DIMENSION:n((e,t)=>`Invalid dimension at '${t}': ${e}. Dimensions should have a numeric value and unit, like { "value": 16, "unit": "px" }`,"INVALID_DIMENSION"),INVALID_DIMENSION_UNIT:n((e,t)=>`Invalid unit at '${t}': ${e}. Unit must be either "px" or "rem"`,"INVALID_DIMENSION_UNIT"),INVALID_FONT_FAMILY:n((e,t)=>`Invalid font family at '${t}': ${e}. Should be a string or array of strings, like "Arial" or ["Arial", "sans-serif"]`,"INVALID_FONT_FAMILY"),INVALID_FONT_WEIGHT:n((e,t)=>`Invalid font weight at '${t}': ${e}. Should be a number between 1-1000 or a keyword like "thin", "light", "normal", "bold"`,"INVALID_FONT_WEIGHT"),INVALID_DURATION:n((e,t)=>`Invalid duration at '${t}': ${e}. Should be like { "value": 300, "unit": "ms" }`,"INVALID_DURATION"),INVALID_DURATION_UNIT:n((e,t)=>`Invalid unit at '${t}': ${e}. Unit must be "ms" or "s"`,"INVALID_DURATION_UNIT"),INVALID_CUBIC_BEZIER:n((e,t)=>`Invalid cubic bezier at '${t}': ${e}. Should be an array of 4 numbers between 0 and 1`,"INVALID_CUBIC_BEZIER"),INVALID_CUBIC_BEZIER_RANGE:n((e,t)=>`Invalid cubic bezier control points at '${t}': ${e}. X values must be between 0 and 1`,"INVALID_CUBIC_BEZIER_RANGE"),INVALID_STROKE_STYLE:n((e,t)=>`Invalid stroke style at '${t}': ${e}. Should be "solid", "dashed", "dotted", etc.`,"INVALID_STROKE_STYLE"),INVALID_STROKE_LINE_CAP:n((e,t)=>`Invalid line cap at '${t}': ${e}. Should be one of: round, butt, square`,"INVALID_STROKE_LINE_CAP"),INVALID_BORDER:n((e,t)=>`Invalid border at '${t}': ${e}. Should have color, width, and style properties`,"INVALID_BORDER"),INVALID_SHADOW:n((e,t)=>`Invalid shadow at '${t}': ${e}. Should have color, offsetX, offsetY properties (blur and spread are optional)`,"INVALID_SHADOW"),INVALID_SHADOW_INSET:n((e,t)=>`Invalid inset value at '${t}': ${e}. Should be true or false`,"INVALID_SHADOW_INSET"),INVALID_TRANSITION:n((e,t)=>`Invalid transition at '${t}': ${e}. Should have duration, delay, and timingFunction properties`,"INVALID_TRANSITION"),INVALID_GRADIENT:n((e,t)=>`Invalid gradient at '${t}': ${e}. Should be an array of color stops with position values between 0 and 1`,"INVALID_GRADIENT"),INVALID_GRADIENT_STOP_POSITION:n((e,t)=>`Invalid gradient stop position at '${t}': ${e}. Position must be between 0 and 1`,"INVALID_GRADIENT_STOP_POSITION"),INVALID_TYPOGRAPHY:n((e,t)=>`Invalid typography at '${t}': ${e}. Should have fontFamily and fontSize (fontWeight, letterSpacing, and lineHeight are optional)`,"INVALID_TYPOGRAPHY"),MISSING_REQUIRED_PROPERTY:n((e,t)=>`Missing required property '${e}' at '${t}'`,"MISSING_REQUIRED_PROPERTY"),INVALID_NUMBER:n((e,t)=>`Invalid number at '${t}': ${e}. Expected a number value`,"INVALID_NUMBER"),INVALID_ARRAY:n((e,t)=>`Invalid array at '${t}': ${e}. Expected an array value`,"INVALID_ARRAY"),MISSING_FLUID_CONFIG:n(e=>`Missing fluid configuration at root level. Token at '${e}' requires fluid viewport settings`,"MISSING_FLUID_CONFIG"),INVALID_FLUID_DIMENSION:n((e,t)=>`Invalid fluid dimension at '${t}': ${e}. Fluid dimensions should have min and max values, like { "min": { "value": 16, "unit": "px" }, "max": { "value": 24, "unit": "px" } }`,"INVALID_FLUID_DIMENSION"),INVALID_VIEWPORT_CONFIG:n((e,t)=>`Invalid viewport configuration at '${t}': ${e}. Viewport config should have min and max dimension values`,"INVALID_VIEWPORT_CONFIG"),MISMATCHED_UNITS:n((e,t,r)=>`Mismatched units at '${r}': min uses '${e}', max uses '${t}'. Both values must use the same unit`,"MISMATCHED_UNITS"),INVALID_FLUID_VALUE_RANGE:n(e=>`Invalid fluid value range at '${e}': min value must be less than max value`,"INVALID_FLUID_VALUE_RANGE"),INVALID_TOKEN_TYPE:n((e,t,r)=>`Invalid token type at '${r}': expected ${e}, got ${t}`,"INVALID_TOKEN_TYPE"),INVALID_TYPE:n((e,t,r)=>`Expected ${e}, received ${typeof t} at '${r}'`,"INVALID_TYPE"),INVALID_ENUM_VALUE:n((e,t,r)=>`Expected value to be one of [${e.join(", ")}], but got ${String(t)} at ${r}`,"INVALID_ENUM_VALUE")},RESOLVE:{CIRCULAR_REFERENCE:n((e,t)=>`Circular reference detected: ${e} -> ${t}`,"CIRCULAR_REFERENCE"),REFERENCE_NOT_FOUND:n((e,t)=>`Reference not found: ${t} in ${e}`,"REFERENCE_NOT_FOUND"),TYPE_MISMATCH:n(e=>`Type mismatch in reference resolution at ${e}`,"TYPE_MISMATCH")},NORMALIZE:{DUPLICATE_FILE_WARNING:n((e,t)=>`Warning: File '${e}' is assigned to multiple collections without modes (in '${t}'). This will create duplicate CSS variables in :root since collections without modes default to root scope.`,"DUPLICATE_FILE_WARNING"),DUPLICATE_MODE_WARNING:n((e,t,r)=>`Warning: File '${e}' is assigned to multiple modes in collection '${t}' (in '${r}'). This means the same token values will be duplicated across different theme selectors.`,"DUPLICATE_MODE_WARNING")},GENERATE:{INVALID_CSS_VALUE:n((e,t)=>`Invalid CSS value for property '${e}': ${t}`,"INVALID_CSS_VALUE"),INVALID_VARIABLE_NAME:n((e,t)=>`Invalid CSS variable name at '${e}': ${t}`,"INVALID_VARIABLE_NAME")}};async function ne(e){const t={files:{},errors:[]};for(const[r,i]of Object.entries(e))try{const o=!i.includes("*")&&!i.endsWith(".json")?re.join(i,"**/*.json"):i,s=await te(o,{absolute:!0,onlyFiles:!0});if(s.length===0){t.errors.push({pattern:i,error:u.LOAD.NO_FILES_FOUND(i)});continue}t.files[r]=s}catch(o){t.errors.push({pattern:i,error:u.LOAD.GLOB_ERROR(i,o instanceof Error?o.message:"Unknown error")})}return t}n(ne,"resolveFiles");async function oe(e){try{const t=await ee(e,"utf-8");return JSON.parse(t)}catch(t){throw t instanceof Error?t instanceof SyntaxError?new Error(u.LOAD.INVALID_JSON(e,t.message)):"code"in t&&t.code==="ENOENT"?new Error(u.LOAD.FILE_NOT_FOUND(e)):new Error(u.LOAD.READ_ERROR(e,t.message)):new Error(u.LOAD.READ_ERROR(e,"Unknown error"))}}n(oe,"loadTree");async function L(e){const t=[],r=[];if(Object.keys(e).length===0)return{trees:[],errors:[{file:"",message:u.LOAD.EMPTY_CONFIG()}]};const{files:i,errors:o}=await ne(e);t.push(...o.map(s=>({file:s.pattern,message:s.error})));for(const[s,a]of Object.entries(i))for(const c of a)try{const f=await oe(c);r.push({name:s,tokens:f})}catch(f){t.push({file:c,message:f instanceof Error?f.message:"Unknown error"})}return{trees:r,errors:t}}n(L,"loadTreesFromConfig");function ie(e,t){const r={},i=[];(e.$description||e.$extensions)&&(r[t.file]={$description:e.$description,$extensions:e.$extensions});function o(s,a=[],c){if(a.length>0&&(s.$description||s.$extensions)&&(r[`${t.file}.${a.join(".")}`]={$description:s.$description,$extensions:s.$extensions}),"$value"in s)return;const f=s.$type||c,d=Object.keys(s).filter(l=>!l.startsWith("$"));for(const l of d){const I=s[l];if(l.includes(".")||l.includes("{")||l.includes("}")){i.push({path:[...a,l].join("."),source:t,message:u.FLATTEN.INVALID_TOKEN_NAME(l)});continue}const m=[...a,l];if("$value"in I){if(!f&&!I.$type){i.push({path:m.join("."),source:t,message:u.FLATTEN.MISSING_INHERITED_TYPE(m.join("."))});continue}r[`${t.file}.${m.join(".")}`]={...I,$type:I.$type||f,$path:m.join("."),$source:t,$originalPath:m.join(".")}}else o(I,m,f)}}return n(o,"processNode"),o(e),{tokens:r,errors:i}}n(ie,"flattenTree");function b(e){return e.reduce((t,{name:r,tokens:i})=>{const{tokens:o,errors:s}=ie(i,{file:r});return{tokens:{...t.tokens,...o},errors:[...t.errors,...s]}},{tokens:{},errors:[]})}n(b,"flatten");function p(e){return typeof e=="string"&&e.startsWith("{")&&e.endsWith("}")}n(p,"isReference");function g(e,t,r,i){return typeof t=="string"&&p(t)?se(e,t,r,i):Array.isArray(t)?t.map(o=>g(e,o,r,i)):typeof t=="object"&&t!==null?Object.entries(t).reduce((s,[a,c])=>({...s,[a]:g(`${e}.${a}`,c,r,i)}),{}):t}n(g,"resolveValue");function V(e){const t={},r=new Set,i=[];for(const[o,s]of Object.entries(e))try{if(!("$value"in s)){t[o]=s;continue}const a=s;t[o]={...a,$resolvedValue:g(a.$path,a.$value,e,r)}}catch(a){const c=a instanceof Error?a.message:String(a),f=s,d=f.$path,l=f.$source;let I,m;c.includes("Circular reference detected")?(I="circular",m=c):c.includes("Reference not found")?(I="missing",m=c):(I="type-mismatch",m=u.RESOLVE.TYPE_MISMATCH(d)),i.push({type:I,path:d,source:l,message:m})}return{resolved:t,errors:i}}n(V,"resolve");function se(e,t,r,i){const o=t.slice(1,-1),s=Object.keys(r).find(f=>{const d=r[f];return d?"$originalPath"in d&&d.$originalPath===o:!1});if(!s)throw new Error(`Reference not found: ${o} in ${e}`);if(i.has(s))throw new Error(`Circular reference detected: ${e} -> ${s}`);const a=r[s];if(!a||!("$value"in a))throw new Error(`Reference not found: ${o} in ${e}`);i.add(s);const c=g(s,a.$value,r,i);return i.delete(s),c}n(se,"resolveReferenceChain");function E(e){return["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","emoji","math","fangsong"].includes(e.toLowerCase())?e:/[\s'"!@#$%^&*()=+[\]{};:|\\/,.<>?~]/.test(e)?`"${e}"`:e}n(E,"quoteFont");const ae={thin:100,hairline:100,"extra-light":200,"ultra-light":200,light:300,normal:400,regular:400,book:400,medium:500,"semi-bold":600,"demi-bold":600,bold:700,"extra-bold":800,"ultra-bold":800,black:900,heavy:900,"extra-black":950,"ultra-black":950};function x(e){return p(e)?{value:e}:typeof e=="number"?{value:e}:{value:ae[e.toLowerCase()]??e}}n(x,"convertFontWeightToken");function ce(e){if(p(e))return{"font-family":e,"font-size":e};const t={"font-family":p(e.fontFamily)?e.fontFamily:Array.isArray(e.fontFamily)?e.fontFamily.map(r=>E(r)).join(", "):E(e.fontFamily),"font-size":p(e.fontSize)?e.fontSize:`${e.fontSize.value}${e.fontSize.unit}`};return e.fontWeight&&(t["font-weight"]=p(e.fontWeight)?e.fontWeight:x(e.fontWeight).value),e.letterSpacing&&(t["letter-spacing"]=p(e.letterSpacing)?e.letterSpacing:`${e.letterSpacing.value}${e.letterSpacing.unit}`),e.lineHeight&&(t["line-height"]=(p(e.lineHeight),e.lineHeight)),t}n(ce,"convertTypographyToken");function ue(e){if(p(e))return{value:e};const t=(p(e.duration),e.duration),r=p(e.timingFunction)?e.timingFunction:`cubic-bezier(${e.timingFunction.join(", ")})`,i=e.delay&&(p(e.delay),e.delay);return{value:[t,r,i].filter(Boolean).join(" ")}}n(ue,"convertTransitionToken");function fe(e){return p(e)?{value:e}:{value:`cubic-bezier(${e.join(", ")})`}}n(fe,"convertCubicBezierToken");function le(e){return p(e)?{value:e}:{value:e}}n(le,"convertNumberToken");function de(e){return p(e)?{value:e}:{value:e.toString()}}n(de,"convertDurationToken");function P(e){return p(e)?{value:e}:typeof e=="string"?{value:e}:{value:`${e.dashArray.map(r=>p(r)?r:`${r.value}${r.unit}`).join(" ")} ${e.lineCap}`}}n(P,"convertStrokeStyleToken");function pe(e){if(p(e))return{value:e};const t=p(e.width)?e.width:`${e.width.value}${e.width.unit}`,r=(p(e.color),e.color),i=typeof e.style=="string"?e.style:P(e.style).value;return{value:`${t} ${i} ${r}`}}n(pe,"convertBorderToken");function U(e){const t=p(e.offsetX)?e.offsetX:`${e.offsetX.value}${e.offsetX.unit}`,r=p(e.offsetY)?e.offsetY:`${e.offsetY.value}${e.offsetY.unit}`,i=p(e.blur)?e.blur:`${e.blur.value}${e.blur.unit}`,o=p(e.spread)?e.spread:`${e.spread.value}${e.spread.unit}`,s=(p(e.color),e.color);return`${e.inset?"inset ":""}${t} ${r} ${i} ${o} ${s}`}n(U,"convertSingleShadow");function Ie(e){return p(e)?{value:e}:Array.isArray(e)?{value:e.map(U).join(", ")}:{value:U(e)}}n(Ie,"convertShadowToken");function me(e){return p(e)?{value:e}:{value:`linear-gradient(${e.map(r=>`${p(r.color),r.color} ${r.position}%`).join(", ")})`}}n(me,"convertGradientToken");function $e(e){return p(e)?{value:e}:{value:Array.isArray(e)?e.map(r=>E(r)).join(", "):E(e)}}n($e,"convertFontFamilyToken");function he(e){return p(e)?{value:e}:{value:`${e.value}${e.unit}`}}n(he,"convertDimensionToken");function T(e,t=16){return e.unit==="px"?e.value:e.value*t}n(T,"normalizeToPixels");function Ae(e,t){const{min:r,max:i}=e,{viewports:o}=t.fluidConfig,s=16,a=T(r,s),c=T(i,s),f=T(o.min,s),d=T(o.max,s);if(a===c)return{value:`${a/s}rem`};const l=a/s,I=c/s,m=f/s,A=d/s,y=(I-l)/(A-m),_=-1*m*y+l;return{value:`clamp(${l}rem, ${_.toFixed(2)}rem + ${(y*100).toFixed(2)}vw, ${I}rem)`}}n(Ae,"convertFluidDimension");function ye(e,t){return p(e)?{value:e}:Ae(e,t)}n(ye,"convertFluidDimensionToken");function ge(e,t,r){const i=Math.max(e,t,r),o=Math.min(e,t,r);let s=0,a=0;const c=(i+o)/2;if(i!==o){const f=i-o;switch(a=c>.5?f/(2-i-o):f/(i+o),i){case e:s=(t-r)/f+(t<r?6:0);break;case t:s=(r-e)/f+2;break;case r:s=(e-t)/f+4;break}s*=60}return[Math.round(s),Math.round(a*100),Math.round(c*100)]}n(ge,"rgbToHsl");const N=n(e=>Number.isInteger(e)?e.toString():Number(e.toFixed(3)).toString(),"formatNumber"),Ee={hex:{type:"standard",convert:n((e,t,r,i)=>{const o=n(s=>Math.round(s*255).toString(16).padStart(2,"0"),"toHex");return`#${o(e)}${o(t)}${o(r)}${i<1?o(i):""}`},"convert")},rgb:{type:"standard",convert:n((e,t,r,i)=>{const o=[e,t,r].map(s=>Math.round(s*255));return i===1?`rgb(${o.join(", ")})`:`rgba(${o.join(", ")}, ${N(i)})`},"convert")},hsl:{type:"standard",convert:n((e,t,r,i)=>{const[o,s,a]=ge(e,t,r);return i===1?`hsl(${o}, ${s}%, ${a}%)`:`hsla(${o}, ${s}%, ${a}%, ${N(i)})`},"convert")},p3:{type:"conditional",featureQuery:"@supports (color: color(display-p3 1 1 1))",convert:n((e,t,r,i)=>{const o=[e,t,r].map(N).join(" ");return i===1?`color(display-p3 ${o})`:`color(display-p3 ${o} / ${N(i)})`},"convert")}};function Te(e,t){if(p(e))return{value:e};const r=t.colorFormat||"hex";if(r==="hex")return{value:e};const i=Ee[r.name];if(!i)return{value:e};const o=e.substring(1),s=parseInt(o.substring(0,2),16)/255,a=parseInt(o.substring(2,4),16)/255,c=parseInt(o.substring(4,6),16)/255,f=o.length===8?parseInt(o.substring(6,8),16)/255:1;return i.type==="conditional"?{value:e,featureValues:[{query:i.featureQuery,value:i.convert(s,a,c,f)}]}:{value:i.convert(s,a,c,f)}}n(Te,"convertColorToken");const G={duration:de,number:le,cubicBezier:fe,color:Te,dimension:he,fluidDimension:ye,typography:ce,border:pe,shadow:Ie,gradient:me,transition:ue,strokeStyle:P,fontFamily:$e,fontWeight:x};function Ne(e,t){const r=G[e.$type];return{...e.$description?{$description:e.$description}:{},...e.$extensions?{$extensions:e.$extensions}:{},$type:e.$type,$value:e.$value,$path:e.$path,$source:e.$source,$originalPath:e.$originalPath,$resolvedValue:e.$resolvedValue,$cssProperties:r(e.$value,t)}}n(Ne,"convertSingleToken");function Se(e,t){const r={};for(const[i,o]of Object.entries(e)){if(!o||typeof o!="object")continue;if(!("$type"in o)){r[i]={...o.$description?{$description:o.$description}:{},...o.$extensions?{$extensions:o.$extensions}:{}};continue}if(!G[o.$type])continue;const s={fluidConfig:t.fluid,colorFormat:t.color?.format,path:o.$path};r[i]=Ne(o,s)}return r}n(Se,"convertTokens");function O(e,t){const r={};for(const[i,o]of Object.entries(e)){r[i]={};for(const[s,a]of Object.entries(o))r[i][s]=Se(a,t)}return r}n(O,"convert");function De(e){return JSON.parse(e)}n(De,"parseJson");const _e={isObject:n(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObject")};function $(e,t,r,i){if(p(t))return[];switch(e.type){case"object":return be(e,t,r,i);case"union":return Ve(e,t,r,i);case"array":return Oe(e,t,r,i);default:return Le(e,t,r,i)}}n($,"validateSchema");function Le(e,t,r,i){return typeof t!==e.type?[{path:r,message:e.errorMessage?.(t,r)||u.VALIDATE.INVALID_TYPE(e.type,t,r),source:i}]:e.validate?.(t,r,i)??[]}n(Le,"validateSimpleValue");function be(e,t,r,i){if(!_e.isObject(t))return[{path:r,message:e.errorMessage?.(t,r)||u.VALIDATE.INVALID_TYPE("object",t,r),source:i}];const o=[],s=t;if(e.required)for(const a of e.required)a in s||o.push({path:`${r}.${a}`,message:u.VALIDATE.MISSING_REQUIRED_PROPERTY(a,r),source:i});for(const[a,c]of Object.entries(e.properties))a in s&&o.push(...$(c,s[a],`${r}.${a}`,i));return o}n(be,"validateObject");function Ve(e,t,r,i){let o=[],s=1/0;for(const a of e.oneOf){if(a.type==="string"&&typeof t!="string"||a.type==="object"&&typeof t!="object")continue;const c=$(a,t,r,i);if(c.length===0)return e.validate?.(t,r,i)??[];c.length<s&&(o=c,s=c.length)}return s===1/0?[{path:r,message:u.VALIDATE.INVALID_TYPE(e.oneOf.map(a=>a.type).join(" or "),t,r),source:i}]:o}n(Ve,"validateUnion");function Oe(e,t,r,i){return Array.isArray(t)?e.validate?.(t,r,i)??[]:[{path:r,message:e.errorMessage?.(t,r)||u.VALIDATE.INVALID_TYPE("array",t,r),source:i}]}n(Oe,"validateArray");const S={tokenType:"color",schema:{type:"string",errorMessage:n((e,t)=>u.VALIDATE.INVALID_COLOR(e,t),"errorMessage"),validate:n((e,t,r)=>/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/.test(e)?[]:[{path:t,message:u.VALIDATE.INVALID_COLOR(e,t),source:r}],"validate")}};function Re(e,t,r){return $(S.schema,e,t,r)}n(Re,"validateColor");const D={tokenType:"number",schema:{type:"number",errorMessage:n((e,t)=>u.VALIDATE.INVALID_NUMBER(e,t),"errorMessage"),validate:n((e,t,r)=>typeof e!="number"||isNaN(e)?[{path:t,message:u.VALIDATE.INVALID_NUMBER(e,t),source:r}]:[],"validate")}};function ve(e,t,r){return $(D.schema,e,t,r)}n(ve,"validateNumber");const h={tokenType:"dimension",schema:{type:"object",errorMessage:n((e,t)=>u.VALIDATE.INVALID_DIMENSION(e,t),"errorMessage"),properties:{value:D.schema,unit:{type:"string",validate:n((e,t,r)=>typeof e!="string"||!["px","rem"].includes(e)?[{path:t,message:u.VALIDATE.INVALID_DIMENSION_UNIT(e,t),source:r}]:[],"validate")}},required:["value","unit"]}};function Fe(e,t,r){return $(h.schema,e,t,r)}n(Fe,"validateDimension");const W={tokenType:"fontFamily",schema:{type:"union",oneOf:[{type:"string",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage")},{type:"array",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage"),validate:n((e,t,r)=>e.every(o=>typeof o=="string")?[]:[{path:t,message:u.VALIDATE.INVALID_FONT_FAMILY(e,t),source:r}],"validate")}],errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage")}};function ke(e,t,r){return $(W.schema,e,t,r)}n(ke,"validateFontFamily");const Me=["thin","hairline","extra-light","ultra-light","light","normal","regular","book","medium","semi-bold","demi-bold","bold","extra-bold","ultra-bold","black","heavy","extra-black","ultra-black"],Y={tokenType:"fontWeight",schema:{type:"union",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),oneOf:[{type:"number",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),validate:n((e,t,r)=>e<1||e>1e3?[{path:t,message:u.VALIDATE.INVALID_FONT_WEIGHT(e,t),source:r}]:[],"validate")},{type:"string",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),validate:n((e,t,r)=>Me.includes(e.toLowerCase())?[]:[{path:t,message:u.VALIDATE.INVALID_FONT_WEIGHT(e,t),source:r}],"validate")}]}};function Ce(e,t,r){return $(Y.schema,e,t,r)}n(Ce,"validateFontWeight");const je=["ms","s"],R={tokenType:"duration",schema:{type:"object",errorMessage:n((e,t)=>u.VALIDATE.INVALID_DURATION(e,t),"errorMessage"),properties:{value:D.schema,unit:{type:"string",validate:n((e,t,r)=>je.includes(e)?[]:[{path:t,message:u.VALIDATE.INVALID_DURATION_UNIT(e,t),source:r}],"validate")}},required:["value","unit"]}};function we(e,t,r){return $(R.schema,e,t,r)}n(we,"validateDuration");const z={tokenType:"cubicBezier",schema:{type:"array",errorMessage:n((e,t)=>u.VALIDATE.INVALID_CUBIC_BEZIER(e,t),"errorMessage"),validate:n((e,t,r)=>{const i=e;if(i.length!==4||!i.every(a=>typeof a=="number"))return[{path:t,message:u.VALIDATE.INVALID_CUBIC_BEZIER(e,t),source:r}];const[o,,s]=i;return o<0||o>1||s<0||s>1?[{path:t,message:u.VALIDATE.INVALID_CUBIC_BEZIER_RANGE(e,t),source:r}]:[]},"validate")}};function xe(e,t,r){return $(z.schema,e,t,r)}n(xe,"validateCubicBezier");const Pe={tokenType:"typography",schema:{type:"object",properties:{fontFamily:W.schema,fontSize:h.schema,letterSpacing:h.schema,lineHeight:D.schema,fontWeight:Y.schema},required:["fontFamily","fontSize"],errorMessage:n((e,t)=>u.VALIDATE.INVALID_TYPOGRAPHY(e,t),"errorMessage")}};function Ue(e,t,r){return $(Pe.schema,e,t,r)}n(Ue,"validateTypography");const Ge=["solid","dashed","dotted","double","groove","ridge","outset","inset"],We=["round","butt","square"],Ye={type:"object",errorMessage:n((e,t)=>u.VALIDATE.INVALID_STROKE_STYLE(e,t),"errorMessage"),properties:{dashArray:{type:"array",validate:n((e,t,r)=>{const i=e,o=[];return i.forEach((s,a)=>{typeof s!="string"&&o.push(...$(h.schema,s,`${t}.${a}`,r))}),o},"validate")},lineCap:{type:"string",validate:n((e,t,r)=>We.includes(e)?[]:[{path:t,message:u.VALIDATE.INVALID_STROKE_LINE_CAP(e,t),source:r}],"validate")}},required:["dashArray","lineCap"]},B={tokenType:"strokeStyle",schema:{type:"union",oneOf:[{type:"string",validate:n((e,t,r)=>!Ge.includes(e)&&typeof e=="string"?[{path:t,message:u.VALIDATE.INVALID_STROKE_STYLE(e,t),source:r}]:[],"validate")},Ye]}};function ze(e,t,r){return $(B.schema,e,t,r)}n(ze,"validateStrokeStyle");const Be={tokenType:"border",schema:{type:"object",properties:{color:S.schema,width:h.schema,style:B.schema},required:["color","width","style"],errorMessage:n((e,t)=>u.VALIDATE.INVALID_BORDER(e,t),"errorMessage")}};function He(e,t,r){return $(Be.schema,e,t,r)}n(He,"validateBorder");const qe={tokenType:"transition",schema:{type:"object",properties:{duration:R.schema,delay:R.schema,timingFunction:z.schema},required:["duration","delay","timingFunction"],errorMessage:n((e,t)=>u.VALIDATE.INVALID_TRANSITION(e,t),"errorMessage")}};function Ke(e,t,r){return $(qe.schema,e,t,r)}n(Ke,"validateTransition");const H={tokenType:"shadow",schema:{type:"object",properties:{color:S.schema,offsetX:h.schema,offsetY:h.schema,blur:h.schema,spread:h.schema,inset:{type:"boolean",errorMessage:n((e,t)=>u.VALIDATE.INVALID_SHADOW_INSET(e,t),"errorMessage")}},required:["color","offsetX","offsetY","blur","spread"],errorMessage:n((e,t)=>u.VALIDATE.INVALID_SHADOW(e,t),"errorMessage")}};function Ze(e,t,r){const i=[];return Array.isArray(e)?(e.forEach((o,s)=>{i.push(...$(H.schema,o,`${t}[${s}]`,r))}),i):$(H.schema,e,t,r)}n(Ze,"validateShadow");const Xe={type:"object",errorMessage:n((e,t)=>u.VALIDATE.INVALID_GRADIENT(e,t),"errorMessage"),properties:{color:{type:"string",validate:S.schema.validate},position:{type:"number",validate:n((e,t,r)=>e<0||e>1?[{path:t,message:u.VALIDATE.INVALID_GRADIENT_STOP_POSITION(e,t),source:r}]:[],"validate")}},required:["color","position"]},Je={tokenType:"gradient",schema:{type:"array",errorMessage:n((e,t)=>u.VALIDATE.INVALID_ARRAY(e,t),"errorMessage"),validate:n((e,t,r)=>{const i=e,o=[];return i.forEach((s,a)=>{o.push(...$(Xe,s,`${t}[${a}]`,r))}),o},"validate")}};function Qe(e,t,r){return $(Je.schema,e,t,r)}n(Qe,"validateGradient");const et={tokenType:"fluidDimension",schema:{type:"object",errorMessage:n((e,t)=>u.VALIDATE.INVALID_FLUID_DIMENSION(e,t),"errorMessage"),properties:{min:h.schema,max:h.schema},required:["min","max"]}};function tt(e,t,r,i){const o=[];return i?.fluid?.viewports||o.push({path:t,message:u.VALIDATE.MISSING_FLUID_CONFIG(t),source:r}),o.push(...$(et.schema,e,t,r)),o}n(tt,"validateFluidDimension");const rt={color:Re,dimension:Fe,fluidDimension:tt,duration:we,cubicBezier:xe,fontFamily:ke,fontWeight:Ce,number:ve,strokeStyle:ze,typography:Ue,border:He,shadow:Ze,gradient:Qe,transition:Ke};function v(e,t){const r=[];for(const[i,o]of Object.entries(e)){if(typeof o!="object"||o===null||!("$type"in o)||!("$path"in o)||o.$path.startsWith("$"))continue;const s=rt[o.$type];if(!s){r.push({path:o.$path,message:u.VALIDATE.UNKNOWN_TOKEN_TYPE(o.$type,o.$path),source:o.$source});continue}r.push(...s(o.$value,o.$path,o.$source,t))}return r}n(v,"validate");function F(e,t){return e.map(r=>({name:r.name,tokens:Object.entries(t).reduce((i,[o,s])=>("$source"in s&&s.$source.file!==r.name||("$type"in s?s.$source.file===r.name&&(i[o]=s):i[o]=s),i),{})}))}n(F,"processTrees");function k(e,t){const r=[],i=[],o=new Map;return t?.length?{...e.reduce((a,{name:c,tokens:f})=>{let d=!1;return t.forEach(l=>{l.modes?.length&&l.modes.forEach(I=>{if(!I.files.includes(c))return;const m=o.get(c);m&&m.collection===l.name&&r.push({type:"warning",message:u.NORMALIZE.DUPLICATE_MODE_WARNING(c,l.name,I.name),file:c,collection:l.name,mode:I.name}),o.set(c,{collection:l.name,mode:I.name}),d=!0;const A=a.tokens[l.name]||{},y=A[I.name]||{};a.tokens[l.name]={...A,[I.name]:{...y,...f}}})}),d||t.forEach(l=>{if(!l.modes&&l.files?.includes(c)){const I=o.get(c);I&&!t.find(m=>m.name===I.collection)?.modes?.length&&r.push({type:"warning",message:u.NORMALIZE.DUPLICATE_FILE_WARNING(c,l.name),file:c,collection:l.name}),o.set(c,{collection:l.name}),d=!0,a.tokens[l.name]={default:{...a.tokens[l.name]?.default,...f}}}}),d||(a.tokens.default={default:{...a.tokens.default?.default,...f}}),a},{tokens:{default:{default:{}}},errors:[],warnings:[],processedFiles:new Map}),errors:i,warnings:r}:{tokens:{default:{default:e.reduce((c,{tokens:f})=>({...c,...f}),{})}},errors:[],warnings:[]}}n(k,"normalizeTokens");const q=new Map;function nt(e){const t=q.get(e);if(t)return t;const r=e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z])([A-Z])(?=[a-z])/g,"$1-$2").toLowerCase();return q.set(e,r),r}n(nt,"toKebabCase");function ot(e){return typeof e=="object"&&e!==null&&typeof e.query=="string"&&typeof e.value=="string"}n(ot,"isFeatureValue");function it(e){return typeof e!="object"||e===null||!("value"in e)||typeof e.value!="string"&&typeof e.value!="number"?!1:"featureValues"in e?Array.isArray(e.featureValues)?e.featureValues.every(ot):!1:!0}n(it,"isSimpleCSSProperties");function M(e){return!!(typeof e=="string"||typeof e=="number"||it(e))}n(M,"isValidCSSValue");function st(e){return/^--[a-zA-Z][a-zA-Z0-9-]*$/.test(e)}n(st,"isValidCSSVariableName");const K="@supports (color: color(display-p3 1 1 1))";function at(e){return e.$type==="typography"}n(at,"isTypographyToken");function C(e){return e.split(".").join("-")}n(C,"formatCSSVarPath");function Z(e){return typeof e=="number"?e:typeof e!="string"?(console.warn("Unexpected value type in convertReferenceToCSSVar, got:",e),String(e)):e.replace(/\{([^}]+)\}/g,(t,r)=>`var(--${r.split(".").map(nt).join("-")})`)}n(Z,"convertReferenceToCSSVar");function ct(e,t){const r=`--${C(e.$path)}`,i=e.$cssProperties;if(!("value"in i))return;const o=i.value;if(!M(o)){t.push({path:e.$path,message:u.GENERATE.INVALID_CSS_VALUE(e.$path,String(o))});return}if(!st(r)){t.push({path:e.$path,message:u.GENERATE.INVALID_VARIABLE_NAME(e.$path,r)});return}return{name:r,value:Z(o)}}n(ct,"generateSingleVariable");function ut(e,t){const r=[];return Object.entries(e.$cssProperties).forEach(([i,o])=>{if(o!==void 0){if(!M(o)){t.push({path:`${e.$path}-${i}`,message:u.GENERATE.INVALID_CSS_VALUE(e.$path,String(o))});return}r.push({name:`--${C(e.$path)}-${i}`,value:Z(o)})}}),r}n(ut,"generateTypographyVariables");function X(e,t){if(e.$type!=="color")return[];const r=e.$cssProperties;if(!("featureValues"in r))return[];const i=[];return r.featureValues?.forEach(o=>{if(o.query===K){if(!M(o.value)){t.push({path:e.$path,message:u.GENERATE.INVALID_CSS_VALUE(e.$path,String(o.value))});return}i.push({name:`--${C(e.$path)}`,value:o.value})}}),i}n(X,"generateFeatureVariables");function J(e){const t=[`${e.selector} {`];if(e.comment&&t.push(` /* ${e.comment} */`),e.vars.length>0){const r=e.vars.map(i=>` ${i.name}: ${i.value};`).join(`
2
- `);t.push(r)}return t.push("}"),t.join(`
3
- `)}n(J,"generateCSSBlock");function ft(e){const t=[];return e.root.vars.length>0&&t.push(J({selector:e.root.selector,vars:e.root.vars})),e.features.forEach(r=>{const o=J({selector:e.root.selector,vars:r.vars}).split(`
1
+ var ae=Object.defineProperty;var o=(e,t)=>ae(e,"name",{value:t,configurable:!0});import{readFile as ce}from"node:fs/promises";import le from"fast-glob";import ue,{relative as b}from"node:path";import{converter as S,formatHex as P}from"culori";const l={LOAD:{FILE_NOT_FOUND:o(e=>`File not found: ${e}`,"FILE_NOT_FOUND"),INVALID_JSON:o((e,t)=>`Invalid JSON in file ${e}: ${t}`,"INVALID_JSON"),READ_ERROR:o((e,t)=>`Error reading file ${e}: ${t}`,"READ_ERROR"),INVALID_SOURCE:o(e=>`Invalid source: expected string or array of file descriptors, got ${typeof e}`,"INVALID_SOURCE"),NO_FILES_FOUND:o(e=>`No files found matching pattern: ${e}.`,"NO_FILES_FOUND"),GLOB_ERROR:o((e,t)=>`Error resolving glob pattern ${e}: ${t}`,"GLOB_ERROR"),EMPTY_CONFIG:o(()=>"No token files specified in sugarcube.config.json","EMPTY_CONFIG")},PARSE:{INVALID_INPUT_TYPE:o(e=>`Invalid input: expected string, got ${e}`,"INVALID_INPUT_TYPE"),JSON_PARSE_ERROR:o(e=>`JSON parsing error: ${e}`,"JSON_PARSE_ERROR"),UNEXPECTED_ERROR:o(e=>`Unexpected error during parsing: ${e}`,"UNEXPECTED_ERROR")},FLATTEN:{INVALID_TOKEN_NAME:o(e=>`Invalid token name '${e}': cannot contain '.', '{', or '}'`,"INVALID_TOKEN_NAME"),INVALID_NODE_STRUCTURE:o(e=>`Invalid node structure at ${e}: expected object`,"INVALID_NODE_STRUCTURE"),MISSING_INHERITED_TYPE:o(e=>`Token at ${e} has no $type (neither explicit nor inherited)`,"MISSING_INHERITED_TYPE"),MISSING_DOLLAR_PREFIX:o(e=>`Token at ${e} is using 'value' or 'type' without the required '$' prefix. Use '$value' and '$type' instead.`,"MISSING_DOLLAR_PREFIX")},METADATA:{COLLECTION_ERROR:o(e=>`Error collecting metadata: ${e}`,"COLLECTION_ERROR"),INVALID_EXTENSIONS:o(e=>`Invalid extensions at ${e}: expected object, got ${typeof e}`,"INVALID_EXTENSIONS"),INVALID_DESCRIPTION:o(e=>`Invalid description at ${e}: expected string, got ${typeof e}`,"INVALID_DESCRIPTION")},VALIDATE:{MISSING_TYPE:o(e=>`Token at '${e}' is missing the "$type" property`,"MISSING_TYPE"),MISSING_VALUE:o(e=>`Token at '${e}' is missing the "$value" property`,"MISSING_VALUE"),UNKNOWN_TOKEN_TYPE:o((e,t)=>`Unknown token type '${e}' at ${t}. Valid types are: color, dimension, fontFamily, fontWeight, duration, cubicBezier, strokeStyle, border, transition, shadow, gradient, typography`,"UNKNOWN_TOKEN_TYPE"),INVALID_COLOR:o((e,t)=>`Invalid color at ${t}: '${e}'. Color should be a valid hex value`,"INVALID_COLOR"),INVALID_DIMENSION:o((e,t)=>`Invalid dimension at '${t}': ${e}. Dimensions should have a numeric value and unit, like { "value": 16, "unit": "px" }`,"INVALID_DIMENSION"),INVALID_DIMENSION_UNIT:o((e,t)=>`Invalid unit at ${t}': '${e}'. Unit must be either "px" or "rem"`,"INVALID_DIMENSION_UNIT"),INVALID_FONT_FAMILY:o((e,t)=>`Invalid font family at '${t}': ${e}. Should be a string or array of strings, like "Arial" or ["Arial", "sans-serif"]`,"INVALID_FONT_FAMILY"),INVALID_FONT_WEIGHT:o((e,t)=>`Invalid font weight at '${t}': ${e}. Should be a number between 1-1000 or a keyword like "thin", "light", "normal", "bold"`,"INVALID_FONT_WEIGHT"),INVALID_DURATION:o((e,t)=>`Invalid duration at '${t}': ${e}. Should be like { "value": 300, "unit": "ms" }`,"INVALID_DURATION"),INVALID_DURATION_UNIT:o((e,t)=>`Invalid unit at ${t}: "${e}". Unit must be "ms" or "s"`,"INVALID_DURATION_UNIT"),INVALID_CUBIC_BEZIER:o((e,t)=>`Invalid cubic bezier at ${t}: "${e}". Should be an array of 4 numbers between 0 and 1`,"INVALID_CUBIC_BEZIER"),INVALID_CUBIC_BEZIER_RANGE:o((e,t)=>`Invalid cubic bezier control points at '${t}': ${e}. X values must be between 0 and 1`,"INVALID_CUBIC_BEZIER_RANGE"),INVALID_STROKE_STYLE:o((e,t)=>`Invalid stroke style at ${t}: "${e}". Should be "solid", "dashed", "dotted", etc.`,"INVALID_STROKE_STYLE"),INVALID_STROKE_LINE_CAP:o((e,t)=>`Invalid line cap at ${t}: "${e}". Should be one of: round, butt, square`,"INVALID_STROKE_LINE_CAP"),INVALID_BORDER:o((e,t)=>`Invalid border at ${t}: "${e}". Should have color, width, and style properties`,"INVALID_BORDER"),INVALID_SHADOW:o((e,t)=>`Invalid shadow at ${t}: "${e}". Should have color, offsetX, offsetY properties (blur and spread are optional)`,"INVALID_SHADOW"),INVALID_SHADOW_INSET:o((e,t)=>`Invalid inset value at ${t}: "${e}". Should be true or false`,"INVALID_SHADOW_INSET"),INVALID_TRANSITION:o((e,t)=>`Invalid transition at ${t}: "${e}". Should have duration, delay, and timingFunction properties`,"INVALID_TRANSITION"),INVALID_GRADIENT:o((e,t)=>`Invalid gradient at ${t}: "${e}". Should be an array of color stops with position values between 0 and 1`,"INVALID_GRADIENT"),INVALID_GRADIENT_STOP_POSITION:o((e,t)=>`Invalid gradient stop position at ${t}: "${e}". Position must be between 0 and 1`,"INVALID_GRADIENT_STOP_POSITION"),INVALID_TYPOGRAPHY:o((e,t)=>`Invalid typography at ${t}: "${e}". Should have fontFamily and fontSize (fontWeight, letterSpacing, and lineHeight are optional)`,"INVALID_TYPOGRAPHY"),MISSING_REQUIRED_PROPERTY:o((e,t)=>`Missing required property '${e}' at ${t}`,"MISSING_REQUIRED_PROPERTY"),INVALID_NUMBER:o((e,t)=>`Invalid number at ${t}: "${e}". Expected a number value`,"INVALID_NUMBER"),INVALID_ARRAY:o((e,t)=>`Invalid array at ${t}: "${e}". Expected an array value`,"INVALID_ARRAY"),MISSING_FLUID_CONFIG:o(e=>`Missing fluid configuration. Token at ${e} requires fluid viewport settings.`,"MISSING_FLUID_CONFIG"),INVALID_FLUID_DIMENSION:o((e,t)=>`Invalid fluid dimension at ${t}: "${e}". Fluid dimensions should have min and max values, like { "min": { "value": 16, "unit": "px" }, "max": { "value": 24, "unit": "px" } }`,"INVALID_FLUID_DIMENSION"),INVALID_VIEWPORT_CONFIG:o((e,t)=>`Invalid viewport configuration at ${t}: "${e}". Viewport config should have min and max dimension values`,"INVALID_VIEWPORT_CONFIG"),MISMATCHED_UNITS:o((e,t,n)=>`Mismatched units at ${n}: min uses '${e}', max uses '${t}'. Both values must use the same unit`,"MISMATCHED_UNITS"),INVALID_FLUID_VALUE_RANGE:o(e=>`Invalid fluid value range at ${e}: min value must be less than max value`,"INVALID_FLUID_VALUE_RANGE"),INVALID_TOKEN_TYPE:o((e,t,n)=>`Invalid token type at ${n}: expected ${e}, got ${t}`,"INVALID_TOKEN_TYPE"),INVALID_TYPE:o((e,t,n)=>`Expected ${e}, received ${typeof t} at ${n}`,"INVALID_TYPE"),INVALID_ENUM_VALUE:o((e,t,n)=>`Expected value to be one of [${e.join(", ")}], but got ${String(t)} at ${n}`,"INVALID_ENUM_VALUE")},RESOLVE:{CIRCULAR_REFERENCE:o((e,t)=>`Circular reference detected: ${e} -> ${t}`,"CIRCULAR_REFERENCE"),REFERENCE_NOT_FOUND:o((e,t)=>`Reference not found: ${t} in ${e}`,"REFERENCE_NOT_FOUND"),TYPE_MISMATCH:o(e=>`Type mismatch in reference resolution at ${e}`,"TYPE_MISMATCH")},NORMALIZE:{DUPLICATE_FILE_WARNING:o((e,t)=>`Warning: File '${e}' is assigned to multiple collections without modes (in '${t}'). This will create duplicate CSS variables in :root since collections without modes default to root scope.`,"DUPLICATE_FILE_WARNING"),DUPLICATE_MODE_WARNING:o((e,t,n)=>`Warning: File '${e}' is assigned to multiple modes in collection '${t}' (in '${n}'). This means the same token values will be duplicated across different theme selectors.`,"DUPLICATE_MODE_WARNING")},GENERATE:{INVALID_CSS_VALUE:o((e,t)=>`Invalid CSS value for property '${e}': ${t}`,"INVALID_CSS_VALUE"),INVALID_VARIABLE_NAME:o((e,t)=>`Invalid CSS variable name at '${e}': ${t}`,"INVALID_VARIABLE_NAME")}};async function U(e){const t={files:[],errors:[]};for(const n of e)try{const r=!n.includes("*")&&!n.endsWith(".json")?ue.join(n,"**/*.json"):n,i=await le(r,{absolute:!0,onlyFiles:!0});if(i.length===0){t.errors.push({pattern:n,error:l.LOAD.NO_FILES_FOUND(n)});continue}t.files.push(...i)}catch(r){t.errors.push({pattern:n,error:l.LOAD.GLOB_ERROR(n,r instanceof Error?r.message:"Unknown error")})}return t}o(U,"resolveFiles");async function G(e){try{const t=await ce(e,"utf-8");return JSON.parse(t)}catch(t){throw t instanceof Error?t instanceof SyntaxError?new Error(l.LOAD.INVALID_JSON(e,t.message)):"code"in t&&t.code==="ENOENT"?new Error(l.LOAD.FILE_NOT_FOUND(e)):new Error(l.LOAD.READ_ERROR(e,t.message)):new Error(l.LOAD.READ_ERROR(e,"Unknown error"))}}o(G,"loadTree");function fe(e){const t=new Set;return e.themes&&Object.values(e.themes).forEach(n=>{n.forEach(r=>t.add(r))}),t}o(fe,"collectThemePaths");async function _(e){const t=[],n=[],r=Array.isArray(e.tokens)?{default:{source:e.tokens,type:"custom"}}:"source"in e.tokens?{default:e.tokens}:e.tokens;for(const[i,s]of Object.entries(r)){const a=fe(s),{files:c,errors:u}=await U(Array.isArray(s.source)?s.source:[s.source]);if(u.length>0){t.push(...u.map(f=>({file:f.pattern,message:f.error})));continue}for(const f of c){const h=b(process.cwd(),f);if(!a.has(h))try{const d=await G(f),m={collection:i,tokens:d,sourcePath:h};n.push(m)}catch(d){t.push({file:f,message:d instanceof Error?d.message:"Unknown error"})}}if(s.themes)for(const[f,h]of Object.entries(s.themes))try{const{files:d,errors:m}=await U(h);if(m.length>0){t.push(...m.map(I=>({file:I.pattern,message:I.error})));continue}for(const I of d)try{const y=await G(I),A={collection:i,theme:f,tokens:y,sourcePath:b(process.cwd(),I)};n.push(A)}catch(y){t.push({file:I,message:y instanceof Error?y.message:"Unknown error"})}}catch(d){t.push({file:h.join(", "),message:d instanceof Error?d.message:"Unknown error"})}}return{trees:n,errors:t}}o(_,"loadTreesFromConfig");async function Y(e){const t=[],n=[],r=new Map;for(const[i,{collection:s,theme:a,content:c}]of Object.entries(e)){r.has(s)||r.set(s,new Map);const u=r.get(s);u.has(a)||u.set(a,[]),u.get(a).push({content:c,path:i})}for(const[i,s]of r)for(const[a,c]of s)for(const{content:u,path:f}of c)try{const h=JSON.parse(u);t.push({collection:i,theme:a,tokens:h,sourcePath:b(process.cwd(),f)})}catch(h){n.push({file:f,message:`Failed to parse JSON content: ${h.message}`})}return{trees:t,errors:n}}o(Y,"loadTreesFromMemory");function de(e){if(typeof e!="object"||e===null||"$value"in e)return!1;const t="value"in e,n="type"in e;if(t&&n)return!0;if(t){const r=e.value;return typeof r=="string"||typeof r=="number"||Array.isArray(r)}return!1}o(de,"looksLikeUnprefixedToken");function pe(e,t){const n={},r=[];function i(a=[]){const c=[t.collection];return t.theme&&c.push(t.theme),a.length>0&&c.push(a.join(".")),c.join(".")}o(i,"createLookupKey"),(e.$description||e.$extensions)&&(n[i()]={$description:e.$description,$extensions:e.$extensions});function s(a,c=[],u){if(c.length>0&&(a.$description||a.$extensions)&&(n[i(c)]={$description:a.$description,$extensions:a.$extensions}),"$value"in a)return;const f=a.$type||u,h=Object.keys(a).filter(d=>!d.startsWith("$"));for(const d of h){const m=a[d],I=[...c,d];if(de(m)){r.push({path:I.join("."),source:t,message:l.FLATTEN.MISSING_DOLLAR_PREFIX(I.join("."))});continue}if(d.includes(".")||d.includes("{")||d.includes("}")){r.push({path:I.join("."),source:t,message:l.FLATTEN.INVALID_TOKEN_NAME(d)});continue}if("$value"in m){if(!f&&!m.$type){r.push({path:I.join("."),source:t,message:l.FLATTEN.MISSING_INHERITED_TYPE(I.join("."))});continue}n[i(I)]={...m,$type:m.$type||f,$path:I.join("."),$source:{collection:t.collection,theme:t.theme,sourcePath:t.sourcePath},$originalPath:I.join(".")}}else s(m,I,f)}}return o(s,"processNode"),s(e),{tokens:n,errors:r}}o(pe,"flattenTree");function L(e){return e.reduce((t,n)=>{const{tokens:r,errors:i}=pe(n.tokens,{collection:n.collection,theme:n.theme,sourcePath:n.sourcePath});return{tokens:{...t.tokens,...r},errors:[...t.errors,...i]}},{tokens:{},errors:[]})}o(L,"flatten");const he={isObject:o(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObject")};function p(e){return typeof e=="string"&&e.startsWith("{")&&e.endsWith("}")}o(p,"isReference");function $(e,t,n,r){if(p(t))return[];switch(e.type){case"object":return Ie(e,t,n,r);case"union":return $e(e,t,n,r);case"array":return ye(e,t,n,r);default:return me(e,t,n,r)}}o($,"validateSchema");function me(e,t,n,r){return typeof t!==e.type?[{path:n,message:e.errorMessage?.(t,n)||l.VALIDATE.INVALID_TYPE(e.type,t,n),source:r}]:e.validate?.(t,n,r)??[]}o(me,"validateSimpleValue");function Ie(e,t,n,r){if(!he.isObject(t))return[{path:n,message:e.errorMessage?.(t,n)||l.VALIDATE.INVALID_TYPE("object",t,n),source:r}];const i=[],s=t;if(e.required)for(const a of e.required)a in s||i.push({path:`${n}.${a}`,message:l.VALIDATE.MISSING_REQUIRED_PROPERTY(a,n),source:r});for(const[a,c]of Object.entries(e.properties))a in s&&i.push(...$(c,s[a],`${n}.${a}`,r));return i}o(Ie,"validateObject");function $e(e,t,n,r){let i=[],s=1/0;for(const a of e.oneOf){if(a.type==="string"&&typeof t!="string"||a.type==="object"&&typeof t!="object")continue;const c=$(a,t,n,r);if(c.length===0)return e.validate?.(t,n,r)??[];c.length<s&&(i=c,s=c.length)}return s===1/0?[{path:n,message:l.VALIDATE.INVALID_TYPE(e.oneOf.map(a=>a.type).join(" or "),t,n),source:r}]:i}o($e,"validateUnion");function ye(e,t,n,r){return Array.isArray(t)?e.validate?.(t,n,r)??[]:[{path:n,message:e.errorMessage?.(t,n)||l.VALIDATE.INVALID_TYPE("array",t,n),source:r}]}o(ye,"validateArray");const E={tokenType:"color",schema:{type:"string",errorMessage:o((e,t)=>l.VALIDATE.INVALID_COLOR(e,t),"errorMessage"),validate:o((e,t,n)=>/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/.test(e)?[]:[{path:t,message:l.VALIDATE.INVALID_COLOR(e,t),source:n}],"validate")}};function ge(e,t,n){return $(E.schema,e,t,n)}o(ge,"validateColor");const T={tokenType:"number",schema:{type:"number",errorMessage:o((e,t)=>l.VALIDATE.INVALID_NUMBER(e,t),"errorMessage"),validate:o((e,t,n)=>typeof e!="number"||isNaN(e)?[{path:t,message:l.VALIDATE.INVALID_NUMBER(e,t),source:n}]:[],"validate")}};function Ae(e,t,n){return $(T.schema,e,t,n)}o(Ae,"validateNumber");const g={tokenType:"dimension",schema:{type:"object",errorMessage:o((e,t)=>l.VALIDATE.INVALID_DIMENSION(e,t),"errorMessage"),properties:{value:T.schema,unit:{type:"string",validate:o((e,t,n)=>typeof e!="string"||!["px","rem"].includes(e)?[{path:t,message:l.VALIDATE.INVALID_DIMENSION_UNIT(e,t),source:n}]:[],"validate")}},required:["value","unit"]}};function Ee(e,t,n){return $(g.schema,e,t,n)}o(Ee,"validateDimension");const z={tokenType:"fontFamily",schema:{type:"union",oneOf:[{type:"string",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage")},{type:"array",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage"),validate:o((e,t,n)=>e.every(i=>typeof i=="string")?[]:[{path:t,message:l.VALIDATE.INVALID_FONT_FAMILY(e,t),source:n}],"validate")}],errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_FAMILY(e,t),"errorMessage")}};function Te(e,t,n){return $(z.schema,e,t,n)}o(Te,"validateFontFamily");const Ne=["thin","hairline","extra-light","ultra-light","light","normal","regular","book","medium","semi-bold","demi-bold","bold","extra-bold","ultra-bold","black","heavy","extra-black","ultra-black"],W={tokenType:"fontWeight",schema:{type:"union",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),oneOf:[{type:"number",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),validate:o((e,t,n)=>e<1||e>1e3?[{path:t,message:l.VALIDATE.INVALID_FONT_WEIGHT(e,t),source:n}]:[],"validate")},{type:"string",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FONT_WEIGHT(e,t),"errorMessage"),validate:o((e,t,n)=>Ne.includes(e.toLowerCase())?[]:[{path:t,message:l.VALIDATE.INVALID_FONT_WEIGHT(e,t),source:n}],"validate")}]}};function De(e,t,n){return $(W.schema,e,t,n)}o(De,"validateFontWeight");const be=["ms","s"],V={tokenType:"duration",schema:{type:"object",errorMessage:o((e,t)=>l.VALIDATE.INVALID_DURATION(e,t),"errorMessage"),properties:{value:T.schema,unit:{type:"string",validate:o((e,t,n)=>be.includes(e)?[]:[{path:t,message:l.VALIDATE.INVALID_DURATION_UNIT(e,t),source:n}],"validate")}},required:["value","unit"]}};function Se(e,t,n){return $(V.schema,e,t,n)}o(Se,"validateDuration");const B={tokenType:"cubicBezier",schema:{type:"array",errorMessage:o((e,t)=>l.VALIDATE.INVALID_CUBIC_BEZIER(e,t),"errorMessage"),validate:o((e,t,n)=>{const r=e;if(r.length!==4||!r.every(a=>typeof a=="number"))return[{path:t,message:l.VALIDATE.INVALID_CUBIC_BEZIER(e,t),source:n}];const[i,,s]=r;return i<0||i>1||s<0||s>1?[{path:t,message:l.VALIDATE.INVALID_CUBIC_BEZIER_RANGE(e,t),source:n}]:[]},"validate")}};function _e(e,t,n){return $(B.schema,e,t,n)}o(_e,"validateCubicBezier");const Le={tokenType:"typography",schema:{type:"object",properties:{fontFamily:z.schema,fontSize:g.schema,letterSpacing:g.schema,lineHeight:T.schema,fontWeight:W.schema},required:["fontFamily","fontSize"],errorMessage:o((e,t)=>l.VALIDATE.INVALID_TYPOGRAPHY(e,t),"errorMessage")}};function Ve(e,t,n){return $(Le.schema,e,t,n)}o(Ve,"validateTypography");const Oe=["solid","dashed","dotted","double","groove","ridge","outset","inset"],ve=["round","butt","square"],Fe={type:"object",errorMessage:o((e,t)=>l.VALIDATE.INVALID_STROKE_STYLE(e,t),"errorMessage"),properties:{dashArray:{type:"array",validate:o((e,t,n)=>{const r=e,i=[];return r.forEach((s,a)=>{typeof s!="string"&&i.push(...$(g.schema,s,`${t}.${a}`,n))}),i},"validate")},lineCap:{type:"string",validate:o((e,t,n)=>ve.includes(e)?[]:[{path:t,message:l.VALIDATE.INVALID_STROKE_LINE_CAP(e,t),source:n}],"validate")}},required:["dashArray","lineCap"]},H={tokenType:"strokeStyle",schema:{type:"union",oneOf:[{type:"string",validate:o((e,t,n)=>!Oe.includes(e)&&typeof e=="string"?[{path:t,message:l.VALIDATE.INVALID_STROKE_STYLE(e,t),source:n}]:[],"validate")},Fe]}};function ke(e,t,n){return $(H.schema,e,t,n)}o(ke,"validateStrokeStyle");const Re={tokenType:"border",schema:{type:"object",properties:{color:E.schema,width:g.schema,style:H.schema},required:["color","width","style"],errorMessage:o((e,t)=>l.VALIDATE.INVALID_BORDER(e,t),"errorMessage")}};function we(e,t,n){return $(Re.schema,e,t,n)}o(we,"validateBorder");const Ce={tokenType:"transition",schema:{type:"object",properties:{duration:V.schema,delay:V.schema,timingFunction:B.schema},required:["duration","delay","timingFunction"],errorMessage:o((e,t)=>l.VALIDATE.INVALID_TRANSITION(e,t),"errorMessage")}};function xe(e,t,n){return $(Ce.schema,e,t,n)}o(xe,"validateTransition");const q={tokenType:"shadow",schema:{type:"object",properties:{color:E.schema,offsetX:g.schema,offsetY:g.schema,blur:g.schema,spread:g.schema,inset:{type:"boolean",errorMessage:o((e,t)=>l.VALIDATE.INVALID_SHADOW_INSET(e,t),"errorMessage")}},required:["color","offsetX","offsetY","blur","spread"],errorMessage:o((e,t)=>l.VALIDATE.INVALID_SHADOW(e,t),"errorMessage")}};function Me(e,t,n){const r=[];return Array.isArray(e)?(e.forEach((i,s)=>{r.push(...$(q.schema,i,`${t}[${s}]`,n))}),r):$(q.schema,e,t,n)}o(Me,"validateShadow");const je={type:"object",errorMessage:o((e,t)=>l.VALIDATE.INVALID_GRADIENT(e,t),"errorMessage"),properties:{color:{type:"string",validate:E.schema.validate},position:{type:"number",validate:o((e,t,n)=>e<0||e>1?[{path:t,message:l.VALIDATE.INVALID_GRADIENT_STOP_POSITION(e,t),source:n}]:[],"validate")}},required:["color","position"]},Pe={tokenType:"gradient",schema:{type:"array",errorMessage:o((e,t)=>l.VALIDATE.INVALID_ARRAY(e,t),"errorMessage"),validate:o((e,t,n)=>{const r=e,i=[];return r.forEach((s,a)=>{i.push(...$(je,s,`${t}[${a}]`,n))}),i},"validate")}};function Ue(e,t,n){return $(Pe.schema,e,t,n)}o(Ue,"validateGradient");const Ge={tokenType:"fluidDimension",schema:{type:"object",errorMessage:o((e,t)=>l.VALIDATE.INVALID_FLUID_DIMENSION(e,t),"errorMessage"),properties:{min:g.schema,max:g.schema},required:["min","max"]}};function Ye(e,t,n){return $(Ge.schema,e,t,n)}o(Ye,"validateFluidDimension");const ze={color:ge,dimension:Ee,fluidDimension:Ye,duration:Se,cubicBezier:_e,fontFamily:Te,fontWeight:De,number:Ae,strokeStyle:ke,typography:Ve,border:we,shadow:Me,gradient:Ue,transition:xe};function O(e){const t=[];for(const[n,r]of Object.entries(e)){if(typeof r!="object"||r===null||!("$type"in r)||!("$path"in r)||r.$path.startsWith("$"))continue;const i=ze[r.$type];if(!i){t.push({path:r.$path,message:l.VALIDATE.UNKNOWN_TOKEN_TYPE(r.$type,r.$path),source:r.$source});continue}t.push(...i(r.$value,r.$path,r.$source))}return t}o(O,"validate");function N(e,t,n,r){return typeof t=="string"&&p(t)?We(e,t,n,r):Array.isArray(t)?t.map(i=>N(e,i,n,r)):typeof t=="object"&&t!==null?Object.entries(t).reduce((s,[a,c])=>({...s,[a]:N(`${e}.${a}`,c,n,r)}),{}):t}o(N,"resolveValue");function v(e){const t={},n=new Set,r=[];for(const[i,s]of Object.entries(e))try{if(!("$value"in s)){t[i]=s;continue}const a=s;t[i]={...a,$resolvedValue:N(a.$path,a.$value,e,n)}}catch(a){const c=a instanceof Error?a.message:String(a),u=s,f=u.$path,h=u.$source;let d,m;c.includes("Circular reference detected")?(d="circular",m=c):c.includes("Reference not found")?(d="missing",m=c):(d="type-mismatch",m=l.RESOLVE.TYPE_MISMATCH(f)),r.push({type:d,path:f,source:h,message:m})}return{resolved:t,errors:r}}o(v,"resolve");function We(e,t,n,r){const i=t.slice(1,-1),s=Object.keys(n).find(u=>{const f=n[u];return f?"$originalPath"in f&&f.$originalPath===i:!1});if(!s)throw new Error(`Reference not found: ${i} in ${e}`);if(r.has(s))throw new Error(`Circular reference detected: ${e} -> ${s}`);const a=n[s];if(!a||!("$value"in a))throw new Error(`Reference not found: ${i} in ${e}`);r.add(s);const c=N(s,a.$value,n,r);return r.delete(s),c}o(We,"resolveReferenceChain");function F(e,t){return e.map(n=>({collection:n.collection,theme:n.theme,tokens:Object.entries(t).reduce((r,[i,s])=>("$source"in s&&(s.$source.collection!==n.collection||n.theme&&s.$source.theme!==n.theme||s.$source.theme&&s.$source.theme!==n.theme)||(!("$type"in s)||s.$source.collection===n.collection&&(!n.theme||s.$source.theme===n.theme))&&(r[i]=s),r),{})}))}o(F,"processTrees");function D(e){return["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","emoji","math","fangsong"].includes(e.toLowerCase())?e:/[\s'"!@#$%^&*()=+[\]{};:|\\/,.<>?~]/.test(e)?`"${e}"`:e}o(D,"quoteFont");const Be={thin:100,hairline:100,"extra-light":200,"ultra-light":200,light:300,normal:400,regular:400,book:400,medium:500,"semi-bold":600,"demi-bold":600,bold:700,"extra-bold":800,"ultra-bold":800,black:900,heavy:900,"extra-black":950,"ultra-black":950};function K(e){return p(e)?{value:e}:typeof e=="number"?{value:e}:{value:Be[e.toLowerCase()]??e}}o(K,"convertFontWeightToken");function He(e){if(p(e))return{"font-family":e,"font-size":e};const t={"font-family":p(e.fontFamily)?e.fontFamily:Array.isArray(e.fontFamily)?e.fontFamily.map(n=>D(n)).join(", "):D(e.fontFamily),"font-size":p(e.fontSize)?e.fontSize:`${e.fontSize.value}${e.fontSize.unit}`};return e.fontWeight&&(t["font-weight"]=p(e.fontWeight)?e.fontWeight:K(e.fontWeight).value),e.letterSpacing&&(t["letter-spacing"]=p(e.letterSpacing)?e.letterSpacing:`${e.letterSpacing.value}${e.letterSpacing.unit}`),e.lineHeight&&(t["line-height"]=(p(e.lineHeight),e.lineHeight)),t}o(He,"convertTypographyToken");function X(e){return e?`${e.value}${e.unit}`:"0ms"}o(X,"formatDuration");function qe(e){if(p(e))return{value:e};const t=p(e.duration)?e.duration:X(e.duration),n=p(e.timingFunction)?e.timingFunction:`cubic-bezier(${e.timingFunction.join(", ")})`,r=e.delay&&(p(e.delay)?e.delay:X(e.delay));return{value:[t,n,r].filter(Boolean).join(" ")}}o(qe,"convertTransitionToken");function Ke(e){return p(e)?{value:e}:{value:`cubic-bezier(${e.join(", ")})`}}o(Ke,"convertCubicBezierToken");function Xe(e){return p(e)?{value:e}:{value:e}}o(Xe,"convertNumberToken");function Ze(e){return p(e)?{value:e}:{value:`${e.value}${e.unit}`}}o(Ze,"convertDurationToken");function Z(e){return p(e)?{value:e}:typeof e=="string"?{value:e}:{value:`${e.dashArray.map(n=>p(n)?n:`${n.value}${n.unit}`).join(" ")} ${e.lineCap}`}}o(Z,"convertStrokeStyleToken");function Je(e){if(p(e))return{value:e};const t=p(e.width)?e.width:`${e.width.value}${e.width.unit}`,n=(p(e.color),e.color),r=typeof e.style=="string"?e.style:Z(e.style).value;return{value:`${t} ${r} ${n}`}}o(Je,"convertBorderToken");function J(e){const t=p(e.offsetX)?e.offsetX:`${e.offsetX.value}${e.offsetX.unit}`,n=p(e.offsetY)?e.offsetY:`${e.offsetY.value}${e.offsetY.unit}`,r=p(e.blur)?e.blur:`${e.blur.value}${e.blur.unit}`,i=p(e.spread)?e.spread:`${e.spread.value}${e.spread.unit}`,s=(p(e.color),e.color);return`${e.inset?"inset ":""}${t} ${n} ${r} ${i} ${s}`}o(J,"convertSingleShadow");function Qe(e){return p(e)?{value:e}:Array.isArray(e)?{value:e.map(J).join(", ")}:{value:J(e)}}o(Qe,"convertShadowToken");function et(e){return p(e)?{value:e}:{value:`linear-gradient(${e.map(n=>{const r=(p(n.color),n.color),i=p(n.position)?n.position:`${n.position*100}`;return`${r} ${i}%`}).join(", ")})`}}o(et,"convertGradientToken");function tt(e){return p(e)?{value:e}:{value:Array.isArray(e)?e.map(n=>D(n)).join(", "):D(e)}}o(tt,"convertFontFamilyToken");function nt(e){return p(e)?{value:e}:{value:`${e.value}${e.unit}`}}o(nt,"convertDimensionToken");function Q(e,t=16){return e.unit==="px"?e.value:e.value*t}o(Q,"normalizeToPixels");function rt(e,t){const{min:n,max:r}=e,i=t.fluidConfig;if(!i)throw new Error(l.VALIDATE.MISSING_FLUID_CONFIG(t.path??""));const s=16,a=Q(n,s),c=Q(r,s),u=i.min,f=i.max;if(a===c)return{value:`${a/s}rem`};const h=a/s,d=c/s,m=u/s,I=f/s,y=(d-h)/(I-m),A=-1*m*y+h;return{value:`clamp(${h}rem, ${A.toFixed(2)}rem + ${(y*100).toFixed(2)}vw, ${d}rem)`}}o(rt,"convertFluidDimension");function ot(e,t){if(p(e))return{value:e};if(!t.fluidConfig)throw new Error(l.VALIDATE.MISSING_FLUID_CONFIG(t.path??""));return rt(e,t)}o(ot,"convertFluidDimensionToken");function k(e,t){try{const n=t==="rgba"?"rgb":t==="hsla"?"hsl":t,r=S(n==="hex"?"rgb":n)(e);if(!r)throw new Error(`Failed to convert color ${e} to ${t}`);switch(n){case"hsl":{if(r.mode!=="hsl")throw new Error("Unexpected color mode");const i=r.h??0,s=r.s??0,a=r.l??0,c=r.alpha;return c!==void 0&&c<1?`hsl(${Math.round(i)} ${Math.round(s*100)}% ${Math.round(a*100)}% / ${c.toFixed(2)})`:`hsl(${Math.round(i)} ${Math.round(s*100)}% ${Math.round(a*100)}%)`}case"oklch":{if(r.mode!=="oklch")throw new Error("Unexpected color mode");const i=r.l??0,s=r.c??0,a=r.h??0,c=r.alpha;return c!==void 0&&c<1?`oklch(${i.toFixed(3)} ${s.toFixed(3)} ${a.toFixed(1)} / ${c.toFixed(2)})`:`oklch(${i.toFixed(3)} ${s.toFixed(3)} ${a.toFixed(1)})`}case"rgb":{if(r.mode!=="rgb")throw new Error("Unexpected color mode");const i=Math.round((r.r??0)*255),s=Math.round((r.g??0)*255),a=Math.round((r.b??0)*255),c=r.alpha;return c!==void 0&&c<1?`rgb(${i} ${s} ${a} / ${c.toFixed(2)})`:`rgb(${i} ${s} ${a})`}case"p3":{if(r.mode!=="p3")throw new Error("Unexpected color mode");const i=r.r??0,s=r.g??0,a=r.b??0,c=r.alpha;return c!==void 0&&c<1?`color(display-p3 ${i.toFixed(6)} ${s.toFixed(6)} ${a.toFixed(6)} / ${c.toFixed(2)})`:`color(display-p3 ${i.toFixed(6)} ${s.toFixed(6)} ${a.toFixed(6)})`}default:{const i=S("rgb")(r);return i?P(i):e}}}catch{const r=S("rgb")(e);return console.warn(`Failed to convert color ${e} to ${t}, falling back to hex`),r?P(r):e}}o(k,"convertHexToColorString");function it(e,t){if(p(e))return{value:e};const n=t.colorFormat||"hex";try{const r=k(e,n);return n==="p3"?{value:k(e,"hex")||e,featureValues:[{query:"@supports (color: color(display-p3 1 1 1))",value:r||e}]}:{value:r||e}}catch{return console.warn(`Failed to convert color ${e} to ${n}, falling back to hex`),{value:k(e,"hex")}}}o(it,"convertColorToken");const ee={duration:Ze,number:Xe,cubicBezier:Ke,color:it,dimension:nt,fluidDimension:ot,typography:He,border:Je,shadow:Qe,gradient:et,transition:qe,strokeStyle:Z,fontFamily:tt,fontWeight:K};function st(e,t){const n=ee[e.$type];return{...e.$description?{$description:e.$description}:{},...e.$extensions?{$extensions:e.$extensions}:{},$type:e.$type,$value:e.$value,$path:e.$path,$source:e.$source,$originalPath:e.$originalPath,$resolvedValue:e.$resolvedValue,$cssProperties:n(e.$value,t)}}o(st,"convertSingleToken");function te(e,t){const n={};for(const[r,i]of Object.entries(e)){if(!i||typeof i!="object")continue;if(!("$type"in i)){n[r]={...i.$description?{$description:i.$description}:{},...i.$extensions?{$extensions:i.$extensions}:{}};continue}if(!ee[i.$type])continue;const s={fluidConfig:t.options?.fluid,colorFormat:t.options?.color,path:i.$path};n[r]=st(i,s)}return n}o(te,"convertTokens");function R(e,t){const n={};for(const[r,i]of Object.entries(e)){const s={default:te(i.default,t)};for(const[a,c]of Object.entries(i))a!=="default"&&(s[a]=te(c,t));n[r]=s}return n}o(R,"convert");const ne=new Map;function at(e){const t=ne.get(e);if(t)return t;const n=e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z])([A-Z])(?=[a-z])/g,"$1-$2").toLowerCase();return ne.set(e,n),n}o(at,"toKebabCase");function w({collection:e,filename:t,separate:n,baseDir:r}){const i=`${t}.variables.css`;return e==="default"?`${r}/${i}`:`${r}/${e}/${i}`}o(w,"getOutputPath");const re="@supports (color: color(display-p3 1 1 1))";function ct(e){return e.$type==="typography"}o(ct,"isTypographyToken");function C(e){return e.split(".").join("-")}o(C,"formatCSSVarPath");function oe(e){return typeof e=="number"?e:typeof e!="string"?(console.warn("Unexpected value type in convertReferenceToCSSVar, got:",e),String(e)):e.replace(/\{([^}]+)\}/g,(t,n)=>`var(--${n.split(".").map(at).join("-")})`)}o(oe,"convertReferenceToCSSVar");function lt(e){const t=e.$cssProperties;if("value"in t)return{name:`--${C(e.$path)}`,value:oe(t.value)}}o(lt,"generateSingleVariable");function ut(e){return Object.entries(e.$cssProperties).filter(([t,n])=>n!==void 0).map(([t,n])=>({name:`--${C(e.$path)}-${t}`,value:oe(n)}))}o(ut,"generateTypographyVariables");function ie(e){if(e.$type!=="color")return[];const t=e.$cssProperties;return"featureValues"in t?t.featureValues?.filter(n=>n.query===re).map(n=>({name:`--${C(e.$path)}`,value:n.value}))??[]:[]}o(ie,"generateFeatureVariables");function se(e){const t=[`${e.selector} {`];if(e.comment&&t.push(` /* ${e.comment} */`),e.vars.length>0){const n=e.vars.map(r=>` ${r.name}: ${r.value};`).join(`
2
+ `);t.push(n)}return t.push("}"),t.join(`
3
+ `)}o(se,"generateCSSBlock");function ft(e){const t=[];return e.root.vars.length>0&&t.push(se({selector:e.root.selector,vars:e.root.vars})),e.features.forEach(n=>{const i=se({selector:e.root.selector,vars:n.vars}).split(`
4
4
  `).map(s=>` ${s}`).join(`
5
- `);t.push(`${r.query} {
6
- ${o}
5
+ `);t.push(`${n.query} {
6
+ ${i}
7
7
  }`)}),t.filter(Boolean).join(`
8
8
 
9
- `)}n(ft,"convertCSSVarsToString");function lt(e,t){if(at(e))return{vars:ut(e,t),features:X(e,t)};const r=ct(e,t);return{vars:r?[r]:[],features:X(e,t)}}n(lt,"generateVariablesForToken");async function j(e,t={}){const r=[],i=Object.entries(e).filter(([f,d])=>f!=="$extensions"&&"$type"in d).map(([f,d])=>lt(d,r));let o=":root";t.collection&&t.mode&&t.mode!=="default"&&(o+=`[data-theme="${t.mode}"]`);const s=i.flatMap(f=>f.vars),a=i.flatMap(f=>f.features||[]),c=ft({root:{selector:o,vars:s},features:a.length?[{query:K,vars:a}]:[]});return{output:[{name:"variables.css",content:dt(c)}],errors:r}}n(j,"generateCSS");function dt(e){return e.endsWith(`
9
+ `)}o(ft,"convertCSSVarsToString");function dt(e){if(ct(e))return{vars:ut(e),features:ie(e)};const t=lt(e);return{vars:t?[t]:[],features:ie(e)}}o(dt,"generateVariablesForToken");async function x(e,t={}){const n=Object.entries(e).filter(([c,u])=>c!=="$extensions"&&"$type"in u).map(([c,u])=>dt(u));let r=":root";t.theme&&t.theme!=="default"&&(r=`[data-theme="${t.theme}"]`);const i=n.flatMap(c=>c.vars),s=n.flatMap(c=>c.features||[]),a=ft({root:{selector:r,vars:i},features:s.length?[{query:re,vars:s}]:[]});return{output:[{name:"tokens.variables.css",content:pt(a)}]}}o(x,"generateCSS");function pt(e){return e.endsWith(`
10
10
  `)?e:e+`
11
- `}n(dt,"formatCSSVars");async function w(e,t){const r=[];return{output:t?.separate?await It(e,r,t):await pt(e,r,t),errors:r}}n(w,"generate");async function pt(e,t,r){const i=[];for(const[o,s]of Object.entries(e))for(const[a,c]of Object.entries(s)){const f=await j(c,{mode:a!=="default"?a:void 0,collection:o!=="default"?o:void 0});t.push(...f.errors.map(d=>({...d,path:`${o}.${a}.${d.path}`}))),f.output[0]?.content&&i.push(f.output[0].content)}return[{name:r?.directory?`${r.directory}/variables.css`:"variables.css",content:i.filter(Boolean).join(`
11
+ `}o(pt,"formatCSSVars");async function M(e,t){const n={};for(const[r,i]of Object.entries(e)){n[r]={default:{}},i.default&&(n[r].default=i.default);for(const[s,a]of Object.entries(i))s!=="default"&&a&&(n[r][s]=a);Object.keys(n[r].default).length===0&&Object.keys(n[r]).length===1&&delete n[r]}return t.output.css.separate?{output:await mt(n,t)}:{output:await ht(n,t)}}o(M,"generate");async function ht(e,t){const n=`${t.output.directories.css}/global/variables`,r=[];for(const[i,s]of Object.entries(e)){const a=[];for(const[c,u]of Object.entries(s)){const f=await x(u,{theme:c!=="default"?c:void 0,collection:i!=="default"?i:void 0});a.push(f.output[0].content)}a.length>0&&r.push({name:w({collection:i,filename:"tokens",separate:!1,baseDir:n}),content:a.filter(Boolean).join(`
12
12
  `).trim()+`
13
- `}]}n(pt,"generateSingleFile");async function It(e,t,r){const i=r?.directory||"",o=[],s=e.default?.default;if(s&&Object.keys(e).length===1){const a=new Map;for(const[c,f]of Object.entries(s)){const d=c.split(".")[0]||"default";a.has(d)||a.set(d,{});const l=a.get(d);l[c]=f}for(const[c,f]of a){const d=await j(f,{});d.output[0]?.content&&o.push({name:`${i}/${c}.css`,content:d.output[0].content}),t.push(...d.errors.map(l=>({...l,path:`${c}.${l.path}`})))}return o}for(const[a,c]of Object.entries(e))if(Object.keys(c).length!==0)for(const[f,d]of Object.entries(c)){if(Object.keys(d).length===0)continue;const l=await j(d,{mode:f!=="default"?f:void 0,collection:a!=="default"?a:void 0});if(t.push(...l.errors.map(I=>({...I,path:`${a}.${f}.${I.path}`}))),l.output[0]?.content){const I=a==="default"?Object.keys(d)[0].split(".")[0]:a;o.push({name:`${i}/${I}.css`,content:l.output[0].content})}}return o}n(It,"generateSeparateFiles");async function mt(e){const t={load:[],flatten:[],validation:[],resolution:[],generation:[]},r={normalization:[]},{trees:i,errors:o}=await L(e.files);t.load.push(...o);const{tokens:s,errors:a}=b(i);t.flatten.push(...a);const c=v(s,e);if(t.validation.push(...c),c.length>0)return{output:[],trees:i,errors:t,warnings:r};const{resolved:f,errors:d}=V(s);t.resolution.push(...d);const l=F(i,f),{tokens:I,warnings:m}=k(l,e.collections);r.normalization.push(...m);const A=O(I,e),{output:y,errors:_}=await w(A,e.output);return t.generation.push(..._),{output:y,trees:i,errors:t,warnings:r}}n(mt,"tokensToCSSPipeline");async function $t(e){const{trees:t,errors:r}=await L(e.files),{tokens:i,errors:o}=b(t),s=v(i,e),{resolved:a,errors:c}=V(i);return{trees:t,flattenedTokens:i,resolved:a,errors:{load:r,flatten:o,validation:s,resolution:c}}}n($t,"validationPipeline");async function ht(e,t,r){const i={generation:[]},o={normalization:[]},s=F(e,t),{tokens:a,warnings:c}=k(s,r.collections);o.normalization.push(...c);const f=O(a,r),{output:d,errors:l}=await w(f,r.output);return i.generation.push(...l),{output:d,errors:i,warnings:o}}n(ht,"generationPipeline");export{O as convert,b as flatten,w as generate,ht as generationPipeline,L as loadTreesFromConfig,k as normalizeTokens,De as parseJson,F as processTrees,V as resolve,mt as tokensToCSSPipeline,v as validate,$t as validationPipeline};
13
+ `})}return r}o(ht,"generateSingleFile");async function mt(e,t){const n=`${t.output.directories.css}/global/variables`,r=[];for(const[i,s]of Object.entries(e))if(Object.keys(s).length!==0){for(const[a,c]of Object.entries(s))if(Object.keys(c).length!==0)if(a==="default"){const u=new Map;for(const[f,h]of Object.entries(c)){if(!("$type"in h))continue;const m=h.$source.sourcePath;u.has(m)||u.set(m,{}),u.get(m)[f]=h}for(const[f,h]of u){if(Object.keys(h).length===0)continue;const d=f.split("/").pop()?.replace(/\.json$/,"")??"tokens",I=(await x(h,{collection:i==="default"?void 0:i})).output[0].content;I&&r.push({name:w({collection:i,filename:d,separate:!0,baseDir:n}),content:I})}}else{const f=(await x(c,{theme:a,collection:i==="default"?void 0:i})).output[0].content;f&&r.push({name:w({collection:i,filename:a,separate:!0,baseDir:n}),content:f})}}return r}o(mt,"generateSeparateFiles");function j(e){const t=[],n=[],r=new Set,i=new Map;e.forEach(c=>{const{collection:u,theme:f="default"}=c;r.add(u),i.has(u)||i.set(u,new Set),i.get(u).add(f)});const s={};function a(c){const u={default:{}};s[c]=u;const f=i.get(c);return f&&f.forEach(h=>{u[h]={}}),u}return o(a,"addCollection"),r.forEach(c=>{a(c)}),e.forEach(c=>{const{collection:u,theme:f="default",tokens:h}=c,d=s[u]||a(u),m=d[f]||(d[f]={});Object.entries(h).forEach(([I,y])=>{const A=I.replace(`${u}.`,"");m[A]=y})}),{tokens:s,errors:n,warnings:t}}o(j,"normalizeTokens");async function It(e){const t={load:[],flatten:[],validation:[],resolution:[]},n={normalization:[]},{trees:r,errors:i}=await _(e);t.load.push(...i);const{tokens:s,errors:a}=L(r);t.flatten.push(...a);const c=O(s);if(t.validation.push(...c),c.length>0)return{output:[],trees:r,errors:t,warnings:n};const{resolved:u,errors:f}=v(s);t.resolution.push(...f);const h=F(r,u),{tokens:d,warnings:m}=j(h);n.normalization.push(...m);const I=R(d,e),{output:y}=await M(I,e);return{output:y,trees:r,errors:t,warnings:n}}o(It,"tokensToCSSPipeline");async function $t(e,t){const{trees:n,errors:r}=await(t.loader.type==="memory"?Y(t.loader.data):_(t.loader.paths)),{tokens:i,errors:s}=L(n),a=O(i),{resolved:c,errors:u}=v(i);return{trees:n,flattenedTokens:i,resolved:c,errors:{load:r,flatten:s,validation:a,resolution:u}}}o($t,"validationPipeline");async function yt(e,t,n){const r={normalization:[]},i=F(e,t),{tokens:s,warnings:a}=j(i);r.normalization.push(...a);const c=R(s,n),{output:u}=await M(c,n);return{output:u,warnings:r}}o(yt,"generationPipeline");export{R as convert,L as flatten,M as generate,yt as generationPipeline,_ as loadTreesFromConfig,Y as loadTreesFromMemory,j as normalizeTokens,F as processTrees,v as resolve,It as tokensToCSSPipeline,O as validate,$t as validationPipeline};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarcube-org/core",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "publishConfig": {
5
5
  "access": "restricted"
6
6
  },
@@ -12,11 +12,13 @@
12
12
  "README.md"
13
13
  ],
14
14
  "devDependencies": {
15
- "@types/picomatch": "^3.0.1",
16
15
  "pkgroll": "^2.5.1",
17
16
  "tsx": "^4.19.2"
18
17
  },
19
18
  "dependencies": {
19
+ "@types/culori": "^2.1.1",
20
+ "@types/picomatch": "^3.0.1",
21
+ "culori": "^4.0.1",
20
22
  "fast-glob": "^3.3.2",
21
23
  "globby": "^14.0.2",
22
24
  "picomatch": "^4.0.2",
@@ -25,7 +27,9 @@
25
27
  "scripts": {
26
28
  "build": "pkgroll --minify",
27
29
  "dev": "pkgroll --watch",
28
- "test": "vitest",
29
- "type-check": "tsc --noEmit"
30
+ "test": "vitest run",
31
+ "test:watch": "vitest",
32
+ "type-check": "tsc --noEmit",
33
+ "ci": "pnpm type-check && pnpm test"
30
34
  }
31
35
  }