@terrazzo/parser
Version:
Parser/validator for the Design Tokens Community Group (DTCG) standard.
177 lines • 6.66 kB
JavaScript
import { getObjMember } from '@terrazzo/json-schema-tools';
import { FONT_WEIGHTS, isAlias, parseColor } from '@terrazzo/token-tools';
/**
* Normalize token value.
* The reason for the “any” typing is this aligns various user-provided inputs to the type
*/
export function normalize(token, { logger, src }) {
switch (token.$type) {
case 'color': {
for (const mode of Object.keys(token.mode)) {
token.mode[mode].$value = normalizeColor(token.mode[mode].$value, {
logger,
node: token.mode[mode].source.node,
src,
token,
});
}
break;
}
case 'fontFamily': {
for (const mode of Object.keys(token.mode)) {
token.mode[mode].$value = normalizeFontFamily(token.mode[mode].$value);
}
break;
}
case 'fontWeight': {
for (const mode of Object.keys(token.mode)) {
token.mode[mode].$value = normalizeFontWeight(token.mode[mode].$value);
}
break;
}
case 'border': {
for (const mode of Object.keys(token.mode)) {
const border = token.mode[mode].$value;
if (!border || typeof border !== 'object') {
continue;
}
if (border.color) {
border.color = normalizeColor(border.color, {
logger,
node: getObjMember(token.mode[mode].source.node, 'color'),
src,
token,
});
}
}
break;
}
case 'shadow': {
for (const mode of Object.keys(token.mode)) {
// normalize to array
if (!Array.isArray(token.mode[mode].$value)) {
token.mode[mode].$value = [token.mode[mode].$value];
}
const $value = token.mode[mode].$value;
for (let i = 0; i < $value.length; i++) {
const shadow = $value[i];
if (!shadow || typeof shadow !== 'object') {
continue;
}
const shadowNode = (token.mode[mode].source.node.type === 'Array'
? token.mode[mode].source.node.elements[i].value
: token.mode[mode].source.node);
if (shadow.color) {
shadow.color = normalizeColor(shadow.color, {
logger,
node: getObjMember(shadowNode, 'color'),
src,
token,
});
}
if (!('inset' in shadow)) {
shadow.inset = false;
}
}
}
break;
}
case 'gradient': {
for (const mode of Object.keys(token.mode)) {
if (!Array.isArray(token.mode[mode].$value)) {
continue;
}
const $value = token.mode[mode].$value;
for (let i = 0; i < $value.length; i++) {
const stop = $value[i];
if (!stop || typeof stop !== 'object') {
continue;
}
const stopNode = token.mode[mode].source.node?.elements?.[i]
?.value;
if (stop.color) {
stop.color = normalizeColor(stop.color, {
logger,
node: getObjMember(stopNode, 'color'),
src,
token,
});
}
}
}
break;
}
// Note: this normalization shouldn’t ever be necessary, but in resolvers
// that introduce new tokens in the non-default permutation, they can bypass
// validation checks, leading to this normalization.
// See https://github.com/terrazzoapp/terrazzo/issues/654#issuecomment-5255484839
case 'transition': {
for (const mode of Object.keys(token.mode)) {
const $value = token.mode[mode].$value;
if (typeof $value !== 'object') {
return;
}
if (!$value.duration) {
$value.duration = { value: 0, unit: 'ms' };
}
if (!$value.delay) {
$value.delay = { value: 0, unit: 'ms' };
}
if (!$value.timingFunction) {
$value.timingFunction = [0, 0, 1, 1];
}
}
break;
}
case 'typography': {
for (const mode of Object.keys(token.mode)) {
const $value = token.mode[mode].$value;
if (typeof $value !== 'object') {
return;
}
for (const [k, v] of Object.entries($value)) {
switch (k) {
case 'fontFamily': {
$value[k] = normalizeFontFamily(v);
break;
}
case 'fontWeight': {
$value[k] = normalizeFontWeight(v);
break;
}
}
}
}
break;
}
}
}
function normalizeColor(value, { logger, node, src, token, }) {
if (typeof value === 'string' && !isAlias(value)) {
logger.warn({
group: 'parser',
label: 'init',
message: `${token.id}: string colors will be deprecated in a future version. Please update to object notation.`,
node,
src,
});
try {
return parseColor(value);
}
catch {
return { alpha: 1, colorSpace: 'srgb', components: [0, 0, 0] };
}
}
else if (value && typeof value === 'object' && value.alpha === undefined) {
value.alpha = 1;
}
return value;
}
function normalizeFontFamily(value) {
return typeof value === 'string' ? [value] : value;
}
function normalizeFontWeight(value) {
return ((typeof value === 'string' && FONT_WEIGHTS[value]) ||
value);
}
//# sourceMappingURL=normalize.js.map