Skip to content

Instantly share code, notes, and snippets.

@yringler
Created June 16, 2023 07:13
Show Gist options
  • Save yringler/aa3a505b298203f097b33ac41387139b to your computer and use it in GitHub Desktop.
Save yringler/aa3a505b298203f097b33ac41387139b to your computer and use it in GitHub Desktop.
style dictionary formatter to add a sibling letter spacing token to typogrophy tokens.
const StyleDictionary = require('style-dictionary');
/**
* The css font shorthand can hold each part of the composite token studio typography token, except for
* letter spacing.
* This formatter creates a partner letter spacing token for each typography token.
* For example:
* --type-100: var(--global-font-weight-extrabold) var(--font-size-1)/var(--line-height-3x-dense) var(--font-nunito-sans);
* --type-100-letter-spacing: var(--global-letter-spacing-5x-loose);
*/
StyleDictionary.registerFormat({
name: 'expandLetterSpacing',
formatter: function ({ dictionary, platform, options, file }) {
const basePropertyFormatter = StyleDictionary.formatHelpers.createPropertyFormatter({
outputReferences: options.outputReferences,
dictionary,
format: 'css'
});
/** @argument token {import('style-dictionary').TransformedToken} */
function propertyFormatter(token) {
const cssVariables = [basePropertyFormatter(token)];
if (token.type == 'typography') {
const value = getLetterSpacing(token);
// Some typography tokens don't specify letter spacing.
if (value) {
const name = ` --${token.name}-letter-spacing`;
cssVariables.push(`${name}: ${value};`);
}
}
return cssVariables.join('\n');
}
return `:host {
${dictionary.allTokens.map(propertyFormatter).join('\n')}
}`;
function getLetterSpacing(token) {
const original = token.original;
let value = '';
/*
* A typography token can either be an object, which defines each part (font size, line height, etc).
* Or it might be an alias (a string) which references another token.
*/
// If it contains the data we need, use that data.
if (typeof original.value == 'object') {
value = getValue(token);
} else {
// If it's a reference, get the value that it's referring to.
// Note that if outputReferences is true, instead of returning the source tokens value, it'll return a
// var(--...) based on the source tokens name.
if (!dictionary.usesReference(original.value)) {
throw "I thought a typography string must be a reference.";
}
value = getValue(dictionary.getReferences(original.value)[0]);
}
return value;
}
/** @argument token {import('style-dictionary').TransformedToken} */
function getValue(token) {
if (!('letterSpacing' in token.original.value)) {
return '';
}
const originalLetterSpacing = token.original.value.letterSpacing;
if (dictionary.usesReference(originalLetterSpacing)) {
const source = dictionary.getReferences(originalLetterSpacing)[0];
return options.outputReferences ? `var(--${source.name})` : source.value;
}
return originalLetterSpacing;
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment