diff --git a/.changeset/gorgeous-lamps-chew.md b/.changeset/gorgeous-lamps-chew.md new file mode 100644 index 000000000..49efca435 --- /dev/null +++ b/.changeset/gorgeous-lamps-chew.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +options.log to be respected in all error logging, including platform specific logs. diff --git a/.changeset/unlucky-cameras-draw.md b/.changeset/unlucky-cameras-draw.md new file mode 100644 index 000000000..a26cf1bb2 --- /dev/null +++ b/.changeset/unlucky-cameras-draw.md @@ -0,0 +1,67 @@ +--- +'style-dictionary': major +--- + +BREAKING: StyleDictionary to be initialized with a new API and have async methods. Use: + +```js +import StyleDictionary from 'style-dictionary'; + +/** + * old: + * const sd = StyleDictionary.extend({ source: ['tokens.json'], platforms: {} }); + * sd.buildAllPlatforms(); + */ +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.buildAllPlatforms(); +``` + +You can still extend a dictionary instance with an extended config, but `.extend()` is only used for this, it is no longer used to initialize the first instance: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +const extended = await sd.extend({ + fileHeader: { + myFileHeader: (defaultMessage) => { + return [...defaultMessage, 'hello, world!']; + } + } +}); +``` + +To ensure your initialized StyleDictionary instance is fully ready and has imported all your tokens, you can await `hasInitialized`: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.json'], platforms: {} }); +await sd.hasInitialized; +console.log(sd.allTokens); +``` + +For error handling and testing purposes, you can also manually initialize the style-dictionary config: + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens.js'], platforms: {} }, { init: false }); +try { + await sd.init(); +} catch(e) { + // handle error, e.g. when tokens.js file has syntax errors and cannot be imported +} +console.log(sd.allTokens); +``` + +The main reason for an initialize step after class instantiation is that async constructors are not a thing in JavaScript, and if you return a promise from a constructor to "hack it", TypeScript will eventually trip over it. + +Due to being able to dynamically (asynchronously) import ES Modules rather than synchronously require CommonJS modules, we had to make the APIs asynchronous, so the following methods are now async: + +- extend +- exportPlatform +- buildAllPlatforms & buildPlatform +- cleanAllPlatforms & cleanPlatform + +In a future release, most other methods will be made async or support async as well, such as parsers, transforms, formats etc. diff --git a/__tests__/__setup.js b/__tests__/__setup.js index d9a4dabd2..1c593e74a 100644 --- a/__tests__/__setup.js +++ b/__tests__/__setup.js @@ -4,15 +4,18 @@ import path from '@bundled-es-modules/path-browserify'; import { fs } from 'style-dictionary/fs'; import { chaiWtrSnapshot } from '../snapshot-plugin/chai-wtr-snapshot.js'; -const constantDate = new Date('2000-01-01'); -// eslint-disable-next-line no-undef -window.Date = function () { - return constantDate; -}; -// eslint-disable-next-line no-undef -window.Date.now = function () { - return constantDate; -}; +export function fixDate() { + const constantDate = new Date('2000-01-01'); + // eslint-disable-next-line no-undef + window.Date = function () { + return constantDate; + }; + // eslint-disable-next-line no-undef + window.Date.now = function () { + return constantDate; + }; +} +fixDate(); /** * We have a bunch of files that we use a mock data for our tests diff --git a/__tests__/common/formatHelpers/fileHeader.test.js b/__tests__/common/formatHelpers/fileHeader.test.js index f421918cd..1e8365721 100644 --- a/__tests__/common/formatHelpers/fileHeader.test.js +++ b/__tests__/common/formatHelpers/fileHeader.test.js @@ -11,6 +11,7 @@ * and limitations under the License. */ import { expect } from 'chai'; +import { fixDate } from '../../__setup.js'; import fileHeader from '../../../lib/common/formatHelpers/fileHeader.js'; const defaultLine1 = `Do not edit directly`; @@ -18,6 +19,10 @@ const defaultLine2 = `Generated on Sat, 01 Jan 2000 00:00:00 GMT`; describe('common', () => { describe('formatHelpers', () => { + beforeEach(() => { + fixDate(); + }); + describe('fileHeader', () => { it(`should default to /**/ comment style`, () => { const comment = fileHeader({}); diff --git a/lib/StyleDictionary.js b/lib/StyleDictionary.js index cd9777af9..e613ad6ca 100644 --- a/lib/StyleDictionary.js +++ b/lib/StyleDictionary.js @@ -363,7 +363,7 @@ export default class StyleDictionary { console.log('\n' + platform); - if (!this.options || !(platform in (this.options.platforms || {}))) { + if (!this.options || !this.options?.platforms[platform]) { throw new Error(`Platform "${platform}" does not exist`); } @@ -402,7 +402,7 @@ export default class StyleDictionary { console.log('\n' + platform); - if (!this.options || !(platform in (this.options.platforms || {}))) { + if (!this.options || !this.options?.platforms[platform]) { throw new Error('Platform ' + platform + " doesn't exist"); } diff --git a/lib/transform/config.js b/lib/transform/config.js index 619afa8a4..8ed4265cd 100644 --- a/lib/transform/config.js +++ b/lib/transform/config.js @@ -30,7 +30,7 @@ const MISSING_TRANSFORM_ERRORS = GroupMessages.GROUP.MissingRegisterTransformErr */ export default function transformConfig(platformConfig, dictionary, platformName) { const to_ret = clone(platformConfig); - to_ret.log = dictionary.log; + to_ret.log = platformConfig.log ?? dictionary.log; // The platform can define either a transformGroup or an array // of transforms. If given a transformGroup that doesn't exist, @@ -131,17 +131,7 @@ None of ${transform_warnings} match the name of a registered transform. } } - if (file.template) { - if (dictionary.format[file.template]) { - GroupMessages.add( - TEMPLATE_DEPRECATION_WARNINGS, - `${file.destination} (template: ${file.template})`, - ); - ext.format = dictionary.format[file.template]; - } else { - throw new Error("Can't find template: " + file.template); - } - } else if (file.format) { + if (file.format) { if (dictionary.format[file.format]) { ext.format = dictionary.format[file.format]; } else {