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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | 8x 8x 9365x 701x 701x 4x 697x 1x 696x 1x 695x 3x 692x 3x 689x 12x 1589x 1589x 2x 1587x 685x 674x 902x 897x 5x 636x 5x 631x 631x 8x 623x 623x 623x 623x 11855x 11851x 8x 2x 6x 6x 675x 59x 616x 616x | /**
* Utility functions for handling value+unit tokens in both string and object formats
* Supports DTCG dimensional and duration types
*/
/**
* Supported value+unit types
* Per DTCG spec:
* - Dimension: https://www.designtokens.org/tr/2025.10/format/#dimension
* - Duration: https://www.designtokens.org/tr/2025.10/format/#duration
*
* Dimensional units (length/size):
* - rem: Relative to root font size (most common)
* - px: Absolute pixels
* - ch: Character width (used in deprecated tokens)
* - %: Percentage (used for circle radius)
*
* Duration units (time):
* - s: Seconds
* - ms: Milliseconds
*/
const SUPPORTED_UNITS = ['rem', 'px', 'ch', '%', 's', 'ms'];
const SUPPORTED_UNITS_REGEX = 'rem|px|ch|%|s|ms';
/**
* Check if a value is a value+unit object with value and unit properties
* Per DTCG spec: dimension/duration values MUST be an object with {value: number, unit: string}
* @param {*} value - The value to check
* @returns {boolean} - True if value is a value+unit object
*/
export function isValueUnitObject(value) {
return (
value &&
typeof value === 'object' &&
!Array.isArray(value) &&
'value' in value &&
'unit' in value &&
typeof value.value === 'number' &&
typeof value.unit === 'string'
);
}
/**
* Validate a value+unit object against DTCG spec requirements
* @param {object} value - The value+unit object to validate
* @param {string} tokenPath - Token path for error messages (optional)
* @throws {Error} If the value+unit object is invalid
*/
export function validateValueUnitObject(value, tokenPath = '') {
const pathInfo = tokenPath ? ` in token "${tokenPath}"` : '';
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new Error(
`Invalid value+unit${pathInfo}: Expected object with {value, unit}, got ${JSON.stringify(value)}`,
);
}
if (!('value' in value)) {
throw new Error(
`Invalid value+unit${pathInfo}: Missing required "value" property. Got ${JSON.stringify(value)}`,
);
}
if (!('unit' in value)) {
throw new Error(
`Invalid value+unit${pathInfo}: Missing required "unit" property. Got ${JSON.stringify(value)}`,
);
}
if (typeof value.value !== 'number') {
throw new Error(
`Invalid value+unit${pathInfo}: Property "value" must be a number, got ${typeof value.value}: ${JSON.stringify(value.value)}`,
);
}
if (typeof value.unit !== 'string') {
throw new Error(
`Invalid value+unit${pathInfo}: Property "unit" must be a string, got ${typeof value.unit}: ${JSON.stringify(value.unit)}`,
);
}
if (!SUPPORTED_UNITS.includes(value.unit)) {
throw new Error(
`Invalid value+unit${pathInfo}: Unsupported unit "${value.unit}". Supported units: ${SUPPORTED_UNITS.join(', ')}`,
);
}
}
/**
* Convert a value+unit value to string format
* Handles both object format {value: 0.25, unit: "rem"} and string format "0.25rem"
* Per DTCG spec, validates value+unit objects strictly
* @param {string|object} value - The value+unit value
* @param {string} tokenPath - Token path for error messages (optional)
* @returns {string} - The value as a string (e.g., "0.25rem")
* @throws {Error} If value is null, undefined, or invalid
*/
export function valueUnitToString(value, tokenPath = '') {
const pathInfo = tokenPath ? ` in token "${tokenPath}"` : '';
// Validate input
if (value === null || value === undefined) {
throw new Error(`valueUnitToString: value cannot be null or undefined${pathInfo}`);
}
if (isValueUnitObject(value)) {
// Validate against DTCG spec requirements
validateValueUnitObject(value, tokenPath);
return `${value.value}${value.unit}`;
}
// If it's already a string, return as-is (for backward compatibility during transition)
if (typeof value === 'string') {
return value;
}
// Anything else is an error
throw new Error(
`valueUnitToString: Expected string or value+unit object${pathInfo}, got ${typeof value}: ${JSON.stringify(value)}`,
);
}
/**
* Parse a value+unit string into value and unit
* Converts string format to DTCG-compliant object format
* @param {string} str - The value+unit string (e.g., "0.25rem", "16px")
* @returns {object|null} - Object with {value, unit} or null if not a value+unit string
*/
export function parseValueUnitString(str) {
if (typeof str !== 'string') {
return null;
}
// Match number (including decimals) followed by unit
// Pattern: digits + optional (. + digits) + unit
const match = str.match(new RegExp(`^(\\d+(\\.\\d+)?)(${SUPPORTED_UNITS_REGEX})$`));
if (!match) {
return null;
}
const value = parseFloat(match[1]);
const unit = match[3]; // Capture group 3 due to nested group
Iif (isNaN(value)) {
return null;
}
return { value, unit };
}
/**
* Get the raw value+unit value from a token, handling both formats
* @param {object} token - The token object
* @returns {string|object|null} - The value+unit value, or null if token is invalid
*/
export function getRawValueUnitValue(token) {
if (!token) return null;
return token.value || token.$value || token.original?.$value;
}
/**
* Extract numeric value from value+unit token (for calculations)
* @param {string|object} value - The value+unit value
* @param {number|null} defaultValue - Value to return if extraction fails (default: null)
* @returns {number|null} - The numeric value or defaultValue
*/
export function extractNumericValue(value, defaultValue = null) {
if (isValueUnitObject(value)) {
return value.value;
}
const parsed = parseValueUnitString(value);
return parsed ? parsed.value : defaultValue;
}
/**
* Extract unit from value+unit token
* @param {string|object} value - The value+unit value
* @param {string|null} defaultValue - Value to return if extraction fails (default: null)
* @returns {string|null} - The unit or defaultValue
*/
export function extractUnit(value, defaultValue = null) {
if (isValueUnitObject(value)) {
return value.unit;
}
const parsed = parseValueUnitString(value);
return parsed ? parsed.unit : defaultValue;
}
|