@khaledeltohamy14/token-pipeline-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/generators/alias-generator.js +257 -0
- package/generators/brand-generator.js +68 -0
- package/generators/category-generator.js +44 -0
- package/generators/component-generator.js +468 -0
- package/generators/global-generator.js +116 -0
- package/generators/theme-generator.js +1168 -0
- package/generators/token-utils.js +355 -0
- package/index.d.ts +34 -0
- package/index.js +148 -0
- package/package.json +35 -0
- package/split/split-token-document.js +58 -0
|
@@ -0,0 +1,1168 @@
|
|
|
1
|
+
const {
|
|
2
|
+
flattenTokens,
|
|
3
|
+
getTokenValue,
|
|
4
|
+
getTokenType,
|
|
5
|
+
isReference,
|
|
6
|
+
cleanReference,
|
|
7
|
+
toDartIdentifier,
|
|
8
|
+
canonicalTokenKey,
|
|
9
|
+
dartLiteral,
|
|
10
|
+
dartType,
|
|
11
|
+
} = require('./token-utils');
|
|
12
|
+
|
|
13
|
+
const PRIMITIVE_CONFIG = {
|
|
14
|
+
spacing: {
|
|
15
|
+
className: 'SpacingTokens',
|
|
16
|
+
importPath:
|
|
17
|
+
'../spacing/spacing_tokens.dart',
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
radius: {
|
|
21
|
+
className: 'RadiusTokens',
|
|
22
|
+
importPath:
|
|
23
|
+
'../radius/radius_tokens.dart',
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
dimensions: {
|
|
27
|
+
className: 'DimensionTokens',
|
|
28
|
+
importPath:
|
|
29
|
+
'../dimensions/dimensions_tokens.dart',
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
typography: {
|
|
33
|
+
className: 'TypographyTokens',
|
|
34
|
+
importPath:
|
|
35
|
+
'../typography/typography_tokens.dart',
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
shadow: {
|
|
39
|
+
className: 'ShadowTokens',
|
|
40
|
+
importPath:
|
|
41
|
+
'../shadow/shadow_tokens.dart',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function createResolver({
|
|
46
|
+
componentTokens = {},
|
|
47
|
+
aliasTokens = {},
|
|
48
|
+
globalTokens = {},
|
|
49
|
+
|
|
50
|
+
spacingTokens = {},
|
|
51
|
+
radiusTokens = {},
|
|
52
|
+
dimensionTokens = {},
|
|
53
|
+
typographyTokens = {},
|
|
54
|
+
shadowTokens = {},
|
|
55
|
+
|
|
56
|
+
brandTokens = {},
|
|
57
|
+
}) {
|
|
58
|
+
const base = {
|
|
59
|
+
component:
|
|
60
|
+
flattenTokens(
|
|
61
|
+
componentTokens
|
|
62
|
+
),
|
|
63
|
+
|
|
64
|
+
alias:
|
|
65
|
+
flattenTokens(
|
|
66
|
+
aliasTokens
|
|
67
|
+
),
|
|
68
|
+
|
|
69
|
+
global:
|
|
70
|
+
flattenTokens(
|
|
71
|
+
globalTokens
|
|
72
|
+
),
|
|
73
|
+
|
|
74
|
+
spacing:
|
|
75
|
+
flattenTokens(
|
|
76
|
+
spacingTokens
|
|
77
|
+
),
|
|
78
|
+
|
|
79
|
+
radius:
|
|
80
|
+
flattenTokens(
|
|
81
|
+
radiusTokens
|
|
82
|
+
),
|
|
83
|
+
|
|
84
|
+
dimensions:
|
|
85
|
+
flattenTokens(
|
|
86
|
+
dimensionTokens
|
|
87
|
+
),
|
|
88
|
+
|
|
89
|
+
typography:
|
|
90
|
+
flattenTokens(
|
|
91
|
+
typographyTokens
|
|
92
|
+
),
|
|
93
|
+
|
|
94
|
+
shadow:
|
|
95
|
+
flattenTokens(
|
|
96
|
+
shadowTokens
|
|
97
|
+
),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const brand = {
|
|
101
|
+
component:
|
|
102
|
+
flattenTokens(
|
|
103
|
+
brandTokens.component ||
|
|
104
|
+
{}
|
|
105
|
+
),
|
|
106
|
+
|
|
107
|
+
alias:
|
|
108
|
+
flattenTokens(
|
|
109
|
+
brandTokens.alias ||
|
|
110
|
+
{}
|
|
111
|
+
),
|
|
112
|
+
|
|
113
|
+
global:
|
|
114
|
+
flattenTokens(
|
|
115
|
+
brandTokens.global ||
|
|
116
|
+
{}
|
|
117
|
+
),
|
|
118
|
+
|
|
119
|
+
spacing:
|
|
120
|
+
flattenTokens(
|
|
121
|
+
brandTokens.spacing ||
|
|
122
|
+
{}
|
|
123
|
+
),
|
|
124
|
+
|
|
125
|
+
radius:
|
|
126
|
+
flattenTokens(
|
|
127
|
+
brandTokens.radius ||
|
|
128
|
+
{}
|
|
129
|
+
),
|
|
130
|
+
|
|
131
|
+
dimensions:
|
|
132
|
+
flattenTokens(
|
|
133
|
+
brandTokens.dimensions ||
|
|
134
|
+
{}
|
|
135
|
+
),
|
|
136
|
+
|
|
137
|
+
typography:
|
|
138
|
+
flattenTokens(
|
|
139
|
+
brandTokens.typography ||
|
|
140
|
+
{}
|
|
141
|
+
),
|
|
142
|
+
|
|
143
|
+
shadow:
|
|
144
|
+
flattenTokens(
|
|
145
|
+
brandTokens.shadow ||
|
|
146
|
+
{}
|
|
147
|
+
),
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/*
|
|
151
|
+
|--------------------------------------------------------------------------
|
|
152
|
+
| Main semantic hierarchy
|
|
153
|
+
|--------------------------------------------------------------------------
|
|
154
|
+
|
|
|
155
|
+
| Brand Component
|
|
156
|
+
| ↓
|
|
157
|
+
| Base Component
|
|
158
|
+
| ↓
|
|
159
|
+
| Brand Alias
|
|
160
|
+
| ↓
|
|
161
|
+
| Base Alias
|
|
162
|
+
| ↓
|
|
163
|
+
| Brand Global
|
|
164
|
+
| ↓
|
|
165
|
+
| Base Global
|
|
166
|
+
|
|
|
167
|
+
|--------------------------------------------------------------------------
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
function findSemantic(
|
|
171
|
+
tokenPath
|
|
172
|
+
) {
|
|
173
|
+
return (
|
|
174
|
+
brand.component[tokenPath] ||
|
|
175
|
+
base.component[tokenPath] ||
|
|
176
|
+
|
|
177
|
+
brand.alias[tokenPath] ||
|
|
178
|
+
base.alias[tokenPath] ||
|
|
179
|
+
|
|
180
|
+
brand.global[tokenPath] ||
|
|
181
|
+
base.global[tokenPath] ||
|
|
182
|
+
|
|
183
|
+
null
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function primitiveInfo(
|
|
188
|
+
referencePath
|
|
189
|
+
) {
|
|
190
|
+
const parts =
|
|
191
|
+
referencePath.split('.');
|
|
192
|
+
|
|
193
|
+
if (parts.length < 2) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const first =
|
|
198
|
+
parts[0];
|
|
199
|
+
|
|
200
|
+
const categoryMap = {
|
|
201
|
+
spacing: 'spacing',
|
|
202
|
+
space: 'spacing',
|
|
203
|
+
|
|
204
|
+
radius: 'radius',
|
|
205
|
+
radii: 'radius',
|
|
206
|
+
|
|
207
|
+
dimension: 'dimensions',
|
|
208
|
+
dimensions: 'dimensions',
|
|
209
|
+
size: 'dimensions',
|
|
210
|
+
sizes: 'dimensions',
|
|
211
|
+
|
|
212
|
+
typography: 'typography',
|
|
213
|
+
type: 'typography',
|
|
214
|
+
|
|
215
|
+
shadow: 'shadow',
|
|
216
|
+
shadows: 'shadow',
|
|
217
|
+
elevation: 'shadow',
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const category =
|
|
221
|
+
categoryMap[first];
|
|
222
|
+
|
|
223
|
+
if (!category) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const pathName =
|
|
228
|
+
parts
|
|
229
|
+
.slice(1)
|
|
230
|
+
.join('.');
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
category,
|
|
234
|
+
pathName,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function findPrimitive(
|
|
239
|
+
category,
|
|
240
|
+
tokenPath
|
|
241
|
+
) {
|
|
242
|
+
return (
|
|
243
|
+
brand[category]?.[tokenPath] ||
|
|
244
|
+
base[category]?.[tokenPath] ||
|
|
245
|
+
null
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function resolvePath(
|
|
250
|
+
tokenPath,
|
|
251
|
+
fallbackType,
|
|
252
|
+
stack = []
|
|
253
|
+
) {
|
|
254
|
+
/*
|
|
255
|
+
* First check semantic hierarchy.
|
|
256
|
+
*/
|
|
257
|
+
const semanticToken =
|
|
258
|
+
findSemantic(
|
|
259
|
+
tokenPath
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
if (semanticToken) {
|
|
263
|
+
return resolveToken(
|
|
264
|
+
semanticToken,
|
|
265
|
+
tokenPath,
|
|
266
|
+
fallbackType,
|
|
267
|
+
stack
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/*
|
|
272
|
+
* Then check primitive category.
|
|
273
|
+
*
|
|
274
|
+
* Example:
|
|
275
|
+
*
|
|
276
|
+
* {spacing.md}
|
|
277
|
+
* {radius.sm}
|
|
278
|
+
* {dimensions.icon.md}
|
|
279
|
+
*/
|
|
280
|
+
const primitive =
|
|
281
|
+
primitiveInfo(
|
|
282
|
+
tokenPath
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
if (primitive) {
|
|
286
|
+
const token =
|
|
287
|
+
findPrimitive(
|
|
288
|
+
primitive.category,
|
|
289
|
+
primitive.pathName
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
if (!token) {
|
|
293
|
+
throw new Error(
|
|
294
|
+
`❌ Unresolved primitive token: ` +
|
|
295
|
+
`${tokenPath}`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return resolveToken(
|
|
300
|
+
token,
|
|
301
|
+
tokenPath,
|
|
302
|
+
fallbackType,
|
|
303
|
+
stack
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
throw new Error(
|
|
308
|
+
`❌ Unresolved theme token: ` +
|
|
309
|
+
`${tokenPath}`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function resolveToken(
|
|
314
|
+
token,
|
|
315
|
+
tokenPath,
|
|
316
|
+
fallbackType,
|
|
317
|
+
stack
|
|
318
|
+
) {
|
|
319
|
+
if (
|
|
320
|
+
stack.includes(tokenPath)
|
|
321
|
+
) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`❌ Circular theme reference: ` +
|
|
324
|
+
`${[
|
|
325
|
+
...stack,
|
|
326
|
+
tokenPath,
|
|
327
|
+
].join(' -> ')}`
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const type =
|
|
332
|
+
getTokenType(token) ||
|
|
333
|
+
fallbackType;
|
|
334
|
+
|
|
335
|
+
const value =
|
|
336
|
+
getTokenValue(token);
|
|
337
|
+
|
|
338
|
+
if (!isReference(value)) {
|
|
339
|
+
return dartLiteral(
|
|
340
|
+
value,
|
|
341
|
+
type,
|
|
342
|
+
tokenPath
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const reference =
|
|
347
|
+
cleanReference(value);
|
|
348
|
+
|
|
349
|
+
/*
|
|
350
|
+
* Resolve reference recursively.
|
|
351
|
+
*/
|
|
352
|
+
return resolveReference(
|
|
353
|
+
reference,
|
|
354
|
+
type,
|
|
355
|
+
[
|
|
356
|
+
...stack,
|
|
357
|
+
tokenPath,
|
|
358
|
+
]
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function resolveReference(
|
|
363
|
+
referencePath,
|
|
364
|
+
fallbackType,
|
|
365
|
+
stack
|
|
366
|
+
) {
|
|
367
|
+
/*
|
|
368
|
+
* Primitive references are direct.
|
|
369
|
+
*/
|
|
370
|
+
const primitive =
|
|
371
|
+
primitiveInfo(
|
|
372
|
+
referencePath
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
if (primitive) {
|
|
376
|
+
const token =
|
|
377
|
+
findPrimitive(
|
|
378
|
+
primitive.category,
|
|
379
|
+
primitive.pathName
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
if (!token) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`❌ Broken primitive reference: ` +
|
|
385
|
+
`{${referencePath}}`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/*
|
|
390
|
+
* Return reference to primitive class
|
|
391
|
+
* rather than resolving to literal.
|
|
392
|
+
*/
|
|
393
|
+
const config =
|
|
394
|
+
PRIMITIVE_CONFIG[
|
|
395
|
+
primitive.category
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
const type =
|
|
399
|
+
getTokenType(token) ||
|
|
400
|
+
fallbackType;
|
|
401
|
+
|
|
402
|
+
return {
|
|
403
|
+
type: dartType(type),
|
|
404
|
+
value:
|
|
405
|
+
`${config.className}.` +
|
|
406
|
+
`${toDartIdentifier(
|
|
407
|
+
primitive.pathName
|
|
408
|
+
)}`,
|
|
409
|
+
importPath:
|
|
410
|
+
config.importPath,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/*
|
|
415
|
+
* Semantic hierarchy.
|
|
416
|
+
*/
|
|
417
|
+
const token =
|
|
418
|
+
findSemantic(
|
|
419
|
+
referencePath
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
if (!token) {
|
|
423
|
+
throw new Error(
|
|
424
|
+
`❌ Broken theme reference: ` +
|
|
425
|
+
`{${referencePath}}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const type =
|
|
430
|
+
getTokenType(token) ||
|
|
431
|
+
fallbackType;
|
|
432
|
+
|
|
433
|
+
const value =
|
|
434
|
+
getTokenValue(token);
|
|
435
|
+
|
|
436
|
+
/*
|
|
437
|
+
* Alias / Component / Global references
|
|
438
|
+
* are recursively resolved.
|
|
439
|
+
*
|
|
440
|
+
* This is what allows:
|
|
441
|
+
*
|
|
442
|
+
* Component
|
|
443
|
+
* ↓
|
|
444
|
+
* Brand Alias
|
|
445
|
+
* ↓
|
|
446
|
+
* Global
|
|
447
|
+
*/
|
|
448
|
+
if (isReference(value)) {
|
|
449
|
+
return resolveReference(
|
|
450
|
+
cleanReference(value),
|
|
451
|
+
type,
|
|
452
|
+
stack
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/*
|
|
457
|
+
* Final global/base value.
|
|
458
|
+
*
|
|
459
|
+
* Instead of embedding:
|
|
460
|
+
*
|
|
461
|
+
* Color(0xFF...)
|
|
462
|
+
*
|
|
463
|
+
* keep the generated theme connected
|
|
464
|
+
* to GlobalTokens.
|
|
465
|
+
*/
|
|
466
|
+
const owner =
|
|
467
|
+
findOwner(
|
|
468
|
+
referencePath
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
if (owner) {
|
|
472
|
+
return {
|
|
473
|
+
type: dartType(type),
|
|
474
|
+
value:
|
|
475
|
+
`${owner.className}.` +
|
|
476
|
+
`${toDartIdentifier(
|
|
477
|
+
owner.path
|
|
478
|
+
)}`,
|
|
479
|
+
importPath:
|
|
480
|
+
owner.importPath,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return dartLiteral(
|
|
485
|
+
value,
|
|
486
|
+
type,
|
|
487
|
+
referencePath
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function findOwner(
|
|
492
|
+
tokenPath
|
|
493
|
+
) {
|
|
494
|
+
if (
|
|
495
|
+
brand.component[tokenPath] ||
|
|
496
|
+
base.component[tokenPath]
|
|
497
|
+
) {
|
|
498
|
+
return {
|
|
499
|
+
className: 'ComponentTokens',
|
|
500
|
+
path: tokenPath,
|
|
501
|
+
importPath:
|
|
502
|
+
'../components/component_tokens.dart',
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (
|
|
507
|
+
brand.alias[tokenPath] ||
|
|
508
|
+
base.alias[tokenPath]
|
|
509
|
+
) {
|
|
510
|
+
return {
|
|
511
|
+
className: 'AliasTokens',
|
|
512
|
+
path: tokenPath,
|
|
513
|
+
importPath:
|
|
514
|
+
'../alias/alias_tokens.dart',
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (
|
|
519
|
+
brand.global[tokenPath] ||
|
|
520
|
+
base.global[tokenPath]
|
|
521
|
+
) {
|
|
522
|
+
return {
|
|
523
|
+
className: 'GlobalTokens',
|
|
524
|
+
path: tokenPath,
|
|
525
|
+
importPath:
|
|
526
|
+
'../global/global_tokens.dart',
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return {
|
|
534
|
+
findSemantic,
|
|
535
|
+
resolvePath,
|
|
536
|
+
resolveReference,
|
|
537
|
+
maps: {
|
|
538
|
+
base,
|
|
539
|
+
brand,
|
|
540
|
+
},
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/*
|
|
545
|
+
|--------------------------------------------------------------------------
|
|
546
|
+
| Theme paths
|
|
547
|
+
|--------------------------------------------------------------------------
|
|
548
|
+
*/
|
|
549
|
+
|
|
550
|
+
function allThemePaths(
|
|
551
|
+
resolver
|
|
552
|
+
) {
|
|
553
|
+
const canonical =
|
|
554
|
+
new Map();
|
|
555
|
+
|
|
556
|
+
const paths = [
|
|
557
|
+
...Object.keys(
|
|
558
|
+
resolver.maps.base.alias
|
|
559
|
+
),
|
|
560
|
+
|
|
561
|
+
...Object.keys(
|
|
562
|
+
resolver.maps.base.component
|
|
563
|
+
),
|
|
564
|
+
|
|
565
|
+
...Object.keys(
|
|
566
|
+
resolver.maps.brand.alias
|
|
567
|
+
),
|
|
568
|
+
|
|
569
|
+
...Object.keys(
|
|
570
|
+
resolver.maps.brand.component
|
|
571
|
+
),
|
|
572
|
+
];
|
|
573
|
+
|
|
574
|
+
for (
|
|
575
|
+
const pathName
|
|
576
|
+
of paths
|
|
577
|
+
) {
|
|
578
|
+
const key =
|
|
579
|
+
canonicalTokenKey(
|
|
580
|
+
pathName
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
/*
|
|
584
|
+
* Component tokens have priority over
|
|
585
|
+
* aliases with the same normalized name.
|
|
586
|
+
*/
|
|
587
|
+
if (
|
|
588
|
+
!canonical.has(key) ||
|
|
589
|
+
pathName
|
|
590
|
+
.toLowerCase()
|
|
591
|
+
.includes('component')
|
|
592
|
+
) {
|
|
593
|
+
canonical.set(
|
|
594
|
+
key,
|
|
595
|
+
pathName
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return [
|
|
601
|
+
...canonical.values()
|
|
602
|
+
].sort();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/*
|
|
606
|
+
|--------------------------------------------------------------------------
|
|
607
|
+
| Generate individual brand theme
|
|
608
|
+
|--------------------------------------------------------------------------
|
|
609
|
+
*/
|
|
610
|
+
|
|
611
|
+
function generateTheme({
|
|
612
|
+
aliasTokens,
|
|
613
|
+
globalTokens,
|
|
614
|
+
componentTokens,
|
|
615
|
+
|
|
616
|
+
spacingTokens,
|
|
617
|
+
radiusTokens,
|
|
618
|
+
dimensionTokens,
|
|
619
|
+
typographyTokens,
|
|
620
|
+
shadowTokens,
|
|
621
|
+
|
|
622
|
+
brandTokens,
|
|
623
|
+
|
|
624
|
+
className,
|
|
625
|
+
}) {
|
|
626
|
+
const resolver =
|
|
627
|
+
createResolver({
|
|
628
|
+
aliasTokens,
|
|
629
|
+
globalTokens,
|
|
630
|
+
componentTokens,
|
|
631
|
+
|
|
632
|
+
spacingTokens,
|
|
633
|
+
radiusTokens,
|
|
634
|
+
dimensionTokens,
|
|
635
|
+
typographyTokens,
|
|
636
|
+
shadowTokens,
|
|
637
|
+
|
|
638
|
+
brandTokens,
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
const paths =
|
|
642
|
+
allThemePaths(
|
|
643
|
+
resolver
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
const body = [];
|
|
647
|
+
const imports =
|
|
648
|
+
new Set();
|
|
649
|
+
|
|
650
|
+
for (
|
|
651
|
+
const tokenPath
|
|
652
|
+
of paths
|
|
653
|
+
) {
|
|
654
|
+
const token =
|
|
655
|
+
resolver.findSemantic(
|
|
656
|
+
tokenPath
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
if (!token) {
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const expression =
|
|
664
|
+
resolver.resolvePath(
|
|
665
|
+
tokenPath,
|
|
666
|
+
getTokenType(token)
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
body.push(
|
|
670
|
+
` static const ` +
|
|
671
|
+
`${expression.type} ` +
|
|
672
|
+
`${toDartIdentifier(tokenPath)} ` +
|
|
673
|
+
`= ${expression.value};`,
|
|
674
|
+
''
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
if (
|
|
678
|
+
expression.importPath
|
|
679
|
+
) {
|
|
680
|
+
imports.add(
|
|
681
|
+
expression.importPath
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
if (
|
|
686
|
+
expression.type === 'Color'
|
|
687
|
+
) {
|
|
688
|
+
imports.add('dart:ui');
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
const out = [
|
|
693
|
+
'// GENERATED FILE - DO NOT EDIT',
|
|
694
|
+
'',
|
|
695
|
+
];
|
|
696
|
+
|
|
697
|
+
if (
|
|
698
|
+
imports.has('dart:ui')
|
|
699
|
+
) {
|
|
700
|
+
out.push(
|
|
701
|
+
"import 'dart:ui';"
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
imports.delete(
|
|
705
|
+
'dart:ui'
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
for (
|
|
710
|
+
const importPath
|
|
711
|
+
of [...imports].sort()
|
|
712
|
+
) {
|
|
713
|
+
out.push(
|
|
714
|
+
`import '${importPath}';`
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (
|
|
719
|
+
imports.size > 0 ||
|
|
720
|
+
out.length > 2
|
|
721
|
+
) {
|
|
722
|
+
out.push('');
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
out.push(
|
|
726
|
+
`class ${className} {`,
|
|
727
|
+
` ${className}._();`,
|
|
728
|
+
'',
|
|
729
|
+
...body,
|
|
730
|
+
'}',
|
|
731
|
+
''
|
|
732
|
+
);
|
|
733
|
+
|
|
734
|
+
return out.join('\n');
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/*
|
|
738
|
+
|--------------------------------------------------------------------------
|
|
739
|
+
| Generate Base + Brand theme container
|
|
740
|
+
|--------------------------------------------------------------------------
|
|
741
|
+
*/
|
|
742
|
+
|
|
743
|
+
function generateThemeTokens({
|
|
744
|
+
aliasTokens,
|
|
745
|
+
globalTokens,
|
|
746
|
+
componentTokens,
|
|
747
|
+
|
|
748
|
+
spacingTokens,
|
|
749
|
+
radiusTokens,
|
|
750
|
+
dimensionTokens,
|
|
751
|
+
typographyTokens,
|
|
752
|
+
shadowTokens,
|
|
753
|
+
|
|
754
|
+
brands = {},
|
|
755
|
+
|
|
756
|
+
}) {
|
|
757
|
+
const baseResolver =
|
|
758
|
+
createResolver({
|
|
759
|
+
aliasTokens,
|
|
760
|
+
globalTokens,
|
|
761
|
+
componentTokens,
|
|
762
|
+
|
|
763
|
+
spacingTokens,
|
|
764
|
+
radiusTokens,
|
|
765
|
+
dimensionTokens,
|
|
766
|
+
typographyTokens,
|
|
767
|
+
shadowTokens,
|
|
768
|
+
|
|
769
|
+
brandTokens: {},
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
const paths =
|
|
773
|
+
allThemePaths(
|
|
774
|
+
baseResolver
|
|
775
|
+
);
|
|
776
|
+
|
|
777
|
+
const brandNames =
|
|
778
|
+
Object.keys(brands);
|
|
779
|
+
|
|
780
|
+
const allPaths =
|
|
781
|
+
new Set(paths);
|
|
782
|
+
|
|
783
|
+
for (
|
|
784
|
+
const brandTokens
|
|
785
|
+
of Object.values(brands)
|
|
786
|
+
) {
|
|
787
|
+
const resolver =
|
|
788
|
+
createResolver({
|
|
789
|
+
aliasTokens,
|
|
790
|
+
globalTokens,
|
|
791
|
+
componentTokens,
|
|
792
|
+
|
|
793
|
+
spacingTokens,
|
|
794
|
+
radiusTokens,
|
|
795
|
+
dimensionTokens,
|
|
796
|
+
typographyTokens,
|
|
797
|
+
shadowTokens,
|
|
798
|
+
|
|
799
|
+
brandTokens,
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
for (
|
|
803
|
+
const tokenPath
|
|
804
|
+
of allThemePaths(
|
|
805
|
+
resolver
|
|
806
|
+
)
|
|
807
|
+
) {
|
|
808
|
+
allPaths.add(
|
|
809
|
+
tokenPath
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
const fields =
|
|
815
|
+
[...allPaths].sort();
|
|
816
|
+
|
|
817
|
+
const rendered = {};
|
|
818
|
+
|
|
819
|
+
const imports =
|
|
820
|
+
new Set();
|
|
821
|
+
|
|
822
|
+
/*
|
|
823
|
+
* Always generate base.
|
|
824
|
+
*/
|
|
825
|
+
rendered.base = {};
|
|
826
|
+
|
|
827
|
+
for (
|
|
828
|
+
const field
|
|
829
|
+
of fields
|
|
830
|
+
) {
|
|
831
|
+
const token =
|
|
832
|
+
baseResolver.findSemantic(
|
|
833
|
+
field
|
|
834
|
+
);
|
|
835
|
+
|
|
836
|
+
if (!token) {
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const expression =
|
|
841
|
+
baseResolver.resolvePath(
|
|
842
|
+
field,
|
|
843
|
+
getTokenType(token)
|
|
844
|
+
);
|
|
845
|
+
|
|
846
|
+
rendered.base[field] =
|
|
847
|
+
expression;
|
|
848
|
+
|
|
849
|
+
if (
|
|
850
|
+
expression.importPath
|
|
851
|
+
) {
|
|
852
|
+
imports.add(
|
|
853
|
+
expression.importPath
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
if (
|
|
858
|
+
expression.type === 'Color'
|
|
859
|
+
) {
|
|
860
|
+
imports.add('dart:ui');
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/*
|
|
865
|
+
* Optional brands.
|
|
866
|
+
*/
|
|
867
|
+
for (
|
|
868
|
+
const brandName
|
|
869
|
+
of brandNames
|
|
870
|
+
) {
|
|
871
|
+
const resolver =
|
|
872
|
+
createResolver({
|
|
873
|
+
aliasTokens,
|
|
874
|
+
globalTokens,
|
|
875
|
+
componentTokens,
|
|
876
|
+
|
|
877
|
+
spacingTokens,
|
|
878
|
+
radiusTokens,
|
|
879
|
+
dimensionTokens,
|
|
880
|
+
typographyTokens,
|
|
881
|
+
shadowTokens,
|
|
882
|
+
|
|
883
|
+
brandTokens:
|
|
884
|
+
brands[brandName],
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
rendered[brandName] = {};
|
|
888
|
+
|
|
889
|
+
for (
|
|
890
|
+
const field
|
|
891
|
+
of fields
|
|
892
|
+
) {
|
|
893
|
+
const token =
|
|
894
|
+
resolver.findSemantic(
|
|
895
|
+
field
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
if (!token) {
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const expression =
|
|
903
|
+
resolver.resolvePath(
|
|
904
|
+
field,
|
|
905
|
+
getTokenType(token)
|
|
906
|
+
);
|
|
907
|
+
|
|
908
|
+
rendered[
|
|
909
|
+
brandName
|
|
910
|
+
][field] = expression;
|
|
911
|
+
if (
|
|
912
|
+
expression.importPath
|
|
913
|
+
) {
|
|
914
|
+
imports.add(
|
|
915
|
+
expression.importPath
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if (
|
|
920
|
+
expression.type === 'Color'
|
|
921
|
+
) {
|
|
922
|
+
imports.add('dart:ui');
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/*
|
|
928
|
+
* Determine field types.
|
|
929
|
+
*/
|
|
930
|
+
const fieldTypes = {};
|
|
931
|
+
|
|
932
|
+
for (
|
|
933
|
+
const field
|
|
934
|
+
of fields
|
|
935
|
+
) {
|
|
936
|
+
const expression =
|
|
937
|
+
rendered.base[field] ||
|
|
938
|
+
Object.values(
|
|
939
|
+
rendered
|
|
940
|
+
).find(
|
|
941
|
+
values =>
|
|
942
|
+
values[field]
|
|
943
|
+
)?.[field];
|
|
944
|
+
|
|
945
|
+
if (expression) {
|
|
946
|
+
fieldTypes[field] =
|
|
947
|
+
expression.type;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
const out = [
|
|
952
|
+
'// GENERATED FILE - DO NOT EDIT',
|
|
953
|
+
'',
|
|
954
|
+
];
|
|
955
|
+
|
|
956
|
+
if (
|
|
957
|
+
imports.has('dart:ui')
|
|
958
|
+
) {
|
|
959
|
+
out.push(
|
|
960
|
+
"import 'dart:ui';"
|
|
961
|
+
);
|
|
962
|
+
|
|
963
|
+
imports.delete(
|
|
964
|
+
'dart:ui'
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
for (
|
|
969
|
+
const importPath
|
|
970
|
+
of [...imports].sort()
|
|
971
|
+
) {
|
|
972
|
+
out.push(
|
|
973
|
+
`import '${importPath}';`
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
out.push('');
|
|
978
|
+
|
|
979
|
+
/*
|
|
980
|
+
* Base theme.
|
|
981
|
+
*/
|
|
982
|
+
out.push(
|
|
983
|
+
'class BaseThemeTokens {',
|
|
984
|
+
' const BaseThemeTokens({'
|
|
985
|
+
);
|
|
986
|
+
|
|
987
|
+
for (
|
|
988
|
+
const field
|
|
989
|
+
of fields
|
|
990
|
+
) {
|
|
991
|
+
if (
|
|
992
|
+
rendered.base[field]
|
|
993
|
+
) {
|
|
994
|
+
out.push(
|
|
995
|
+
` required this.${toDartIdentifier(
|
|
996
|
+
field
|
|
997
|
+
)},`
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
out.push(
|
|
1003
|
+
' });',
|
|
1004
|
+
''
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
for (
|
|
1008
|
+
const field
|
|
1009
|
+
of fields
|
|
1010
|
+
) {
|
|
1011
|
+
if (
|
|
1012
|
+
rendered.base[field]
|
|
1013
|
+
) {
|
|
1014
|
+
out.push(
|
|
1015
|
+
` final ${fieldTypes[field]} ` +
|
|
1016
|
+
`${toDartIdentifier(field)};`
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
out.push(
|
|
1022
|
+
'}',
|
|
1023
|
+
''
|
|
1024
|
+
);
|
|
1025
|
+
|
|
1026
|
+
/*
|
|
1027
|
+
* No brands?
|
|
1028
|
+
*
|
|
1029
|
+
* Base is still completely valid.
|
|
1030
|
+
*/
|
|
1031
|
+
if (
|
|
1032
|
+
brandNames.length === 0
|
|
1033
|
+
) {
|
|
1034
|
+
out.push(
|
|
1035
|
+
'class AppThemeTokens {',
|
|
1036
|
+
' const AppThemeTokens._();',
|
|
1037
|
+
'',
|
|
1038
|
+
' static const base = BaseThemeTokens('
|
|
1039
|
+
);
|
|
1040
|
+
|
|
1041
|
+
for (
|
|
1042
|
+
const field
|
|
1043
|
+
of fields
|
|
1044
|
+
) {
|
|
1045
|
+
const value =
|
|
1046
|
+
rendered.base[field];
|
|
1047
|
+
|
|
1048
|
+
if (!value) {
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
out.push(
|
|
1053
|
+
` ${toDartIdentifier(field)}: ` +
|
|
1054
|
+
`${value.value},`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
out.push(
|
|
1059
|
+
' );',
|
|
1060
|
+
'}',
|
|
1061
|
+
''
|
|
1062
|
+
);
|
|
1063
|
+
} else {
|
|
1064
|
+
/*
|
|
1065
|
+
* Brand theme objects.
|
|
1066
|
+
*/
|
|
1067
|
+
out.push(
|
|
1068
|
+
'class BrandThemeTokens extends BaseThemeTokens {',
|
|
1069
|
+
' const BrandThemeTokens({'
|
|
1070
|
+
);
|
|
1071
|
+
|
|
1072
|
+
for (
|
|
1073
|
+
const field
|
|
1074
|
+
of fields
|
|
1075
|
+
) {
|
|
1076
|
+
if (
|
|
1077
|
+
rendered.base[field]
|
|
1078
|
+
) {
|
|
1079
|
+
out.push(
|
|
1080
|
+
` required super.${toDartIdentifier(
|
|
1081
|
+
field
|
|
1082
|
+
)},`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
out.push(
|
|
1088
|
+
' });',
|
|
1089
|
+
'}',
|
|
1090
|
+
''
|
|
1091
|
+
);
|
|
1092
|
+
|
|
1093
|
+
for (
|
|
1094
|
+
const brandName
|
|
1095
|
+
of brandNames
|
|
1096
|
+
) {
|
|
1097
|
+
const values =
|
|
1098
|
+
rendered[brandName];
|
|
1099
|
+
|
|
1100
|
+
out.push(
|
|
1101
|
+
`const ${toDartIdentifier(
|
|
1102
|
+
brandName
|
|
1103
|
+
)}ThemeTokens = BrandThemeTokens(`
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1106
|
+
for (
|
|
1107
|
+
const field
|
|
1108
|
+
of fields
|
|
1109
|
+
) {
|
|
1110
|
+
const value =
|
|
1111
|
+
values[field] ||
|
|
1112
|
+
rendered.base[field];
|
|
1113
|
+
|
|
1114
|
+
if (!value) {
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
out.push(
|
|
1119
|
+
` ${toDartIdentifier(field)}: ` +
|
|
1120
|
+
`${value.value},`
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
out.push(
|
|
1125
|
+
');',
|
|
1126
|
+
''
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
out.push(
|
|
1131
|
+
'class AppThemeTokens {',
|
|
1132
|
+
' const AppThemeTokens._();',
|
|
1133
|
+
'',
|
|
1134
|
+
' static const base = BaseThemeTokens('
|
|
1135
|
+
);
|
|
1136
|
+
|
|
1137
|
+
for (
|
|
1138
|
+
const field
|
|
1139
|
+
of fields
|
|
1140
|
+
) {
|
|
1141
|
+
const value =
|
|
1142
|
+
rendered.base[field];
|
|
1143
|
+
|
|
1144
|
+
if (!value) {
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
out.push(
|
|
1149
|
+
` ${toDartIdentifier(field)}: ` +
|
|
1150
|
+
`${value.value},`
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
out.push(
|
|
1155
|
+
' );',
|
|
1156
|
+
'}',
|
|
1157
|
+
''
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
return out.join('\n');
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
module.exports = {
|
|
1165
|
+
createResolver,
|
|
1166
|
+
renderTheme: generateTheme,
|
|
1167
|
+
renderThemeTokens: generateThemeTokens,
|
|
1168
|
+
};
|