diff --git a/.changeset/pink-mangos-divide.md b/.changeset/pink-mangos-divide.md new file mode 100644 index 000000000..b3f94e6d2 --- /dev/null +++ b/.changeset/pink-mangos-divide.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Allow transformGroup to be combined with transforms, where standalone transforms will be added after the group's transforms. diff --git a/__tests__/transform/config.test.js b/__tests__/transform/config.test.js index 4718215ae..6de599d9b 100644 --- a/__tests__/transform/config.test.js +++ b/__tests__/transform/config.test.js @@ -54,5 +54,47 @@ None of "barTransform", "bazTransform" match the name of a registered transform. expect(transformConfig.bind(null, noTransformCfg, dictionary, 'test')).to.throw(err); }); + + it('allows combining transformGroup with transforms', () => { + const cfg = { + transformGroup: { + foobarTransformGroup: ['fooTransform', 'barTransform'], + }, + transform: { + fooTransform: { + name: 'fooTransform', + type: 'attribute', + transformer: function () { + return { foo: 'foo' }; + }, + }, + barTransform: { + name: 'barTransform', + type: 'attribute', + transformer: function () { + return { bar: 'bar' }; + }, + }, + quxTransform: { + name: 'quxTransform', + type: 'attribute', + transformer: function () { + return { qux: 'qux' }; + }, + }, + }, + }; + + const platformCfg = { + transformGroup: 'foobarTransformGroup', + transforms: ['quxTransform'], + }; + const transformedCfg = transformConfig(platformCfg, cfg, 'test'); + expect(transformedCfg.transforms.map((t) => t.name)).to.eql([ + 'fooTransform', + 'barTransform', + 'quxTransform', + ]); + }); }); }); diff --git a/__tests__/transform/propertySetup.test.js b/__tests__/transform/tokenSetup.test.js similarity index 100% rename from __tests__/transform/propertySetup.test.js rename to __tests__/transform/tokenSetup.test.js diff --git a/__tests__/transform/property.test.js b/__tests__/transform/transformToken.test.js similarity index 91% rename from __tests__/transform/property.test.js rename to __tests__/transform/transformToken.test.js index 1725f64e9..fc60fbe9d 100644 --- a/__tests__/transform/property.test.js +++ b/__tests__/transform/transformToken.test.js @@ -11,7 +11,7 @@ * and limitations under the License. */ import { expect } from 'chai'; -import token from '../../lib/transform/token.js'; +import transformToken from '../../lib/transform/token.js'; const config = { transforms: [ @@ -44,14 +44,14 @@ const config = { describe('transform', () => { describe('token', () => { it('transform token and apply transforms', async () => { - const test = await token({ attributes: { baz: 'blah' } }, config, {}); + const test = await transformToken({ attributes: { baz: 'blah' } }, config, {}); expect(test).to.have.nested.property('attributes.bar', 'foo'); expect(test).to.have.property('name', 'hello'); }); // This allows transformObject utility to then consider this token's transformation undefined and thus "deferred" it('returns a token as undefined if transitive transformer dictates that the transformation has to be deferred', async () => { - const result = await token( + const result = await transformToken( { value: '16', original: { diff --git a/docs/transform_groups.md b/docs/transform_groups.md index 54417efb3..3e2aa4741 100644 --- a/docs/transform_groups.md +++ b/docs/transform_groups.md @@ -20,6 +20,25 @@ You use transformGroups in your config file under platforms > [platform] > trans } ``` +## Combining with transforms + +You can also combine transforms with transformGroup: + +```json +{ + "source": ["tokens/**/*.json"], + "platforms": { + "android": { + "transformGroup": "android", + "transforms": ["name/cti/snake"] + } + } +} +``` + +The transforms that are standalone will be added **after** the ones inside the transformGroup. +If it's important to determine the order of these yourself, you can always register a custom transformGroup to have more granular control. + --- ## Pre-defined Transform groups diff --git a/lib/transform/config.js b/lib/transform/config.js index ee823edbc..3e4cc9387 100644 --- a/lib/transform/config.js +++ b/lib/transform/config.js @@ -39,17 +39,14 @@ export default function transformConfig(platformConfig, dictionary, platformName const to_ret = { ...platformConfig }; // structuredClone not suitable due to config being able to contain Function() etc. to_ret.log = platformConfig.log ?? dictionary.log; - // The platform can define either a transformGroup or an array + // The platform can both a transformGroup or an array // of transforms. If given a transformGroup that doesn't exist, // it will throw an error to make the user aware that the transformGroup doesn't // exist. A valid case is if the user defines neither, no transforms will be // applied. /** @type {string[]} */ let transforms = []; - if (to_ret.transforms) { - // typecast because at this point, transforms are still strings without functions - transforms = /** @type {string[]} */ (to_ret.transforms); - } else if (to_ret.transformGroup) { + if (to_ret.transformGroup) { if (dictionary.transformGroup[to_ret.transformGroup]) { transforms = dictionary.transformGroup[to_ret.transformGroup]; } else { @@ -61,6 +58,11 @@ Unknown transformGroup "${to_ret.transformGroup}" found in platform "${platformN } } + if (to_ret.transforms) { + // typecast because at this point, transforms are still strings without functions + transforms = transforms.concat(/** @type {string[]} */ (to_ret.transforms)); + } + // Transforms are an array of strings that map to functions on // the StyleDictionary module. We need to map the strings to // the actual functions.