amzn / style-dictionary

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

File splitting API #1264

Open jorenbroekema opened 2 months ago

jorenbroekema commented 2 months ago

Define files programatically

Below was commented by @jorgecasar https://github.com/amzn/style-dictionary/issues/643#issuecomment-956388868

I would like to be able to generate files based on current dictionary. When you have a dynamic number of components or you have more than 100 components tokenized it's hard to maintain the list of files.

Export all components variables into a single file is not efficient when you can include in your app only a sub set of all available components.

I would like to have something like this:

files: [{
  destination: `components/*.css`,
  format: 'css/component',
  filter: token => token.path[0] === 'component',
  split: dictionary => {
    const uniqueItems = [...new Set(
      dictionary.allTokens
      .filter(token => token.attributes?.item)
      .map(token => token.attributes.item)
    )]
    return uniqueItems.map(item => ({
      destination: `${component}.css`,
      filter: token => token.item === item,
    }));
  }
}]

Then easily you can get 1 file per item or any other split you would like to do attending to the token properties.

To which I then replied:

Technically it is already possible to generate a files array programmatically to accomplish what you want, but I agree it would be cool to provide some kind of utility that makes this simpler.

A JSON way of doing it might be:

{
  "files": [{
    "format": "css/component",
    "filter": "componentFilter", // assume this is registered, it's optional
    "split": {
      "by": "{attributes.item}", // any prop ref on token in dictionary
      "destination": "components/*/tokens.css" // * replaced by resolved "by" value e.g. attributes.item = "button"
    }
  }]
}

Or if you need more flexibility, I suppose you can always go a bit deeper with JS instead

const cfg = {
  files: [{
    format: 'css/component',
    filter: token => token.path[0] === 'component',
    split: {
      by: (token) => token.attributes.item, // some prop on the token's attributes
      destination: (byValue) => `components/${byValue}/tokens.css`
    }
  }]
}

Originally posted by @jorenbroekema in https://github.com/amzn/style-dictionary/issues/643#issuecomment-1740610773

Might be worth investigating this topic for v5