Created
June 16, 2023 07:13
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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