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

Consider passing the current file object to filter matchers #923

Open pascalduez opened 1 year ago

pascalduez commented 1 year ago

Hi,

I have a similar need than the "matching build files" example. Basically I would like to enforce token tiers by explicitely splitting exposed files by tier. For instance core.css, semantic.css, component.css, instead of a monolithic tokens.css.

The solution in the "matching build files" example is great, except it forces to have the filter defined inline, at the file declaration level. Problems, this does not scale well, it can quickly turn your config into a really verbose and dense mess. It also prevent from using filters declared by either registerFilter or on the filter config object key. Moreover, I have several chained filters for one file.

filter: {
  'hello/abstract': filters.abstract.matcher,
  'hello/styles': chain(
    filters.abstract.matcher,
    token => !isTypography(token)
  ),
  // ... etc.
};

What I would like to achieve:

matcher: (token, file) => {
  // Do something with the `file` object, either path or `options`.
}
filter: {
  'hello/abstract': filters.abstract.matcher,
  'hello/styles': chain(
    filters.abstract.matcher,
    token => !isTypography(token),
   (token, file) => { ... }
  ),
  // or
 'hello/tiers': (token, file) => { ... }
};

It turns out that the change to make this possible is very minimal and non breaking. Just introducing a simple closure.

https://github.com/amzn/style-dictionary/blob/e1626a7d60e084bff18c4dc7f45e964c3ae00f54/lib/buildFile.js#L54-L55

Would be turned into

  const predicate = (token) => filter(token, file);
  const filteredProperties = filterProperties(dictionary, predicate);

And then updating the matcher types accordingly.

Would that be something conceivable?