amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.93k stars 557 forks source link

Can I use getReference or somehow get access to the reference token inside of a transformer? #1164

Closed lukasoppermann closed 7 months ago

lukasoppermann commented 7 months ago

Hey,

I am trying to create a transformer that adds the css variable as a value to a token. My idea would be to use getReferences to get the referenced tokens converted name and turn this into a css variable name.

However, I am not sure if this works, or if this can only be done within a fromatter.

jorenbroekema commented 7 months ago

Hey, not sure if you found the answer to your question since you closed it but yes you can use the getReferences utility inside a format, since you have access to the transformed dictionary https://style-dictionary-v4.netlify.app/reference/utils/references/#getreferences , you should scroll down tothe Complicated Example which I think is super similar to what you're trying to do!

lukasoppermann commented 7 months ago

Hey @jorenbroekema I did not find the answer. However I was wondering if I can use it in a transformer? Is this possible?

jorenbroekema commented 7 months ago

That's a little bit more tricky but can be done:

import StyleDictionary from 'style-dictionary';
import { usesReferences, getReferences } from 'style-dictionary/utils';

const sd = new StyleDictionary('config.json');
await sd.hasInitialized;
const { tokens } = sd;

// best to register it on the instance, because the transformer function
// relies on "tokens" which is an instance prop and not a class prop
sd.registerTransform({
  name: 'transformer-that-uses-tokens-object',
  type: 'value',
  transitive: true,
  transformer: (token, _, options) => {
    const val = options.usesDtcg ? token.$value : token.value;
    const originalVal = options.usesDtcg ? token.original.$value : token.original.value;
    if (usesReferences(originalVal)) {
      const refs = getReferences(originalVal, tokens);
    }
    return token.value;
  }
});

await sd.buildAllPlatforms();

Important to note here is that you have to make the transform transitive because otherwise it will never run on tokens that contain references, and note that once it does run, the references will be resolved, so you'll need the token.original.value to grab the references.

I haven't tested this code myself locally but let me know if you run into issues