Skip to content

Commit

Permalink
feat: move formats global prop to hooks.formats, align api
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenbroekema committed May 6, 2024
1 parent 7a384aa commit 24db531
Show file tree
Hide file tree
Showing 49 changed files with 275 additions and 216 deletions.
67 changes: 67 additions & 0 deletions .changeset/seven-candles-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
'style-dictionary': major
---

BREAKING: Formats, when registered, are put inside the `hooks.formats` property now, as opposed to `format`.
The `formatter` handler function has been renamed to `format` for consistency.

The importable type interfaces have also been renamed, `Formatter` is now `FormatFn` and `FormatterArguments` is now `FormatFnArguments`.
Note that you can also use `Format['format']` instead of `FormatFn`, or `Parameters<Format['format']>` instead of `FormatFnArguments`, so these renames may not matter.

Before:

```ts
import StyleDictionary from 'style-dictionary';
import type { Formatter, FormatterArguments } from 'style-dictionary/types';

// register it with register method
StyleDictionary.registerFormat({
name: 'custom/json',
formatter: ({ dictionary }) => JSON.stringify(dictionary, 2, null),
})

export default {
// OR define it inline
format: {
'custom/json': ({ dictionary }) => JSON.stringify(dictionary, 2, null),
},
platforms: {
json: {
files: [{
destination: 'output.json',
format: 'custom/json'
}],
},
},
};
```

After:

```ts
import StyleDictionary from 'style-dictionary';
import type { FormatFn, FormatFnArguments } from 'style-dictionary/types';

// register it with register method
StyleDictionary.registerFormat({
name: 'custom/json',
format: ({ dictionary }) => JSON.stringify(dictionary, 2, null),
})

export default {
// OR define it inline
hooks: {
formats: {
'custom/json': ({ dictionary }) => JSON.stringify(dictionary, 2, null),
},
},
platforms: {
json: {
files: [{
destination: 'output.json',
format: 'custom/json'
}],
},
},
};
```
2 changes: 1 addition & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ jobs:
run: npx playwright install --with-deps chromium

- name: Browser tests
run: npm run test:browser
run: npm run test
2 changes: 1 addition & 1 deletion __integration__/async.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('integration', async function () {

SDExtension.registerFormat({
name: 'custom/css',
formatter: async function ({ dictionary, file, options }) {
format: async function ({ dictionary, file, options }) {
await sleep(10);
const { outputReferences } = options;
return (
Expand Down
16 changes: 9 additions & 7 deletions __integration__/customFormats.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ describe('integration', async () => {
const sd = new StyleDictionary({
source: [`__integration__/tokens/size/padding.json`],
// Adding formats directly to SD
format: {
inlineCustomFormatWithOldArgs: (dictionary, platform, file) => {
return JSON.stringify({ dictionary, platform, file }, null, 2);
},
inlineCustomFormatWithNewArgs: (opts) => {
return JSON.stringify(opts, null, 2);
hooks: {
formats: {
inlineCustomFormatWithOldArgs: (dictionary, platform, file) => {
return JSON.stringify({ dictionary, platform, file }, null, 2);
},
inlineCustomFormatWithNewArgs: (opts) => {
return JSON.stringify(opts, null, 2);
},
},
},
platforms: {
Expand Down Expand Up @@ -78,7 +80,7 @@ describe('integration', async () => {

sd.registerFormat({
name: 'registerCustomFormatWithNewArgs',
formatter: (opts) => {
format: (opts) => {
return JSON.stringify(opts, null, 2);
},
});
Expand Down
4 changes: 2 additions & 2 deletions __tests__/buildFiles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const platformWithFilter = {
],
};

const platformWithoutFormatter = {
const platformWithoutFormat = {
buildPath: '__tests__/__output/',
files: [
{
Expand Down Expand Up @@ -98,7 +98,7 @@ describe('buildFiles', () => {
});

it('should throw if missing a format', async () => {
await expect(buildFiles(dictionary, platformWithoutFormatter)).to.eventually.rejectedWith(
await expect(buildFiles(dictionary, platformWithoutFormat)).to.eventually.rejectedWith(
'Please supply a format',
);
});
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/action.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ registerSuite({
},
registerMethod: 'registerAction',
prop: 'actions',
hooks: true,
});

describe('register', () => {
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/fileHeader.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ registerSuite({
},
registerMethod: 'registerFileHeader',
prop: 'fileHeaders',
hooks: true,
});

describe('register', () => {
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/filter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ registerSuite({
},
registerMethod: 'registerFilter',
prop: 'filters',
hooks: true,
});

describe('register', () => {
Expand Down
28 changes: 14 additions & 14 deletions __tests__/register/format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import { registerSuite } from './register.suite.js';

registerSuite({
config: {
formatter: () => {},
format: () => {},
},
registerMethod: 'registerFormat',
prop: 'format',
prop: 'formats',
});

describe('register', () => {
Expand All @@ -30,34 +30,34 @@ describe('register', () => {
const errorMessage = `Can't register format; format.name must be a string`;
expect(() => {
StyleDictionaryExtended.registerFormat({
formatter: function () {},
format: function () {},
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: 1,
formatter: function () {},
format: function () {},
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: [],
formatter: function () {},
format: function () {},
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: {},
formatter: function () {},
format: function () {},
});
}).to.throw(errorMessage);
});

it('should error if format is not a function', () => {
const errorMessage = `Can't register format; format.formatter must be a function`;
const errorMessage = `Can't register format; format.format must be a function`;
expect(() => {
StyleDictionaryExtended.registerFormat({
name: 'test',
Expand All @@ -67,43 +67,43 @@ describe('register', () => {
expect(() => {
StyleDictionaryExtended.registerFormat({
name: 'test',
formatter: 1,
format: 1,
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: 'test',
formatter: 'name',
format: 'name',
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: 'test',
formatter: [],
format: [],
});
}).to.throw(errorMessage);

expect(() => {
StyleDictionaryExtended.registerFormat({
name: 'test',
formatter: {},
format: {},
});
}).to.throw(errorMessage);
});

it('should work if name and format are good', () => {
StyleDictionaryExtended.registerFormat({
name: 'scss',
formatter: function () {},
format: function () {},
});
expect(typeof StyleDictionaryExtended.format['scss']).to.equal('function');
expect(typeof StyleDictionaryExtended.hooks.formats['scss']).to.equal('function');
});

it('should properly pass the registered format to instances', async () => {
const SDE2 = await StyleDictionaryExtended.extend({});
expect(typeof SDE2.format['scss']).to.equal('function');
expect(typeof SDE2.hooks.formats['scss']).to.equal('function');
});
});
});
1 change: 0 additions & 1 deletion __tests__/register/parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ registerSuite({
},
registerMethod: 'registerParser',
prop: 'parsers',
hooks: true,
});

describe('register', () => {
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/preprocessor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ registerSuite({
},
registerMethod: 'registerPreprocessor',
prop: 'preprocessors',
hooks: true,
});

describe('register/transformGroup', async () => {
Expand Down
57 changes: 15 additions & 42 deletions __tests__/register/register.suite.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ export function registerSuite(opts) {

describe('Register Test Suite', () => {
const reset = () => {
if (opts.hooks) {
StyleDictionary.hooks[prop] = defaultPropVal;
} else {
StyleDictionary[prop] = defaultPropVal;
}
StyleDictionary.hooks[prop] = defaultPropVal;
};
beforeEach(() => {
reset();
Expand All @@ -37,15 +33,9 @@ export function registerSuite(opts) {
const sd1 = new StyleDictionary();
const sd2 = new StyleDictionary();
const sd3 = await sd2.extend();
if (opts.hooks) {
expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined;
} else {
expect(sd1[prop][configFoo.name]).to.not.be.undefined;
expect(sd2[prop][configFoo.name]).to.not.be.undefined;
expect(sd3[prop][configFoo.name]).to.not.be.undefined;
}
expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined;
});

it(`should allow registering ${prop} on instance, affecting only that instance`, async () => {
Expand All @@ -54,15 +44,9 @@ export function registerSuite(opts) {
const sd3 = await sd2.extend();

sd2[registerMethod](configFoo);
if (opts.hooks) {
expect(sd1.hooks[prop][configFoo.name]).to.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.be.undefined;
} else {
expect(sd1[prop][configFoo.name]).to.be.undefined;
expect(sd2[prop][configFoo.name]).to.not.be.undefined;
expect(sd3[prop][configFoo.name]).to.be.undefined;
}
expect(sd1.hooks[prop][configFoo.name]).to.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.be.undefined;
});

it(`should combine class and instance registrations for ${prop} on the instance`, async () => {
Expand All @@ -73,25 +57,14 @@ export function registerSuite(opts) {
sd2[registerMethod](configBar);
const sd3 = await sd2.extend();

if (opts.hooks) {
expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined;
// should not be registered on sd1, because we registered only on sd2
expect(sd1.hooks[prop][configBar.name]).to.be.undefined;
expect(sd2.hooks[prop][configBar.name]).to.not.be.undefined;
// should be registered because sd3 extends sd2
expect(sd3.hooks[prop][configBar.name]).to.not.be.undefined;
} else {
expect(sd1[prop][configFoo.name]).to.not.be.undefined;
expect(sd2[prop][configFoo.name]).to.not.be.undefined;
expect(sd3[prop][configFoo.name]).to.not.be.undefined;
// should not be registered on sd1, because we registered only on sd2
expect(sd1[prop][configBar.name]).to.be.undefined;
expect(sd2[prop][configBar.name]).to.not.be.undefined;
// should be registered because sd3 extends sd2
expect(sd3[prop][configBar.name]).to.not.be.undefined;
}
expect(sd1.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd2.hooks[prop][configFoo.name]).to.not.be.undefined;
expect(sd3.hooks[prop][configFoo.name]).to.not.be.undefined;
// should not be registered on sd1, because we registered only on sd2
expect(sd1.hooks[prop][configBar.name]).to.be.undefined;
expect(sd2.hooks[prop][configBar.name]).to.not.be.undefined;
// should be registered because sd3 extends sd2
expect(sd3.hooks[prop][configBar.name]).to.not.be.undefined;
});
});
});
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/transform.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ registerSuite({
},
registerMethod: 'registerTransform',
prop: 'transforms',
hooks: true,
});

describe('register', () => {
Expand Down
1 change: 0 additions & 1 deletion __tests__/register/transformGroup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ registerSuite({
},
registerMethod: 'registerTransformGroup',
prop: 'transformGroups',
hooks: true,
});

describe('register/transformGroup', async () => {
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/Hooks/Formats/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { fileHeader, formattedVariables } from 'style-dictionary/utils';

StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: async ({ dictionary, file, options }) => {
format: async ({ dictionary, file, options }) => {
const { outputReferences } = options;
const header = await fileHeader({ file });
return (
Expand Down
Loading

0 comments on commit 24db531

Please sign in to comment.