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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 25x 25x 127x 127x 52x 52x 52x 52x 52x 25x 49x 40x 40x 9x 9x 9x 9x 7x 7x 7x 7x 32x 32x 4x 4x 3x 34x 34x 2x 2x 2x 2x 2x 2x 2x 32x 30x 30x 25x 25x 25x 39x 38x 4x 34x 25x | /**
* Parser for SLDS CSS custom property files.
* Extracts color tokens from --slds-g-color-* and --slds-r-color-* properties,
* resolves var() references and light-dark() functions, and outputs normalized hex values.
*/
import { MODE, normalizeHex, toHex, parseLightDarkFunction } from './color-utils.js';
/**
* Scan CSS lines and collect all --slds-g-* and --slds-r-* custom properties.
* @param {string[]} lines
* @returns {Map<string, string>}
*/
function parseCssProperties(lines) {
const props = new Map();
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed.startsWith('--slds-g-') && !trimmed.startsWith('--slds-r-')) continue;
const colonIdx = trimmed.indexOf(':');
Iif (colonIdx === -1) continue;
const semiIdx = trimmed.indexOf(';', colonIdx);
Iif (semiIdx === -1) continue;
props.set(trimmed.substring(0, colonIdx).trim(), trimmed.substring(colonIdx + 1, semiIdx).trim());
}
return props;
}
/**
* Recursively resolve a CSS var() reference to a concrete value.
* Handles light-dark() extraction when a mode is specified.
* @param {string} value
* @param {Map<string, string>} allProperties
* @param {Set<string>} visited - tracks visited refs to prevent infinite loops
* @param {string|null} mode - MODE.LIGHT | MODE.DARK | null
* @returns {string}
*/
function resolveVar(value, allProperties, visited = new Set(), mode = null) {
if (!value.startsWith('var(')) {
Iif (mode && value.includes('light-dark(')) {
const parsed = parseLightDarkFunction(value);
if (parsed) return mode === MODE.LIGHT ? parsed.lightValue : parsed.darkValue;
}
return value;
}
const varEnd = value.indexOf(')', value.indexOf('var('));
Iif (varEnd === -1) return value;
const refName = value
.substring(value.indexOf('var(') + 4, varEnd)
.split(',')[0]
.trim();
if (visited.has(refName)) return value;
const refValue = allProperties.get(refName);
Iif (!refValue) return value;
visited.add(refName);
return resolveVar(refValue, allProperties, visited, mode);
}
/** Store a hex color under both -light and -dark suffixed keys. */
function setLightDark(colors, tokenName, hex) {
colors.set(`${tokenName}-${MODE.LIGHT}`, hex);
colors.set(`${tokenName}-${MODE.DARK}`, hex);
}
/**
* Process a --slds-r-color-* reference token: resolve to a direct hex value
* (reference tokens don't use light-dark(), same value for both modes).
*/
function processReferenceToken(colors, tokenName, value, allProperties) {
const resolvedHex = resolveVar(value, allProperties, new Set(), null);
if (resolvedHex && /^#[0-9a-f]{6}$/i.test(resolvedHex)) {
setLightDark(colors, tokenName, normalizeHex(resolvedHex));
}
}
/**
* Process a --slds-g-color-* global token: handles both light-dark() semantic
* tokens (produces separate light/dark entries) and single static values.
*/
function processGlobalToken(colors, tokenName, value, allProperties) {
const resolvedValue = resolveVar(value, allProperties);
if (resolvedValue.includes('light-dark(')) {
const parsed = parseLightDarkFunction(resolvedValue);
Iif (!parsed) return;
const lightHex = toHex(resolveVar(parsed.lightValue, allProperties, new Set(), MODE.LIGHT));
const darkHex = toHex(resolveVar(parsed.darkValue, allProperties, new Set(), MODE.DARK));
Eif (lightHex) colors.set(`${tokenName}-${MODE.LIGHT}`, lightHex);
Eif (darkHex) colors.set(`${tokenName}-${MODE.DARK}`, darkHex);
return;
}
if (resolvedValue && !resolvedValue.startsWith('var(')) {
const hex = toHex(resolvedValue);
if (hex) setLightDark(colors, tokenName, hex);
}
}
/**
* Parse all color tokens from concatenated CSS file content.
* Performs two passes: first collects all custom properties for var() resolution,
* then processes only color properties into normalized hex values.
* @param {string} cssContent
* @returns {Map<string, string>} token name → hex (e.g. 'color-brand-base-50-light' → 'aabbcc')
*/
export function parseColorsFromCSS(cssContent) {
const colors = new Map();
const allProperties = parseCssProperties(cssContent.split('\n'));
for (const [propName, value] of allProperties.entries()) {
if (!propName.startsWith('--slds-g-color') && !propName.startsWith('--slds-r-color')) continue;
if (propName.startsWith('--slds-r-color-')) {
processReferenceToken(colors, propName.replace('--slds-r-color-', 'color-'), value, allProperties);
} else {
processGlobalToken(colors, propName.replace('--slds-g-', ''), value, allProperties);
}
}
return colors;
}
|