Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 50x 26x 2x 59x 4x 3x 57x 41x 41x 41x 19x 18x 18x 11x 19x 19x 8x 8x 3x 3x 1x 1x 2x 40x 40x 43x 43x 13x 43x | /**
* Shared utilities for parsing Android (Kotlin) and iOS (Swift) color token files.
* Both platforms follow the same structural pattern: a class/object declaration
* establishes the current light/dark mode, then individual token lines are either
* direct hex values or references to other tokens.
*/
import { MODE } from './color-utils.js';
/**
* Determine MODE.LIGHT / MODE.DARK from a class or object name, or null if indeterminate.
* @param {string} className
* @returns {string|null}
*/
export function classNameToMode(className) {
if (className.includes('Light')) return MODE.LIGHT;
if (className.includes('Dark')) return MODE.DARK;
return null;
}
/**
* If the token belongs to a palette class, prefix it with 'palette' so that
* platform-specific normalizers can produce the correct CSS token name.
* @param {string} tokenName - raw property name from the source file
* @param {string|null} currentClass - class/object name currently being parsed
* @param {RegExp} paletteClassRe - regex that matches a palette class name
* @returns {string}
*/
export function resolvePaletteTokenName(tokenName, currentClass, paletteClassRe) {
if (!currentClass?.includes('Palette')) return tokenName;
if (!paletteClassRe.exec(currentClass)) return tokenName;
return `palette${tokenName.charAt(0).toUpperCase() + tokenName.slice(1)}`;
}
/**
* Store a directly-resolved color into both the staging directColors map and the output colors map.
* @param {Map<string, string>} directColors - staging map keyed as `tokenName-mode`
* @param {Map<string, string>} colors - output map
* @param {string} fullTokenName
* @param {string} hexValue
* @param {string|null} mode
* @param {(name: string) => string} normalizeTokenName
*/
export function storeDirectToken(directColors, colors, fullTokenName, hexValue, mode, normalizeTokenName) {
if (!mode) return;
directColors.set(`${fullTokenName}-${mode}`, hexValue);
const standardName = normalizeTokenName(fullTokenName);
Eif (standardName) colors.set(`${standardName}-${mode}`, hexValue);
}
/**
* Attempt to resolve one reference assignment into a concrete hex value.
* Returns true if the token was newly added to `colors`.
* @param {{ tokenName: string, refProperty: string, mode: string|null, refMode?: string|null }} assignment
* @param {Map<string, string>} directColors
* @param {Map<string, string>} colors
* @param {(name: string) => string} normalizeTokenName
* @returns {boolean}
*/
export function tryResolveAssignment(
{ tokenName, refProperty, mode, refMode },
directColors,
colors,
normalizeTokenName,
) {
if (!mode) return false;
const standardName = `${normalizeTokenName(tokenName)}-${mode}`;
if (colors.has(standardName)) return false;
const lookupMode = refMode ?? mode;
const refHex = directColors.get(`${refProperty}-${lookupMode}`);
if (refHex) {
colors.set(standardName, refHex);
return true;
}
const resolvedRefValue = colors.get(`${normalizeTokenName(refProperty)}-${lookupMode}`);
if (resolvedRefValue) {
colors.set(standardName, resolvedRefValue);
return true;
}
return false;
}
/**
* Iteratively resolve reference assignments until no new tokens can be resolved
* or the maximum iteration limit is reached (prevents infinite loops on circular refs).
* @param {Array<{tokenName: string, refProperty: string, mode: string|null, refMode?: string|null}>} assignments
* @param {Map<string, string>} directColors
* @param {Map<string, string>} colors - mutated in place
* @param {(name: string) => string} normalizeTokenName
*/
export function resolveReferences(assignments, directColors, colors, normalizeTokenName) {
let maxIterations = 10;
let resolvedCount;
do {
resolvedCount = 0;
for (const assignment of assignments) {
if (tryResolveAssignment(assignment, directColors, colors, normalizeTokenName)) resolvedCount++;
}
maxIterations--;
} while (resolvedCount > 0 && maxIterations > 0);
}
|