Skip to content

Preprocessors

Starting in version 4.0, you can define custom preprocessors to process the dictionary object as a whole, after it all token files have been parsed and combined into one. This is useful if you want to do more complex transformations on the dictionary as a whole, when all other ways are not powerful enough.

Preprocessors can be applied globally or per platform.

That said, preprocessing the full dictionary gives ultimate flexibility when needed.


Preprocessor structure

A preprocessor is an object with two props:

  • name: the name of the preprocessor
  • preprocessor a callback function that receives the dictionary and SD options as parameters, and returns the processed dictionary
my-preprocessor.js
const myPreprocessor = {
name: 'strip-third-party-meta',
preprocessor: (dictionary, options) => {
delete dictionary.thirdPartyMetadata;
return dictionary;
},
};

Asynchronous callback functions are also supported, giving even more flexibility.

my-preprocessor-async.js
const myPreprocessor = {
name: 'strip-props',
preprocessor: async (dictionary, options) => {
const propsToDelete = await someAPICall();
propsToDelete.forEach((propName) => {
delete dictionary[propName];
});
return dictionary;
},
};

Using preprocessors

First you will need to tell Style Dictionary about your parser. You can do this in two ways:

  1. Using the .registerPreprocessor method
  2. Inline in the configuration

.registerPreprocessor

import StyleDictionary from 'style-dictionary';
StyleDictionary.registerPreprocessor(myPreprocessor);

Inline

export default {
hooks: {
preprocessors: {
'strip-props': myPreprocessor,
},
},
// ... the rest of the configuration
};

Applying it in config

{
"source": ["**/*.tokens.json"],
"preprocessors": ["strip-props"]
}

or platform-specific:

{
"source": ["**/*.tokens.json"],
"platforms": {
"css": {
"transformGroup": "css",
"preprocessors": ["strip-props"]
}
}
}

Preprocessor examples

Stripping description property recursively in the entire dictionary object:

StyleDictionary.registerPreprocessor({
name: 'strip-descriptions',
preprocessor: (dict, options) => {
// recursively traverse token objects and delete description props
function removeDescription(slice) {
delete slice.description;
Object.values(slice).forEach((value) => {
if (typeof value === 'object') {
removeDescription(value);
}
});
return slice;
}
return removeDescription(dict);
},
});

Default preprocessors

There are two default preprocessors that are always applied and run before other custom preprocessors do:

  • typeDtcgDelegate, for DTCG tokens, make sure the $type is either already present or gets inherited from the closest ancestor that has it defined, so that the $type is always available on the token level, for ease of use
  • expandObjectTokens, a private preprocessor that will expand object-value (composite) tokens when user config has this enabled.