From e432d8308e9d4cc3176bb5fc8afd883e714442e8 Mon Sep 17 00:00:00 2001 From: jorenbroekema Date: Tue, 28 Nov 2023 18:00:58 +0100 Subject: [PATCH] chore: update docs --- docs/_coverpage.md | 1 + docs/_sidebar.md | 1 + docs/api.md | 193 ++++++++++-------- docs/config.md | 12 +- docs/extending.md | 14 +- docs/formats.md | 38 +--- docs/parsers.md | 4 +- docs/quick_start.md | 13 +- docs/templates.md | 7 - docs/tokens.md | 10 +- docs/using_the_npm_module.md | 41 ++-- docs/version_4.md | 26 +++ lib/StyleDictionary.js | 18 +- .../formatHelpers/createPropertyFormatter.js | 17 +- lib/common/formatHelpers/fileHeader.js | 1 + .../formatHelpers/formattedVariables.js | 1 + lib/common/formatHelpers/getTypeScriptType.js | 1 + lib/common/formatHelpers/iconsWithPrefix.js | 1 + lib/common/formatHelpers/index.js | 4 + lib/common/formatHelpers/minifyDictionary.js | 1 + .../setComposeObjectProperties.js | 1 + .../formatHelpers/setSwiftFileProperties.js | 1 + lib/common/formatHelpers/sortByName.js | 1 + lib/common/formatHelpers/sortByReference.js | 1 + lib/register/preprocessor.js | 7 +- package-lock.json | 20 ++ package.json | 4 +- scripts/generateDocs.cjs | 41 ++-- 28 files changed, 273 insertions(+), 207 deletions(-) delete mode 100644 docs/templates.md create mode 100644 docs/version_4.md diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 00aae4947..9a05ec947 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -10,5 +10,6 @@ [Get Started](README.md) [See what's new in 3.0!](version_3.md) +[See what's new in 4.0!](version_4.md) ![color](#D9F8F5) diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 4707c7183..e905c5c6d 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -2,6 +2,7 @@ - [Overview](README.md) - [What's new in 3.0](version_3.md) + - [What's new in 4.0](version_4.md) - [Quick Start](quick_start.md) - [Examples](examples.md) - [Config](config.md) diff --git a/docs/api.md b/docs/api.md index 0ad28a9d3..d2c1e7194 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,13 +1,88 @@ - - # API -### buildAllPlatforms +## new StyleDictionary() + +> new StyleDictionary() ⇒ [style-dictionary](#module_style-dictionary) + +Create a new StyleDictionary instance. + +| Param | Type | Description | +| ------------ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| config | [Config](#Config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | +| options | Object | Options object when creating a new StyleDictionary instance. | +| options.init | Boolean | `true` by default but can be disabled to delay initializing the dictionary. You can then call `sdInstance.init()` yourself, e.g. for testing or error handling purposes. | + +**Example** + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary('config.json'); +const sdTwo = new StyleDictionary({ + source: ['tokens/*.json'], + platforms: { + scss: { + transformGroup: 'scss', + buildPath: 'build/', + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, + // ... + }, +}); +``` + +## init + +> StyleDictionary.init() ⇒ [Promise](#module_style-dictionary) + +Called automatically when doing `new StyleDictionary(config)` unless passing a second argument with `init` property set to `false`. In this scenario, you can call `.init()` manually, e.g. for testing or error handling purposes. + +## extend + +> StyleDictionary.extend(config) ⇒ [Promise](#module_style-dictionary) + +Extend a Style Dictionary instance with a config object, to create an extension instance. + +| Param | Type | Description | +| -------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| config | [Config](#Config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | +| mutateOriginal | [Boolean](#Config) | Whether or not the original SD instance should be mutated during extension. `false` by default. You will likely never need to set this to `true`, consider this argument private. | + +**Example** + +```js +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary('config.json'); + +const sdExtended = await sd.extend({ + source: ['tokens/*.json'], + platforms: { + scss: { + transformGroup: 'scss', + buildPath: 'build/', + files: [ + { + destination: 'variables.scss', + format: 'scss/variables', + }, + ], + }, + // ... + }, +}); +``` + +--- -> StyleDictionary.buildAllPlatforms() ⇒ [style-dictionary](#module_style-dictionary) +## buildAllPlatforms + +> StyleDictionary.buildAllPlatforms() ⇒ [Promise](#module_style-dictionary) The only top-level method that needs to be called to build the Style Dictionary. @@ -15,15 +90,19 @@ to build the Style Dictionary. **Example** ```js -const StyleDictionary = require('style-dictionary').extend('config.json'); -StyleDictionary.buildAllPlatforms(); +import StyleDictionary from 'style-dictionary'; +const sd = new StyleDictionary('config.json'); + +// Async, so you can do `await` or .then() if you +// want to execute code after buildAllPlatforms has completed +await sd.buildAllPlatforms(); ``` --- -### buildPlatform +## buildPlatform -> StyleDictionary.buildPlatform(platform) ⇒ [style-dictionary](#module_style-dictionary) +> StyleDictionary.buildPlatform(platform) ⇒ [Promise](#module_style-dictionary) Takes a platform and performs all transforms to the tokens object (non-mutative) then @@ -40,7 +119,9 @@ build each platform defined in the config. **Example** ```js -StyleDictionary.buildPlatform('web'); +// Async, so you can do `await` or .then() if you +// want to execute code after buildAllPlatforms has completed +await sd.buildPlatform('web'); ``` ```bash @@ -49,9 +130,9 @@ $ style-dictionary build --platform web --- -### cleanAllPlatforms +## cleanAllPlatforms -> StyleDictionary.cleanAllPlatforms() ⇒ [style-dictionary](#module_style-dictionary) +> StyleDictionary.cleanAllPlatforms() ⇒ [Promise](#module_style-dictionary) Does the reverse of [buildAllPlatforms](#buildAllPlatforms) by performing a clean on each platform. This removes all the files @@ -59,9 +140,9 @@ defined in the platform and calls the undo method on any actions. --- -### cleanPlatform +## cleanPlatform -> StyleDictionary.cleanPlatform(platform) ⇒ [style-dictionary](#module_style-dictionary) +> StyleDictionary.cleanPlatform(platform) ⇒ [Promise](#module_style-dictionary) Takes a platform and performs all transforms to the tokens object (non-mutative) then @@ -73,9 +154,9 @@ cleans all the files and performs the undo method of any [actions](actions.md). --- -### exportPlatform +## exportPlatform -> StyleDictionary.exportPlatform(platform) ⇒ Object +> StyleDictionary.exportPlatform(platform) ⇒ Promise Exports a tokens object with applied platform transforms. @@ -89,42 +170,7 @@ dictionary in JS build tools like webpack. --- -### extend - -> StyleDictionary.extend(config) ⇒ [style-dictionary](#module_style-dictionary) - -Create a Style Dictionary - -| Param | Type | Description | -| ------ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| config | [Config](#Config) | Configuration options to build your style dictionary. If you pass a string, it will be used as a path to a JSON config file. You can also pass an object with the configuration. | - -**Example** - -```js -const StyleDictionary = require('style-dictionary').extend('config.json'); - -const StyleDictionary = require('style-dictionary').extend({ - source: ['tokens/*.json'], - platforms: { - scss: { - transformGroup: 'scss', - buildPath: 'build/', - files: [ - { - destination: 'variables.scss', - format: 'scss/variables', - }, - ], - }, - // ... - }, -}); -``` - ---- - -### registerAction +## registerAction > StyleDictionary.registerAction(action) ⇒ [style-dictionary](#module_style-dictionary) @@ -165,7 +211,7 @@ StyleDictionary.registerAction({ --- -### registerFileHeader +## registerFileHeader > StyleDictionary.registerFileHeader(options) ⇒ [style-dictionary](#module_style-dictionary) @@ -191,7 +237,7 @@ StyleDictionary.registerFileHeader({ --- -### registerFilter +## registerFilter > StyleDictionary.registerFilter(filter) ⇒ [style-dictionary](#module_style-dictionary) @@ -216,7 +262,7 @@ StyleDictionary.registerFilter({ --- -### registerFormat +## registerFormat > StyleDictionary.registerFormat(format) ⇒ [style-dictionary](#module_style-dictionary) @@ -241,7 +287,7 @@ StyleDictionary.registerFormat({ --- -### registerParser +## registerParser > StyleDictionary.registerParser(pattern, parse) ⇒ [style-dictionary](#module_style-dictionary) @@ -265,7 +311,7 @@ StyleDictionary.registerParser({ --- -### registerPreprocessor +## registerPreprocessor > StyleDictionary.registerPreprocessor({ name, preprocessor }) => [style-dictionary](#module_style-dictionary) @@ -291,32 +337,7 @@ StyleDictionary.registerPreprocessor({ --- -### registerTemplate - -> ~~StyleDictionary.registerTemplate(template) ⇒ [style-dictionary](#module_style-dictionary)~~ - -**_Deprecated_** - -Add a custom template to the Style Dictionary - -| Param | Type | Description | -| ----------------- | ------------------- | --------------------------------------------------------------------------- | -| template | Object | | -| template.name | String | The name of your template. You will refer to this in your config.json file. | -| template.template | String | Path to your lodash template | - -**Example** - -```js -StyleDictionary.registerTemplate({ - name: 'Swift/colors', - template: __dirname + '/templates/swift/colors.template', -}); -``` - ---- - -### registerTransform +## registerTransform > StyleDictionary.registerTransform(transform) ⇒ [style-dictionary](#module_style-dictionary) @@ -352,7 +373,7 @@ StyleDictionary.registerTransform({ --- -### registerTransformGroup +## registerTransformGroup > StyleDictionary.registerTransformGroup(transformGroup) ⇒ [style-dictionary](#module_style-dictionary) diff --git a/docs/config.md b/docs/config.md index 13b28edf8..381329f4a 100644 --- a/docs/config.md +++ b/docs/config.md @@ -56,7 +56,7 @@ Here is an example using a CommonJS module for configuration: ```javascript // config.js -module.exports = { +export default { source: [`tokens/**/*.json`], // If you don't want to call the registerTransform method a bunch of times // you can override the whole transform object directly. This works because @@ -116,20 +116,20 @@ You can also use Style Dictionary as an [npm module](using_the_npm_module.md) an ```javascript // build.js -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; -const myStyleDictionary = StyleDictionary.extend({ +const myStyleDictionary = new StyleDictionary({ // configuration }); -myStyleDictionary.buildAllPlatforms(); +await myStyleDictionary.buildAllPlatforms(); // You can also extend Style Dictionary multiple times: -const myOtherStyleDictionary = myStyleDictionary.extend({ +const myOtherStyleDictionary = await myStyleDictionary.extend({ // new configuration }); -myOtherStyleDictionary.buildAllPlatforms(); +await myOtherStyleDictionary.buildAllPlatforms(); ``` You would then change your npm script or CLI command to run that file with Node: diff --git a/docs/extending.md b/docs/extending.md index 11b45aacc..a6f70bd9e 100644 --- a/docs/extending.md +++ b/docs/extending.md @@ -18,7 +18,7 @@ There is a straightforward way to extend Style Dictionary to meet your needs - s Importing a configuration, defining a new `time/seconds` transform, and building the style dictionary. ```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; StyleDictionary.registerTransform({ name: 'time/seconds', @@ -31,14 +31,16 @@ StyleDictionary.registerTransform({ }, }); -StyleDictionary.buildAllPlatforms(); +const sd = new StyleDictionary('config.json'); +await sd.buildAllPlatforms(); ``` Export your extended style dictionary as a node module (without building) if you need other projects to depend on it. ```javascript // package a -const StyleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; + StyleDictionary.registerTransform({ name: 'name/uppercase', type: 'name', @@ -47,8 +49,10 @@ StyleDictionary.registerTransform({ }, }); -module.exports = StyleDictionary; +const sd = new StyleDictionary('config.json'); + +export default sd; // package b -const StyleDictionary = require('package-a'); +import sd from 'package-a'; ``` diff --git a/docs/formats.md b/docs/formats.md index 97a2239d4..4032c2b5a 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -60,9 +60,9 @@ In this example we are adding the `mapName` configuration to the `scss/map-deep` A special file configuration is `filter`, which will filter the tokens before they get to the format. This allows you to re-use the same format to generate multiple files with different sets of tokens. Filtering tokens works by adding a `filter` attribute on the file object, where `filter` is: +- An object which gets passed to [Lodash's filter method](https://lodash.com/docs/4.17.14#filter). - A string that references the name of a registered filter, using the [`registerFilter`](api.md#registerfilter) method - A function that takes a token and returns a boolean if the token should be included (true) or excluded (false). **This is only available if you are defining your configuration in Javascript.** -- An object which is treated similar to [Lodash's matches method](https://lodash.com/docs/4.17.15#matches). ```javascript { @@ -361,8 +361,6 @@ Here are the available format helper methods: ### createPropertyFormatter -> formatHelpers.createPropertyFormatter(options) ⇒ function - Creates a function that can be used to format a property. This can be useful to use as the function on `dictionary.allTokens.map`. The formatting is configurable either by supplying a `format` option or a `formatting` object @@ -393,7 +391,7 @@ which uses: prefix, indentation, separator, suffix, and commentStyle. options.formattingObject

Custom formatting properties that define parts of a declaration line in code. The configurable strings are: prefix, indentation, separator, suffix, and commentStyle. Those are used to generate a line like this: ${indentation}${prefix}${prop.name}${separator} ${prop.value}${suffix}

- options.themeableBoolean

[false] - Whether properties should default to being themeable.

+ options.themeableBoolean

[false] - Whether tokens should default to being themeable.

@@ -419,8 +417,6 @@ StyleDictionary.registerFormat({ ### fileHeader -> formatHelpers.fileHeader(options) ⇒ String - This is for creating the comment at the top of generated files with the generated at date. It will use the custom file header if defined on the configuration, or use the default file header. @@ -441,7 +437,7 @@ default file header. options.commentStyleString

The only options are 'short' and 'xml', which will use the // or <!-- --> style comments respectively. Anything else will use /* style comments.

- options.formattingObject

Custom formatting tokens that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer.

+ options.formattingObject

Custom formatting properties that define parts of a comment in code. The configurable strings are: prefix, lineSeparator, header, and footer.

@@ -464,8 +460,6 @@ StyleDictionary.registerFormat({ ### formattedVariables -> formatHelpers.formattedVariables(options) ⇒ String - This is used to create lists of variables like Sass variables or CSS custom properties @@ -514,8 +508,6 @@ StyleDictionary.registerFormat({ ### getTypeScriptType -> formatHelpers.getTypeScriptType(value, options) ⇒ String - Given some value, returns a basic valid TypeScript type for that value. Supports numbers, strings, booleans, arrays and objects of any of those types. @@ -560,8 +552,6 @@ StyleDictionary.registerFormat({ ### iconsWithPrefix -> formatHelpers.iconsWithPrefix(prefix, allTokens, options) ⇒ String - This is used to create CSS (and CSS pre-processor) lists of icons. It assumes you are using an icon font and creates helper classes with the :before pseudo-selector to add a unicode character. @@ -601,8 +591,6 @@ StyleDictionary.registerFormat({ ### minifyDictionary -> formatHelpers.minifyDictionary(obj) ⇒ Object - Outputs an object stripping out everything except values
@@ -633,8 +621,6 @@ StyleDictionary.registerFormat({ ### setComposeObjectProperties -> formatHelpers.setComposeObjectProperties(options) ⇒ Object - Outputs an object for compose format configurations. Sets import.
@@ -654,8 +640,6 @@ Outputs an object for compose format configurations. Sets import. ### setSwiftFileProperties -> formatHelpers.setSwiftFileProperties(options, objectType, transformGroup) ⇒ Object - Outputs an object with swift format configurations. Sets import, object type and access control.
@@ -681,8 +665,6 @@ Outputs an object with swift format configurations. Sets import, object type and ### sortByName -> formatHelpers.sortByName(a, b) ⇒ Integer - A sorting function to be used when iterating over `dictionary.allTokens` in a format. @@ -722,8 +704,6 @@ StyleDictionary.registerFormat({ ### sortByReference -> formatHelpers.sortByReference(dictionary) ⇒ function - A function that returns a sorting function to be used with Array.sort that will sort the allTokens array based on references. This is to make sure if you use output references that you never use a reference before it is @@ -758,12 +738,13 @@ Any templating language can work as long as there is a node module for it. All y Here is a quick example for Lodash. ```js -const styleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; +const sd = await StyleDictionary.extend('config.json'); const _ = require('lodash'); const template = _.template(fs.readFileSync('templates/myFormat.template')); -styleDictionary.registerFormat({ +sd.registerFormat({ name: 'my/format', formatter: template, }); @@ -774,12 +755,13 @@ styleDictionary.registerFormat({ And another example for Handlebars. ```js -const styleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; +const sd = await StyleDictionary.extend('config.json'); const Handlebars = require('handlebars'); const template = Handlebars.compile(fs.readFileSync('templates/MyTemplate.hbs').toString()); -styleDictionary.registerFormat({ +sd.registerFormat({ name: 'my/format', formatter: function ({ dictionary, platform }) { return template({ @@ -1231,7 +1213,7 @@ StyleDictionaryPackage.registerFormat({ return ( 'declare const root: RootObject\n' + 'export default root\n' + - JsonToTS(dictionary.properties).join('\n') + JsonToTS(dictionary.tokens).join('\n') ); }, }); diff --git a/docs/parsers.md b/docs/parsers.md index 86639b02a..5d4934664 100644 --- a/docs/parsers.md +++ b/docs/parsers.md @@ -33,7 +33,7 @@ First you will need to tell Style Dictionary about your parser. You can do this ### .registerParser ```javascript -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; StyleDictionary.registerParser({ pattern: /\.json$/, @@ -46,7 +46,7 @@ StyleDictionary.registerParser({ ### Inline ```javascript -module.exports = { +export default { parsers: [ { pattern: /\.json$/, diff --git a/docs/quick_start.md b/docs/quick_start.md index ca02c390b..2648ebfe3 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -277,15 +277,18 @@ More detailed information about [using the Style Dictionary CLI is available her You can also use the style dictionary build system in node if you want to [extend](extending.md) the functionality or use it in another build system like Grunt or Gulp. ```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; -StyleDictionary.buildAllPlatforms(); +const sd = new StyleDictionary('config.json'); +await sd.buildAllPlatforms(); ``` -The `.extend()` method is an overloaded method that can also take a [configuration](config.md) object. +The StyleDictionary constructor can also take a [configuration](config.md) object. ```javascript -const StyleDictionary = require('style-dictionary').extend({ +import StyleDictionary from 'style-dictionary'; + +const sd = new StyleDictionary({ source: ['tokens/**/*.json'], platforms: { scss: { @@ -302,7 +305,7 @@ const StyleDictionary = require('style-dictionary').extend({ }, }); -StyleDictionary.buildAllPlatforms(); +await sd.buildAllPlatforms(); ``` More detailed information about [using the Style Dictionary npm module is available here](using_the_npm_module.md). diff --git a/docs/templates.md b/docs/templates.md deleted file mode 100644 index c9229f40b..000000000 --- a/docs/templates.md +++ /dev/null @@ -1,7 +0,0 @@ -# Templates - -Templates are deprecated in favor of [Formats](formats.md) and will be removed in the future. If you want to use a template, create a [Format that uses templating](formats.md?id=using-a-template-templating-engine-to-create-a-format). - -> _**Why are Templates being deprecated in favor of Formats?**_ - -> It is a simplification for users, no power is being removed. Anything you could do in a Template you can do in a Format. Since they both did the same thing people became confused on which method they were supposed to use for output. Even worse, we actually required you to specify if the output you wanted was defined as a format or as a template, even for those formats and templates included in Style Dictionary by default. This was a bad plan and caused problems for many users. Lastly, Style Dictionary aims to provide power and flexibility without forcing you to use any particular system, but only Lodash Templates were supported under the old template system. Using formats, you can use any templating engine you would like. diff --git a/docs/tokens.md b/docs/tokens.md index d6b6fb9d1..3c0cd1e74 100644 --- a/docs/tokens.md +++ b/docs/tokens.md @@ -133,7 +133,7 @@ Tokens can be defined _inline_ in the Style Dictionary configuration, or in file ```javascript // config.js -module.exports = { +export default { tokens: { color: { background: { @@ -150,7 +150,7 @@ module.exports = { Generally you will have too many design tokens to include them all inline, so you can separate them out into their own files. You can tell Style Dictionary where to find your design token files with the `source` and `include` attributes in the configuration like this: ```javascript -module.exports = { +export default { include: [ // you can list singular files: `node_modules/my-other-style-dictionary/tokens.json`, @@ -171,7 +171,7 @@ module.exports = { Style Dictionary takes all the files it finds in the include and source arrays and performs a deep merge on them. It will first add files in the include array, in order, and then the source array in order. Later files will take precedence. For example if you defined 2 source files like this: ```javascript -module.exports = { +export default { source: [`tokens.json`, `tokens2.json`], }; ``` @@ -221,7 +221,7 @@ This example would show a warning in the console that you have a collision at `c One way to write your design token files is to write them in Javascript rather than JSON. The only requirement for writing your source files in Javascript is to use a CommonJS module to export a plain object. For example: ```javascript -module.exports = { +export default { color: { base: { red: { value: '#ff0000' }, @@ -260,7 +260,7 @@ const baseColors = { // Use a reduce function to take the array of keys in baseColor // and map them to an object with the same keys. -module.exports = Object.keys(baseColors).reduce((ret, color) => { +export default Object.keys(baseColors).reduce((ret, color) => { return Object.assign({}, ret, { [color]: { // generate the shades/tints for each color diff --git a/docs/using_the_npm_module.md b/docs/using_the_npm_module.md index c86d47eb5..bcea8686c 100644 --- a/docs/using_the_npm_module.md +++ b/docs/using_the_npm_module.md @@ -41,9 +41,10 @@ Update "build.js" to the name of the file you created. Using a JSON [configuration](config.md) file, that looks like this: ```javascript -const StyleDictionary = require('style-dictionary').extend('config.json'); +import StyleDictionary from 'style-dictionary'; -StyleDictionary.buildAllPlatforms(); +const sd = new StyleDictionary('config.json'); +await sd.buildAllPlatforms(); ``` Alternatively, you can pass in a [configuration](config.md) object to the extend call. The `buildAllPlatforms` call is the same. @@ -72,38 +73,42 @@ StyleDictionary.buildAllPlatforms(); You can `extend` Style Dictionary multiple times and call `buildAllPlatforms` as many times as you need. This can be useful if you are creating nested (parent-child) themes with Style Dictionary. ```javascript -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; -const styleDictionary = StyleDictionary.extend({ +const sd = new StyleDictionary({ // add custom formats/transforms }); -styleDictionary - .extend({ +await ( + await sd.extend({ // ... }) - .buildAllPlatforms(); +).buildAllPlatforms(); -styleDictionary - .extend({ +await ( + await sd.extend({ // ... }) - .buildAllPlatforms(); +).buildAllPlatforms(); ``` Another way to do this is to loop over an array and apply different configurations to Style Dictionary: ```javascript -const StyleDictionary = require('style-dictionary'); +import StyleDictionary from 'style-dictionary'; const brands = [`brand-1`, `brand-2`, `brand-3`]; -brands.forEach((brand) => { - StyleDictionary.extend({ - include: [`tokens/default/**/*.json`], - source: [`tokens/${brand}/**/*.json`], - // ... - }).buildAllPlatforms(); -}); + +await Promise.all( + brands.map((brand) => { + const sd = new StyleDictionary({ + include: [`tokens/default/**/*.json`], + source: [`tokens/${brand}/**/*.json`], + // ... + }); + return sd.buildAllPlatforms(); + }), +); ``` The [multi-brand-multi-platform example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) uses this method. diff --git a/docs/version_4.md b/docs/version_4.md new file mode 100644 index 000000000..84b8dec3a --- /dev/null +++ b/docs/version_4.md @@ -0,0 +1,26 @@ +# Version 4 + +In May 2021, we started [an issue / RFC, "What would you like to see in Style-Dictionary 4.0?"](https://github.com/amzn/style-dictionary/issues/643) to gather feedback on what the community would like to see. +Fortunately, in August 2023, the folks at [Tokens Studio](https://tokens.studio/) contacted us about co-maintaining this project, and leading the v4 release (and beyond)! + +We have started working on the biggest and most important changes, like migrating to ESM, making the library browser-compatible out of the box, and supporting asynchronicity in Style-Dictionary's various APIs. There will be multiple prereleases to battle-test these changes before a final v4.0 is released. + +You can follow [this roadmap board](https://github.com/orgs/amzn/projects/4/views/1?layout=board) to keep an eye on the developments for v4.0, we will also keep adding to this board when we encounter changes we'd like to see in v4.0 that would entail a breaking change. Absence of something in this roadmap does not mean we don't see value in it, but rather that it could also be added in a (non-breaking) minor release within v4.x.x. + +## From the folks at Tokens Studio + +Hi everyone! I'm Joren from Tokens Studio, a big fan of this project (see [Style-Dictionary-Play](https://www.style-dictionary-play.dev/), [Token Configurator](https://configurator.tokens.studio/), [sd-transforms](https://github.com/tokens-studio/sd-transforms)) and the main pusher behind leading a 4.0 release of this project, I think it would be good to explain from our perspective why we've made the move to collaborate with Amazon on this. + +At Tokens Studio, we're a huge fan of Design Tokens and the workflows they enable. We believe exporting design tokens to various platforms is a key ingredient in ensuring that the journey from design to implementation code is smooth. +In our minds, Style-Dictionary has been the most popular and most flexible library for reaching that goal, and so we want to build on top of that. +Rather than starting our own spinoff tool, we much prefer bringing Style-Dictionary further, together with its vibrant community of contributors, which is why we reached out to Danny Banks. + +I think it's important to stress that it is our shared vision to keep Style-Dictionary as an agnostic (so not "Tokens Studio"-specific) and flexible tool. As Tokens Studio, while we are highly incentivized to see this project progress further to strengthen our product journey, we value the open source community highly and want to make sure this library remains the go-to tool for exporting Design Tokens, whether you use Tokens Studio or not. + +We are very open to feedback and collaboration, feel free to reach out to us in [our Slack](https://join.slack.com/t/tokens-studio/shared_invite/zt-1p8ea3m6t-C163oJcN9g3~YZTKRgo2hg) -> `style-dictionary-v4` channel! + +## List of Changes + +The prereleases will contain breaking changes, so it's important to read the list of changes since v3 if you're looking to migrate. + +You can find the list of changes in [our changelog on the v4 branch](https://github.com/amzn/style-dictionary/blob/v4/CHANGELOG.md) diff --git a/lib/StyleDictionary.js b/lib/StyleDictionary.js index 8c81071d5..ed0bb2303 100644 --- a/lib/StyleDictionary.js +++ b/lib/StyleDictionary.js @@ -51,6 +51,8 @@ import cleanActions from './cleanActions.js'; const PROPERTY_VALUE_COLLISIONS = GroupMessages.GROUP.PropertyValueCollisions; const PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; +// TODO: add Type interface for this class + /** * Style Dictionary module * @@ -69,17 +71,6 @@ export default class StyleDictionary { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility static VERSION = ''; static formatHelpers = formatHelpers; - - /** - * Below is a ton of boilerplate. Explanation: - * - * You can register things on the StyleDictionary class level e.g. StyleDictionary.registerFormat() - * You can also register these things on StyleDictionary instance (through config) or on StyleDictionary instance's platform property. - * - * Therefore, we have to make use of static props vs instance props and use getters and setters to merge these together. - * In the extend() method is where we merge config props into the SD instance. - * Platform specific options are handled and merged by exportPlatform -> transformConfig - */ static transform = transform; static transformGroup = transformGroup; static format = format; @@ -121,6 +112,11 @@ export default class StyleDictionary { return registerFileHeader.call(this, ...args); } + /** + * + * @param {Object|string} [config] + * @param {{ init: boolean }} [options] + */ constructor(config = {}, { init = true } = {}) { // dynamically add these instance methods to delegate to class methods for register [ diff --git a/lib/common/formatHelpers/createPropertyFormatter.js b/lib/common/formatHelpers/createPropertyFormatter.js index dd5b7640c..7a52caff8 100644 --- a/lib/common/formatHelpers/createPropertyFormatter.js +++ b/lib/common/formatHelpers/createPropertyFormatter.js @@ -79,6 +79,15 @@ function addComment(to_ret_prop, options) { * is configurable either by supplying a `format` option or a `formatting` object * which uses: prefix, indentation, separator, suffix, and commentStyle. * @memberof module:formatHelpers + * @name createPropertyFormatter + * @param {Object} options + * @param {Boolean} options.outputReferences - Whether or not to output references. You will want to pass this from the `options` object sent to the formatter function. + * @param {Boolean} options.outputReferenceFallbacks - Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the formatter function. + * @param {Dictionary} options.dictionary - The dictionary object sent to the formatter function + * @param {String} options.format - Available formats are: 'css', 'sass', 'less', and 'stylus'. If you want to customize the format and can't use one of those predefined formats, use the `formatting` option + * @param {Object} options.formatting - Custom formatting properties that define parts of a declaration line in code. The configurable strings are: prefix, indentation, separator, suffix, and commentStyle. Those are used to generate a line like this: `${indentation}${prefix}${prop.name}${separator} ${prop.value}${suffix}` + * @param {Boolean} options.themeable [false] - Whether tokens should default to being themeable. + * @returns {Function} * @example * ```javascript * StyleDictionary.registerFormat({ @@ -94,14 +103,6 @@ function addComment(to_ret_prop, options) { * } * }); * ``` - * @param {Object} options - * @param {Boolean} options.outputReferences - Whether or not to output references. You will want to pass this from the `options` object sent to the formatter function. - * @param {Boolean} options.outputReferenceFallbacks - Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the formatter function. - * @param {Dictionary} options.dictionary - The dictionary object sent to the formatter function - * @param {String} options.format - Available formats are: 'css', 'sass', 'less', and 'stylus'. If you want to customize the format and can't use one of those predefined formats, use the `formatting` option - * @param {Object} options.formatting - Custom formatting properties that define parts of a declaration line in code. The configurable strings are: prefix, indentation, separator, suffix, and commentStyle. Those are used to generate a line like this: `${indentation}${prefix}${prop.name}${separator} ${prop.value}${suffix}` - * @param {Boolean} options.themeable [false] - Whether tokens should default to being themeable. - * @returns {Function} */ export default function createPropertyFormatter({ outputReferences = false, diff --git a/lib/common/formatHelpers/fileHeader.js b/lib/common/formatHelpers/fileHeader.js index f589ab38e..4b426ceac 100644 --- a/lib/common/formatHelpers/fileHeader.js +++ b/lib/common/formatHelpers/fileHeader.js @@ -28,6 +28,7 @@ const defaultFormatting = { * It will use the custom file header if defined on the configuration, or use the * default file header. * @memberof module:formatHelpers + * @name fileHeader * @param {Object} options * @param {File} options.file - The file object that is passed to the formatter. * @param {String} options.commentStyle - The only options are 'short' and 'xml', which will use the // or \ style comments respectively. Anything else will use \/\* style comments. diff --git a/lib/common/formatHelpers/formattedVariables.js b/lib/common/formatHelpers/formattedVariables.js index 81e835854..659b53454 100644 --- a/lib/common/formatHelpers/formattedVariables.js +++ b/lib/common/formatHelpers/formattedVariables.js @@ -22,6 +22,7 @@ const defaultFormatting = { * * This is used to create lists of variables like Sass variables or CSS custom properties * @memberof module:formatHelpers + * @name formattedVariables * @param {Object} options * @param {String} options.format - What type of variables to output. Options are: css, sass, less, and stylus * @param {Object} options.dictionary - The dictionary object that gets passed to the formatter method. diff --git a/lib/common/formatHelpers/getTypeScriptType.js b/lib/common/formatHelpers/getTypeScriptType.js index 40ad40e9b..42eb0d869 100644 --- a/lib/common/formatHelpers/getTypeScriptType.js +++ b/lib/common/formatHelpers/getTypeScriptType.js @@ -16,6 +16,7 @@ * Supports numbers, strings, booleans, arrays and objects of any of those types. * * @memberof module:formatHelpers + * @name getTypeScriptType * @example * ```javascript * StyleDictionary.registerFormat({ diff --git a/lib/common/formatHelpers/iconsWithPrefix.js b/lib/common/formatHelpers/iconsWithPrefix.js index 045d86fbc..730f91eb9 100644 --- a/lib/common/formatHelpers/iconsWithPrefix.js +++ b/lib/common/formatHelpers/iconsWithPrefix.js @@ -18,6 +18,7 @@ * a unicode character. * __You probably don't need this.__ * @memberof module:formatHelpers + * @name iconsWithPrefix * @param {String} prefix - Character to prefix variable names, like '$' for Sass * @param {Token[]} allTokens - allTokens array on the dictionary object passed to the formatter function. * @param {Object} options - options object passed to the formatter function. diff --git a/lib/common/formatHelpers/index.js b/lib/common/formatHelpers/index.js index c750d91c2..17ce06517 100644 --- a/lib/common/formatHelpers/index.js +++ b/lib/common/formatHelpers/index.js @@ -11,6 +11,10 @@ * and limitations under the License. */ +/** + * @module formatHelpers + */ + export { default as createPropertyFormatter } from './createPropertyFormatter.js'; export { default as fileHeader } from './fileHeader.js'; export { default as formattedVariables } from './formattedVariables.js'; diff --git a/lib/common/formatHelpers/minifyDictionary.js b/lib/common/formatHelpers/minifyDictionary.js index 3b916a6c3..3316defee 100644 --- a/lib/common/formatHelpers/minifyDictionary.js +++ b/lib/common/formatHelpers/minifyDictionary.js @@ -14,6 +14,7 @@ /** * Outputs an object stripping out everything except values * @memberof module:formatHelpers + * @name minifyDictionary * @param {Object} obj - The object to minify. You will most likely pass `dictionary.tokens` to it. * @returns {Object} * @example diff --git a/lib/common/formatHelpers/setComposeObjectProperties.js b/lib/common/formatHelpers/setComposeObjectProperties.js index 1fb23851f..96bd9cacb 100644 --- a/lib/common/formatHelpers/setComposeObjectProperties.js +++ b/lib/common/formatHelpers/setComposeObjectProperties.js @@ -14,6 +14,7 @@ /** * Outputs an object for compose format configurations. Sets import. * @memberof module:formatHelpers + * @name setComposeObjectProperties * @param {Object} options - The options object declared at configuration * @returns {Object} */ diff --git a/lib/common/formatHelpers/setSwiftFileProperties.js b/lib/common/formatHelpers/setSwiftFileProperties.js index 54ee930c9..a4d78fd70 100644 --- a/lib/common/formatHelpers/setSwiftFileProperties.js +++ b/lib/common/formatHelpers/setSwiftFileProperties.js @@ -14,6 +14,7 @@ /** * Outputs an object with swift format configurations. Sets import, object type and access control. * @memberof module:formatHelpers + * @name setSwiftFileProperties * @param {Object} options - The options object declared at configuration * @param {String} objectType - The type of the object in the final file. Could be a class, enum, struct, etc. * @param {String} transformGroup - The transformGroup of the file, so it can be applied proper import diff --git a/lib/common/formatHelpers/sortByName.js b/lib/common/formatHelpers/sortByName.js index f501d7a30..c594721f4 100644 --- a/lib/common/formatHelpers/sortByName.js +++ b/lib/common/formatHelpers/sortByName.js @@ -15,6 +15,7 @@ * A sorting function to be used when iterating over `dictionary.allTokens` in * a format. * @memberof module:formatHelpers + * @name sortByName * @example * ```javascript * StyleDictionary.registerFormat({ diff --git a/lib/common/formatHelpers/sortByReference.js b/lib/common/formatHelpers/sortByReference.js index 01c4629c1..35e055106 100644 --- a/lib/common/formatHelpers/sortByReference.js +++ b/lib/common/formatHelpers/sortByReference.js @@ -17,6 +17,7 @@ * if you use output references that you never use a reference before it is * defined. * @memberof module:formatHelpers + * @name sortByReference * @example * ```javascript * dictionary.allTokens.sort(sortByReference(dictionary)) diff --git a/lib/register/preprocessor.js b/lib/register/preprocessor.js index c62f1dbf4..828a15d14 100644 --- a/lib/register/preprocessor.js +++ b/lib/register/preprocessor.js @@ -13,12 +13,13 @@ /** * @typedef {import('../../types/Preprocessor').Preprocessor} Preprocessor + */ + +/** * Adds a custom preprocessor to preprocess the parsed dictionary, before transforming individual tokens. * @static * @memberof module:style-dictionary - * @param {Object} Preprocessor - Preprocessor object - * @param {String} Preprocessor.name - Name of the format to be referenced in your config.json - * @param {function} Preprocessor.preprocessor - Function to preprocess the dictionary. The function should return a plain Javascript object. + * @param {Preprocessor} cfg - Preprocessor object * @returns {module:style-dictionary} * @example * ```js diff --git a/package-lock.json b/package-lock.json index 2ce01a0f7..765caac2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "style-dictionary": "bin/style-dictionary" }, "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@changesets/cli": "^2.26.2", "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^16.0.0", @@ -821,6 +822,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", diff --git a/package.json b/package.json index eb00e9690..7b1213fbe 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,7 @@ "generate-docs": "node ./scripts/generateDocs.cjs", "serve-docs": "docsify serve docs -p 3000 -P 12345", "install-cli": "npm install -g $(npm pack)", - "release": "node scripts/inject-version.js && changeset publish", - "postrelease": "node ./scripts/version.cjs && npm run generate-docs", + "release": "node ./scripts/version.cjs && npm run generate-docs && node scripts/inject-version.js && changeset publish", "prepare": "husky install", "postinstall": "patch-package" }, @@ -116,6 +115,7 @@ "tinycolor2": "^1.6.0" }, "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@changesets/cli": "^2.26.2", "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^16.0.0", diff --git a/scripts/generateDocs.cjs b/scripts/generateDocs.cjs index 5ab6e3c05..55a0d18b6 100644 --- a/scripts/generateDocs.cjs +++ b/scripts/generateDocs.cjs @@ -10,24 +10,24 @@ EDIT ${source} OR JSDOC COMMENT INSTEAD! ${input}`; } -const DOCS_PATH = './docs/api.md'; -const docs = jsdoc2md.renderSync({ - files: ['fs.js', 'fs-node.js', 'lib/**/*.js'], - template: fs.readFileSync('scripts/handlebars/templates/api.hbs').toString(), - // 'no-gfm': true, - separators: true, - partial: [ - 'scripts/handlebars/header.hbs', - 'scripts/handlebars/sig-name.hbs', - 'scripts/handlebars/body.hbs', - ], - configure: '.jsdoc.json', -}); +// TODO: re-enable automatic generation of API docs via template and JSDocs +// const DOCS_PATH = './docs/api.md'; +// const docs = jsdoc2md.renderSync({ +// files: ['lib/**/*.js'], +// template: fs.readFileSync('scripts/handlebars/templates/api.hbs').toString(), +// // 'no-gfm': true, +// separators: true, +// partial: [ +// 'scripts/handlebars/header.hbs', +// 'scripts/handlebars/sig-name.hbs', +// 'scripts/handlebars/body.hbs', +// ], +// configure: '.jsdoc.json', +// }); -fs.ensureFileSync(DOCS_PATH); -fs.writeFileSync(DOCS_PATH, prependWarning(docs, 'scripts/handlebars/templates/api.hbs')); -execSync(`git add ${DOCS_PATH}`); -console.log(DOCS_PATH + ' generated.'); +// fs.ensureFileSync(DOCS_PATH); +// fs.writeFileSync(DOCS_PATH, prependWarning(docs, 'scripts/handlebars/templates/api.hbs')); +// console.log(DOCS_PATH + ' generated.'); const TRANSFORMS_PATH = './docs/transforms.md'; const transforms = jsdoc2md.renderSync({ @@ -44,7 +44,6 @@ fs.writeFileSync( TRANSFORMS_PATH, prependWarning(transforms, 'scripts/handlebars/templates/api.hbs'), ); -execSync(`git add ${TRANSFORMS_PATH}`); console.log(TRANSFORMS_PATH + ' generated.'); const TRANSFORM_GROUPS_PATH = './docs/transform_groups.md'; @@ -62,7 +61,6 @@ fs.writeFileSync( TRANSFORM_GROUPS_PATH, prependWarning(transform_groups, 'scripts/handlebars/templates/api.hbs'), ); -execSync(`git add ${TRANSFORM_GROUPS_PATH}`); console.log(TRANSFORM_GROUPS_PATH + ' generated.'); const ACTIONS_PATH = './docs/actions.md'; @@ -77,7 +75,6 @@ const actions = jsdoc2md.renderSync({ fs.ensureFileSync(ACTIONS_PATH); fs.writeFileSync(ACTIONS_PATH, prependWarning(actions, 'scripts/handlebars/templates/api.hbs')); -execSync(`git add ${ACTIONS_PATH}`); console.log(ACTIONS_PATH + ' generated.'); const FORMATS_PATH = './docs/formats.md'; @@ -92,5 +89,7 @@ const formats = jsdoc2md.renderSync({ fs.ensureFileSync(FORMATS_PATH); fs.writeFileSync(FORMATS_PATH, prependWarning(formats, 'scripts/handlebars/templates/api.hbs')); -execSync(`git add ${FORMATS_PATH}`); console.log(FORMATS_PATH + ' generated.'); + +execSync(`npm run format:prettier`); +execSync(`git add ./docs/`);