dispersa 0.4.1 → 0.4.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/README.md +8 -9
- package/dist/builders.cjs +479 -598
- package/dist/builders.cjs.map +1 -1
- package/dist/builders.d.cts +4 -3
- package/dist/builders.d.ts +4 -3
- package/dist/builders.js +479 -598
- package/dist/builders.js.map +1 -1
- package/dist/cli/cli.js +27 -19
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/index.js +27 -19
- package/dist/cli/index.js.map +1 -1
- package/dist/filters.cjs +1 -1
- package/dist/filters.cjs.map +1 -1
- package/dist/filters.js +1 -1
- package/dist/filters.js.map +1 -1
- package/dist/{index-dwm-xYbQ.d.cts → index-CNT2Meyf.d.cts} +79 -74
- package/dist/{index-Bkedvob6.d.ts → index-CqdaN3X0.d.ts} +79 -74
- package/dist/index.cjs +638 -771
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +638 -771
- package/dist/index.js.map +1 -1
- package/dist/preprocessors.cjs.map +1 -1
- package/dist/preprocessors.js.map +1 -1
- package/dist/renderers.cjs.map +1 -1
- package/dist/renderers.d.cts +2 -2
- package/dist/renderers.d.ts +2 -2
- package/dist/renderers.js.map +1 -1
- package/dist/transforms.cjs +5 -17
- package/dist/transforms.cjs.map +1 -1
- package/dist/transforms.d.cts +1 -5
- package/dist/transforms.d.ts +1 -5
- package/dist/transforms.js +6 -17
- package/dist/transforms.js.map +1 -1
- package/package.json +1 -1
package/dist/builders.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var changeCase = require('change-case');
|
|
3
4
|
var culori = require('culori');
|
|
4
5
|
var prettier = require('prettier');
|
|
5
6
|
|
|
@@ -52,13 +53,12 @@ function formatDeprecationMessage(token, description = "", format = "bracket") {
|
|
|
52
53
|
}
|
|
53
54
|
const deprecationMsg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
54
55
|
if (format === "comment") {
|
|
55
|
-
const
|
|
56
|
-
return `DEPRECATED${
|
|
57
|
-
} else {
|
|
58
|
-
const msg = deprecationMsg ? `: ${deprecationMsg}` : "";
|
|
59
|
-
const prefix = `[DEPRECATED${msg}]`;
|
|
60
|
-
return description ? `${prefix} ${description}` : prefix;
|
|
56
|
+
const msg2 = deprecationMsg ? ` ${deprecationMsg}` : "";
|
|
57
|
+
return `DEPRECATED${msg2}`;
|
|
61
58
|
}
|
|
59
|
+
const msg = deprecationMsg ? `: ${deprecationMsg}` : "";
|
|
60
|
+
const prefix = `[DEPRECATED${msg}]`;
|
|
61
|
+
return description ? `${prefix} ${description}` : prefix;
|
|
62
62
|
}
|
|
63
63
|
function stripInternalTokenMetadata(tokens) {
|
|
64
64
|
const cleaned = {};
|
|
@@ -71,6 +71,30 @@ function stripInternalTokenMetadata(tokens) {
|
|
|
71
71
|
function getSortedTokenEntries(tokens) {
|
|
72
72
|
return Object.entries(tokens).sort(([nameA], [nameB]) => nameA.localeCompare(nameB));
|
|
73
73
|
}
|
|
74
|
+
function buildNestedTokenObject(tokens, extractValue) {
|
|
75
|
+
const result = {};
|
|
76
|
+
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
77
|
+
setNestedValue(result, token.path, extractValue(token));
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
function setNestedValue(root, path, value) {
|
|
82
|
+
let current = root;
|
|
83
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
84
|
+
const part = path[i];
|
|
85
|
+
if (part == null) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!(part in current)) {
|
|
89
|
+
current[part] = {};
|
|
90
|
+
}
|
|
91
|
+
current = current[part];
|
|
92
|
+
}
|
|
93
|
+
const lastPart = path[path.length - 1];
|
|
94
|
+
if (lastPart != null) {
|
|
95
|
+
current[lastPart] = value;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
74
98
|
function getPureAliasReferenceName(value) {
|
|
75
99
|
if (typeof value !== "string") {
|
|
76
100
|
return void 0;
|
|
@@ -90,6 +114,35 @@ function sanitizeDataAttributeName(value) {
|
|
|
90
114
|
function escapeCssString(value) {
|
|
91
115
|
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r?\n/g, " ");
|
|
92
116
|
}
|
|
117
|
+
function groupTokensByType(tokens, typeGroupMap) {
|
|
118
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
119
|
+
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
120
|
+
const groupName = typeGroupMap[token.$type ?? ""] ?? "Other";
|
|
121
|
+
const existing = groupMap.get(groupName) ?? [];
|
|
122
|
+
existing.push(token);
|
|
123
|
+
groupMap.set(groupName, existing);
|
|
124
|
+
}
|
|
125
|
+
return Array.from(groupMap.entries()).map(([name, groupTokens]) => ({
|
|
126
|
+
name,
|
|
127
|
+
tokens: groupTokens
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
function indentStr(width, level) {
|
|
131
|
+
return " ".repeat(width * level);
|
|
132
|
+
}
|
|
133
|
+
function buildGeneratedFileHeader() {
|
|
134
|
+
return [
|
|
135
|
+
"// Generated by Dispersa - do not edit manually",
|
|
136
|
+
"// https://github.com/dispersa-core/dispersa"
|
|
137
|
+
].join("\n");
|
|
138
|
+
}
|
|
139
|
+
function toSafeIdentifier(name, keywords, capitalize) {
|
|
140
|
+
const camel = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
|
|
141
|
+
const cased = capitalize ? camel.charAt(0).toUpperCase() + camel.slice(1) : camel.charAt(0).toLowerCase() + camel.slice(1);
|
|
142
|
+
const safe = /^\d/.test(cased) ? `_${cased}` : cased;
|
|
143
|
+
const keyCheck = capitalize ? safe.charAt(0).toLowerCase() + safe.slice(1) : safe;
|
|
144
|
+
return keywords.has(keyCheck) ? `\`${safe}\`` : safe;
|
|
145
|
+
}
|
|
93
146
|
function normalizeModifierInputs(inputs) {
|
|
94
147
|
const normalized = {};
|
|
95
148
|
for (const [key, value] of Object.entries(inputs)) {
|
|
@@ -97,6 +150,14 @@ function normalizeModifierInputs(inputs) {
|
|
|
97
150
|
}
|
|
98
151
|
return normalized;
|
|
99
152
|
}
|
|
153
|
+
function assertFileRequired(buildPath, outputFile, outputName, presetLabel) {
|
|
154
|
+
const requiresFile = buildPath !== void 0 && buildPath !== "";
|
|
155
|
+
if (!outputFile && requiresFile) {
|
|
156
|
+
throw new ConfigurationError(
|
|
157
|
+
`Output "${outputName}": file is required for ${presetLabel} output`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
100
161
|
function buildStablePermutationKey(modifierInputs, dimensions) {
|
|
101
162
|
return dimensions.map((dimension) => `${dimension}=${modifierInputs[dimension] ?? ""}`).join("|");
|
|
102
163
|
}
|
|
@@ -146,14 +207,18 @@ function generatePermutationKey(modifierInputs, resolver, isBase) {
|
|
|
146
207
|
}
|
|
147
208
|
return buildStablePermutationKey(normalizedInputs, metadata.dimensions);
|
|
148
209
|
}
|
|
149
|
-
function
|
|
150
|
-
const { outputName, extension, modifierInputs, resolver, defaults } = params;
|
|
210
|
+
function isBasePermutation(modifierInputs, defaults) {
|
|
151
211
|
const normalizedInputs = normalizeModifierInputs(modifierInputs);
|
|
152
212
|
const normalizedDefaults = normalizeModifierInputs(defaults);
|
|
153
|
-
|
|
154
|
-
|
|
213
|
+
return Object.entries(normalizedDefaults).every(([key, value]) => normalizedInputs[key] === value);
|
|
214
|
+
}
|
|
215
|
+
function buildInMemoryOutputKey(params) {
|
|
216
|
+
const { outputName, extension, modifierInputs, resolver, defaults } = params;
|
|
217
|
+
const permutationKey = generatePermutationKey(
|
|
218
|
+
modifierInputs,
|
|
219
|
+
resolver,
|
|
220
|
+
isBasePermutation(modifierInputs, defaults)
|
|
155
221
|
);
|
|
156
|
-
const permutationKey = generatePermutationKey(modifierInputs, resolver, isBase);
|
|
157
222
|
return `${outputName}-${permutationKey}.${extension}`;
|
|
158
223
|
}
|
|
159
224
|
function buildMetadata(resolver) {
|
|
@@ -267,6 +332,7 @@ function resolveFileName(fileName, modifierInputs) {
|
|
|
267
332
|
}
|
|
268
333
|
var init_utils = __esm({
|
|
269
334
|
"src/renderers/bundlers/utils.ts"() {
|
|
335
|
+
init_errors();
|
|
270
336
|
init_token_utils();
|
|
271
337
|
}
|
|
272
338
|
});
|
|
@@ -276,36 +342,38 @@ var js_exports = {};
|
|
|
276
342
|
__export(js_exports, {
|
|
277
343
|
bundleAsJsModule: () => bundleAsJsModule
|
|
278
344
|
});
|
|
345
|
+
function updateStringTracking(state, char) {
|
|
346
|
+
if (!state.escaped && (char === '"' || char === "'" || char === "`")) {
|
|
347
|
+
if (!state.inString) {
|
|
348
|
+
state.inString = true;
|
|
349
|
+
state.stringChar = char;
|
|
350
|
+
} else if (char === state.stringChar) {
|
|
351
|
+
state.inString = false;
|
|
352
|
+
state.stringChar = "";
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
state.escaped = !state.escaped && char === "\\";
|
|
356
|
+
}
|
|
279
357
|
function extractObjectFromJsModule(formattedJs) {
|
|
280
358
|
const assignmentMatch = /const\s+\w+\s*=\s*\{/.exec(formattedJs);
|
|
281
359
|
if (!assignmentMatch) {
|
|
282
360
|
return "{}";
|
|
283
361
|
}
|
|
284
362
|
const startIndex = assignmentMatch.index + assignmentMatch[0].length - 1;
|
|
363
|
+
const state = { inString: false, stringChar: "", escaped: false };
|
|
285
364
|
let braceCount = 0;
|
|
286
|
-
let inString = false;
|
|
287
|
-
let stringChar = "";
|
|
288
|
-
let escaped = false;
|
|
289
365
|
for (let i = startIndex; i < formattedJs.length; i++) {
|
|
290
366
|
const char = formattedJs[i];
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
stringChar = char;
|
|
295
|
-
} else if (char === stringChar) {
|
|
296
|
-
inString = false;
|
|
297
|
-
stringChar = "";
|
|
298
|
-
}
|
|
367
|
+
updateStringTracking(state, char);
|
|
368
|
+
if (state.inString) {
|
|
369
|
+
continue;
|
|
299
370
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (braceCount === 0) {
|
|
307
|
-
return formattedJs.substring(startIndex, i + 1);
|
|
308
|
-
}
|
|
371
|
+
if (char === "{") {
|
|
372
|
+
braceCount++;
|
|
373
|
+
} else if (char === "}") {
|
|
374
|
+
braceCount--;
|
|
375
|
+
if (braceCount === 0) {
|
|
376
|
+
return formattedJs.substring(startIndex, i + 1);
|
|
309
377
|
}
|
|
310
378
|
}
|
|
311
379
|
}
|
|
@@ -402,22 +470,19 @@ __export(json_exports, {
|
|
|
402
470
|
bundleAsJson: () => bundleAsJson
|
|
403
471
|
});
|
|
404
472
|
async function bundleAsJson(bundleData, resolver, formatTokens) {
|
|
473
|
+
if (!formatTokens) {
|
|
474
|
+
throw new ConfigurationError("JSON formatter was not provided");
|
|
475
|
+
}
|
|
405
476
|
const metadata = buildMetadata(resolver);
|
|
406
477
|
const tokens = {};
|
|
407
478
|
for (const { tokens: tokenSet, modifierInputs } of bundleData) {
|
|
408
479
|
const cleanTokens = stripInternalMetadata(tokenSet);
|
|
409
|
-
if (!formatTokens) {
|
|
410
|
-
throw new ConfigurationError("JSON formatter was not provided");
|
|
411
|
-
}
|
|
412
480
|
const normalizedInputs = normalizeModifierInputs(modifierInputs);
|
|
413
481
|
const key = buildStablePermutationKey(normalizedInputs, metadata.dimensions);
|
|
414
482
|
const themeJson = await formatTokens(cleanTokens);
|
|
415
483
|
tokens[key] = JSON.parse(themeJson);
|
|
416
484
|
}
|
|
417
|
-
const bundle = {
|
|
418
|
-
_meta: metadata,
|
|
419
|
-
tokens
|
|
420
|
-
};
|
|
485
|
+
const bundle = { _meta: metadata, tokens };
|
|
421
486
|
return JSON.stringify(bundle, null, 2);
|
|
422
487
|
}
|
|
423
488
|
var init_json = __esm({
|
|
@@ -426,6 +491,17 @@ var init_json = __esm({
|
|
|
426
491
|
init_utils();
|
|
427
492
|
}
|
|
428
493
|
});
|
|
494
|
+
function nameKebabCase() {
|
|
495
|
+
return {
|
|
496
|
+
transform: (token) => {
|
|
497
|
+
const name = changeCase.kebabCase(token.path.join(" "));
|
|
498
|
+
return {
|
|
499
|
+
...token,
|
|
500
|
+
name
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
}
|
|
429
505
|
function isColorObject(value) {
|
|
430
506
|
return typeof value === "object" && value !== null && "colorSpace" in value && "components" in value;
|
|
431
507
|
}
|
|
@@ -483,7 +559,7 @@ function colorObjectToHex(color) {
|
|
|
483
559
|
return culori.formatHex(culoriColor);
|
|
484
560
|
}
|
|
485
561
|
|
|
486
|
-
// src/processing/
|
|
562
|
+
// src/processing/transforms/built-in/dimension-converter.ts
|
|
487
563
|
function isDimensionObject(value) {
|
|
488
564
|
return typeof value === "object" && value !== null && "value" in value && "unit" in value;
|
|
489
565
|
}
|
|
@@ -491,6 +567,14 @@ function dimensionObjectToString(dimension) {
|
|
|
491
567
|
return `${dimension.value}${dimension.unit}`;
|
|
492
568
|
}
|
|
493
569
|
|
|
570
|
+
// src/processing/transforms/built-in/duration-converter.ts
|
|
571
|
+
function isDurationObject(value) {
|
|
572
|
+
return typeof value === "object" && value !== null && "value" in value && "unit" in value && value.unit !== void 0;
|
|
573
|
+
}
|
|
574
|
+
function durationObjectToString(duration) {
|
|
575
|
+
return `${duration.value}${duration.unit}`;
|
|
576
|
+
}
|
|
577
|
+
|
|
494
578
|
// src/renderers/android.ts
|
|
495
579
|
init_errors();
|
|
496
580
|
init_token_utils();
|
|
@@ -552,9 +636,6 @@ function resolveColorFormat(format) {
|
|
|
552
636
|
}
|
|
553
637
|
return "argb_hex";
|
|
554
638
|
}
|
|
555
|
-
function indent(width, level) {
|
|
556
|
-
return " ".repeat(width * level);
|
|
557
|
-
}
|
|
558
639
|
function escapeKotlinString(str) {
|
|
559
640
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
|
|
560
641
|
}
|
|
@@ -570,22 +651,6 @@ function roundComponent(value) {
|
|
|
570
651
|
function toResourceName(family) {
|
|
571
652
|
return family.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
|
|
572
653
|
}
|
|
573
|
-
function toPascalCase(name) {
|
|
574
|
-
const pascal = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
|
|
575
|
-
const result = pascal.charAt(0).toUpperCase() + pascal.slice(1);
|
|
576
|
-
if (/^\d/.test(result)) {
|
|
577
|
-
return `_${result}`;
|
|
578
|
-
}
|
|
579
|
-
return KOTLIN_KEYWORDS.has(result.charAt(0).toLowerCase() + result.slice(1)) ? `\`${result}\`` : result;
|
|
580
|
-
}
|
|
581
|
-
function toKotlinIdentifier(name) {
|
|
582
|
-
const camel = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
|
|
583
|
-
const identifier = camel.charAt(0).toLowerCase() + camel.slice(1);
|
|
584
|
-
if (/^\d/.test(identifier)) {
|
|
585
|
-
return `_${identifier}`;
|
|
586
|
-
}
|
|
587
|
-
return KOTLIN_KEYWORDS.has(identifier) ? `\`${identifier}\`` : identifier;
|
|
588
|
-
}
|
|
589
654
|
var AndroidRenderer = class {
|
|
590
655
|
async format(context, options) {
|
|
591
656
|
if (!options?.packageName) {
|
|
@@ -593,6 +658,7 @@ var AndroidRenderer = class {
|
|
|
593
658
|
`Output "${context.output.name}": packageName is required for Android output`
|
|
594
659
|
);
|
|
595
660
|
}
|
|
661
|
+
const visibility = options?.visibility;
|
|
596
662
|
const opts = {
|
|
597
663
|
preset: options?.preset ?? "standalone",
|
|
598
664
|
packageName: options.packageName,
|
|
@@ -600,7 +666,8 @@ var AndroidRenderer = class {
|
|
|
600
666
|
colorFormat: resolveColorFormat(options?.colorFormat),
|
|
601
667
|
colorSpace: options?.colorSpace ?? "sRGB",
|
|
602
668
|
structure: options?.structure ?? "nested",
|
|
603
|
-
visibility
|
|
669
|
+
visibility,
|
|
670
|
+
visPrefix: visibility ? `${visibility} ` : "",
|
|
604
671
|
indent: options?.indent ?? 4
|
|
605
672
|
};
|
|
606
673
|
if (opts.preset === "bundle") {
|
|
@@ -633,19 +700,6 @@ var AndroidRenderer = class {
|
|
|
633
700
|
// -----------------------------------------------------------------------
|
|
634
701
|
// Flat structure grouping
|
|
635
702
|
// -----------------------------------------------------------------------
|
|
636
|
-
groupTokensByType(tokens) {
|
|
637
|
-
const groupMap = /* @__PURE__ */ new Map();
|
|
638
|
-
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
639
|
-
const groupName = KOTLIN_TYPE_GROUP_MAP[token.$type ?? ""] ?? "Other";
|
|
640
|
-
const existing = groupMap.get(groupName) ?? [];
|
|
641
|
-
existing.push(token);
|
|
642
|
-
groupMap.set(groupName, existing);
|
|
643
|
-
}
|
|
644
|
-
return Array.from(groupMap.entries()).map(([name, groupTokens]) => ({
|
|
645
|
-
name,
|
|
646
|
-
tokens: groupTokens
|
|
647
|
-
}));
|
|
648
|
-
}
|
|
649
703
|
/**
|
|
650
704
|
* Builds a flattened camelCase name from a token's path, stripping the
|
|
651
705
|
* type prefix segment (which is already represented by the group object).
|
|
@@ -654,7 +708,7 @@ var AndroidRenderer = class {
|
|
|
654
708
|
const path = token.path;
|
|
655
709
|
const withoutTypePrefix = path.length > 1 ? path.slice(1) : path;
|
|
656
710
|
const joined = withoutTypePrefix.join("_");
|
|
657
|
-
return
|
|
711
|
+
return toSafeIdentifier(joined, KOTLIN_KEYWORDS, false);
|
|
658
712
|
}
|
|
659
713
|
// -----------------------------------------------------------------------
|
|
660
714
|
// Rendering
|
|
@@ -666,22 +720,21 @@ var AndroidRenderer = class {
|
|
|
666
720
|
return this.formatAsNested(tokens, options);
|
|
667
721
|
}
|
|
668
722
|
formatAsNested(tokens, options) {
|
|
723
|
+
const tokenTypes = this.collectTokenTypesFromEntries(tokens);
|
|
669
724
|
const tree = this.buildTokenTree(tokens);
|
|
670
|
-
|
|
671
|
-
this.collectTokenTypes(tree, tokenTypes);
|
|
672
|
-
return this.buildFile(tokenTypes, options, (lines, vis) => {
|
|
725
|
+
return this.buildFile(tokenTypes, options, (lines) => {
|
|
673
726
|
lines.push(`@Suppress("unused")`);
|
|
674
|
-
lines.push(`${
|
|
727
|
+
lines.push(`${options.visPrefix}object ${options.objectName} {`);
|
|
675
728
|
this.renderTreeChildren(lines, tree, 1, options);
|
|
676
729
|
lines.push("}");
|
|
677
730
|
});
|
|
678
731
|
}
|
|
679
732
|
formatAsFlat(tokens, options) {
|
|
680
|
-
const groups =
|
|
733
|
+
const groups = groupTokensByType(tokens, KOTLIN_TYPE_GROUP_MAP);
|
|
681
734
|
const tokenTypes = this.collectTokenTypesFromEntries(tokens);
|
|
682
|
-
return this.buildFile(tokenTypes, options, (lines
|
|
735
|
+
return this.buildFile(tokenTypes, options, (lines) => {
|
|
683
736
|
lines.push(`@Suppress("unused")`);
|
|
684
|
-
lines.push(`${
|
|
737
|
+
lines.push(`${options.visPrefix}object ${options.objectName} {`);
|
|
685
738
|
this.renderFlatGroups(lines, groups, 1, options);
|
|
686
739
|
lines.push("}");
|
|
687
740
|
});
|
|
@@ -692,9 +745,8 @@ var AndroidRenderer = class {
|
|
|
692
745
|
*/
|
|
693
746
|
buildFile(tokenTypes, options, renderBody) {
|
|
694
747
|
const imports = this.collectImports(tokenTypes, options);
|
|
695
|
-
const vis = options.visibility ? `${options.visibility} ` : "";
|
|
696
748
|
const lines = [];
|
|
697
|
-
lines.push(
|
|
749
|
+
lines.push(buildGeneratedFileHeader());
|
|
698
750
|
lines.push("");
|
|
699
751
|
lines.push(`package ${options.packageName}`);
|
|
700
752
|
lines.push("");
|
|
@@ -705,19 +757,18 @@ var AndroidRenderer = class {
|
|
|
705
757
|
lines.push("");
|
|
706
758
|
}
|
|
707
759
|
if (tokenTypes.has("shadow")) {
|
|
708
|
-
lines.push(...this.buildShadowTokenClass(
|
|
760
|
+
lines.push(...this.buildShadowTokenClass(options));
|
|
709
761
|
lines.push("");
|
|
710
762
|
}
|
|
711
|
-
renderBody(lines
|
|
763
|
+
renderBody(lines);
|
|
712
764
|
lines.push("");
|
|
713
765
|
return lines.join("\n");
|
|
714
766
|
}
|
|
715
767
|
renderFlatGroups(lines, groups, baseDepth, options) {
|
|
716
|
-
const
|
|
717
|
-
const
|
|
718
|
-
const valIndent = indent(options.indent, baseDepth + 1);
|
|
768
|
+
const groupIndent = indentStr(options.indent, baseDepth);
|
|
769
|
+
const valIndent = indentStr(options.indent, baseDepth + 1);
|
|
719
770
|
for (const group of groups) {
|
|
720
|
-
lines.push(`${groupIndent}${
|
|
771
|
+
lines.push(`${groupIndent}${options.visPrefix}object ${group.name} {`);
|
|
721
772
|
for (const token of group.tokens) {
|
|
722
773
|
const kotlinName = this.buildFlatKotlinName(token);
|
|
723
774
|
const kotlinValue = this.formatKotlinValue(token, options, baseDepth + 1);
|
|
@@ -725,23 +776,24 @@ var AndroidRenderer = class {
|
|
|
725
776
|
if (token.$description) {
|
|
726
777
|
lines.push(`${valIndent}/** ${escapeKDoc(token.$description)} */`);
|
|
727
778
|
}
|
|
728
|
-
lines.push(
|
|
779
|
+
lines.push(
|
|
780
|
+
`${valIndent}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`
|
|
781
|
+
);
|
|
729
782
|
}
|
|
730
783
|
lines.push(`${groupIndent}}`);
|
|
731
784
|
lines.push("");
|
|
732
785
|
}
|
|
733
786
|
}
|
|
734
787
|
renderTreeChildren(lines, node, depth, options) {
|
|
735
|
-
const
|
|
736
|
-
const pad = indent(options.indent, depth);
|
|
788
|
+
const pad = indentStr(options.indent, depth);
|
|
737
789
|
const entries = Array.from(node.children.entries());
|
|
738
790
|
for (let idx = 0; idx < entries.length; idx++) {
|
|
739
791
|
const [key, child] = entries[idx];
|
|
740
792
|
if (child.token && child.children.size === 0) {
|
|
741
793
|
this.renderLeaf(lines, key, child.token, depth, options);
|
|
742
794
|
} else if (child.children.size > 0 && !child.token) {
|
|
743
|
-
const objectName =
|
|
744
|
-
lines.push(`${pad}${
|
|
795
|
+
const objectName = toSafeIdentifier(key, KOTLIN_KEYWORDS, true);
|
|
796
|
+
lines.push(`${pad}${options.visPrefix}object ${objectName} {`);
|
|
745
797
|
this.renderTreeChildren(lines, child, depth + 1, options);
|
|
746
798
|
lines.push(`${pad}}`);
|
|
747
799
|
if (idx < entries.length - 1) {
|
|
@@ -754,30 +806,23 @@ var AndroidRenderer = class {
|
|
|
754
806
|
}
|
|
755
807
|
}
|
|
756
808
|
renderLeaf(lines, key, token, depth, options) {
|
|
757
|
-
const
|
|
758
|
-
const
|
|
759
|
-
const kotlinName = toKotlinIdentifier(key);
|
|
809
|
+
const pad = indentStr(options.indent, depth);
|
|
810
|
+
const kotlinName = toSafeIdentifier(key, KOTLIN_KEYWORDS, false);
|
|
760
811
|
const kotlinValue = this.formatKotlinValue(token, options, depth);
|
|
761
812
|
const annotation = this.typeAnnotationSuffix(token);
|
|
762
813
|
if (token.$description) {
|
|
763
814
|
lines.push(`${pad}/** ${escapeKDoc(token.$description)} */`);
|
|
764
815
|
}
|
|
765
|
-
lines.push(`${pad}${
|
|
766
|
-
}
|
|
767
|
-
buildFileHeader() {
|
|
768
|
-
return [
|
|
769
|
-
"// Generated by Dispersa - do not edit manually",
|
|
770
|
-
"// https://github.com/timges/dispersa"
|
|
771
|
-
].join("\n");
|
|
816
|
+
lines.push(`${pad}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`);
|
|
772
817
|
}
|
|
773
818
|
// -----------------------------------------------------------------------
|
|
774
819
|
// Shadow data class
|
|
775
820
|
// -----------------------------------------------------------------------
|
|
776
|
-
buildShadowTokenClass(
|
|
777
|
-
const i1 =
|
|
821
|
+
buildShadowTokenClass(options) {
|
|
822
|
+
const i1 = indentStr(options.indent, 1);
|
|
778
823
|
return [
|
|
779
824
|
"@Immutable",
|
|
780
|
-
`${
|
|
825
|
+
`${options.visPrefix}data class ShadowToken(`,
|
|
781
826
|
`${i1}val color: Color,`,
|
|
782
827
|
`${i1}val elevation: Dp,`,
|
|
783
828
|
`${i1}val offsetX: Dp,`,
|
|
@@ -828,14 +873,6 @@ var AndroidRenderer = class {
|
|
|
828
873
|
}
|
|
829
874
|
return Array.from(imports).sort();
|
|
830
875
|
}
|
|
831
|
-
collectTokenTypes(node, types) {
|
|
832
|
-
if (node.token?.$type) {
|
|
833
|
-
types.add(node.token.$type);
|
|
834
|
-
}
|
|
835
|
-
for (const child of node.children.values()) {
|
|
836
|
-
this.collectTokenTypes(child, types);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
876
|
collectTokenTypesFromEntries(tokens) {
|
|
840
877
|
const types = /* @__PURE__ */ new Set();
|
|
841
878
|
for (const [, token] of Object.entries(tokens)) {
|
|
@@ -1062,9 +1099,8 @@ var AndroidRenderer = class {
|
|
|
1062
1099
|
return map[name.toLowerCase()];
|
|
1063
1100
|
}
|
|
1064
1101
|
formatDurationValue(value) {
|
|
1065
|
-
if (
|
|
1066
|
-
|
|
1067
|
-
return dur.unit === "ms" ? `${dur.value}.milliseconds` : `${dur.value}.seconds`;
|
|
1102
|
+
if (isDurationObject(value)) {
|
|
1103
|
+
return value.unit === "ms" ? `${value.value}.milliseconds` : `${value.value}.seconds`;
|
|
1068
1104
|
}
|
|
1069
1105
|
return typeof value === "number" ? `${value}.milliseconds` : "0.milliseconds";
|
|
1070
1106
|
}
|
|
@@ -1082,8 +1118,8 @@ var AndroidRenderer = class {
|
|
|
1082
1118
|
const elevation = isDimensionObject(shadow.blur) ? this.formatDimensionValue(shadow.blur) : "0.dp";
|
|
1083
1119
|
const offsetX = isDimensionObject(shadow.offsetX) ? this.formatDimensionValue(shadow.offsetX) : "0.dp";
|
|
1084
1120
|
const offsetY = isDimensionObject(shadow.offsetY) ? this.formatDimensionValue(shadow.offsetY) : "0.dp";
|
|
1085
|
-
const propIndent =
|
|
1086
|
-
const closeIndent =
|
|
1121
|
+
const propIndent = indentStr(options.indent, depth + 1);
|
|
1122
|
+
const closeIndent = indentStr(options.indent, depth);
|
|
1087
1123
|
return [
|
|
1088
1124
|
"ShadowToken(",
|
|
1089
1125
|
`${propIndent}color = ${color},`,
|
|
@@ -1132,8 +1168,8 @@ var AndroidRenderer = class {
|
|
|
1132
1168
|
if (parts.length === 0) {
|
|
1133
1169
|
return "TextStyle()";
|
|
1134
1170
|
}
|
|
1135
|
-
const propIndent =
|
|
1136
|
-
const closeIndent =
|
|
1171
|
+
const propIndent = indentStr(options.indent, depth + 1);
|
|
1172
|
+
const closeIndent = indentStr(options.indent, depth);
|
|
1137
1173
|
return `TextStyle(
|
|
1138
1174
|
${parts.map((p) => `${propIndent}${p}`).join(",\n")},
|
|
1139
1175
|
${closeIndent})`;
|
|
@@ -1142,12 +1178,12 @@ ${closeIndent})`;
|
|
|
1142
1178
|
// Output: standalone
|
|
1143
1179
|
// -----------------------------------------------------------------------
|
|
1144
1180
|
async formatStandalone(context, options) {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1181
|
+
assertFileRequired(
|
|
1182
|
+
context.buildPath,
|
|
1183
|
+
context.output.file,
|
|
1184
|
+
context.output.name,
|
|
1185
|
+
"standalone Android"
|
|
1186
|
+
);
|
|
1151
1187
|
const files = {};
|
|
1152
1188
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
1153
1189
|
const processedTokens = stripInternalMetadata(tokens);
|
|
@@ -1167,12 +1203,12 @@ ${closeIndent})`;
|
|
|
1167
1203
|
// Output: bundle
|
|
1168
1204
|
// -----------------------------------------------------------------------
|
|
1169
1205
|
async formatBundle(context, options) {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1206
|
+
assertFileRequired(
|
|
1207
|
+
context.buildPath,
|
|
1208
|
+
context.output.file,
|
|
1209
|
+
context.output.name,
|
|
1210
|
+
"bundle Android"
|
|
1211
|
+
);
|
|
1176
1212
|
const content = this.formatBundleContent(context, options);
|
|
1177
1213
|
const fileName = context.output.file ? resolveFileName(context.output.file, context.meta.basePermutation) : buildInMemoryOutputKey({
|
|
1178
1214
|
outputName: context.output.name,
|
|
@@ -1185,15 +1221,15 @@ ${closeIndent})`;
|
|
|
1185
1221
|
}
|
|
1186
1222
|
formatBundleContent(context, options) {
|
|
1187
1223
|
const allTokenTypes = this.collectAllPermutationTypes(context);
|
|
1188
|
-
return this.buildFile(allTokenTypes, options, (lines
|
|
1189
|
-
const i1 =
|
|
1224
|
+
return this.buildFile(allTokenTypes, options, (lines) => {
|
|
1225
|
+
const i1 = indentStr(options.indent, 1);
|
|
1190
1226
|
lines.push(`@Suppress("unused")`);
|
|
1191
|
-
lines.push(`${
|
|
1227
|
+
lines.push(`${options.visPrefix}object ${options.objectName} {`);
|
|
1192
1228
|
for (let idx = 0; idx < context.permutations.length; idx++) {
|
|
1193
1229
|
const { tokens, modifierInputs } = context.permutations[idx];
|
|
1194
1230
|
const processedTokens = stripInternalMetadata(tokens);
|
|
1195
1231
|
const permName = this.buildPermutationName(modifierInputs);
|
|
1196
|
-
lines.push(`${i1}${
|
|
1232
|
+
lines.push(`${i1}${options.visPrefix}object ${permName} {`);
|
|
1197
1233
|
this.renderBundleTokens(lines, processedTokens, options, 2);
|
|
1198
1234
|
lines.push(`${i1}}`);
|
|
1199
1235
|
if (idx < context.permutations.length - 1) {
|
|
@@ -1204,20 +1240,17 @@ ${closeIndent})`;
|
|
|
1204
1240
|
});
|
|
1205
1241
|
}
|
|
1206
1242
|
collectAllPermutationTypes(context) {
|
|
1207
|
-
const
|
|
1243
|
+
const types = /* @__PURE__ */ new Set();
|
|
1208
1244
|
for (const { tokens } of context.permutations) {
|
|
1209
|
-
const
|
|
1210
|
-
|
|
1211
|
-
if (token.$type) {
|
|
1212
|
-
allTokenTypes.add(token.$type);
|
|
1213
|
-
}
|
|
1245
|
+
for (const t of this.collectTokenTypesFromEntries(stripInternalMetadata(tokens))) {
|
|
1246
|
+
types.add(t);
|
|
1214
1247
|
}
|
|
1215
1248
|
}
|
|
1216
|
-
return
|
|
1249
|
+
return types;
|
|
1217
1250
|
}
|
|
1218
1251
|
renderBundleTokens(lines, tokens, options, baseDepth) {
|
|
1219
1252
|
if (options.structure === "flat") {
|
|
1220
|
-
const groups =
|
|
1253
|
+
const groups = groupTokensByType(tokens, KOTLIN_TYPE_GROUP_MAP);
|
|
1221
1254
|
this.renderFlatGroups(lines, groups, baseDepth, options);
|
|
1222
1255
|
return;
|
|
1223
1256
|
}
|
|
@@ -1229,7 +1262,7 @@ ${closeIndent})`;
|
|
|
1229
1262
|
if (values.length === 0) {
|
|
1230
1263
|
return "Default";
|
|
1231
1264
|
}
|
|
1232
|
-
return values.map((v) =>
|
|
1265
|
+
return values.map((v) => toSafeIdentifier(v, KOTLIN_KEYWORDS, true)).join("");
|
|
1233
1266
|
}
|
|
1234
1267
|
};
|
|
1235
1268
|
function androidRenderer() {
|
|
@@ -1249,19 +1282,19 @@ init_token_utils();
|
|
|
1249
1282
|
// src/renderers/bundlers/css.ts
|
|
1250
1283
|
init_errors();
|
|
1251
1284
|
init_utils();
|
|
1285
|
+
var REF_PREFIX_SETS = "#/sets/";
|
|
1286
|
+
var REF_PREFIX_MODIFIERS = "#/modifiers/";
|
|
1252
1287
|
var getSourceSet = (token) => {
|
|
1253
1288
|
if (typeof token !== "object" || token === null) {
|
|
1254
1289
|
return void 0;
|
|
1255
1290
|
}
|
|
1256
|
-
|
|
1257
|
-
return typeof maybe._sourceSet === "string" ? maybe._sourceSet : void 0;
|
|
1291
|
+
return "_sourceSet" in token && typeof token._sourceSet === "string" ? token._sourceSet : void 0;
|
|
1258
1292
|
};
|
|
1259
1293
|
var getSourceModifier = (token) => {
|
|
1260
1294
|
if (typeof token !== "object" || token === null) {
|
|
1261
1295
|
return void 0;
|
|
1262
1296
|
}
|
|
1263
|
-
|
|
1264
|
-
return typeof maybe._sourceModifier === "string" ? maybe._sourceModifier : void 0;
|
|
1297
|
+
return "_sourceModifier" in token && typeof token._sourceModifier === "string" ? token._sourceModifier : void 0;
|
|
1265
1298
|
};
|
|
1266
1299
|
async function bundleAsCss(bundleData, resolver, options, formatTokens) {
|
|
1267
1300
|
const baseItem = bundleData.find((item) => item.isBase);
|
|
@@ -1346,6 +1379,15 @@ async function formatModifierPermutation({ tokens, modifierInputs }, baseItem, o
|
|
|
1346
1379
|
return `/* Modifier: ${modifier}=${context} */
|
|
1347
1380
|
${css2}`;
|
|
1348
1381
|
}
|
|
1382
|
+
function addLayerBlock(blocks, included, key, blockTokens, description) {
|
|
1383
|
+
if (Object.keys(blockTokens).length === 0) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
for (const k of Object.keys(blockTokens)) {
|
|
1387
|
+
included.add(k);
|
|
1388
|
+
}
|
|
1389
|
+
blocks.push({ key, description, tokens: blockTokens });
|
|
1390
|
+
}
|
|
1349
1391
|
function collectSetTokens(tokens, setName, included) {
|
|
1350
1392
|
const result = {};
|
|
1351
1393
|
for (const [name, token] of Object.entries(tokens)) {
|
|
@@ -1376,75 +1418,67 @@ function collectRemainder(tokens, included) {
|
|
|
1376
1418
|
function buildSetLayerBlocks(tokens, resolver) {
|
|
1377
1419
|
const blocks = [];
|
|
1378
1420
|
const included = /* @__PURE__ */ new Set();
|
|
1379
|
-
const addBlock = (key, blockTokens, description) => {
|
|
1380
|
-
if (Object.keys(blockTokens).length === 0) {
|
|
1381
|
-
return;
|
|
1382
|
-
}
|
|
1383
|
-
for (const k of Object.keys(blockTokens)) {
|
|
1384
|
-
included.add(k);
|
|
1385
|
-
}
|
|
1386
|
-
blocks.push({ key, description, tokens: blockTokens });
|
|
1387
|
-
};
|
|
1388
1421
|
for (const item of resolver.resolutionOrder) {
|
|
1389
1422
|
const ref = item.$ref;
|
|
1390
|
-
if (typeof ref !== "string" || !ref.startsWith(
|
|
1423
|
+
if (typeof ref !== "string" || !ref.startsWith(REF_PREFIX_SETS)) {
|
|
1391
1424
|
continue;
|
|
1392
1425
|
}
|
|
1393
|
-
const setName = ref.slice(
|
|
1394
|
-
|
|
1426
|
+
const setName = ref.slice(REF_PREFIX_SETS.length);
|
|
1427
|
+
addLayerBlock(
|
|
1428
|
+
blocks,
|
|
1429
|
+
included,
|
|
1395
1430
|
`Set: ${setName}`,
|
|
1396
1431
|
collectSetTokens(tokens, setName, included),
|
|
1397
1432
|
resolver.sets?.[setName]?.description
|
|
1398
1433
|
);
|
|
1399
1434
|
}
|
|
1400
|
-
|
|
1435
|
+
addLayerBlock(blocks, included, "Unattributed", collectRemainder(tokens, included));
|
|
1401
1436
|
return blocks;
|
|
1402
1437
|
}
|
|
1403
1438
|
function buildDefaultLayerBlocks(tokens, baseModifierInputs, resolver) {
|
|
1404
1439
|
const blocks = [];
|
|
1405
1440
|
const included = /* @__PURE__ */ new Set();
|
|
1406
1441
|
const baseInputs = normalizeModifierInputs(baseModifierInputs);
|
|
1407
|
-
const addBlock = (key, blockTokens, description) => {
|
|
1408
|
-
if (Object.keys(blockTokens).length === 0) {
|
|
1409
|
-
return;
|
|
1410
|
-
}
|
|
1411
|
-
for (const k of Object.keys(blockTokens)) {
|
|
1412
|
-
included.add(k);
|
|
1413
|
-
}
|
|
1414
|
-
blocks.push({ key, description, tokens: blockTokens });
|
|
1415
|
-
};
|
|
1416
1442
|
for (const item of resolver.resolutionOrder) {
|
|
1417
1443
|
const ref = item.$ref;
|
|
1418
1444
|
if (typeof ref !== "string") {
|
|
1419
1445
|
continue;
|
|
1420
1446
|
}
|
|
1421
|
-
|
|
1422
|
-
const setName = ref.slice("#/sets/".length);
|
|
1423
|
-
addBlock(
|
|
1424
|
-
`Set: ${setName}`,
|
|
1425
|
-
collectSetTokens(tokens, setName, included),
|
|
1426
|
-
resolver.sets?.[setName]?.description
|
|
1427
|
-
);
|
|
1428
|
-
continue;
|
|
1429
|
-
}
|
|
1430
|
-
if (ref.startsWith("#/modifiers/")) {
|
|
1431
|
-
const modifierName = ref.slice("#/modifiers/".length);
|
|
1432
|
-
const modifier = resolver.modifiers?.[modifierName];
|
|
1433
|
-
const selectedContext = baseInputs[modifierName.toLowerCase()];
|
|
1434
|
-
if (!modifier || !selectedContext) {
|
|
1435
|
-
continue;
|
|
1436
|
-
}
|
|
1437
|
-
const expectedSource = `${modifierName}-${selectedContext}`.toLowerCase();
|
|
1438
|
-
addBlock(
|
|
1439
|
-
`Modifier: ${modifierName}=${selectedContext} (default)`,
|
|
1440
|
-
collectModifierTokens(tokens, expectedSource, included),
|
|
1441
|
-
modifier.description
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1447
|
+
processResolutionOrderRef(ref, tokens, blocks, included, baseInputs, resolver);
|
|
1444
1448
|
}
|
|
1445
|
-
|
|
1449
|
+
addLayerBlock(blocks, included, "Unattributed", collectRemainder(tokens, included));
|
|
1446
1450
|
return blocks;
|
|
1447
1451
|
}
|
|
1452
|
+
function processResolutionOrderRef(ref, tokens, blocks, included, baseInputs, resolver) {
|
|
1453
|
+
if (ref.startsWith(REF_PREFIX_SETS)) {
|
|
1454
|
+
const setName = ref.slice(REF_PREFIX_SETS.length);
|
|
1455
|
+
addLayerBlock(
|
|
1456
|
+
blocks,
|
|
1457
|
+
included,
|
|
1458
|
+
`Set: ${setName}`,
|
|
1459
|
+
collectSetTokens(tokens, setName, included),
|
|
1460
|
+
resolver.sets?.[setName]?.description
|
|
1461
|
+
);
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
if (!ref.startsWith(REF_PREFIX_MODIFIERS)) {
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
const modifierName = ref.slice(REF_PREFIX_MODIFIERS.length);
|
|
1468
|
+
const modifier = resolver.modifiers?.[modifierName];
|
|
1469
|
+
const selectedContext = baseInputs[modifierName.toLowerCase()];
|
|
1470
|
+
if (!modifier || !selectedContext) {
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
const expectedSource = `${modifierName}-${selectedContext}`.toLowerCase();
|
|
1474
|
+
addLayerBlock(
|
|
1475
|
+
blocks,
|
|
1476
|
+
included,
|
|
1477
|
+
`Modifier: ${modifierName}=${selectedContext} (default)`,
|
|
1478
|
+
collectModifierTokens(tokens, expectedSource, included),
|
|
1479
|
+
modifier.description
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1448
1482
|
function findSingleDiffPermutation(bundleData, modifierName, context, baseInputs) {
|
|
1449
1483
|
const normalizedModifier = modifierName.toLowerCase();
|
|
1450
1484
|
const normalizedContext = context.toLowerCase();
|
|
@@ -1459,6 +1493,36 @@ function findSingleDiffPermutation(bundleData, modifierName, context, baseInputs
|
|
|
1459
1493
|
return Object.entries(baseInputs).every(([k, v]) => k === normalizedModifier || inputs[k] === v);
|
|
1460
1494
|
});
|
|
1461
1495
|
}
|
|
1496
|
+
function pushUniqueBundleItem(ordered, includedKeys, item) {
|
|
1497
|
+
if (!item) {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
const key = stableInputsKey(item.modifierInputs);
|
|
1501
|
+
if (includedKeys.has(key)) {
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
includedKeys.add(key);
|
|
1505
|
+
ordered.push(item);
|
|
1506
|
+
}
|
|
1507
|
+
function appendModifierPermutations(bundleData, modifiers, orderedNames, baseInputs, ordered, includedKeys) {
|
|
1508
|
+
for (const modifierName of orderedNames) {
|
|
1509
|
+
const modifierDef = modifiers[modifierName];
|
|
1510
|
+
if (!modifierDef) {
|
|
1511
|
+
continue;
|
|
1512
|
+
}
|
|
1513
|
+
const defaultValue = baseInputs[modifierName.toLowerCase()] ?? "";
|
|
1514
|
+
for (const ctx of Object.keys(modifierDef.contexts)) {
|
|
1515
|
+
if (defaultValue === ctx.toLowerCase()) {
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
pushUniqueBundleItem(
|
|
1519
|
+
ordered,
|
|
1520
|
+
includedKeys,
|
|
1521
|
+
findSingleDiffPermutation(bundleData, modifierName, ctx, baseInputs)
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1462
1526
|
function orderBundleData(bundleData, resolver, baseItem) {
|
|
1463
1527
|
const modifiers = resolver.modifiers;
|
|
1464
1528
|
if (!modifiers) {
|
|
@@ -1475,31 +1539,15 @@ function orderBundleData(bundleData, resolver, baseItem) {
|
|
|
1475
1539
|
}
|
|
1476
1540
|
const includedKeys = /* @__PURE__ */ new Set();
|
|
1477
1541
|
const ordered = [];
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
ordered.push(item);
|
|
1488
|
-
};
|
|
1489
|
-
pushUnique(baseItem);
|
|
1490
|
-
for (const modifierName of orderedModifierNames) {
|
|
1491
|
-
const modifierDef = modifiers[modifierName];
|
|
1492
|
-
if (!modifierDef) {
|
|
1493
|
-
continue;
|
|
1494
|
-
}
|
|
1495
|
-
const defaultValue = baseInputs[modifierName.toLowerCase()] ?? "";
|
|
1496
|
-
for (const ctx of Object.keys(modifierDef.contexts)) {
|
|
1497
|
-
if (defaultValue === ctx.toLowerCase()) {
|
|
1498
|
-
continue;
|
|
1499
|
-
}
|
|
1500
|
-
pushUnique(findSingleDiffPermutation(bundleData, modifierName, ctx, baseInputs));
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1542
|
+
pushUniqueBundleItem(ordered, includedKeys, baseItem);
|
|
1543
|
+
appendModifierPermutations(
|
|
1544
|
+
bundleData,
|
|
1545
|
+
modifiers,
|
|
1546
|
+
orderedModifierNames,
|
|
1547
|
+
baseInputs,
|
|
1548
|
+
ordered,
|
|
1549
|
+
includedKeys
|
|
1550
|
+
);
|
|
1503
1551
|
return ordered.length > 0 ? ordered : bundleData;
|
|
1504
1552
|
}
|
|
1505
1553
|
function getOrderedModifierNames(resolver) {
|
|
@@ -1511,10 +1559,10 @@ function getOrderedModifierNames(resolver) {
|
|
|
1511
1559
|
if (typeof ref !== "string") {
|
|
1512
1560
|
continue;
|
|
1513
1561
|
}
|
|
1514
|
-
if (!ref.startsWith(
|
|
1562
|
+
if (!ref.startsWith(REF_PREFIX_MODIFIERS)) {
|
|
1515
1563
|
continue;
|
|
1516
1564
|
}
|
|
1517
|
-
const name = ref.slice(
|
|
1565
|
+
const name = ref.slice(REF_PREFIX_MODIFIERS.length);
|
|
1518
1566
|
if (seen.has(name)) {
|
|
1519
1567
|
continue;
|
|
1520
1568
|
}
|
|
@@ -1585,24 +1633,22 @@ var CssRenderer = class _CssRenderer {
|
|
|
1585
1633
|
...options,
|
|
1586
1634
|
referenceTokens: options?.referenceTokens ?? tokens
|
|
1587
1635
|
};
|
|
1588
|
-
const
|
|
1636
|
+
const sortedTokens = getSortedTokenEntries(tokens).map(([, token]) => token);
|
|
1589
1637
|
const referenceTokens = opts.referenceTokens;
|
|
1590
1638
|
const lines = [];
|
|
1591
|
-
|
|
1592
|
-
this.buildCssBlock(lines, groupTokens, selector, tokens, referenceTokens, opts);
|
|
1593
|
-
}
|
|
1639
|
+
this.buildCssBlock(lines, sortedTokens, opts.selector, tokens, referenceTokens, opts);
|
|
1594
1640
|
const cssString = lines.join("");
|
|
1595
1641
|
return opts.minify ? cssString : await this.formatWithPrettier(cssString);
|
|
1596
1642
|
}
|
|
1597
1643
|
buildCssBlock(lines, groupTokens, selector, tokens, referenceTokens, opts) {
|
|
1598
|
-
const
|
|
1644
|
+
const indent = opts.minify ? "" : " ";
|
|
1599
1645
|
const newline = opts.minify ? "" : "\n";
|
|
1600
1646
|
const space = opts.minify ? "" : " ";
|
|
1601
1647
|
const hasMediaQuery = opts.mediaQuery != null && opts.mediaQuery !== "";
|
|
1602
|
-
const tokenIndent = hasMediaQuery ?
|
|
1648
|
+
const tokenIndent = hasMediaQuery ? indent + indent : indent;
|
|
1603
1649
|
if (hasMediaQuery) {
|
|
1604
1650
|
lines.push(`@media ${opts.mediaQuery}${space}{${newline}`);
|
|
1605
|
-
lines.push(`${
|
|
1651
|
+
lines.push(`${indent}${selector}${space}{${newline}`);
|
|
1606
1652
|
} else {
|
|
1607
1653
|
lines.push(`${selector}${space}{${newline}`);
|
|
1608
1654
|
}
|
|
@@ -1619,21 +1665,21 @@ var CssRenderer = class _CssRenderer {
|
|
|
1619
1665
|
);
|
|
1620
1666
|
}
|
|
1621
1667
|
if (hasMediaQuery) {
|
|
1622
|
-
lines.push(`${
|
|
1668
|
+
lines.push(`${indent}}${newline}`);
|
|
1623
1669
|
}
|
|
1624
1670
|
lines.push(`}${newline}${newline}`);
|
|
1625
1671
|
}
|
|
1626
|
-
pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences,
|
|
1672
|
+
pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent, newline, space) {
|
|
1627
1673
|
const entries = this.buildCssEntries(token, tokens, referenceTokens, preserveReferences);
|
|
1628
1674
|
if (token.$deprecated != null && token.$deprecated !== false) {
|
|
1629
1675
|
const deprecationMsg = formatDeprecationMessage(token, "", "comment");
|
|
1630
|
-
lines.push(`${
|
|
1676
|
+
lines.push(`${indent}/* ${this.sanitizeCssCommentText(deprecationMsg)} */${newline}`);
|
|
1631
1677
|
}
|
|
1632
1678
|
if (token.$description && token.$description !== "") {
|
|
1633
|
-
lines.push(`${
|
|
1679
|
+
lines.push(`${indent}/* ${this.sanitizeCssCommentText(token.$description)} */${newline}`);
|
|
1634
1680
|
}
|
|
1635
1681
|
for (const entry of entries) {
|
|
1636
|
-
lines.push(`${
|
|
1682
|
+
lines.push(`${indent}--${entry.name}:${space}${entry.value};${newline}`);
|
|
1637
1683
|
}
|
|
1638
1684
|
}
|
|
1639
1685
|
async formatWithPrettier(css2) {
|
|
@@ -1648,15 +1694,6 @@ var CssRenderer = class _CssRenderer {
|
|
|
1648
1694
|
return css2;
|
|
1649
1695
|
}
|
|
1650
1696
|
}
|
|
1651
|
-
/**
|
|
1652
|
-
* Group tokens by selector (for theme support)
|
|
1653
|
-
*/
|
|
1654
|
-
groupTokens(tokens, options) {
|
|
1655
|
-
const sortedTokens = getSortedTokenEntries(tokens).map(([, token]) => token);
|
|
1656
|
-
return {
|
|
1657
|
-
[options.selector]: sortedTokens
|
|
1658
|
-
};
|
|
1659
|
-
}
|
|
1660
1697
|
buildCssEntries(token, tokens, referenceTokens, preserveReferences) {
|
|
1661
1698
|
if (preserveReferences) {
|
|
1662
1699
|
const refName = getPureAliasReferenceName(token.originalValue);
|
|
@@ -1798,7 +1835,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
1798
1835
|
leaves.push({ path, value });
|
|
1799
1836
|
return;
|
|
1800
1837
|
}
|
|
1801
|
-
if (isColorObject(value) || isDimensionObject(value) ||
|
|
1838
|
+
if (isColorObject(value) || isDimensionObject(value) || isDurationObject(value)) {
|
|
1802
1839
|
leaves.push({ path, value });
|
|
1803
1840
|
return;
|
|
1804
1841
|
}
|
|
@@ -1841,8 +1878,8 @@ var CssRenderer = class _CssRenderer {
|
|
|
1841
1878
|
if (isDimensionObject(value)) {
|
|
1842
1879
|
return dimensionObjectToString(value);
|
|
1843
1880
|
}
|
|
1844
|
-
if (
|
|
1845
|
-
return
|
|
1881
|
+
if (isDurationObject(value)) {
|
|
1882
|
+
return durationObjectToString(value);
|
|
1846
1883
|
}
|
|
1847
1884
|
if (typeof value === "string") {
|
|
1848
1885
|
return value;
|
|
@@ -1905,15 +1942,6 @@ var CssRenderer = class _CssRenderer {
|
|
|
1905
1942
|
isPrimitiveValue(value) {
|
|
1906
1943
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
1907
1944
|
}
|
|
1908
|
-
isDurationObject(value) {
|
|
1909
|
-
return typeof value === "object" && value !== null && "value" in value && "unit" in value && value.unit !== void 0;
|
|
1910
|
-
}
|
|
1911
|
-
formatDurationValue(value) {
|
|
1912
|
-
if (typeof value === "string") {
|
|
1913
|
-
return value;
|
|
1914
|
-
}
|
|
1915
|
-
return `${value.value}${value.unit}`;
|
|
1916
|
-
}
|
|
1917
1945
|
/**
|
|
1918
1946
|
* Format token value for CSS
|
|
1919
1947
|
* Handles DTCG 2025.10 object formats for colors and dimensions
|
|
@@ -1934,8 +1962,8 @@ var CssRenderer = class _CssRenderer {
|
|
|
1934
1962
|
return typeof value === "string" ? value : dimensionObjectToString(value);
|
|
1935
1963
|
}
|
|
1936
1964
|
if (type === "duration") {
|
|
1937
|
-
if (
|
|
1938
|
-
return
|
|
1965
|
+
if (isDurationObject(value)) {
|
|
1966
|
+
return durationObjectToString(value);
|
|
1939
1967
|
}
|
|
1940
1968
|
if (typeof value === "string") {
|
|
1941
1969
|
return value;
|
|
@@ -2025,16 +2053,16 @@ var CssRenderer = class _CssRenderer {
|
|
|
2025
2053
|
*/
|
|
2026
2054
|
formatTransition(value) {
|
|
2027
2055
|
const parts = [];
|
|
2028
|
-
if (
|
|
2029
|
-
parts.push(
|
|
2056
|
+
if (isDurationObject(value.duration)) {
|
|
2057
|
+
parts.push(durationObjectToString(value.duration));
|
|
2030
2058
|
} else if (value.duration != null) {
|
|
2031
2059
|
parts.push(String(value.duration));
|
|
2032
2060
|
}
|
|
2033
2061
|
if (Array.isArray(value.timingFunction) && value.timingFunction.length === 4) {
|
|
2034
2062
|
parts.push(`cubic-bezier(${value.timingFunction.join(", ")})`);
|
|
2035
2063
|
}
|
|
2036
|
-
if (
|
|
2037
|
-
parts.push(
|
|
2064
|
+
if (isDurationObject(value.delay)) {
|
|
2065
|
+
parts.push(durationObjectToString(value.delay));
|
|
2038
2066
|
} else if (value.delay != null) {
|
|
2039
2067
|
parts.push(String(value.delay));
|
|
2040
2068
|
}
|
|
@@ -2044,7 +2072,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
2044
2072
|
const bundleData = context.permutations.map(({ tokens, modifierInputs }) => ({
|
|
2045
2073
|
tokens,
|
|
2046
2074
|
modifierInputs,
|
|
2047
|
-
isBase:
|
|
2075
|
+
isBase: isBasePermutation(modifierInputs, context.meta.defaults)
|
|
2048
2076
|
}));
|
|
2049
2077
|
return await bundleAsCss(bundleData, context.resolver, options, async (tokens, resolved) => {
|
|
2050
2078
|
return await this.formatTokens(tokens, {
|
|
@@ -2054,12 +2082,12 @@ var CssRenderer = class _CssRenderer {
|
|
|
2054
2082
|
});
|
|
2055
2083
|
}
|
|
2056
2084
|
async formatStandalone(context, options) {
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2085
|
+
assertFileRequired(
|
|
2086
|
+
context.buildPath,
|
|
2087
|
+
context.output.file,
|
|
2088
|
+
context.output.name,
|
|
2089
|
+
"standalone CSS"
|
|
2090
|
+
);
|
|
2063
2091
|
const files = {};
|
|
2064
2092
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
2065
2093
|
const { fileName, content } = await this.buildStandaloneFile(
|
|
@@ -2073,7 +2101,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
2073
2101
|
return { kind: "outputTree", files };
|
|
2074
2102
|
}
|
|
2075
2103
|
async buildStandaloneFile(tokens, modifierInputs, context, options) {
|
|
2076
|
-
const isBase =
|
|
2104
|
+
const isBase = isBasePermutation(modifierInputs, context.meta.defaults);
|
|
2077
2105
|
const { modifierName, modifierContext } = this.resolveModifierContext(
|
|
2078
2106
|
modifierInputs,
|
|
2079
2107
|
context,
|
|
@@ -2110,12 +2138,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
2110
2138
|
return { fileName, content };
|
|
2111
2139
|
}
|
|
2112
2140
|
async formatModifier(context, options) {
|
|
2113
|
-
|
|
2114
|
-
if (!context.output.file && requiresFile) {
|
|
2115
|
-
throw new ConfigurationError(
|
|
2116
|
-
`Output "${context.output.name}": file is required for modifier CSS output`
|
|
2117
|
-
);
|
|
2118
|
-
}
|
|
2141
|
+
assertFileRequired(context.buildPath, context.output.file, context.output.name, "modifier CSS");
|
|
2119
2142
|
if (!context.resolver.modifiers) {
|
|
2120
2143
|
throw new ConfigurationError("Modifier preset requires modifiers to be defined in resolver");
|
|
2121
2144
|
}
|
|
@@ -2141,7 +2164,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
2141
2164
|
}
|
|
2142
2165
|
async buildModifierBaseFile(context, options) {
|
|
2143
2166
|
const basePermutation = context.permutations.find(
|
|
2144
|
-
({ modifierInputs }) =>
|
|
2167
|
+
({ modifierInputs }) => isBasePermutation(modifierInputs, context.meta.defaults)
|
|
2145
2168
|
);
|
|
2146
2169
|
if (!basePermutation) {
|
|
2147
2170
|
return void 0;
|
|
@@ -2154,25 +2177,40 @@ var CssRenderer = class _CssRenderer {
|
|
|
2154
2177
|
if (setBlocks.length === 0) {
|
|
2155
2178
|
return void 0;
|
|
2156
2179
|
}
|
|
2180
|
+
const { selector, mediaQuery } = this.resolveBaseModifierContext(context, options);
|
|
2181
|
+
const content = await this.formatSetBlocksCss(
|
|
2182
|
+
setBlocks,
|
|
2183
|
+
basePermutation.tokens,
|
|
2184
|
+
selector,
|
|
2185
|
+
mediaQuery,
|
|
2186
|
+
options
|
|
2187
|
+
);
|
|
2188
|
+
const fileName = context.output.file ? resolveBaseFileName(context.output.file, context.meta.defaults) : `${context.output.name}-base.css`;
|
|
2189
|
+
return { fileName, content };
|
|
2190
|
+
}
|
|
2191
|
+
resolveBaseModifierContext(context, options) {
|
|
2157
2192
|
const modifiers = context.resolver.modifiers;
|
|
2158
2193
|
const firstModifierName = Object.keys(modifiers)[0] ?? "";
|
|
2159
2194
|
const firstModifierContext = context.meta.defaults[firstModifierName] ?? "";
|
|
2160
2195
|
const baseModifierInputs = { ...context.meta.defaults };
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2196
|
+
return {
|
|
2197
|
+
selector: resolveSelector(
|
|
2198
|
+
options.selector,
|
|
2199
|
+
firstModifierName,
|
|
2200
|
+
firstModifierContext,
|
|
2201
|
+
true,
|
|
2202
|
+
baseModifierInputs
|
|
2203
|
+
),
|
|
2204
|
+
mediaQuery: resolveMediaQuery(
|
|
2205
|
+
options.mediaQuery,
|
|
2206
|
+
firstModifierName,
|
|
2207
|
+
firstModifierContext,
|
|
2208
|
+
true,
|
|
2209
|
+
baseModifierInputs
|
|
2210
|
+
)
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
2213
|
+
async formatSetBlocksCss(setBlocks, referenceTokens, selector, mediaQuery, options) {
|
|
2176
2214
|
const cssBlocks = [];
|
|
2177
2215
|
for (const block of setBlocks) {
|
|
2178
2216
|
const cleanTokens = stripInternalMetadata(block.tokens);
|
|
@@ -2188,9 +2226,7 @@ var CssRenderer = class _CssRenderer {
|
|
|
2188
2226
|
cssBlocks.push(`${header}
|
|
2189
2227
|
${css2}`);
|
|
2190
2228
|
}
|
|
2191
|
-
|
|
2192
|
-
const fileName = context.output.file ? resolveBaseFileName(context.output.file, context.meta.defaults) : `${context.output.name}-base.css`;
|
|
2193
|
-
return { fileName, content };
|
|
2229
|
+
return cssBlocks.join("\n");
|
|
2194
2230
|
}
|
|
2195
2231
|
collectTokensForModifierContext(modifierName, contextValue, permutations) {
|
|
2196
2232
|
const expectedSource = `${modifierName}-${contextValue}`;
|
|
@@ -2267,13 +2303,6 @@ ${css2}`);
|
|
|
2267
2303
|
}
|
|
2268
2304
|
return { modifierName: "", modifierContext: "" };
|
|
2269
2305
|
}
|
|
2270
|
-
isBasePermutation(modifierInputs, defaults) {
|
|
2271
|
-
const normalizedInputs = normalizeModifierInputs(modifierInputs);
|
|
2272
|
-
const normalizedDefaults = normalizeModifierInputs(defaults);
|
|
2273
|
-
return Object.entries(normalizedDefaults).every(
|
|
2274
|
-
([key, value]) => normalizedInputs[key] === value
|
|
2275
|
-
);
|
|
2276
|
-
}
|
|
2277
2306
|
};
|
|
2278
2307
|
function cssRenderer() {
|
|
2279
2308
|
const rendererInstance = new CssRenderer();
|
|
@@ -2285,9 +2314,18 @@ function cssRenderer() {
|
|
|
2285
2314
|
};
|
|
2286
2315
|
}
|
|
2287
2316
|
|
|
2317
|
+
// src/tokens/types.ts
|
|
2318
|
+
function isShadowToken(token) {
|
|
2319
|
+
return token.$type === "shadow";
|
|
2320
|
+
}
|
|
2321
|
+
function isTypographyToken(token) {
|
|
2322
|
+
return token.$type === "typography";
|
|
2323
|
+
}
|
|
2324
|
+
function isBorderToken(token) {
|
|
2325
|
+
return token.$type === "border";
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2288
2328
|
// src/renderers/ios.ts
|
|
2289
|
-
init_errors();
|
|
2290
|
-
init_token_utils();
|
|
2291
2329
|
init_utils();
|
|
2292
2330
|
var toSRGB2 = culori.converter("rgb");
|
|
2293
2331
|
var toP32 = culori.converter("p3");
|
|
@@ -2376,94 +2414,68 @@ var IosRenderer = class {
|
|
|
2376
2414
|
return await this.formatStandalone(context, opts);
|
|
2377
2415
|
}
|
|
2378
2416
|
formatTokens(tokens, options) {
|
|
2379
|
-
if (options.structure === "grouped") {
|
|
2380
|
-
return this.formatAsGrouped(tokens, options);
|
|
2381
|
-
}
|
|
2382
|
-
return this.formatAsEnum(tokens, options);
|
|
2383
|
-
}
|
|
2384
|
-
formatAsEnum(tokens, options) {
|
|
2385
2417
|
const access = options.accessLevel;
|
|
2386
|
-
const groups =
|
|
2418
|
+
const groups = groupTokensByType(tokens, SWIFT_TYPE_GROUP_MAP);
|
|
2387
2419
|
const imports = this.collectImports(tokens);
|
|
2388
|
-
const i1 = this.indentStr(options.indent, 1);
|
|
2389
|
-
const i2 = this.indentStr(options.indent, 2);
|
|
2390
2420
|
const staticPrefix = this.staticLetPrefix(options);
|
|
2391
2421
|
const frozen = this.frozenPrefix(options);
|
|
2392
2422
|
const lines = [];
|
|
2393
|
-
lines.push(
|
|
2423
|
+
lines.push(buildGeneratedFileHeader());
|
|
2394
2424
|
lines.push("");
|
|
2395
2425
|
for (const imp of imports) {
|
|
2396
2426
|
lines.push(`import ${imp}`);
|
|
2397
2427
|
}
|
|
2398
2428
|
lines.push(...this.buildStructDefinitions(tokens, access, options));
|
|
2429
|
+
this.pushTokenLayout(lines, groups, options, access, staticPrefix, frozen);
|
|
2430
|
+
lines.push(...this.buildViewExtensions(tokens, access, options));
|
|
2431
|
+
if (options.structure !== "grouped") {
|
|
2432
|
+
lines.push("");
|
|
2433
|
+
}
|
|
2434
|
+
return lines.join("\n");
|
|
2435
|
+
}
|
|
2436
|
+
pushTokenLayout(lines, groups, options, access, staticPrefix, frozen) {
|
|
2437
|
+
const i1 = indentStr(options.indent, 1);
|
|
2438
|
+
const i2 = indentStr(options.indent, 2);
|
|
2439
|
+
if (options.structure === "grouped") {
|
|
2440
|
+
this.pushGroupedLayout(lines, groups, options, access, i1, i2, staticPrefix, frozen);
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
2399
2443
|
lines.push("");
|
|
2400
2444
|
lines.push(`${frozen}${access} enum ${options.enumName} {`);
|
|
2401
2445
|
for (const group of groups) {
|
|
2402
2446
|
lines.push(`${i1}${frozen}${access} enum ${group.name} {`);
|
|
2403
|
-
|
|
2404
|
-
const swiftName = this.buildQualifiedSwiftName(token);
|
|
2405
|
-
const swiftValue = this.formatSwiftValue(token, options);
|
|
2406
|
-
const typeAnnotation = this.getTypeAnnotation(token);
|
|
2407
|
-
const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
|
|
2408
|
-
const docComment = this.buildDocComment(token, i2);
|
|
2409
|
-
if (docComment) {
|
|
2410
|
-
lines.push(docComment);
|
|
2411
|
-
}
|
|
2412
|
-
lines.push(`${i2}${access} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
|
|
2413
|
-
}
|
|
2447
|
+
this.pushTokenDeclarations(lines, group.tokens, options, access, i2, staticPrefix);
|
|
2414
2448
|
lines.push(`${i1}}`);
|
|
2415
2449
|
lines.push("");
|
|
2416
2450
|
}
|
|
2417
2451
|
lines.push("}");
|
|
2418
|
-
lines.push(...this.buildViewExtensions(tokens, access, options));
|
|
2419
|
-
lines.push("");
|
|
2420
|
-
return lines.join("\n");
|
|
2421
2452
|
}
|
|
2422
|
-
|
|
2423
|
-
const access = options.accessLevel;
|
|
2453
|
+
pushGroupedLayout(lines, groups, options, access, i1, i2, staticPrefix, frozen) {
|
|
2424
2454
|
const namespace = options.extensionNamespace;
|
|
2425
|
-
const groups = this.groupTokensByType(tokens);
|
|
2426
|
-
const imports = this.collectImports(tokens);
|
|
2427
|
-
const i1 = this.indentStr(options.indent, 1);
|
|
2428
|
-
const i2 = this.indentStr(options.indent, 2);
|
|
2429
|
-
const staticPrefix = this.staticLetPrefix(options);
|
|
2430
|
-
const frozen = this.frozenPrefix(options);
|
|
2431
|
-
const lines = [];
|
|
2432
|
-
lines.push(this.buildFileHeader());
|
|
2433
|
-
lines.push("");
|
|
2434
|
-
for (const imp of imports) {
|
|
2435
|
-
lines.push(`import ${imp}`);
|
|
2436
|
-
}
|
|
2437
|
-
lines.push(...this.buildStructDefinitions(tokens, access, options));
|
|
2438
2455
|
lines.push("");
|
|
2439
2456
|
lines.push(`${frozen}${access} enum ${namespace} {}`);
|
|
2440
2457
|
lines.push("");
|
|
2441
2458
|
for (const group of groups) {
|
|
2442
2459
|
lines.push(`${access} extension ${namespace} {`);
|
|
2443
2460
|
lines.push(`${i1}${frozen}enum ${group.name} {`);
|
|
2444
|
-
|
|
2445
|
-
const swiftName = this.buildQualifiedSwiftName(token);
|
|
2446
|
-
const swiftValue = this.formatSwiftValue(token, options);
|
|
2447
|
-
const typeAnnotation = this.getTypeAnnotation(token);
|
|
2448
|
-
const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
|
|
2449
|
-
const docComment = this.buildDocComment(token, i2);
|
|
2450
|
-
if (docComment) {
|
|
2451
|
-
lines.push(docComment);
|
|
2452
|
-
}
|
|
2453
|
-
lines.push(`${i2}${access} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
|
|
2454
|
-
}
|
|
2461
|
+
this.pushTokenDeclarations(lines, group.tokens, options, access, i2, staticPrefix);
|
|
2455
2462
|
lines.push(`${i1}}`);
|
|
2456
2463
|
lines.push("}");
|
|
2457
2464
|
lines.push("");
|
|
2458
2465
|
}
|
|
2459
|
-
lines.push(...this.buildViewExtensions(tokens, access, options));
|
|
2460
|
-
return lines.join("\n");
|
|
2461
2466
|
}
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
+
pushTokenDeclarations(lines, tokens, options, access, indent, staticPrefix) {
|
|
2468
|
+
for (const token of tokens) {
|
|
2469
|
+
const swiftName = this.buildQualifiedSwiftName(token);
|
|
2470
|
+
const swiftValue = this.formatSwiftValue(token, options);
|
|
2471
|
+
const typeAnnotation = this.getTypeAnnotation(token);
|
|
2472
|
+
const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
|
|
2473
|
+
const docComment = this.buildDocComment(token, indent);
|
|
2474
|
+
if (docComment) {
|
|
2475
|
+
lines.push(docComment);
|
|
2476
|
+
}
|
|
2477
|
+
lines.push(`${indent}${access} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
|
|
2478
|
+
}
|
|
2467
2479
|
}
|
|
2468
2480
|
collectImports(tokens) {
|
|
2469
2481
|
const imports = /* @__PURE__ */ new Set();
|
|
@@ -2478,24 +2490,11 @@ var IosRenderer = class {
|
|
|
2478
2490
|
/**
|
|
2479
2491
|
* Builds a `///` doc comment from a token's `$description`, if present.
|
|
2480
2492
|
*/
|
|
2481
|
-
buildDocComment(token,
|
|
2493
|
+
buildDocComment(token, indent) {
|
|
2482
2494
|
if (!token.$description) {
|
|
2483
2495
|
return void 0;
|
|
2484
2496
|
}
|
|
2485
|
-
return `${
|
|
2486
|
-
}
|
|
2487
|
-
groupTokensByType(tokens) {
|
|
2488
|
-
const groupMap = /* @__PURE__ */ new Map();
|
|
2489
|
-
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
2490
|
-
const groupName = SWIFT_TYPE_GROUP_MAP[token.$type ?? ""] ?? "Other";
|
|
2491
|
-
const existing = groupMap.get(groupName) ?? [];
|
|
2492
|
-
existing.push(token);
|
|
2493
|
-
groupMap.set(groupName, existing);
|
|
2494
|
-
}
|
|
2495
|
-
return Array.from(groupMap.entries()).map(([name, groupTokens]) => ({
|
|
2496
|
-
name,
|
|
2497
|
-
tokens: groupTokens
|
|
2498
|
-
}));
|
|
2497
|
+
return `${indent}/// ${token.$description}`;
|
|
2499
2498
|
}
|
|
2500
2499
|
/**
|
|
2501
2500
|
* Builds a qualified Swift name from a token's path, preserving parent
|
|
@@ -2508,43 +2507,40 @@ var IosRenderer = class {
|
|
|
2508
2507
|
const path = token.path;
|
|
2509
2508
|
const withoutTypePrefix = path.length > 1 ? path.slice(1) : path;
|
|
2510
2509
|
const joined = withoutTypePrefix.join("_");
|
|
2511
|
-
return
|
|
2510
|
+
return toSafeIdentifier(joined, SWIFT_KEYWORDS, false);
|
|
2512
2511
|
}
|
|
2513
2512
|
formatSwiftValue(token, options) {
|
|
2514
|
-
const value = token
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
}
|
|
2542
|
-
if (token.$type === "number") {
|
|
2543
|
-
return String(value);
|
|
2544
|
-
}
|
|
2545
|
-
if (token.$type === "cubicBezier" && Array.isArray(value) && value.length === 4) {
|
|
2546
|
-
return `UnitCurve.bezier(startControlPoint: UnitPoint(x: ${value[0]}, y: ${value[1]}), endControlPoint: UnitPoint(x: ${value[2]}, y: ${value[3]}))`;
|
|
2513
|
+
const { $type, $value: value } = token;
|
|
2514
|
+
switch ($type) {
|
|
2515
|
+
case "color":
|
|
2516
|
+
return this.formatColorValue(value, options);
|
|
2517
|
+
case "dimension":
|
|
2518
|
+
return this.formatDimensionValue(value);
|
|
2519
|
+
case "fontFamily":
|
|
2520
|
+
return this.formatFontFamilyValue(value);
|
|
2521
|
+
case "fontWeight":
|
|
2522
|
+
return this.formatFontWeightValue(value);
|
|
2523
|
+
case "duration":
|
|
2524
|
+
return this.formatDurationValue(value);
|
|
2525
|
+
case "shadow":
|
|
2526
|
+
return this.formatShadowValue(value, options);
|
|
2527
|
+
case "typography":
|
|
2528
|
+
return this.formatTypographyValue(value);
|
|
2529
|
+
case "border":
|
|
2530
|
+
return this.formatBorderValue(value, options);
|
|
2531
|
+
case "gradient":
|
|
2532
|
+
return this.formatGradientValue(value, options);
|
|
2533
|
+
case "number":
|
|
2534
|
+
return String(value);
|
|
2535
|
+
case "cubicBezier":
|
|
2536
|
+
if (Array.isArray(value) && value.length === 4) {
|
|
2537
|
+
return `UnitCurve.bezier(startControlPoint: UnitPoint(x: ${value[0]}, y: ${value[1]}), endControlPoint: UnitPoint(x: ${value[2]}, y: ${value[3]}))`;
|
|
2538
|
+
}
|
|
2539
|
+
break;
|
|
2547
2540
|
}
|
|
2541
|
+
return this.formatSwiftPrimitive(value);
|
|
2542
|
+
}
|
|
2543
|
+
formatSwiftPrimitive(value) {
|
|
2548
2544
|
if (typeof value === "string") {
|
|
2549
2545
|
return `"${this.escapeSwiftString(value)}"`;
|
|
2550
2546
|
}
|
|
@@ -2577,9 +2573,7 @@ var IosRenderer = class {
|
|
|
2577
2573
|
}
|
|
2578
2574
|
formatDimensionValue(value) {
|
|
2579
2575
|
if (isDimensionObject(value)) {
|
|
2580
|
-
|
|
2581
|
-
const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
|
|
2582
|
-
return String(ptValue);
|
|
2576
|
+
return this.dimensionToPoints(value);
|
|
2583
2577
|
}
|
|
2584
2578
|
return String(value);
|
|
2585
2579
|
}
|
|
@@ -2646,7 +2640,7 @@ var IosRenderer = class {
|
|
|
2646
2640
|
return map[name.toLowerCase()];
|
|
2647
2641
|
}
|
|
2648
2642
|
formatDurationValue(value) {
|
|
2649
|
-
if (
|
|
2643
|
+
if (isDurationObject(value)) {
|
|
2650
2644
|
const dur = value;
|
|
2651
2645
|
const seconds = dur.unit === "ms" ? dur.value / 1e3 : dur.value;
|
|
2652
2646
|
return String(seconds);
|
|
@@ -2695,9 +2689,7 @@ var IosRenderer = class {
|
|
|
2695
2689
|
if (!isDimensionObject(typo.letterSpacing)) {
|
|
2696
2690
|
return "0";
|
|
2697
2691
|
}
|
|
2698
|
-
|
|
2699
|
-
const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
|
|
2700
|
-
return String(ptValue);
|
|
2692
|
+
return this.dimensionToPoints(typo.letterSpacing);
|
|
2701
2693
|
}
|
|
2702
2694
|
extractLineSpacing(typo) {
|
|
2703
2695
|
if (typo.lineHeight == null || typeof typo.lineHeight !== "number") {
|
|
@@ -2706,18 +2698,19 @@ var IosRenderer = class {
|
|
|
2706
2698
|
if (!isDimensionObject(typo.fontSize)) {
|
|
2707
2699
|
return "0";
|
|
2708
2700
|
}
|
|
2709
|
-
const
|
|
2710
|
-
const basePt = dim.unit === "rem" ? dim.value * 16 : dim.value;
|
|
2701
|
+
const basePt = this.dimensionToNumericPoints(typo.fontSize);
|
|
2711
2702
|
const lineHeightPt = Math.round(basePt * typo.lineHeight * 100) / 100;
|
|
2712
2703
|
return String(lineHeightPt - basePt);
|
|
2713
2704
|
}
|
|
2705
|
+
dimensionToNumericPoints(dim) {
|
|
2706
|
+
return dim.unit === "rem" ? dim.value * 16 : dim.value;
|
|
2707
|
+
}
|
|
2714
2708
|
dimensionToPoints(dim) {
|
|
2715
|
-
|
|
2716
|
-
return String(ptValue);
|
|
2709
|
+
return String(this.dimensionToNumericPoints(dim));
|
|
2717
2710
|
}
|
|
2718
2711
|
/** Formats a dimension as a CGFloat literal (appends `.0` for integers). */
|
|
2719
2712
|
dimensionToCGFloat(dim) {
|
|
2720
|
-
const ptValue =
|
|
2713
|
+
const ptValue = this.dimensionToNumericPoints(dim);
|
|
2721
2714
|
return Number.isInteger(ptValue) ? `${ptValue}.0` : String(ptValue);
|
|
2722
2715
|
}
|
|
2723
2716
|
getTypeAnnotation(token) {
|
|
@@ -2736,21 +2729,12 @@ var IosRenderer = class {
|
|
|
2736
2729
|
return void 0;
|
|
2737
2730
|
}
|
|
2738
2731
|
}
|
|
2739
|
-
toSwiftIdentifier(name) {
|
|
2740
|
-
const camel = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
|
|
2741
|
-
const identifier = camel.charAt(0).toLowerCase() + camel.slice(1);
|
|
2742
|
-
const safe = /^\d/.test(identifier) ? `_${identifier}` : identifier;
|
|
2743
|
-
return SWIFT_KEYWORDS.has(safe) ? `\`${safe}\`` : safe;
|
|
2744
|
-
}
|
|
2745
2732
|
escapeSwiftString(str) {
|
|
2746
2733
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
2747
2734
|
}
|
|
2748
2735
|
roundComponent(value) {
|
|
2749
2736
|
return Math.round(value * 1e4) / 1e4;
|
|
2750
2737
|
}
|
|
2751
|
-
indentStr(width, level) {
|
|
2752
|
-
return " ".repeat(width * level);
|
|
2753
|
-
}
|
|
2754
2738
|
/**
|
|
2755
2739
|
* Returns the prefix for `static let` declarations.
|
|
2756
2740
|
* Swift 6 requires `nonisolated(unsafe)` on global stored properties.
|
|
@@ -2766,34 +2750,25 @@ var IosRenderer = class {
|
|
|
2766
2750
|
structConformances(options) {
|
|
2767
2751
|
return options.swiftVersion === "6.0" ? ": Sendable" : "";
|
|
2768
2752
|
}
|
|
2769
|
-
hasShadowTokens(tokens) {
|
|
2770
|
-
return Object.values(tokens).some((t) => t.$type === "shadow");
|
|
2771
|
-
}
|
|
2772
|
-
hasTypographyTokens(tokens) {
|
|
2773
|
-
return Object.values(tokens).some((t) => t.$type === "typography");
|
|
2774
|
-
}
|
|
2775
|
-
hasBorderTokens(tokens) {
|
|
2776
|
-
return Object.values(tokens).some((t) => t.$type === "border");
|
|
2777
|
-
}
|
|
2778
2753
|
/** Emits all struct definitions needed by the token set. */
|
|
2779
2754
|
buildStructDefinitions(tokens, access, options) {
|
|
2780
2755
|
const lines = [];
|
|
2781
|
-
if (
|
|
2756
|
+
if (Object.values(tokens).some(isShadowToken)) {
|
|
2782
2757
|
lines.push("");
|
|
2783
2758
|
lines.push(...this.buildShadowStyleStruct(access, options));
|
|
2784
2759
|
}
|
|
2785
|
-
if (
|
|
2760
|
+
if (Object.values(tokens).some(isTypographyToken)) {
|
|
2786
2761
|
lines.push("");
|
|
2787
2762
|
lines.push(...this.buildTypographyStyleStruct(access, options));
|
|
2788
2763
|
}
|
|
2789
|
-
if (
|
|
2764
|
+
if (Object.values(tokens).some(isBorderToken)) {
|
|
2790
2765
|
lines.push("");
|
|
2791
2766
|
lines.push(...this.buildBorderStyleStruct(access, options));
|
|
2792
2767
|
}
|
|
2793
2768
|
return lines;
|
|
2794
2769
|
}
|
|
2795
2770
|
buildShadowStyleStruct(access, options) {
|
|
2796
|
-
const i1 =
|
|
2771
|
+
const i1 = indentStr(options.indent, 1);
|
|
2797
2772
|
const conformances = this.structConformances(options);
|
|
2798
2773
|
const frozen = this.frozenPrefix(options);
|
|
2799
2774
|
return [
|
|
@@ -2807,7 +2782,7 @@ var IosRenderer = class {
|
|
|
2807
2782
|
];
|
|
2808
2783
|
}
|
|
2809
2784
|
buildTypographyStyleStruct(access, options) {
|
|
2810
|
-
const i1 =
|
|
2785
|
+
const i1 = indentStr(options.indent, 1);
|
|
2811
2786
|
const conformances = this.structConformances(options);
|
|
2812
2787
|
const frozen = this.frozenPrefix(options);
|
|
2813
2788
|
return [
|
|
@@ -2819,7 +2794,7 @@ var IosRenderer = class {
|
|
|
2819
2794
|
];
|
|
2820
2795
|
}
|
|
2821
2796
|
buildBorderStyleStruct(access, options) {
|
|
2822
|
-
const i1 =
|
|
2797
|
+
const i1 = indentStr(options.indent, 1);
|
|
2823
2798
|
const conformances = this.structConformances(options);
|
|
2824
2799
|
const frozen = this.frozenPrefix(options);
|
|
2825
2800
|
return [
|
|
@@ -2832,9 +2807,9 @@ var IosRenderer = class {
|
|
|
2832
2807
|
/** Emits convenience View extensions for shadow and typography application. */
|
|
2833
2808
|
buildViewExtensions(tokens, access, options) {
|
|
2834
2809
|
const lines = [];
|
|
2835
|
-
const i1 =
|
|
2836
|
-
const i2 =
|
|
2837
|
-
if (
|
|
2810
|
+
const i1 = indentStr(options.indent, 1);
|
|
2811
|
+
const i2 = indentStr(options.indent, 2);
|
|
2812
|
+
if (Object.values(tokens).some(isShadowToken)) {
|
|
2838
2813
|
lines.push("");
|
|
2839
2814
|
lines.push(`${access} extension View {`);
|
|
2840
2815
|
lines.push(`${i1}func shadowStyle(_ style: ShadowStyle) -> some View {`);
|
|
@@ -2844,7 +2819,7 @@ var IosRenderer = class {
|
|
|
2844
2819
|
lines.push(`${i1}}`);
|
|
2845
2820
|
lines.push("}");
|
|
2846
2821
|
}
|
|
2847
|
-
if (
|
|
2822
|
+
if (Object.values(tokens).some(isTypographyToken)) {
|
|
2848
2823
|
lines.push("");
|
|
2849
2824
|
lines.push(`${access} extension View {`);
|
|
2850
2825
|
lines.push(`${i1}func typographyStyle(_ style: TypographyStyle) -> some View {`);
|
|
@@ -2876,12 +2851,12 @@ var IosRenderer = class {
|
|
|
2876
2851
|
return `Gradient(stops: [${stops.join(", ")}])`;
|
|
2877
2852
|
}
|
|
2878
2853
|
async formatStandalone(context, options) {
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2854
|
+
assertFileRequired(
|
|
2855
|
+
context.buildPath,
|
|
2856
|
+
context.output.file,
|
|
2857
|
+
context.output.name,
|
|
2858
|
+
"standalone iOS"
|
|
2859
|
+
);
|
|
2885
2860
|
const files = {};
|
|
2886
2861
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
2887
2862
|
const processedTokens = stripInternalMetadata(tokens);
|
|
@@ -2910,7 +2885,6 @@ function iosRenderer() {
|
|
|
2910
2885
|
|
|
2911
2886
|
// src/renderers/js-module.ts
|
|
2912
2887
|
init_utils();
|
|
2913
|
-
init_errors();
|
|
2914
2888
|
init_token_utils();
|
|
2915
2889
|
var JsModuleRenderer = class {
|
|
2916
2890
|
async format(context, options) {
|
|
@@ -2926,18 +2900,13 @@ var JsModuleRenderer = class {
|
|
|
2926
2900
|
const bundleData = context.permutations.map(({ tokens, modifierInputs }) => ({
|
|
2927
2901
|
tokens: stripInternalMetadata(tokens),
|
|
2928
2902
|
modifierInputs,
|
|
2929
|
-
isBase:
|
|
2903
|
+
isBase: isBasePermutation(modifierInputs, context.meta.defaults)
|
|
2930
2904
|
}));
|
|
2931
2905
|
return await bundleAsJsModule2(bundleData, context.resolver, opts, async (tokens) => {
|
|
2932
2906
|
return await this.formatTokens(tokens, opts);
|
|
2933
2907
|
});
|
|
2934
2908
|
}
|
|
2935
|
-
|
|
2936
|
-
if (!context.output.file && requiresFile) {
|
|
2937
|
-
throw new ConfigurationError(
|
|
2938
|
-
`Output "${context.output.name}": file is required for JS module output`
|
|
2939
|
-
);
|
|
2940
|
-
}
|
|
2909
|
+
assertFileRequired(context.buildPath, context.output.file, context.output.name, "JS module");
|
|
2941
2910
|
const files = {};
|
|
2942
2911
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
2943
2912
|
const cleanTokens = stripInternalMetadata(tokens);
|
|
@@ -2991,42 +2960,18 @@ var JsModuleRenderer = class {
|
|
|
2991
2960
|
lines.push(`export default ${varName}`);
|
|
2992
2961
|
return lines;
|
|
2993
2962
|
}
|
|
2994
|
-
/**
|
|
2995
|
-
* Convert tokens to plain object with flat or nested structure
|
|
2996
|
-
*/
|
|
2997
2963
|
tokensToPlainObject(tokens, structure) {
|
|
2964
|
+
if (structure === "nested") {
|
|
2965
|
+
return buildNestedTokenObject(tokens, (token) => token.$value);
|
|
2966
|
+
}
|
|
2998
2967
|
const result = {};
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
result[name] = token.$value;
|
|
3002
|
-
}
|
|
3003
|
-
} else {
|
|
3004
|
-
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
3005
|
-
const parts = token.path;
|
|
3006
|
-
let current = result;
|
|
3007
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3008
|
-
const part = parts[i];
|
|
3009
|
-
if (part == null) {
|
|
3010
|
-
continue;
|
|
3011
|
-
}
|
|
3012
|
-
if (!(part in current)) {
|
|
3013
|
-
current[part] = {};
|
|
3014
|
-
}
|
|
3015
|
-
current = current[part];
|
|
3016
|
-
}
|
|
3017
|
-
const lastPart = parts[parts.length - 1];
|
|
3018
|
-
if (lastPart != null) {
|
|
3019
|
-
current[lastPart] = token.$value;
|
|
3020
|
-
}
|
|
3021
|
-
}
|
|
2968
|
+
for (const [name, token] of getSortedTokenEntries(tokens)) {
|
|
2969
|
+
result[name] = token.$value;
|
|
3022
2970
|
}
|
|
3023
2971
|
return result;
|
|
3024
2972
|
}
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
*/
|
|
3028
|
-
addObjectProperties(lines, obj, indent2) {
|
|
3029
|
-
const indentStr = " ".repeat(indent2);
|
|
2973
|
+
addObjectProperties(lines, obj, indent) {
|
|
2974
|
+
const indentStr2 = " ".repeat(indent);
|
|
3030
2975
|
const entries = Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
|
|
3031
2976
|
for (let i = 0; i < entries.length; i++) {
|
|
3032
2977
|
const entry = entries[i];
|
|
@@ -3035,14 +2980,16 @@ var JsModuleRenderer = class {
|
|
|
3035
2980
|
}
|
|
3036
2981
|
const [key, value] = entry;
|
|
3037
2982
|
const isLast = i === entries.length - 1;
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
lines.push(`${indentStr}${this.quoteKey(key)}: ${valueStr}${isLast ? "" : ","}`);
|
|
2983
|
+
const isNestedObject = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2984
|
+
if (!isNestedObject) {
|
|
2985
|
+
lines.push(
|
|
2986
|
+
`${indentStr2}${this.quoteKey(key)}: ${JSON.stringify(value)}${isLast ? "" : ","}`
|
|
2987
|
+
);
|
|
2988
|
+
continue;
|
|
3045
2989
|
}
|
|
2990
|
+
lines.push(`${indentStr2}${this.quoteKey(key)}: {`);
|
|
2991
|
+
this.addObjectProperties(lines, value, indent + 1);
|
|
2992
|
+
lines.push(`${indentStr2}}${isLast ? "" : ","}`);
|
|
3046
2993
|
}
|
|
3047
2994
|
}
|
|
3048
2995
|
/**
|
|
@@ -3054,9 +3001,6 @@ var JsModuleRenderer = class {
|
|
|
3054
3001
|
}
|
|
3055
3002
|
return `"${key}"`;
|
|
3056
3003
|
}
|
|
3057
|
-
isBasePermutation(modifierInputs, defaults) {
|
|
3058
|
-
return Object.entries(modifierInputs).every(([key, value]) => value === defaults[key]);
|
|
3059
|
-
}
|
|
3060
3004
|
};
|
|
3061
3005
|
function jsRenderer() {
|
|
3062
3006
|
const rendererInstance = new JsModuleRenderer();
|
|
@@ -3070,7 +3014,6 @@ function jsRenderer() {
|
|
|
3070
3014
|
|
|
3071
3015
|
// src/renderers/json.ts
|
|
3072
3016
|
init_utils();
|
|
3073
|
-
init_errors();
|
|
3074
3017
|
init_token_utils();
|
|
3075
3018
|
var JsonRenderer = class {
|
|
3076
3019
|
async format(context, options) {
|
|
@@ -3085,18 +3028,13 @@ var JsonRenderer = class {
|
|
|
3085
3028
|
const bundleData = context.permutations.map(({ tokens, modifierInputs }) => ({
|
|
3086
3029
|
tokens: stripInternalMetadata(tokens),
|
|
3087
3030
|
modifierInputs,
|
|
3088
|
-
isBase:
|
|
3031
|
+
isBase: isBasePermutation(modifierInputs, context.meta.defaults)
|
|
3089
3032
|
}));
|
|
3090
3033
|
return await bundleAsJson2(bundleData, context.resolver, async (tokens) => {
|
|
3091
3034
|
return await this.formatTokens(tokens, opts);
|
|
3092
3035
|
});
|
|
3093
3036
|
}
|
|
3094
|
-
|
|
3095
|
-
if (!context.output.file && requiresFile) {
|
|
3096
|
-
throw new ConfigurationError(
|
|
3097
|
-
`Output "${context.output.name}": file is required for JSON output`
|
|
3098
|
-
);
|
|
3099
|
-
}
|
|
3037
|
+
assertFileRequired(context.buildPath, context.output.file, context.output.name, "JSON");
|
|
3100
3038
|
const files = {};
|
|
3101
3039
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
3102
3040
|
const processedTokens = stripInternalMetadata(tokens);
|
|
@@ -3156,55 +3094,11 @@ var JsonRenderer = class {
|
|
|
3156
3094
|
}
|
|
3157
3095
|
return result;
|
|
3158
3096
|
}
|
|
3159
|
-
/**
|
|
3160
|
-
* Nest tokens by path (values only)
|
|
3161
|
-
*/
|
|
3162
3097
|
nestValues(tokens) {
|
|
3163
|
-
|
|
3164
|
-
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
3165
|
-
const parts = token.path;
|
|
3166
|
-
let current = result;
|
|
3167
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3168
|
-
const part = parts[i];
|
|
3169
|
-
if (part === null || part === void 0) {
|
|
3170
|
-
continue;
|
|
3171
|
-
}
|
|
3172
|
-
if (!(part in current)) {
|
|
3173
|
-
current[part] = {};
|
|
3174
|
-
}
|
|
3175
|
-
current = current[part];
|
|
3176
|
-
}
|
|
3177
|
-
const lastPart = parts[parts.length - 1];
|
|
3178
|
-
if (lastPart !== null && lastPart !== void 0) {
|
|
3179
|
-
current[lastPart] = token.$value;
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
return result;
|
|
3098
|
+
return buildNestedTokenObject(tokens, (token) => token.$value);
|
|
3183
3099
|
}
|
|
3184
|
-
/**
|
|
3185
|
-
* Nest tokens by path (with metadata)
|
|
3186
|
-
*/
|
|
3187
3100
|
nestTokens(tokens) {
|
|
3188
|
-
|
|
3189
|
-
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
3190
|
-
const parts = token.path;
|
|
3191
|
-
let current = result;
|
|
3192
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3193
|
-
const part = parts[i];
|
|
3194
|
-
if (part === null || part === void 0) {
|
|
3195
|
-
continue;
|
|
3196
|
-
}
|
|
3197
|
-
if (!(part in current)) {
|
|
3198
|
-
current[part] = {};
|
|
3199
|
-
}
|
|
3200
|
-
current = current[part];
|
|
3201
|
-
}
|
|
3202
|
-
const lastPart = parts[parts.length - 1];
|
|
3203
|
-
if (lastPart !== null && lastPart !== void 0) {
|
|
3204
|
-
current[lastPart] = this.serializeToken(token);
|
|
3205
|
-
}
|
|
3206
|
-
}
|
|
3207
|
-
return result;
|
|
3101
|
+
return buildNestedTokenObject(tokens, (token) => this.serializeToken(token));
|
|
3208
3102
|
}
|
|
3209
3103
|
serializeToken(token) {
|
|
3210
3104
|
return {
|
|
@@ -3215,9 +3109,6 @@ var JsonRenderer = class {
|
|
|
3215
3109
|
...token.$extensions != null && { $extensions: token.$extensions }
|
|
3216
3110
|
};
|
|
3217
3111
|
}
|
|
3218
|
-
isBasePermutation(modifierInputs, defaults) {
|
|
3219
|
-
return Object.entries(modifierInputs).every(([key, value]) => value === defaults[key]);
|
|
3220
|
-
}
|
|
3221
3112
|
};
|
|
3222
3113
|
function jsonRenderer() {
|
|
3223
3114
|
const rendererInstance = new JsonRenderer();
|
|
@@ -3230,7 +3121,6 @@ function jsonRenderer() {
|
|
|
3230
3121
|
}
|
|
3231
3122
|
|
|
3232
3123
|
// src/renderers/tailwind.ts
|
|
3233
|
-
init_errors();
|
|
3234
3124
|
init_token_utils();
|
|
3235
3125
|
|
|
3236
3126
|
// src/renderers/bundlers/tailwind.ts
|
|
@@ -3259,6 +3149,13 @@ async function bundleAsTailwind(bundleData, options, formatThemeTokens, formatOv
|
|
|
3259
3149
|
}
|
|
3260
3150
|
return cssBlocks.join("\n");
|
|
3261
3151
|
}
|
|
3152
|
+
function resolveModifierSelectorAndMedia(options, modifier, context, modifierInputs) {
|
|
3153
|
+
const normalized = normalizeModifierInputs(modifierInputs);
|
|
3154
|
+
return {
|
|
3155
|
+
selector: resolveSelector(options.selector, modifier, context, false, normalized),
|
|
3156
|
+
mediaQuery: resolveMediaQuery(options.mediaQuery, modifier, context, false, normalized)
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3262
3159
|
async function formatModifierOverride({ tokens, modifierInputs }, baseItem, options, formatOverrideBlock) {
|
|
3263
3160
|
const differenceCount = countModifierDifferences(modifierInputs, baseItem.modifierInputs);
|
|
3264
3161
|
if (differenceCount > 1) {
|
|
@@ -3271,19 +3168,11 @@ async function formatModifierOverride({ tokens, modifierInputs }, baseItem, opti
|
|
|
3271
3168
|
const expectedSource = getExpectedSource(modifierInputs, baseItem.modifierInputs);
|
|
3272
3169
|
const [modifier, context] = parseModifierSource(expectedSource);
|
|
3273
3170
|
const cleanTokens = stripInternalMetadata(tokensToInclude);
|
|
3274
|
-
const selector =
|
|
3275
|
-
options
|
|
3276
|
-
modifier,
|
|
3277
|
-
context,
|
|
3278
|
-
false,
|
|
3279
|
-
normalizeModifierInputs(modifierInputs)
|
|
3280
|
-
);
|
|
3281
|
-
const mediaQuery = resolveMediaQuery(
|
|
3282
|
-
options.mediaQuery,
|
|
3171
|
+
const { selector, mediaQuery } = resolveModifierSelectorAndMedia(
|
|
3172
|
+
options,
|
|
3283
3173
|
modifier,
|
|
3284
3174
|
context,
|
|
3285
|
-
|
|
3286
|
-
normalizeModifierInputs(modifierInputs)
|
|
3175
|
+
modifierInputs
|
|
3287
3176
|
);
|
|
3288
3177
|
const css2 = await formatOverrideBlock(cleanTokens, selector, mediaQuery, options.minify);
|
|
3289
3178
|
return `/* Modifier: ${modifier}=${context} */
|
|
@@ -3372,7 +3261,7 @@ var TailwindRenderer = class {
|
|
|
3372
3261
|
*/
|
|
3373
3262
|
async formatTokens(tokens, options) {
|
|
3374
3263
|
const lines = [];
|
|
3375
|
-
const
|
|
3264
|
+
const indent = options.minify ? "" : " ";
|
|
3376
3265
|
const newline = options.minify ? "" : "\n";
|
|
3377
3266
|
const space = options.minify ? "" : " ";
|
|
3378
3267
|
if (options.includeImport) {
|
|
@@ -3394,7 +3283,7 @@ var TailwindRenderer = class {
|
|
|
3394
3283
|
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
3395
3284
|
const varName = this.buildVariableName(token);
|
|
3396
3285
|
const varValue = this.formatValue(token);
|
|
3397
|
-
lines.push(`${
|
|
3286
|
+
lines.push(`${indent}--${varName}:${space}${varValue};${newline}`);
|
|
3398
3287
|
}
|
|
3399
3288
|
lines.push(`}${newline}`);
|
|
3400
3289
|
const cssString = lines.join("");
|
|
@@ -3405,15 +3294,15 @@ var TailwindRenderer = class {
|
|
|
3405
3294
|
* Used for modifier overrides (e.g., dark mode) appended after the @theme block.
|
|
3406
3295
|
*/
|
|
3407
3296
|
async formatOverrideBlock(tokens, selector, mediaQuery, minify) {
|
|
3408
|
-
const
|
|
3297
|
+
const indent = minify ? "" : " ";
|
|
3409
3298
|
const newline = minify ? "" : "\n";
|
|
3410
3299
|
const space = minify ? "" : " ";
|
|
3411
3300
|
const hasMediaQuery = mediaQuery !== "";
|
|
3412
|
-
const tokenIndent = hasMediaQuery ?
|
|
3301
|
+
const tokenIndent = hasMediaQuery ? indent + indent : indent;
|
|
3413
3302
|
const lines = [];
|
|
3414
3303
|
if (hasMediaQuery) {
|
|
3415
3304
|
lines.push(`@media ${mediaQuery}${space}{${newline}`);
|
|
3416
|
-
lines.push(`${
|
|
3305
|
+
lines.push(`${indent}${selector}${space}{${newline}`);
|
|
3417
3306
|
} else {
|
|
3418
3307
|
lines.push(`${selector}${space}{${newline}`);
|
|
3419
3308
|
}
|
|
@@ -3423,7 +3312,7 @@ var TailwindRenderer = class {
|
|
|
3423
3312
|
lines.push(`${tokenIndent}--${varName}:${space}${varValue};${newline}`);
|
|
3424
3313
|
}
|
|
3425
3314
|
if (hasMediaQuery) {
|
|
3426
|
-
lines.push(`${
|
|
3315
|
+
lines.push(`${indent}}${newline}`);
|
|
3427
3316
|
lines.push(`}${newline}`);
|
|
3428
3317
|
} else {
|
|
3429
3318
|
lines.push(`}${newline}`);
|
|
@@ -3450,8 +3339,8 @@ var TailwindRenderer = class {
|
|
|
3450
3339
|
if (token.$type === "dimension" && isDimensionObject(value)) {
|
|
3451
3340
|
return dimensionObjectToString(value);
|
|
3452
3341
|
}
|
|
3453
|
-
if (token.$type === "duration" &&
|
|
3454
|
-
return
|
|
3342
|
+
if (token.$type === "duration" && isDurationObject(value)) {
|
|
3343
|
+
return durationObjectToString(value);
|
|
3455
3344
|
}
|
|
3456
3345
|
if (token.$type === "fontFamily") {
|
|
3457
3346
|
if (Array.isArray(value)) {
|
|
@@ -3506,9 +3395,6 @@ var TailwindRenderer = class {
|
|
|
3506
3395
|
}
|
|
3507
3396
|
return parts.join(" ");
|
|
3508
3397
|
}
|
|
3509
|
-
isDurationObject(value) {
|
|
3510
|
-
return typeof value === "object" && value !== null && "value" in value && "unit" in value && value.unit !== void 0;
|
|
3511
|
-
}
|
|
3512
3398
|
async formatWithPrettier(css2) {
|
|
3513
3399
|
try {
|
|
3514
3400
|
return await prettier__default.default.format(css2, {
|
|
@@ -3525,7 +3411,7 @@ var TailwindRenderer = class {
|
|
|
3525
3411
|
const bundleData = context.permutations.map(({ tokens, modifierInputs }) => ({
|
|
3526
3412
|
tokens,
|
|
3527
3413
|
modifierInputs,
|
|
3528
|
-
isBase:
|
|
3414
|
+
isBase: isBasePermutation(modifierInputs, context.meta.defaults)
|
|
3529
3415
|
}));
|
|
3530
3416
|
return await bundleAsTailwind(
|
|
3531
3417
|
bundleData,
|
|
@@ -3535,12 +3421,12 @@ var TailwindRenderer = class {
|
|
|
3535
3421
|
);
|
|
3536
3422
|
}
|
|
3537
3423
|
async formatStandalone(context, options) {
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3424
|
+
assertFileRequired(
|
|
3425
|
+
context.buildPath,
|
|
3426
|
+
context.output.file,
|
|
3427
|
+
context.output.name,
|
|
3428
|
+
"standalone Tailwind"
|
|
3429
|
+
);
|
|
3544
3430
|
const files = {};
|
|
3545
3431
|
for (const { tokens, modifierInputs } of context.permutations) {
|
|
3546
3432
|
const processedTokens = stripInternalMetadata(tokens);
|
|
@@ -3556,11 +3442,6 @@ var TailwindRenderer = class {
|
|
|
3556
3442
|
}
|
|
3557
3443
|
return outputTree(files);
|
|
3558
3444
|
}
|
|
3559
|
-
isBasePermutation(modifierInputs, defaults) {
|
|
3560
|
-
return Object.entries(defaults).every(
|
|
3561
|
-
([key, value]) => modifierInputs[key]?.toLowerCase() === value.toLowerCase()
|
|
3562
|
-
);
|
|
3563
|
-
}
|
|
3564
3445
|
};
|
|
3565
3446
|
function tailwindRenderer() {
|
|
3566
3447
|
const rendererInstance = new TailwindRenderer();
|
|
@@ -3588,7 +3469,7 @@ function css(config) {
|
|
|
3588
3469
|
file,
|
|
3589
3470
|
renderer: cssRenderer(),
|
|
3590
3471
|
options: { preset, ...rendererOptions },
|
|
3591
|
-
transforms,
|
|
3472
|
+
transforms: [nameKebabCase(), ...transforms ?? []],
|
|
3592
3473
|
filters,
|
|
3593
3474
|
hooks
|
|
3594
3475
|
};
|