From 048bbab4dafba0b7639f2042903896e64c2a698e Mon Sep 17 00:00:00 2001 From: Danny Banks Date: Wed, 12 May 2021 16:08:02 -0700 Subject: [PATCH] chore(docs): v3 docs update (#617) Fixes #571 #159 #605 * Renamed "style properties" to "design tokens" * Adding tokens and allTokens to the core internal data structure to be consistent with this change. This is purely additional, properties and allProperties still exist and this should not break existing code. Moving forward examples should use tokens rather than properties. * properties.md -> tokens.md * Adding more content in this doc page about: * All potential attributes #605 * Default attributes Style Dictionary adds * More info on what categories the CTI currently supports #571 * Information on file formats for token files, including JS modules #159, and custom parsers for token files * Updated broken links (linking to "master" branch instead of "main") * Updated the examples page with all new examples * Added a page on custom parsers * Added information about transitive transforms * Removed "docs/build_process.md" in favor of "docs/architecture.md" because the content was mostly the same. * Cleaned up configuration content * Updated language around config file formats and how to define the configuration * Added information about configuration attributes and separated it out into sections: top-level config attributes including customization, platform attributes, and file attributes, for readability * Cleaning up some spacing and headers in markdown files --- CONTRIBUTING.md | 6 +- README.md | 58 +- .../__snapshots__/customFormats.test.js.snap | 686 +++++++++++++++++- __tests__/formats/scssVariables.test.js | 2 +- docs/README.md | 20 +- docs/_sidebar.md | 4 +- docs/actions.md | 6 +- docs/api.md | 38 +- docs/architecture.md | 20 +- docs/assets/styles.css | 3 +- docs/build_process.md | 16 - docs/config.md | 190 +++-- docs/examples.md | 45 +- docs/extending.md | 1 + docs/formats.md | 58 +- docs/package_structure.md | 6 +- docs/parsers.md | 71 ++ docs/properties.md | 167 ----- docs/quick_start.md | 24 +- docs/tokens.md | 398 ++++++++++ docs/transform_groups.md | 8 +- docs/transforms.md | 144 ++-- docs/using_the_cli.md | 52 +- docs/using_the_npm_module.md | 69 +- examples/README.md | 52 +- .../advanced/assets-base64-embed/README.md | 8 +- .../advanced/assets-base64-embed/config.json | 2 +- .../{properties => tokens}/assets/fonts.json | 0 .../{properties => tokens}/assets/icons.json | 0 .../{properties => tokens}/assets/images.json | 0 .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/size/font.json | 0 .../advanced/auto-rebuild-watcher/README.md | 10 +- .../advanced/auto-rebuild-watcher/config.json | 2 +- .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/size/font.json | 0 .../advanced/custom-file-header/README.md | 2 +- examples/advanced/custom-file-header/build.js | 6 +- .../custom-formats-with-templates/build.js | 12 +- .../templates/android-xml.template | 4 +- .../templates/android-xml_alt.hbs | 2 +- .../templates/ios-plist.template | 4 +- .../templates/ios-plist_alt.pug | 16 +- .../templates/web-scss.template | 2 +- examples/advanced/custom-transforms/README.md | 30 +- examples/advanced/custom-transforms/build.js | 48 +- .../{properties => tokens}/button.json | 0 .../{properties => tokens}/colors.json | 0 .../{properties => tokens}/font.json | 0 .../{properties => tokens}/spacing.json | 0 .../advanced/matching-build-files/README.md | 10 +- .../advanced/matching-build-files/config.js | 8 +- .../{properties => tokens}/button/base.json | 0 .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/index.js | 0 .../{properties => tokens}/size/base.json | 0 .../multi-brand-multi-platform/README.md | 32 +- .../multi-brand-multi-platform/build.js | 6 +- .../brands/brand-1/color.json | 0 .../brands/brand-2/color.json | 0 .../brands/brand-3/color.json | 0 .../globals/button.json | 0 .../globals/color/base.json | 0 .../globals/color/font.json | 0 .../globals/font/index.json | 0 .../globals/size/font.json | 0 .../platforms/android/button.json | 0 .../platforms/android/font.json | 0 .../platforms/ios/button.json | 0 .../platforms/ios/font.json | 0 .../platforms/web/button.json | 0 .../platforms/web/font.json | 0 .../README.md | 12 +- .../config.js | 32 +- .../color/background.js | 0 .../{properties => tokens}/color/border.js | 0 .../{properties => tokens}/color/brand.js | 0 .../{properties => tokens}/color/core.js | 0 .../{properties => tokens}/color/font.js | 0 .../{properties => tokens}/color/index.js | 0 .../{properties => tokens}/index.js | 0 .../{properties => tokens}/size/border.js | 0 .../{properties => tokens}/size/font.js | 0 .../{properties => tokens}/size/index.js | 0 .../{properties => tokens}/size/padding.js | 0 examples/advanced/npm-module/config.json | 2 +- .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/size/font.json | 0 .../advanced/referencing_aliasing/README.md | 16 +- .../advanced/referencing_aliasing/config.json | 2 +- .../{properties => tokens}/button/button.json | 0 .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/globals.json | 0 .../{properties => tokens}/size/font.json | 0 .../advanced/tokens-deprecation/README.md | 6 +- .../advanced/tokens-deprecation/config.json | 2 +- .../advanced/tokens-deprecation/package.json | 2 +- .../templates/ios-plist.template | 2 +- .../templates/web-scss.template | 2 +- .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/size/font.json | 0 .../advanced/variables-in-outputs/README.md | 2 +- .../variables-in-outputs/sd.config.js | 2 +- examples/basic/README.md | 10 +- examples/basic/config.json | 2 +- .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/size/font.json | 0 examples/complete/README.md | 5 +- examples/complete/config.json | 2 +- .../{properties => tokens}/asset/font.json | 0 .../color/background.json | 0 .../{properties => tokens}/color/base.json | 0 .../{properties => tokens}/color/border.json | 0 .../{properties => tokens}/color/brand.json | 0 .../{properties => tokens}/color/chart.json | 0 .../{properties => tokens}/color/font.json | 0 .../{properties => tokens}/content/icon.json | 0 .../complete/{properties => tokens}/font.json | 0 .../{properties => tokens}/size/font.json | 0 .../{properties => tokens}/size/icon.json | 0 .../{properties => tokens}/size/padding.json | 0 .../complete/{properties => tokens}/time.json | 0 index.js | 4 + lib/buildFile.js | 2 + lib/buildFiles.js | 4 +- lib/buildPlatform.js | 2 +- lib/cleanFiles.js | 4 +- lib/cleanPlatform.js | 11 +- lib/common/actions.js | 19 +- .../formatHelpers/createPropertyFormatter.js | 4 +- lib/common/formatHelpers/fileHeader.js | 2 +- .../formatHelpers/formattedVariables.js | 6 +- lib/common/formatHelpers/iconsWithPrefix.js | 20 +- lib/common/formatHelpers/minifyDictionary.js | 4 +- lib/common/formatHelpers/sortByName.js | 4 +- lib/common/formatHelpers/sortByReference.js | 4 +- lib/common/formats.js | 82 +-- lib/common/templates/android/colors.template | 2 +- lib/common/templates/android/dimens.template | 2 +- .../templates/android/fontDimens.template | 2 +- .../templates/android/integers.template | 2 +- .../templates/android/resources.template | 2 +- lib/common/templates/android/strings.template | 2 +- .../templates/flutter/class.dart.template | 2 +- .../templates/ios-swift/class.swift.template | 2 +- .../templates/ios-swift/enum.swift.template | 2 +- lib/common/templates/ios/colors.h.template | 2 +- lib/common/templates/ios/colors.m.template | 2 +- lib/common/templates/ios/macros.template | 2 +- lib/common/templates/ios/plist.template | 2 +- lib/common/templates/ios/static.h.template | 2 +- lib/common/templates/ios/static.m.template | 2 +- lib/common/templates/ios/strings.h.template | 2 +- lib/common/templates/ios/strings.m.template | 4 +- lib/common/templates/scss/map-deep.template | 2 +- lib/common/templates/scss/map-flat.template | 2 +- .../static-style-guide/index.html.template | 2 +- lib/common/transformGroups.js | 4 +- lib/common/transforms.js | 340 ++++----- lib/exportPlatform.js | 2 +- lib/extend.js | 33 +- lib/filterProperties.js | 6 +- lib/register/action.js | 2 +- lib/register/filter.js | 6 +- lib/register/format.js | 10 +- lib/register/parser.js | 2 +- lib/register/transform.js | 16 +- lib/transform/object.js | 2 +- lib/utils/createDictionary.js | 15 +- scripts/handlebars/templates/actions.hbs | 6 +- scripts/handlebars/templates/formats.hbs | 16 +- .../handlebars/templates/transform_groups.hbs | 4 +- scripts/handlebars/templates/transforms.hbs | 66 +- 179 files changed, 2224 insertions(+), 969 deletions(-) delete mode 100644 docs/build_process.md create mode 100644 docs/parsers.md delete mode 100644 docs/properties.md create mode 100644 docs/tokens.md rename examples/advanced/assets-base64-embed/{properties => tokens}/assets/fonts.json (100%) rename examples/advanced/assets-base64-embed/{properties => tokens}/assets/icons.json (100%) rename examples/advanced/assets-base64-embed/{properties => tokens}/assets/images.json (100%) rename examples/advanced/assets-base64-embed/{properties => tokens}/color/base.json (100%) rename examples/advanced/assets-base64-embed/{properties => tokens}/color/font.json (100%) rename examples/advanced/assets-base64-embed/{properties => tokens}/size/font.json (100%) rename examples/advanced/auto-rebuild-watcher/{properties => tokens}/color/base.json (100%) rename examples/advanced/auto-rebuild-watcher/{properties => tokens}/color/font.json (100%) rename examples/advanced/auto-rebuild-watcher/{properties => tokens}/size/font.json (100%) rename examples/advanced/custom-transforms/{properties => tokens}/button.json (100%) rename examples/advanced/custom-transforms/{properties => tokens}/colors.json (100%) rename examples/advanced/custom-transforms/{properties => tokens}/font.json (100%) rename examples/advanced/custom-transforms/{properties => tokens}/spacing.json (100%) rename examples/advanced/matching-build-files/{properties => tokens}/button/base.json (100%) rename examples/advanced/matching-build-files/{properties => tokens}/color/base.json (100%) rename examples/advanced/matching-build-files/{properties => tokens}/index.js (100%) rename examples/advanced/matching-build-files/{properties => tokens}/size/base.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/brands/brand-1/color.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/brands/brand-2/color.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/brands/brand-3/color.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/globals/button.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/globals/color/base.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/globals/color/font.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/globals/font/index.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/globals/size/font.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/android/button.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/android/font.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/ios/button.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/ios/font.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/web/button.json (100%) rename examples/advanced/multi-brand-multi-platform/{properties => tokens}/platforms/web/font.json (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/background.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/border.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/brand.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/core.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/font.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/color/index.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/index.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/size/border.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/size/font.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/size/index.js (100%) rename examples/advanced/node-modules-as-config-and-properties/{properties => tokens}/size/padding.js (100%) rename examples/advanced/npm-module/{properties => tokens}/color/base.json (100%) rename examples/advanced/npm-module/{properties => tokens}/color/font.json (100%) rename examples/advanced/npm-module/{properties => tokens}/size/font.json (100%) rename examples/advanced/referencing_aliasing/{properties => tokens}/button/button.json (100%) rename examples/advanced/referencing_aliasing/{properties => tokens}/color/base.json (100%) rename examples/advanced/referencing_aliasing/{properties => tokens}/color/font.json (100%) rename examples/advanced/referencing_aliasing/{properties => tokens}/globals.json (100%) rename examples/advanced/referencing_aliasing/{properties => tokens}/size/font.json (100%) rename examples/advanced/tokens-deprecation/{properties => tokens}/color/base.json (100%) rename examples/advanced/tokens-deprecation/{properties => tokens}/color/font.json (100%) rename examples/advanced/tokens-deprecation/{properties => tokens}/size/font.json (100%) rename examples/basic/{properties => tokens}/color/base.json (100%) rename examples/basic/{properties => tokens}/color/font.json (100%) rename examples/basic/{properties => tokens}/size/font.json (100%) rename examples/complete/{properties => tokens}/asset/font.json (100%) rename examples/complete/{properties => tokens}/color/background.json (100%) rename examples/complete/{properties => tokens}/color/base.json (100%) rename examples/complete/{properties => tokens}/color/border.json (100%) rename examples/complete/{properties => tokens}/color/brand.json (100%) rename examples/complete/{properties => tokens}/color/chart.json (100%) rename examples/complete/{properties => tokens}/color/font.json (100%) rename examples/complete/{properties => tokens}/content/icon.json (100%) rename examples/complete/{properties => tokens}/font.json (100%) rename examples/complete/{properties => tokens}/size/font.json (100%) rename examples/complete/{properties => tokens}/size/icon.json (100%) rename examples/complete/{properties => tokens}/size/padding.json (100%) rename examples/complete/{properties => tokens}/time.json (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef1293cd8..4bdb1f771 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ We use npm as our package manager. After downloading the repo, please use the co We use ESLint on the code to ensure a consistent style. Any new code committed must pass our ESLint tests. Take a look at our [ESLint file][eslint]. ### Code Rules -1. **Do not mutate property names or values in a format.** Mutations like this should happen in a transformer. +1. **Do not mutate token names or values in a format.** Mutations like this should happen in a transformer. 1. **Be as generic as possible.** Do not hard-code any values or configuration in formats. 1. **Fail loudly.** Users should be aware if something is missing or configurations aren't correct. This will help debug any issues instead of failing silently. 1. **Rely on few dependencies.** This framework is meant to be extended and allows for customization. We don't want to bring a slew of dependencies that most people don't need. @@ -82,6 +82,6 @@ We use [docsify](https://docsify.js.org/#/) to transform the markdown files into [issues]: https://github.com/amzn/style-dictionary/issues [pr]: https://github.com/amzn/style-dictionary/pulls -[license]: https://github.com/amzn/style-dictionary/blob/master/LICENSE +[license]: https://github.com/amzn/style-dictionary/blob/main/LICENSE [cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement -[eslint]: https://github.com/amzn/style-dictionary/blob/master/.eslintrc.json +[eslint]: https://github.com/amzn/style-dictionary/blob/main/.eslintrc.json diff --git a/README.md b/README.md index 265753633..78adb6f25 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,16 @@ [![npm version](https://img.shields.io/npm/v/style-dictionary.svg?style=flat-square)](https://badge.fury.io/js/style-dictionary) ![license](https://img.shields.io/npm/l/style-dictionary.svg?style=flat-square) -[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/amzn/style-dictionary/blob/master/CONTRIBUTING.md#submitting-pull-requests) -
-[![Build Status](https://img.shields.io/travis/amzn/style-dictionary.svg?style=flat-square)](https://travis-ci.org/amzn/style-dictionary) +[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md#submitting-pull-requests) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/amzn/style-dictionary/Test?style=flat-square)](https://github.com/amzn/style-dictionary/actions/workflows/test.yml) [![downloads](https://img.shields.io/npm/dm/style-dictionary.svg?style=flat-square)](https://www.npmjs.com/package/style-dictionary) # Style Dictionary > *Style once, use everywhere.* -A Style Dictionary uses design tokens to define styles once and use those styles on any platform or language. It provides a single place to create and edit your styles, and exports these properties to all the places you need - iOS, Android, CSS, JS, HTML, sketch files, style documentation, etc. It is available as a CLI through npm, but can also be used like any normal node module if you want to extend its functionality. +A Style Dictionary uses design tokens to define styles once and use those styles on any platform or language. It provides a single place to create and edit your styles, and exports these tokens to all the places you need - iOS, Android, CSS, JS, HTML, sketch files, style documentation, etc. It is available as a CLI through npm, but can also be used like any normal node module if you want to extend its functionality. -When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. StyleDictionary solves this by automatically generating style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across your workflow. +When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. Style Dictionary solves this by automatically generating style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across your workflow. For detailed usage head to https://amzn.github.io/style-dictionary @@ -24,7 +23,7 @@ For detailed usage head to https://amzn.github.io/style-dictionary * [Usage](#usage) * [Example](#example) * [Quick Start](#quick-start) -* [Style Properties](#style-properties) +* [Design Tokens](#design-tokens) * [Extending](#extending) * [Contributing](#contributing) * [License](#license) @@ -73,7 +72,7 @@ StyleDictionary.buildAllPlatforms(); The `.extend()` method is an overloaded method that can also take an object with the configuration in the same format as a config.json file. ```javascript const StyleDictionary = require('style-dictionary').extend({ - source: ['properties/**/*.json'], + source: ['tokens/**/*.json'], platforms: { scss: { transformGroup: 'scss', @@ -93,10 +92,11 @@ StyleDictionary.buildAllPlatforms(); ## Example [Take a look at some of our examples](examples/) -A style dictionary is a collection of style properties, key/value pairs that describe stylistic attributes like colors, sizes, icons, motion, etc. A style dictionary defines these style properties in JSON files, and can also include static assets like images and fonts. Here is a basic example of what the package structure can look like: +A style dictionary is a collection of design tokens, key/value pairs that describe stylistic attributes like colors, sizes, icons, motion, etc. A style dictionary defines these design tokens in JSON or Javascript files, and can also include static assets like images and fonts. Here is a basic example of what the package structure can look like: + ``` ├── config.json -├── properties/ +├── tokens/ │ ├── size/ │ ├── font.json │ ├── color/ @@ -108,10 +108,11 @@ A style dictionary is a collection of style properties, key/value pairs that des ``` ### config.json -This tells the style dictionary build system how and what to build. The default file path is config.json in the root of the project, but you can name it whatever you want, you can pass in the `--config` flag. +This tells the style dictionary build system how and what to build. The default file path is `config.json` or `config.js` in the root of the project, but you can name it whatever you want by passing in the `--config` flag to the [CLI](https://amzn.github.io/style-dictionary/#/using_the_cli). + ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", @@ -132,13 +133,14 @@ This tells the style dictionary build system how and what to build. The default } } ``` + | Attribute | Type | Description | | :--- | :--- | :--- | -| source | Array | Paths to the property json files. Can have globs. | +| source | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files files however you want. | +| include | Array | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. The Style Dictionary uses this as a base collection of tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | | platforms | Object | Sets of platform files to be built. | -| platforms | Array | Paths to the property json files. Can have globs. | -| platform.transformGroup | String (optional) | Apply a group of transforms to the properties, must either define this or `transforms`. | -| platform.transforms | Array (optional) | Transforms to apply sequentially to all properties. Can be a built-in one or you can create your own. | +| platform.transformGroup | String (optional) | Apply a group of transforms to the tokens, must either define this or `transforms`. | +| platform.transforms | Array (optional) | Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. | | platform.buildPath | String (optional) | Base path to build the files, must end with a trailing slash. | | platform.files | Array (optional) | Files to be generated for this platform. | | platform.file.destination | String (optional) | Location to build the file, will be appended to the buildPath. | @@ -146,7 +148,8 @@ This tells the style dictionary build system how and what to build. The default | platform.file.options | Object (optional) | A set of extra options associated with the file. | | platform.file.options.showFileHeader | Boolean | If the generated file should have a "Do not edit + Timestamp" header (where the format supports it). By default is "true". | -### Properties +### Design Tokens + ```json { "size": { @@ -160,7 +163,7 @@ This tells the style dictionary build system how and what to build. The default } ``` -Here we are creating some basic font size properties. The style definition size.font.small.value is "10px" for example. The style definition size.font.base.value is automatically aliased to the value found in size.font.medium.value and both of those resolve to "16px". +Here we are creating some basic font size design tokens. The style definition size.font.small.value is "10px" for example. The style definition size.font.base.value is automatically aliased to the value found in size.font.medium.value and both of those resolve to "16px". Now what the style dictionary build system will do with this information is convert it to different formats, enabling these values to be used in any type of codebase. From this one file you can generate any number of files like: @@ -187,16 +190,21 @@ float const SizeFontBase = 16.00f; ## Quick Start + The style dictionary framework comes with some example code to get you stared. Install the node module globally, create a directory and `cd` into it. + ``` $ npm i -g style-dictionary $ mkdir MyStyleDictionary $ cd MyStyleDictionary ``` + Now run: + ``` $ style-dictionary init basic ``` + This command will copy over the example files found in [example](examples/) in this repo. Now you have an example project set up. You can make changes to the style dictionary and rebuild the project by running: ``` @@ -206,13 +214,13 @@ $ style-dictionary build Take a look at the documentation for the example code. -## Style Properties +## Design Tokens -A style property is an attribute to describe something visually. It is atomic (it cannot be broken down further). Style properties have a name, a value, and optional attributes or metadata. The name of a property can be anything, but we have a proposed naming structure that works really well in the next section. +A design token is an attribute to describe something visually. It is atomic (it cannot be broken down further). Design tokens have a name, a value, and optional attributes or metadata. The name of a token can be anything, but we have a proposed naming structure that we find works really well in the next section. ### Category/Type/Item Structure -While not exactly necessary, we feel this classification structure of style properties makes the most sense semantically. Style properties can be organized into a hierarchical tree structure with the top level, category, defining the primitive nature of the property. For example, we have the color category and every property underneath is always a color. As you proceed down the tree to type, item, sub-item, and state, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. Now you can structure your property json files like simple objects: +While not exactly necessary, we feel this classification structure of design tokens makes the most sense semantically. Design tokens can be organized into a hierarchical tree structure with the top level, category, defining the primitive nature of the token. For example, we have the color category and every token underneath is always a color. As you proceed down the tree to type, item, sub-item, and state, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. Now you can structure your token json files like simple objects: ``` { @@ -225,15 +233,15 @@ While not exactly necessary, we feel this classification structure of style prop } ``` - The CTI is implicit in the structure, the category and type is 'size' and 'font', and there are 2 properties 'base' and 'large'. +The CTI is implicit in the structure, the category and type is 'size' and 'font', and there are 2 tokens 'base' and 'large'. - Structuring style properties in this manner gives us consistent naming and accessing of these properties. You don't need to remember if it is button_color_error or error_button_color, it is color_background_button_error! +Structuring design tokens in this manner gives us consistent naming and accessing of these tokens. You don't need to remember if it is button_color_error or error_button_color, it is color_background_button_error! - You can organize and name your style properties however you want, there are no restrictions. But we have a good amount of helpers if you do use this structure, like the 'attribute/cti' transform which adds attributes to the property of its CTI based on the path in the object. There are a lot of name transforms as well for when you want a flat structure like for Sass variables. +You can organize and name your design tokens however you want, there are no restrictions. But we have a good amount of helpers if you do use this structure, like the 'attribute/cti' transform which adds attributes to the token of its CTI based on the path in the object. There are a lot of name transforms as well for when you want a flat structure like for Sass variables. - Also, the CTI structure provides a good mechanism to target transforms for specific kinds of properties. All of the transforms provided by the framework use the CTI of a property to know if it should be applied. For instance, the 'color/hex' transform only applies to properties of the category 'color'. +Also, the CTI structure provides a good mechanism to target transforms for specific kinds of tokens. All of the transforms provided by the framework use the CTI of a token to know if it should be applied. For instance, the 'color/hex' transform only applies to tokens of the category 'color'. -You can also add a _comment_ to a style property: +You can also add a _comment_ to a design token: ``` { diff --git a/__integration__/__snapshots__/customFormats.test.js.snap b/__integration__/__snapshots__/customFormats.test.js.snap index 2db8996df..842a01f3d 100644 --- a/__integration__/__snapshots__/customFormats.test.js.snap +++ b/__integration__/__snapshots__/customFormats.test.js.snap @@ -163,6 +163,166 @@ exports[`integration custom formats inline custom with new args should match sna ] } ], + \\"tokens\\": { + \\"size\\": { + \\"padding\\": { + \\"small\\": { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + \\"medium\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + \\"large\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + \\"xl\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + } + } + }, + \\"allTokens\\": [ + { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + ], \\"_properties\\": { \\"size\\": { \\"padding\\": { @@ -622,6 +782,166 @@ exports[`integration custom formats inline custom with old args should match sna ] } ], + \\"tokens\\": { + \\"size\\": { + \\"padding\\": { + \\"small\\": { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + \\"medium\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + \\"large\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + \\"xl\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + } + } + }, + \\"allTokens\\": [ + { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + ], \\"_properties\\": { \\"size\\": { \\"padding\\": { @@ -936,37 +1256,197 @@ exports[`integration custom formats inline custom with old args should match sna \\"otherOption\\": \\"Test\\" } } - ], - \\"transforms\\": [ + ], + \\"transforms\\": [ + { + \\"type\\": \\"attribute\\" + }, + { + \\"type\\": \\"name\\" + }, + { + \\"type\\": \\"value\\" + }, + { + \\"type\\": \\"value\\" + } + ], + \\"actions\\": [] + }, + \\"file\\": { + \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", + \\"options\\": { + \\"showFileHeader\\": true, + \\"otherOption\\": \\"Test\\" + } + } +}" +`; + +exports[`integration custom formats register custom format with new args should match snapshot 1`] = ` +"{ + \\"dictionary\\": { + \\"properties\\": { + \\"size\\": { + \\"padding\\": { + \\"small\\": { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + \\"medium\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + \\"large\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + \\"xl\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + } + } + }, + \\"allProperties\\": [ { - \\"type\\": \\"attribute\\" + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] }, { - \\"type\\": \\"name\\" + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] }, { - \\"type\\": \\"value\\" + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] }, { - \\"type\\": \\"value\\" + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] } ], - \\"actions\\": [] - }, - \\"file\\": { - \\"destination\\": \\"inlineCustomFormatWithOldArgs.json\\", - \\"options\\": { - \\"showFileHeader\\": true, - \\"otherOption\\": \\"Test\\" - } - } -}" -`; - -exports[`integration custom formats register custom format with new args should match snapshot 1`] = ` -"{ - \\"dictionary\\": { - \\"properties\\": { + \\"tokens\\": { \\"size\\": { \\"padding\\": { \\"small\\": { @@ -1048,7 +1528,7 @@ exports[`integration custom formats register custom format with new args should } } }, - \\"allProperties\\": [ + \\"allTokens\\": [ { \\"value\\": \\"0.5rem\\", \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", @@ -1585,6 +2065,166 @@ exports[`integration custom formats register custom format with old args should ] } ], + \\"tokens\\": { + \\"size\\": { + \\"padding\\": { + \\"small\\": { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + \\"medium\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + \\"large\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + \\"xl\\": { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + } + } + }, + \\"allTokens\\": [ + { + \\"value\\": \\"0.5rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 0.5 + }, + \\"name\\": \\"SizePaddingSmall\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"small\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"small\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingMedium\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"medium\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"medium\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingLarge\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"large\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"large\\" + ] + }, + { + \\"value\\": \\"1rem\\", + \\"filePath\\": \\"__integration__/tokens/size/padding.json\\", + \\"isSource\\": true, + \\"original\\": { + \\"value\\": 1 + }, + \\"name\\": \\"SizePaddingXl\\", + \\"attributes\\": { + \\"category\\": \\"size\\", + \\"type\\": \\"padding\\", + \\"item\\": \\"xl\\" + }, + \\"path\\": [ + \\"size\\", + \\"padding\\", + \\"xl\\" + ] + } + ], \\"_properties\\": { \\"size\\": { \\"padding\\": { diff --git a/__tests__/formats/scssVariables.test.js b/__tests__/formats/scssVariables.test.js index 55889b23e..3e501b680 100644 --- a/__tests__/formats/scssVariables.test.js +++ b/__tests__/formats/scssVariables.test.js @@ -82,7 +82,7 @@ describe('formats', () => { expect(formattedScss).not.toMatch("!default"); - themeableDictionary.allProperties[0].themeable = true; + themeableDictionary.allTokens[0].themeable = true; themeableScss = formatter(createFormatArgs({ dictionary: themeableDictionary, file, diff --git a/docs/README.md b/docs/README.md index 8ec130d96..eaa8467b6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,9 +2,8 @@ [![npm version](https://img.shields.io/npm/v/style-dictionary.svg?style=flat-square)](https://badge.fury.io/js/style-dictionary) ![license](https://img.shields.io/npm/l/style-dictionary.svg?style=flat-square) -[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/amzn/style-dictionary/blob/master/CONTRIBUTING.md#submitting-pull-requests) -
-[![Build Status](https://img.shields.io/travis/amzn/style-dictionary.svg?style=flat-square)](https://travis-ci.org/amzn/style-dictionary) +[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md#submitting-pull-requests) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/amzn/style-dictionary/Test?style=flat-square)](https://github.com/amzn/style-dictionary/actions/workflows/test.yml) [![downloads](https://img.shields.io/npm/dm/style-dictionary.svg?style=flat-square)](https://www.npmjs.com/package/style-dictionary) # Style Dictionary @@ -12,7 +11,7 @@ A Style Dictionary is a system that allows you to define styles once, in a way for any platform or language to consume. A single place to create and edit your styles, and a single command exports these rules to all the places you need them - iOS, Android, CSS, JS, HTML, sketch files, style documentation, etc. It is available as a [CLI](using_the_cli.md) through npm, but can also be used like any normal [npm module](using_the_npm_module.md) if you want to [extend](extending.md) its functionality. -When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. StyleDictionary solves this by automatically generating style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across your workflow. +When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. Style Dictionary solves this by automatically generating style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across your workflow. ## Watch the Demo on Youtube [![Watch the video](assets/fake_player.png)](http://youtu.be/1HREvonfqhY) @@ -22,12 +21,12 @@ When you are managing user experiences, it can be quite challenging to keep styl ## The Basics __A style dictionary consists of:__ -1. [Style properties](properties.md), organized in JSON files +1. [Design tokens](tokens.md), organized in JSON, JSON5, or JS files 1. Static assets (e.g. fonts, icons, images, sounds, etc.), organized into folders -1. [Configuration](config.md), defining the transformation of the properties and assets for each output platform +1. [Configuration](config.md), defining the [transformation](transforms.md) and [formatting](formats.md) of the tokens and assets for each output platform __What a style dictionary does:__ -1. Transforms style properties and assets into platform specific deliverables +1. Transforms design tokens and assets into platform specific deliverables 1. Creates human readable artifacts (e.g. documentation, design libraries, etc) __Things you can build with a style dictionary:__ @@ -39,15 +38,14 @@ __Things you can build with a style dictionary:__ **The value of using Style Dictionary to build all of these is that they are all consistent and up to date.** -The Style Dictionary framework is fully extensible and modular. You can create any type of file from a style dictionary. -If there is a new language, platform, or file type you need, you can easily [extend](extending.md) the style dictionary framework to create the necessary files. +The Style Dictionary framework is fully extensible and modular. You can create any type of file from a style dictionary. If there is a new language, platform, or file type you need, you can easily [extend](extending.md) the style dictionary framework to create the necessary files. ## Contributing -Please help make this framework better. For more information take a look at [CONTRIBUTING.md](https://github.com/amzn/style-dictionary/blob/master/CONTRIBUTING.md) +Please help make this framework better. For more information take a look at [CONTRIBUTING.md](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) ## License -[Apache 2.0](https://github.com/amzn/style-dictionary/blob/master/LICENSE) +[Apache 2.0](https://github.com/amzn/style-dictionary/blob/main/LICENSE) diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 0cac1f3b6..2da7a968a 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -3,16 +3,16 @@ - [Quick Start](quick_start.md) - [Examples](examples.md) - [Config](config.md) - - [Properties](properties.md) + - [Tokens](tokens.md) - [Package structure](package_structure.md) - [Extending](extending.md) - Reference - [Architecture](architecture.md) - - [Build Process](build_process.md) - [Using the CLI](using_the_cli.md) - [Using the NPM Module](using_the_npm_module.md) - [API](api.md) + - [Parsers](parsers.md) - [Transforms](transforms.md) - [Transform groups](transform_groups.md) - [Formats](formats.md) diff --git a/docs/actions.md b/docs/actions.md index 8234cce60..62b279d37 100644 --- a/docs/actions.md +++ b/docs/actions.md @@ -6,13 +6,13 @@ EDIT scripts/handlebars/templates/api.hbs OR JSDOC COMMENT INSTEAD! Actions provide a way to run custom build code such as generating binary assets like images. -Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/master/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). +Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). You use actions in your config file under platforms > [platform] > actions ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transformGroup": "android", @@ -28,7 +28,7 @@ You use actions in your config file under platforms > [platform] > actions ## Pre-defined Actions -[lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/actions.js) +[lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/actions.js) ### android/copyImages diff --git a/docs/api.md b/docs/api.md index 945992ab8..709032849 100644 --- a/docs/api.md +++ b/docs/api.md @@ -28,7 +28,7 @@ StyleDictionary.buildAllPlatforms(); Takes a platform and performs all transforms to -the properties object (non-mutative) then +the tokens object (non-mutative) then builds all the files and performs any actions. This is useful if you only want to build the artifacts of one platform to speed up the build process. @@ -70,8 +70,8 @@ defined in the platform and calls the undo method on any actions. Takes a platform and performs all transforms to -the properties object (non-mutative) then -cleans all the files and perfoms the undo method of any [actions](actions.md). +the tokens object (non-mutative) then +cleans all the files and performs the undo method of any [actions](actions.md). | Param | Type | @@ -87,7 +87,7 @@ cleans all the files and perfoms the undo method of any [actions](actions.md). -Exports a properties object with applied +Exports a tokens object with applied platform transforms. This is useful if you want to use a style @@ -119,7 +119,7 @@ Create a Style Dictionary const StyleDictionary = require('style-dictionary').extend('config.json'); const StyleDictionary = require('style-dictionary').extend({ - source: ['properties/*.json'], + source: ['tokens/*.json'], platforms: { scss: { transformGroup: 'scss', @@ -142,7 +142,7 @@ const StyleDictionary = require('style-dictionary').extend({ -Adds a custom action to the style property builder. Custom +Adds a custom action to Style Dictionary. Custom actions can do whatever you need, such as: copying files, base64'ing files, running other build scripts, etc. After you register a custom action, you then use that @@ -223,14 +223,14 @@ Add a custom filter to the style dictionary | --- | --- | --- | | filter | Object | | | filter.name | String | Name of the filter to be referenced in your config.json | -| filter.matcher | function | Matcher function, return boolean if the property should be included. | +| filter.matcher | function | Matcher function, return boolean if the token should be included. | **Example** ```js StyleDictionary.registerFilter({ name: 'isColor', - matcher: function(prop) { - return prop.attributes.category === 'color'; + matcher: function(token) { + return token.attributes.category === 'color'; } }) ``` @@ -257,7 +257,7 @@ Add a custom format to the style dictionary StyleDictionary.registerFormat({ name: 'json', formatter: function({dictionary, platform, options, file}) { - return JSON.stringify(dictionary.properties, null, 2); + return JSON.stringify(dictionary.tokens, null, 2); } }) ``` @@ -275,7 +275,7 @@ Adds a custom parser to parse style dictionary files | Param | Type | Description | | --- | --- | --- | -| pattern | Regex | - | +| pattern | Regex | A file path regular expression to match which files this parser should be be used on. This is similar to how webpack loaders work. `/\.json$/` will match any file ending in '.json', for example. | | parse | function | Function to parse the file contents. Takes 1 argument, which is an object with 2 attributes: contents wich is the string of the file contents and filePath. The function should return a plain Javascript object. | **Example** @@ -324,7 +324,7 @@ StyleDictionary.registerTemplate({ Add a custom transform to the Style Dictionary -Transforms can manipulate a property's name, value, or attributes +Transforms can manipulate a token's name, value, or attributes | Param | Type | Description | @@ -333,22 +333,22 @@ Transforms can manipulate a property's name, value, or attributes | transform.type | String | Type of transform, can be: name, attribute, or value | | transform.name | String | Name of the transformer (used by transformGroup to call a list of transforms). | | transform.transitive | Boolean | If the value transform should be applied transitively, i.e. should be applied to referenced values as well as absolute values. | -| [transform.matcher] | function | Matcher function, return boolean if transform should be applied. If you omit the matcher function, it will match all properties. | -| transform.transformer | function | Performs a transform on a property object, should return a string or object depending on the type. Will only update certain properties by which you can't mess up property objects on accident. | +| [transform.matcher] | function | Matcher function, return boolean if transform should be applied. If you omit the matcher function, it will match all tokens. | +| transform.transformer | function | Modifies a design token object. The transformer function will receive the token and the platform configuration as its arguments. The transformer function should return a string for name transforms, an object for attribute transforms, and same type of value for a value transform. | **Example** ```js StyleDictionary.registerTransform({ name: 'time/seconds', type: 'value', - matcher: function(prop) { - return prop.attributes.category === 'time'; + matcher: function(token) { + return token.attributes.category === 'time'; }, - transformer: function(prop) { + transformer: function(token) { // Note the use of prop.original.value, // before any transforms are performed, the build system - // clones the original property to the 'original' attribute. - return (parseInt(prop.original.value) / 1000).toString() + 's'; + // clones the original token to the 'original' attribute. + return (parseInt(token.original.value) / 1000).toString() + 's'; } }); ``` diff --git a/docs/architecture.md b/docs/architecture.md index fbd6e94c8..28bad20e6 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,4 +1,4 @@ -# Architecture Overview +# Architecture This is how Style Dictionary works under the hood. @@ -8,11 +8,13 @@ Let's take a closer look into each of these steps. ## 1. Parse the config -Style Dictionary is a configuration based framework, you tell it what to do in a configuration file. Style Dictionary first parses this configuration to know what to do. +Style Dictionary is a configuration based framework, you tell it what to do in a configuration file. Style Dictionary first parses this [configuration](config.md) to know what to do. ## 2. Find all token files -In your [config](config.md) file you define a `source`, which is an array of file paths. This tells Style Dictionary where to find your token files. You can have them anywhere and in any folder structure as long as you tell Style Dictionary where to find them. +In your [config](config.md) file can define `include` and `source`, which are arrays of file path globs. These tell Style Dictionary where to find your token files. You can have them anywhere and in any folder structure as long as you tell Style Dictionary where to find them. + +If there are [custom parsers](parsers.md) defined, Style Dictionary will run those on files the parsers match. ## 3. Deep merge token files @@ -20,18 +22,24 @@ Style Dictionary takes all the files it found and performs a deep merge. This al ## 4. Iterate over the platforms -For each platform defined in your [config](config.md), Style Dictionary will do a few steps to get it ready to be consumed on that platform. You don't need to worry about one platform affecting another because everything that happens in a platform is non-destructive +For each platform defined in your [config](config.md), Style Dictionary will do a few steps to get it ready to be consumed on that platform. You don't need to worry about one platform affecting another because everything that happens in a platform is non-destructive. ## 4a. Transform the tokens Style Dictionary now traverses over the whole token object and looks for design tokens. It does this by looking for anything with a `value` key. When it comes across a design token, it then performs all the [transforms](transforms.md) defined in your [config](config.md) in order. +Value transforms, transforms that modify a token's value, are skipped if the token references another token. Starting in 3.0, you can define a [transitive transform](transforms.md#transitive-transforms) that will transform a value that references another token after that reference has been resolved. + ## 4b. Resolve aliases / references to other values -After all the tokens have been transformed, it then does another pass over the token object looking for aliases, which look like `"{size.font.base.value}"`. When it finds these, it then replaces the reference with the transformed value. As we have a single complete token object, aliases can be in any token file and still work. +After all the tokens have been transformed, it then does another pass over the token object looking for aliases, which look like `"{size.font.base.value}"`. When it finds these, it then replaces the reference with the transformed value. Because Style Dictionary merges all token files into a single object, aliases can be in any token file and still work. ## 4c. Format the tokens into files Now all the design tokens are ready to be written to a file. Style Dictionary takes the whole transformed and resolved token object and for each file defined in the platform it [formats](formats.md) the token object and write the output to a file. Internally, Style Dictionary creates a flat array of all the design tokens it finds in addition to the token object. This is how you can output a flat SCSS variables file. -After Style Dictionary does steps 4-6 for each platform, now you have all your output files that are ready to consume in each platform and codebase. +## 4d. Run actions + +[Actions](actions.md) are custom code that run in a platform after the files are generated. They are useful for things like copying assets to specific build directories or generating images. + +After Style Dictionary does steps 4a-4d for each platform, you will have all your output files that are ready to consume in each platform and codebase. diff --git a/docs/assets/styles.css b/docs/assets/styles.css index ba887e1f4..d6748878c 100644 --- a/docs/assets/styles.css +++ b/docs/assets/styles.css @@ -272,7 +272,8 @@ section.cover .cover-main { } .markdown-section hr { - border-bottom: 5px solid transparent; + width: 25%; + border-bottom: 5px solid #F1F1F2; } .token.punctuation { diff --git a/docs/build_process.md b/docs/build_process.md deleted file mode 100644 index 95936a01d..000000000 --- a/docs/build_process.md +++ /dev/null @@ -1,16 +0,0 @@ -# Build Process - -Here is what the build system is doing under the hood. - -![build structure](assets/build-diagram.png) - -1. The build system reads in a configuration -1. If there is an `includes` attribute in the config, it will take those files and deep merge them into the `properties` object -1. It takes all the JSON files in the `source` attribute in the config and performs a deep merge onto the `properties` object -1. Then it iterates over the platforms in the config and: - 1. Performs all transforms, in order, defined in the transforms attribute or transformGroup - 1. Builds all files defined in the files array - 1. Performs any actions defined in the actions attribute - -# How to Build -You can build a style dictionary [using the cli](using_the_cli.md) or [using the npm module](using_the_npm_module.md). diff --git a/docs/config.md b/docs/config.md index 8a961d24e..ab185e647 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,17 +1,53 @@ # Configuration -Style dictionaries are configuration driven. Your config file defines what executes and what to output when the style dictionary builds. +Style dictionaries are configuration driven. Your configuration lets Style Dictionary know: -By default, Style Dictionary looks for a `config.json` file in the root of your package. If not found, it looks for a `config.js` file in the root of your package. You can also specify a custom location when you use the [CLI](using_the_cli.md). If you want a custom build system using the [npm module](using_the_npm_module.md), you can specify a custom location for a configuration file or use a plain Javascript object. +1. Where to find your [design tokens](tokens.md) +1. How to transform and format them to generate output files -## config.js -You can find out more about creating configurations in JS in our documentation about using the [npm module](using_the_npm_module.md). Additionally you can create your configuration as a Node module and export it: +Here is an example configuration: + +```json +{ + "source": ["tokens/**/*.json"], + "platforms": { + "scss": { + "transformGroup": "scss", + "prefix": "sd", + "buildPath": "build/scss/", + "files": [{ + "destination": "_variables.scss", + "format": "scss/variables" + }], + "actions": ["copy_assets"] + }, + "android": { + "transforms": ["attribute/cti", "name/cti/snake", "color/hex", "size/remToSp", "size/remToDp"], + "buildPath": "build/android/src/main/res/values/", + "files": [{ + "destination": "style_dictionary_colors.xml", + "format": "android/colors" + }] + } + } +} +``` + +## Configuration file formats + +Style Dictionary supports configuration files in these file formats: + +* JSON +* JSON5 +* Javascript (CommonJS) + +Here is an example using a CommonJS module for configuration: ```javascript // config.js module.exports = { source: [`tokens/**/*.json`], - // If you don't want to call the registerTransform method a bunch of times + // 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 // the .extend method copies everything in the config // to itself, allowing you to override things. It's also doing a deep merge @@ -20,14 +56,14 @@ module.exports = { // Now we can use the transform 'myTransform' below myTransform: { type: 'name', - transformer: (prop) => prop.path.join('_').toUpperCase() + transformer: (token) => token.path.join('_').toUpperCase() } }, // Same with formats, you can now write them directly to this config // object. The name of the format is the key. format: { myFormat: ({dictionary, platform}) => { - return dictionary.allProperties.map(prop => `${prop.name}: ${prop.value}`).join('\n'); + return dictionary.allTokens.map(token => `${token.name}: ${token.value}`).join('\n'); } }, platforms: { @@ -36,60 +72,106 @@ module.exports = { } ``` +Some interesting things you can do in a CommonJS file that you cannot do in a JSON file: + +* Add custom transforms, formats, filters, actions, and parsers +* Programmatically generate your configuration + + +---- + + +## Using configuration files + +By default, the Style Dictionary [CLI](using_the_cli.md) looks for a `config.json` or `config.js` file in the root of your package. + ```json5 // package.json - "scripts": { - "build": "style-dictionary build" - } +"scripts": { + "build": "style-dictionary build" +} ``` -## config.json - Here is a quick example: -```json -{ - "source": ["properties/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "scss", - "prefix": "sd", - "buildPath": "build/scss/", - "files": [{ - "destination": "_variables.scss", - "format": "scss/variables" - }], - "actions": ["copy_assets"] - }, - "android": { - "transforms": ["attribute/cti", "name/cti/snake", "color/hex", "size/remToSp", "size/remToDp"], - "buildPath": "build/android/src/main/res/values/", - "files": [{ - "destination": "style_dictionary_colors.xml", - "format": "android/colors" - }] - } - } +You can also specify a custom location when you use the [CLI](using_the_cli.md) with the `--config` parameter. + +```json5 +// package.json +"scripts": { + "build": "style-dictionary build --config ./sd.config.js" +} +``` + +## Using in Node + +You can also use Style Dictionary as an [npm module](using_the_npm_module.md) and further customize how Style Dictionary is run, for example running Style Dictionary multiple times with different configurations. To do this you would create a Javascript file that imports the Style Dictionary npm module and calls the [`.extend`](api.md#extend) and [`.buildAllPlatforms`](api.md#buildallplatforms) functions. + +```javascript +// build.js +const StyleDictionary = require('style-dictionary'); + +const myStyleDictionary = StyleDictionary.extend({ + // configuration +}); + +myStyleDictionary.buildAllPlatforms(); + +// You can also extend Style Dictionary multiple times: +const myOtherStyleDictionary = myStyleDictionary.extend({ + // new configuration +}); + +myOtherStyleDictionary.buildAllPlatforms(); +``` + +You would then change your npm script or CLI command to run that file with Node: + +```json5 +// package.json +"scripts": { + "build": "node build.js" } ``` +---- + + +## Attributes + | Attribute | Type | Description | | :--- | :--- | :--- | -| parsers | Array[Object] (optional) | Custom token parsers to run on token files | -| parsers[].pattern | Regex | A file regular expression to match files the parser should run on. | -| parsers[].parser | Function | Parser function that takes the string content of the file and returns a plain Javascript object. | -| include | Array[String] (optional) | An array of path [globs](https://github.com/isaacs/node-glob) to Style Dictionary property files that contain default styles. The Style Dictionary uses this as a base collection of properties. The properties found using the "source" attribute will overwrite properties found using include. | -| source | Array[String] | An array of path [globs](https://github.com/isaacs/node-glob) to JSON files that contain style properties. The Style Dictionary will do a deep merge of all of the JSON files, allowing you to separate your properties into multiple files. | -| platforms | Object | An object containing platform config objects that describe how the Style Dictionary should build for that platform. You can add any arbitrary attributes on this object that will get passed to formats and actions (more on these in a bit). This is useful for things like build paths, name prefixes, variable names, etc. | -| platform.transforms | Array[String] (optional) | An array of [transforms](transforms.md) to be performed on the style properties object. These will transform the properties in a non-destructive way, allowing each platform to transform the properties. Transforms to apply sequentially to all properties. Can be a built-in one or you can create your own. | -| platform.transformGroup | String (optional) | A string that maps to an array of transforms. This makes it easier to reference transforms by grouping them together. You must either define this or [transforms](transforms.md). | -| platform.buildPath | String (optional) | Base path to build the files, must end with a trailing slash. | -| platform.options | Object (optional) | Options that apply to all files in the platform, for example `outputReferences` and `showFileHeader` -| platform.files | Array (optional) | Files to be generated for this platform. | -| platform.file.destination | String (optional) | Location to build the file, will be appended to the buildPath. | -| platform.file.format | String (optional) | [Format](formats.md) used to generate the file. Can be a built-in one or you can create your own via [registerFormat](api.md#registerformat). | -| platform.file.filter | String/Function/Object (optional) | A function, string or object used to filter the properties that will be included in the file. If a function is provided, each property will be passed to the function and the result (true or false) will determine whether the property is included. If an object is provided, each property will be matched against the object using a partial deep comparison. If a match is found, the property is included. If a string is passed, is considered a custom filter registered via [registerFilter](api.md#registerfilter) | -| platform.file.options | Object (optional) | A set of extra options associated with the file. Includes `showFileHeader` and `outputReferences`. | -| platform.file.options.showFileHeader | Boolean | If the generated file should have a "Do not edit + Timestamp" header (where the format supports it). By default is "true". | -| platform.file.options.outputReferences | Boolean | If the file should keep token [references](formats.md#references-in-output-files). By default this is "false". -| platform.actions | Array[String] (optional) | [Actions](actions.md) to be performed after the files are built for that platform. Actions can be any arbitrary code you want to run like copying files, generating assets, etc. You can use pre-defined actions or create custom actions. | +| transform | Object (optional) | Custom [transforms](transforms.md) you can include inline rather than using `.registerTransform`. The keys in this object will be the transform's name, the value should be an object with `type` +| format | Object (optional) | Custom [formats](formats.md) you can include inline in the configuration rather than using `.registerFormat`. The keys in this object will be for format's name and value should be the formatter function. +| action | Object (optional) | Custom inline [actions](actions.md). The keys in this object will be the action's name and the value should be an object containing `do` and `undo` methods. +| parsers | Array[Parser] (optional) | Custom [file parsers](parsers.md) to run on input files | +| include | Array[String] (optional) | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files that contain default styles. Style Dictionary uses this as a base collection of design tokens. The tokens found using the "source" attribute will overwrite tokens found using include. | +| source | Array[String] | An array of file path [globs](https://github.com/isaacs/node-glob) to design token files. Style Dictionary will do a deep merge of all of the token files, allowing you to organize your files files however you want. | +| tokens | Object | The tokens object is a way to include inline design tokens as opposed to using the `source` and `include` arrays. +| properties | Object | **DEPRECATED** The properties object has been renamed to `tokens`. Using the `properties` object will still work for backwards compatibility. +| platforms | Object[Platform] | An object containing [platform](#platform) config objects that describe how the Style Dictionary should build for that platform. You can add any arbitrary attributes on this object that will get passed to formats and actions (more on these in a bit). This is useful for things like build paths, name prefixes, variable names, etc. ----- +### Platform + +A platform is a build target that tells Style Dictionary how to properly transform and format your design tokens for output to a specific platform. You can have as many platforms as you need and you can name them anything, there are no restrictions. + +| Attribute | Type | Description | +| :--- | :--- | :--- | +| transforms | Array[String] (optional) | An array of [transforms](transforms.md) to be performed on the design tokens. These will transform the tokens in a non-destructive way, allowing each platform to transform the tokens. Transforms to apply sequentially to all tokens. Can be a built-in one or you can create your own. +| transformGroup | String (optional) | A string that maps to an array of transforms. This makes it easier to reference transforms by grouping them together. You must either define this or [transforms](transforms.md). +| buildPath | String (optional) | Base path to build the files, must end with a trailing slash. +| options | Object (optional) | Options that apply to all files in the platform, for example `outputReferences` and `showFileHeader` +| files | Array[File] (optional) | [Files](#file) to be generated for this platform. +| actions | Array[String] (optional) | [Actions](actions.md) to be performed after the files are built for that platform. Actions can be any arbitrary code you want to run like copying files, generating assets, etc. You can use pre-defined actions or create custom actions. + +### File + +A File configuration object represents a single output file. The `options` object on the file configuration will take precedence over the `options` object defined at the platform level. + +| Attribute | Type | Description | +| :--- | :--- | :--- | +| destination | String (optional) | Location to build the file, will be appended to the buildPath. | +| format | String (optional) | [Format](formats.md) used to generate the file. Can be a built-in one or you can create your own via [registerFormat](api.md#registerformat). | +| filter | String/Function/Object (optional) | A function, string or object used to filter the tokens that will be included in the file. If a function is provided, each design token will be passed to the function and the result (true or false) will determine whether the design token is included. If an object is provided, each design token will be matched against the object using a partial deep comparison. If a match is found, the design token is included. If a string is passed, is considered a custom filter registered via [registerFilter](api.md#registerfilter) | +| options | Object (optional) | A set of extra options associated with the file. Includes `showFileHeader` and `outputReferences`. | +| options.showFileHeader | Boolean | If the generated file should have a comment at the top about being generated. The default fileHeader comment has "Do not edit + Timestamp". By default is "true". | +| options.fileHeader | String/Function (optional) | A custom fileHeader that can be either a name of a registered file header (string) or an inline [fileHeader](formats.md#customfileheader) function. +| options.outputReferences | Boolean | If the file should keep token [references](formats.md#references-in-output-files). By default this is "false". diff --git a/docs/examples.md b/docs/examples.md index c19d5c88e..f37209cc5 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,6 +1,6 @@ # Examples -To get you started, there are some example packages included that you can use. You can [take a look at the code on Github](https://github.com/amzn/style-dictionary/tree/master/examples/) or you can use the CLI included to generate a new package using some of these examples. Here is how you can do that: +To get you started, there are some example packages included that you can use. You can [take a look at the code on Github](https://github.com/amzn/style-dictionary/tree/main/examples/) or you can use the CLI included to generate a new package using some of these examples. Here is how you can do that: ```bash $ mkdir MyFolder @@ -11,31 +11,42 @@ $ style-dictionary init [example] Where `[example]` is one of: `basic`, `complete`. ## Basic -[View on Github](https://github.com/amzn/style-dictionary/tree/master/examples/basic) +[View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/basic) This example code is bare-bones to show you what this framework can do. Use this if you want to play around with what the Style Dictionary can do. ## Complete -[View on Github](https://github.com/amzn/style-dictionary/tree/master/examples/complete) +[View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/complete) This is a more complete package and should have everything you need to get started. This package can be consumed as a Cocoapod on iOS, as a node module for web, and as a local library for Android. ## Advanced -[View the folder](https://github.com/amzn/style-dictionary/tree/master/examples/advanced) - -If you want to look at more advanced examples of possible applications and customizations of Style Dictionary, the `examples/advanced` folder on GitHub contains these extra folders: - -* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. -* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the properties. -* [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. -* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the properties when converted to design tokens. -* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with property values depending on brand and platforms. -* [**npm-module**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. -* [**s3**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. -* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a property and assign it to the value –or attribute– of another property. -* [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. -* [**component-cti**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. +[View the folder](https://github.com/amzn/style-dictionary/tree/main/examples/advanced) + +If you want to look at more advanced examples of possible applications and customizations of Style Dictionary, the [`examples/advanced`](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/) folder on GitHub contains these extra folders: + +* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. +* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. +* [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. +* [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. +* [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. +* [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. +* [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. +* [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. +* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. +* [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. +* [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. +* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. +* [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. +* [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. +* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. +* [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. +* [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. +* [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references +* [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. +* [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. + --- diff --git a/docs/extending.md b/docs/extending.md index 83a8c76a5..3222e47f8 100644 --- a/docs/extending.md +++ b/docs/extending.md @@ -9,6 +9,7 @@ There is a straightforward way to extend Style Dictionary to meet your needs - s * [registerFormat](api.md#registerformat) * [registerTemplate](api.md#registertemplate) (deprecated) * [registerAction](api.md#registeraction) +* [registerParser](api.md#registerparser) ## Extension Examples Importing a configuration, defining a new `time/seconds` transform, and building the style dictionary. diff --git a/docs/formats.md b/docs/formats.md index f7f257970..3be350a5e 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -14,7 +14,7 @@ You use formats in your config file under platforms > [platform] > files > [file ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "css": { "transformGroup": "css", @@ -37,7 +37,7 @@ Formats can take configuration to make them more flexible. This allows you to re ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", @@ -59,7 +59,7 @@ A special file configuration is `filter`, which will filter the tokens before th * 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 if you are defining your configuration in Javascript rather than JSON. The filter function takes a token as the property and should return a boolean if the token should be included (true) or excluded (false). +* 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.** ```javascript { @@ -71,7 +71,7 @@ A special file configuration is `filter`, which will filter the tokens before th } ``` -The token/property that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](properties.md?id=default-property-metadata) added by Style Dictionary. +The design token that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](tokens.md?id=default-design-token-metadata) added by Style Dictionary. ## References in output files @@ -232,16 +232,16 @@ The formatter function that is called when Style Dictionary builds files. args.dictionaryObject

The transformed and resolved dictionary object

- args.dictionary.propertiesObject

Object structure of the tokens/properties that has been transformed and references resolved.

+ args.dictionary.tokensObject

Object structure of the tokens that has been transformed and references resolved.

- args.dictionary.allPropertiesArray

Flattened array of all the tokens/properties. This makes it easy to output a list, like a list of SCSS variables.

+ args.dictionary.allTokensArray

Flattened array of all the tokens. This makes it easy to output a list, like a list of SCSS variables.

args.dictionary.usesReferencefunction

Use this function to see if a token's value uses a reference. This is the same function style dictionary uses internally to detect a reference.

- args.dictionary.getReferencesfunction

Use this function to get the tokens/properties that it references. You can use this to output a reference in your custom format. For example: dictionary.getReferences(token.original.value) // returns an array of the referenced token objects

+ args.dictionary.getReferencesfunction

Use this function to get the tokens that it references. You can use this to output a reference in your custom format. For example: dictionary.getReferences(token.original.value) // returns an array of the referenced token objects

args.platformObject

The platform configuration this format is being called in.

@@ -260,7 +260,7 @@ The formatter function that is called when Style Dictionary builds files. StyleDictionary.registerFormat({ name: 'myCustomFormat', formatter: function({dictionary, platform, options, file}) { - return JSON.stringify(dictionary.properties, null, 2); + return JSON.stringify(dictionary.tokens, null, 2); } }) ``` @@ -305,7 +305,7 @@ To take advantage of outputting references in your custom formats there are 2 he StyleDictionary.registerFormat({ name: `es6WithReferences`, formatter: function({dictionary}) { - return dictionary.allProperties.map(token => { + return dictionary.allTokens.map(token => { let value = JSON.stringify(token.value); // the `dictionary` object now has `usesReference()` and // `getReferences()` methods. `usesReference()` will return true if @@ -351,7 +351,7 @@ Here are the available format helper methods: > 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.allProperties.map`. The formatting +to use as the function on `dictionary.allTokens.map`. The formatting is configurable either by supplying a `format` option or a `formatting` object which uses: prefix, indentation, separator, suffix, and commentStyle. @@ -390,7 +390,7 @@ StyleDictionary.registerFormat({ dictionary, format: 'css' }); - return dictionary.allProperties.map(formatProperty).join('\n'); + return dictionary.allTokens.map(formatProperty).join('\n'); } }); ``` @@ -431,7 +431,7 @@ StyleDictionary.registerFormat({ name: 'myCustomFormat', formatter: function({ dictionary, file }) { return fileHeader({file, 'short') + - dictionary.allProperties.map(token => `${token.name} = ${token.value}`) + dictionary.allTokens.map(token => `${token.name} = ${token.value}`) .join('\n'); } }); @@ -481,10 +481,10 @@ StyleDictionary.registerFormat({ * * * ### iconsWithPrefix -> formatHelpers.iconsWithPrefix(prefix, properties, options) ⇒ String +> 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 psuedo-selector to add +using an icon font and creates helper classes with the :before pseudo-selector to add a unicode character. __You probably don't need this.__ @@ -499,7 +499,7 @@ __You probably don't need this.__ prefixString

Character to prefix variable names, like '$' for Sass

- propertiesArray.<Property>

allProperties array on the dictionary object passed to the formatter function.

+ allTokensArray.<Token>

allTokens array on the dictionary object passed to the formatter function.

optionsObject

options object passed to the formatter function.

@@ -512,7 +512,7 @@ __You probably don't need this.__ StyleDictionary.registerFormat({ name: 'myCustomFormat', formatter: function({ dictionary, options }) { - return iconsWithPrefix('$', dictionary.allProperties, options); + return iconsWithPrefix('$', dictionary.allTokens, options); } }); ``` @@ -532,7 +532,7 @@ Outputs an object stripping out everything except values - objObject

The object to minify. You will most likely pass dictionary.properties to it.

+ objObject

The object to minify. You will most likely pass dictionary.tokens to it.

@@ -542,7 +542,7 @@ Outputs an object stripping out everything except values StyleDictionary.registerFormat({ name: 'myCustomFormat', formatter: function({ dictionary }) { - return JSON.stringify(minifyDictionary(dictionary.properties)); + return JSON.stringify(minifyDictionary(dictionary.tokens)); } }); ``` @@ -552,7 +552,7 @@ StyleDictionary.registerFormat({ ### sortByName > formatHelpers.sortByName(a, b) ⇒ Integer -A sorting function to be used when iterating over `dictionary.allProperties` in +A sorting function to be used when iterating over `dictionary.allTokens` in a format. **Returns**: Integer - -1 or 1 depending on which element should come first based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort @@ -577,7 +577,7 @@ a format. StyleDictionary.registerFormat({ name: 'myCustomFormat', formatter: function({ dictionary, options }) { - return dictionary.allProperties.sort(sortByName) + return dictionary.allTokens.sort(sortByName) .map(token => `${token.name} = ${token.value}`) .join('\n'); } @@ -590,7 +590,7 @@ StyleDictionary.registerFormat({ > formatHelpers.sortByReference(dictionary) ⇒ function A function that returns a sorting function to be used with Array.sort that -will sort the allProperties array based on references. This is to make sure +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 defined. @@ -608,7 +608,7 @@ defined. **Example** ```javascript -dictionary.allProperties.sort(sortByReference(dictionary)) +dictionary.allTokens.sort(sortByReference(dictionary)) ``` * * * @@ -618,7 +618,7 @@ dictionary.allProperties.sort(sortByReference(dictionary)) Formatters are functions and created easily with most templating engines. Formats can be built using templates if there is a lot of boilerplate code to insert (e.g. ObjectiveC files). If the output consists of only the values (e.g. a flat SCSS variables file), writing a formatter function directly may be easier. -Any templating language can work as there is a node module for it. All you need to do is register a format that calls your template and returns a string. +Any templating language can work as long as there is a node module for it. All you need to do is register a format that calls your template and returns a string. Here is a quick example for Lodash. @@ -648,7 +648,7 @@ styleDictionary.registerFormat({ name: 'my/format', formatter: function({dictionary, platform}) { return template({ - properties: dictionary.properties, + tokens: dictionary.tokens, options: platform }); } @@ -661,7 +661,7 @@ styleDictionary.registerFormat({ ## Pre-defined Formats -These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/formats.js) +These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/formats.js) Want a format? [You can request it here](https://github.com/amzn/style-dictionary/issues). @@ -747,7 +747,7 @@ $tokens: { Creates a SCSS file with variable definitions based on the style dictionary. -Add `!default` to any variable by setting a `themeable: true` property in the token's definition. +Add `!default` to any variable by setting a `themeable: true` attribute in the token's definition. @@ -1091,7 +1091,7 @@ filter: { Creates a resource xml file with all the integers in your style dictionary. It filters your -style properties by `prop.attributes.category === 'time'` +design tokens by `token.attributes.category === 'time'` It is recommended to use the 'android/resources' format with a custom filter instead of this format: @@ -1122,7 +1122,7 @@ filter: { Creates a resource xml file with all the strings in your style dictionary. Filters your -style properties by `prop.attributes.category === 'content'` +design tokens by `token.attributes.category === 'content'` It is recommended to use the 'android/resources' format with a custom filter instead of this format: @@ -1190,7 +1190,7 @@ object StyleDictionary { ### ios/macros -Creates an Objective-C header file with macros for style properties +Creates an Objective-C header file with macros for design tokens **Example** ```objectivec diff --git a/docs/package_structure.md b/docs/package_structure.md index e84f69c91..44e55990d 100644 --- a/docs/package_structure.md +++ b/docs/package_structure.md @@ -1,12 +1,12 @@ # Package Structure -Style dictionaries are configuration driven. A style dictionary package must contain a configuration and reference a path to property files. You can optionally include assets in your package. +Style dictionaries are configuration driven. A style dictionary package must contain a configuration and reference a path to design token files. You can optionally include assets in your package. Here is a basic example of what a style dictionary package looks like. ``` ├── config.json -├── properties/ +├── tokens/ │ ├── size/ │ ├── font.json │ ├── color/ @@ -21,7 +21,7 @@ Here is a basic example of what a style dictionary package looks like. | Name | Description | | :--- | :--- | | config.json | This is where the [configuration](config.md) for the style dictionary lives, where you define what happens when Style Dictionary runs | -| property files | [Properties](properties.md) are saved as a collection of JSON or JS module files. We usually keep them in a `properties` directory, but you can put them wherever you like - the path to them should be in the `source` attribute on your `config.json` file. | +| design token files | [Design tokens](tokens.md) are saved as a collection of JSON or JS module files. You can put them wherever you like - the path to them should be in the `source` attribute on your `config.json` file. | | assets (optional) | Assets can be included in your style dictionary package, allowing you to keep them in your style dictionary as a single source of truth. | diff --git a/docs/parsers.md b/docs/parsers.md new file mode 100644 index 000000000..465b822d9 --- /dev/null +++ b/docs/parsers.md @@ -0,0 +1,71 @@ +# Parsers + +Starting in version 3.0, you can define custom parsers to parse design token files. This allows you to define your design token files in *any* language you like as long as you can write a parser for it. + +A custom parser matches design token files based on a file path regular expression. It will get the contents of a file as a string and should return an object of the data. + +Custom parsers can be used to keep design token files in other languages like YAML, but they can also be used to add extra metadata or modify the design tokens themselves before they get to Style Dictionary. For example, you could modify the token object based on its file path or programmatically generate tokens based on the data in certain files. + + +---- + + +## Parser structure + +A parser has 2 parts: a pattern which is a regular expression to match against a file path, and a parse function which takes the file path and contents of the file and is expected to return a function. + +```javascript +const myParser = { + pattern: /\.json$/, + parse: ({ filePath, contents }) => { + return JSON.parse(contents); + } +} +``` + + +---- + + +## Using parsers + +First you will need to tell Style Dictionary about your parser. You can do this in two ways: + +1. Using the `.registerParser` method +1. Inline in the [configuration](config.md) + +### .registerParser + +```javascript +const StyleDictionary = require('style-dictionary'); + +StyleDictionary.registerParser({ + pattern: /\.json$/, + parse: ({ filePath, contents }) => { + return JSON.parse(contents); + } +}); +``` + +### Inline + +```javascript +module.exports = { + parsers: [{ + pattern: /\.json$/, + parse: ({ filePath, contents }) => { + return JSON.parse(contents); + } + }], + // ... the rest of the configuration +} +``` + + +---- + + +## Parser examples + +* [More in-depth custom parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) +* [Using custom parsers to support YAML design token files](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) diff --git a/docs/properties.md b/docs/properties.md deleted file mode 100644 index 61d3bdf3c..000000000 --- a/docs/properties.md +++ /dev/null @@ -1,167 +0,0 @@ -# Properties - -> Synonyms: design tokens, design variables, design constants, atoms - -Style properties are stored in a collection of JSON or JS module files. We usually keep them in a `properties` directory, but you can put them wherever you like, they need to be referenced in the `source` attribute on your `config.json` file. - -A property is a collection of attributes that describe any fundamental/atomic visual style. Each attribute is a `key:value` pair. A property name and its value are considered a design token (or design variable/constant/atom). - -![Terminology for different parts of a JSON property](assets/property-definitions.png) - -A property is transformed for use in different platforms, languages, and contexts. A simple example is color. A color can be represented in many ways, all of these are the same color: `#ffffff`, `rgb(255,255,255)`, `hsl(0,0,1)`. - -A property file organizes properties in a structured way for quick access. Property files are organized as a deep object with the leaf nodes being the style key:value pairs. - -## Examples - -```json -{ - "color": { - "font": { - "base": { "value": "#111111" }, - "secondary": { "value": "#333333" }, - "tertiary": { "value": "#666666" }, - "inverse": { - "base": { "value": "#ffffff" } - } - } - } -} -``` - -Any object in the JSON that has a `value` attribute on it is a property; in this example there are 4 style properties: `color.font.base`, `color.font.secondary`, `color.font.tertiary`, and `color.font.inverse.base`. - -For any properties you wish to output, the "value" attribute is required. This provides the data that will be used throughout the build process (and ultimately used for styling in your deliverables). You can optionally include any custom attributes you would like (e.g. "comment" with a string or "metadata" as an object with its own attributes). - -### Example Property -Here you can see a property of "size.font.small" with two attributes: -1. the required "value" attribute, set to "10" -1. the optional "comment" attribute (The "comment" attribute is treated in a special way - the comment will appear in output files when the output format supports comments.) -```json -{ - "size": { - "font": { - "small" : { - "value": "10", - "comment": "the smallest font allowed for readability" - }, - } - } -} -``` - -### Multiple Properties -Multiple properties in a single file are simple to read and understand using the recommended [`Category / Type / Item (CTI)`](#category-type-item) method -```json -{ - "size": { - "font": { - "small" : { "value": "10" }, - "medium": { "value": "16" }, - "large" : { "value": "24" }, - } - } -} -``` - -### Attribute reference / alias -You can reference (alias) existing values by using the dot-notation object path (the fully articulated property name) in brackets. Note that this only applies to values; referencing a non-value property will cause unexpected results in your output. -```json -{ - "size": { - "font": { - "small" : { "value": "10" }, - "medium": { "value": "16" }, - "large" : { "value": "24" }, - "base" : { "value": "{size.font.medium.value}" } - } - } -} -``` -See more in the advanced [referencing-aliasing example](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/referencing_aliasing). - -## Category / Type / Item - -This CTI structure is not required. However, we feel this classification structure makes the most sense semantically. - -Style properties are organized into a hierarchical tree structure with 'category' defining the primitive nature of the property. For example, we have the color category and every property underneath is always a color. As you proceed down the tree, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. It's like the animal kingdom classification: - -![](assets/cti.png) - -Now you can structure your property JSON files like simple objects: - -```json -{ - "size": { - "font": { - "base": { "value": "16" }, - "large": { "value": "20" } - } - } -} -``` - -The CTI is implicit in the structure, the category is 'size' and the type is 'font', and there are 2 properties 'base' and 'large'. - -Structuring style properties in this manner gives us consistent naming and accessing of these properties. You don't need to remember if it is `button_color_error` or `error_button_color`, it is `color_background_button_error`! - -You can organize and name your style properties however you want, **there are no restrictions**. But there are a good amount of helpers if you do use this structure, like the 'attribute/cti' transform which adds attributes to the property of its CTI based on the path in the object. There are a lot of names transforms as well for when you want a flat structure like for Sass variables. - -Also, the CTI structure provides a good mechanism to target transforms for specific kinds of properties. All of the transforms provided by the framework use the CTI structure to know if it should be applied. For instance, the 'color/hex' transform only applies to properties of the category 'color'. - -## Default property metadata - -Style Dictionary adds some metadata on each property that helps with transforms and formats. Here is what Style Dictionary adds onto each property: - -| Attribute | Type | Description | -| :--- | :--- | :--- | -| name | String | A default name of the property that is set to the key of the property. -| path | Array[String] | The object path of the property. `color: { background: { primary: { value: "#fff" } } }` will have a path of `['color','background', 'primary']`. -| original | Object | A pristine copy of the original property object. This is to make sure transforms and formats always have the unmodified version of the original property. -| filePath | String | The file path of the file the token is defined in. This file path is derived from the `source` or `include` file path arrays defined in the [configuration](config.md). -| isSource | Boolean | If the token is from a file defined in the `source` array as opposed to `include` in the [configuration](config.md). - -Given this configuration: - -```json -{ - "source": ["tokens/**/*.json"] - //... -} -``` - -This source file: - -```json -// tokens/color/background.json -{ - "color": { - "background": { - "primary": { "value": "#fff" } - } - } -} -``` - -becomes: - -```json -{ - "color": { - "background": { - "primary": { - "name": "primary", - "value": "#fff", - "path": ["color","background","primary"], - "original": { - "value": "#fff" - }, - "filePath": "tokens/color/background.json", - "isSource": true - } - } - } -} -``` - ----- diff --git a/docs/quick_start.md b/docs/quick_start.md index 7ca552c83..04df150b3 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -1,28 +1,33 @@ # Quick Start ## Installation + *Note that you must have [node (and npm) installed](https://www.npmjs.com/get-npm) before you can follow this guide.* If you want to use the CLI, you can install it globally via npm: + ```bash $ npm install -g style-dictionary ``` Or you can install it like a normal npm dependency. Style Dictionary is a build tool, and you are most likely to use it as a dev dependency: + ```bash $ npm install -D style-dictionary ``` - ## Creating a New Project + The CLI comes with some starter code to get a new project started easily. + ```bash $ mkdir MyStyleD $ cd MyStyleD $ style-dictionary init basic ``` -This command will copy over the example files found in the [basic example](https://github.com/amzn/style-dictionary/tree/master/examples/basic) in this repo and then run the `style-dictionary build` command to generate the build artifacts. You should see something like this output: +This command will copy over the example files found in the [basic example](https://github.com/amzn/style-dictionary/tree/main/examples/basic) in this repo and then run the `style-dictionary build` command to generate the build artifacts. You should see something like this output: + ``` Copying starter files... @@ -60,7 +65,7 @@ Pat yourself on the back, you built your first style dictionary! Take a look at ``` ├── README.md ├── config.json -├── properties/ +├── tokens/ │ ├── color/ │ ├── base.json │ ├── font.json @@ -186,15 +191,15 @@ $size-font-base: 1rem; ``` Pretty nifty! This shows a few things happening: -1. The build system does a deep merge of all the property JSON files defined in the `source` attribute of `config.json`. This allows you to split up the property JSON files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. -1. The build system resolves references to other style property values. `{size.font.medium.value}` is resolved properly. -1. The build system handles references to property values in other files as well (as you can see in `properties/color/font.json`). +1. The build system does a deep merge of all the design token files defined in the `source` attribute of `config.json`. This allows you to split up the design token files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. +1. The build system resolves references to other design tokens. `{size.font.medium.value}` is resolved properly. +1. The build system handles references to design token values in other files as well (as you can see in `tokens/color/font.json`). 1. Values are transformed specifically for each platform. ## Making a change -Now let's make a change and see how that affects things. Open up `properties/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. Now: +Now let's make a change and see how that affects things. Open up `tokens/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. Now: **Android** ```xml @@ -256,7 +261,9 @@ Call this in the root directory of your project, which must include a [configura More detailed information about [using the Style Dictionary CLI is available here](using_the_cli.md). ### Node + 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'); @@ -264,9 +271,10 @@ StyleDictionary.buildAllPlatforms(); ``` The `.extend()` method is an overloaded method that can also take a [configuration](config.md) object. + ```javascript const StyleDictionary = require('style-dictionary').extend({ - source: ['properties/**/*.json'], + source: ['tokens/**/*.json'], platforms: { scss: { transformGroup: 'scss', diff --git a/docs/tokens.md b/docs/tokens.md new file mode 100644 index 000000000..7c2c64c5b --- /dev/null +++ b/docs/tokens.md @@ -0,0 +1,398 @@ +# Design Tokens + +> Synonyms: style properties, design variables, design constants, atoms + +Design tokens are the platform-agnostic way to define the input for Style Dictionary. A design token is a collection of attributes that describe any fundamental/atomic visual style. Each attribute is a key-value pair. + +![Terminology for different parts of a JSON property](assets/property-definitions.png) + +A design token is transformed for use in different platforms, languages, and contexts. A simple example is color. A color can be represented in many ways, all of these are the same color: `#ffffff`, `rgb(255,255,255)`, `hsl(0,0,1)`. + +A collection of design tokens which are organized in a nested object make the Style Dictionary. Here is an example of design tokens written for Style Dictionary: + +```json +{ + "color": { + "font": { + "base": { "value": "#111111" }, + "secondary": { "value": "#333333" }, + "tertiary": { "value": "#666666" }, + "inverse": { + "base": { "value": "#ffffff" } + } + } + } +} +``` + +Any node in the object that has a `value` attribute on it is a design token. In this example there are 4 style design tokens: `color.font.base`, `color.font.secondary`, `color.font.tertiary`, and `color.font.inverse.base`. + +## Design token attributes + +For any design tokens you wish to output, the "value" attribute is required. This provides the data that will be used throughout the build process (and ultimately used for styling in your deliverables). You can optionally include any custom attributes you would like (e.g. "comment" with a string or "metadata" as an object with its own attributes). + +| Attribute | Type | Description | +| :--- | :--- | :--- | +| value | Any | The value of the design token. This can be any type of data, a hex string, an integer, a file path to a file, even an object or array. +| comment | String (optional) | The comment attribute will show up in a code comment in output files if the format supports it. +| themeable | Boolean (optional) | This is used in formats that support override-able or themable values like the `!default` flag in Sass. +| name | String (optional) | Usually the name for a design token is generated with a [name transform](transforms.md#transform-types), but you can write your own if you choose. By default Style Dictionary will add a default name which is the key of the design token object. +| attributes | Object (optional) | Extra information about the design token you want to include. [Attribute transforms](transforms.md#transform-types) will modify this object so be careful + +You can add any attributes or data you want in a design token and Style Dictionary will pass it along to transforms and formats. For example, you could add a `deprecated` flag like in [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation). Other things you can do is add documentation information about each design token or information about color contrast. + +### Default design token metadata + +Style Dictionary adds some default metadata on each design token that helps with transforms and formats. Here is what Style Dictionary adds onto each design token: + +| Attribute | Type | Description | +| :--- | :--- | :--- | +| name | String | A default name of the design token that is set to the key of the design token. This is only added if you do not provide one. +| path | Array[String] | The object path of the design token. `color: { background: { primary: { value: "#fff" } } }` will have a path of `['color','background', 'primary']`. +| original | Object | A pristine copy of the original design token object. This is to make sure transforms and formats always have the unmodified version of the original design token. +| filePath | String | The file path of the file the token is defined in. This file path is derived from the `source` or `include` file path arrays defined in the [configuration](config.md). +| isSource | Boolean | If the token is from a file defined in the `source` array as opposed to `include` in the [configuration](config.md). + +Given this configuration: + +```json5 +{ + "source": ["tokens/**/*.json"] + //... +} +``` + +This design token: + +```json5 +// tokens/color/background.json +{ + "color": { + "background": { + "primary": { "value": "#fff" } + } + } +} +``` + +becomes: + +```json5 +{ + "color": { + "background": { + "primary": { + "name": "primary", + "value": "#fff", + "path": ["color","background","primary"], + "original": { + "value": "#fff" + }, + "filePath": "tokens/color/background.json", + "isSource": true + } + } + } +} +``` + + +---- + + +## Referencing / Aliasing + +You can reference (alias) existing values by using the dot-notation object path (the fully articulated design token name) in curly brackets. Note that this only applies to values; referencing a non-value design token will cause unexpected results in your output. + +```json +{ + "size": { + "font": { + "small" : { "value": "10" }, + "medium": { "value": "16" }, + "large" : { "value": "24" }, + "base" : { "value": "{size.font.medium.value}" } + } + } +} +``` + +See more in the advanced [referencing-aliasing example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing). + + +---- + + +## Defining design tokens + +Design token files can included inline in the configuration, or be written in separate files. Style Dictionary supports these languages for design token files: + +* JSON +* [JSON5](https://json5.org) +* CommonJS modules +* Potentially any language with [custom parsers](#customfileparsers) + +Tokens can be defined *inline* in the Style Dictionary configuration, or in files. You can add a `tokens` object to your Style Dictionary configuration like this: + +```javascript +// config.js +module.exports = { + tokens: { + color: { + background: { + primary: { value: "#fff" } + } + } + }, + platforms: { + //... + } +} +``` + +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 = { + include: [ + // you can list singular files: + `node_modules/my-other-style-dictionary/tokens.json` + ], + source: [ + // or use file path [globs](https://www.npmjs.com/package/glob) + // this says grab all files in the tokens directory with a .json extension + `tokens/**/*.json` + ] + // ... +} +``` + +**You can organize your design token files in any way as long as you can tell Style Dictionary where to find them.** The directory and file structure of design token files does not have any effect on the object structure of the tokens because Style Dictionary does a deep merge on all design token files. Separating tokens into files and folders is to make the authoring experience cleaner and more flexible. + +### Collision warnings + +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 = { + source: [ + `tokens.json`, + `tokens2.json` + ] +} +``` + +```json5 +// tokens.json +{ + "color": { + "background": { + "primary": { "value": "#fff" }, + "secondary": { "value": "#ccc" } + } + } +} +``` + +```json5 +// tokens2.json +{ + "color": { + "background": { + "primary": { "value": "#eee" }, + "tertiary": { "value": "#999" } + } + } +} +``` + +The resulting merged dictionary would be: + +```json5 +{ + "color": { + "background": { + "primary": { "value": "#eee" }, + "secondary": { "value": "#ccc" }, + "tertiary": { "value": "#999" } + } + } +} +``` + +This example would show a warning in the console that you have a collision at `color.background.primary` because 2 source files defined the same design token. A file in source overriding a file in include will not show a warning because the intent is that you include files you want to potentially override. For example, if you had multiple brands and you wanted to share a default theme, you could include the default theme and then override certain parts. + +### CommonJS modules + +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 = { + color: { + base: { + red: { value: '#ff0000' } + } + } +} +``` + +is equivalent to this JSON file: + +```json +{ + "color": { + "base": { + "red": { "value": "#ff0000" } + } + } +} +``` + +You might prefer authoring your design token files in Javascript because it can be a bit more friendly to read and write (don't have to quote keys, can leave dangling commas, etc.). Writing your design token files as Javascript gives you more freedom to do complex things like generating many tokens based on code: + +```javascript +const Color = require('tinycolor2'); + +const baseColors = { + red: {h: 4, s: 62, v: 90}, + purple: {h: 262, s: 47, v: 65}, + blue: {h: 206, s: 70, v: 85}, + teal: {h: 178, s: 75, v: 80}, + green: {h: 119, s: 47, v: 73}, + yellow: {h: 45, s: 70, v: 95}, + orange: {h: 28, s: 76, v: 98}, + grey: {h: 240, s: 14, v: 35}, +} + +// 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) => { + return Object.assign({}, ret, { + [color]: { + // generate the shades/tints for each color + "20": { value: Color(baseColors[color]).lighten(30).toString()}, + "40": { value: Color(baseColors[color]).lighten(25).toString()}, + "60": { value: Color(baseColors[color]).lighten(20).toString()}, + "80": { value: Color(baseColors[color]).lighten(10).toString()}, + "100": { value: baseColors[color]}, + "120": { value: Color(baseColors[color]).darken(10).toString()}, + "140": { value: Color(baseColors[color]).darken(20).toString()} + } + }) +}, {}); +``` + +Take a look at the [this example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) if you want to see a more in-depth example of using Javascript files as input. + +### Custom file parsers + +Starting in 3.0, you can define custom parsers to parse your source files. This allows you to author your design token files in other languages like [YAML](https://yaml.org/). Custom parsers run on certain input files based on a file path pattern regular expression (similar to how Webpack loaders work). The parser function gets the contents of the file and is expected to return an object of the data of that file for Style Dictionary to merge with the other input file data. + +```javascript +const StyleDictionary = require('style-dictionary'); + +StyleDictionary.registerParser({ + pattern: /.json$/, + parse: ({contents, filePath}) => { + return JSON.parse(contents); + } +}); +``` + +[Here is a complete custom file parser example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) + +[yaml-tokens example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) + + +---- + + +## Design token structure + +You can structure your tokens any way you want. You could have a flat object rather than a nested one: + +```json +{ + "colorBackgroundPrimary": { "value": "#fff" }, + "sizePaddingLarge": { "value": 4 } +} +``` + +### Category / Type / Item + +**This structure is not required.** This is just one example of how to structure your design tokens. + +Design tokens are organized into a hierarchical tree structure with 'category' defining the primitive nature of the design token. For example, we have the color category and every design token underneath is always a color. As you proceed down the tree, you get more specific about what that color is. Is it a background color, a text color, or a border color? What kind of text color is it? You get the point. It's like the animal kingdom classification: + +![](assets/cti.png) + +Now you can structure your tokens in a nested object like this: + +```json +{ + "size": { + "font": { + "base": { "value": "16" }, + "large": { "value": "20" } + } + } +} +``` + +The CTI is implicit in the structure, the category is 'size' and the type is 'font', and there are 2 tokens 'base' and 'large'. + +Structuring design tokens in this manner gives us consistent naming and accessing of these tokens. You don't need to remember if it is `button_color_error` or `error_button_color`, it is `color_background_button_error`! + +You can organize and name your design tokens however you want, **there are no restrictions**. But there are a good amount of helpers if you do use this structure, like the 'attribute/cti' transform which adds attributes to the design token of its CTI based on the path in the object. There are a lot of names transforms as well for when you want a flat structure like for Sass variables. + +Also, the CTI structure provides a good mechanism to target transforms for specific kinds of tokens. All of the transforms provided by the framework use the CTI structure to know if it should be applied. For instance, the 'color/hex' transform only applies to tokens of the category 'color'. + +Here are the categories and types the built-in transforms and formats use: + +#### Category: color +Everything under this category is a color. You can further organize by background, font, border, etc. if you want. The built-ins only look for a category of `color` +* [`color/rgb`](transforms.md#colorrgb) +* [`color/hsl`](transforms.md#colorhsl) +* [`color/hsl-4`](transforms.md#colorhsl-4) +* [`color/hex`](transforms.md#colorhex) +* [`color/hex8`](transforms.md#colorhex8) +* [`color/hex8android`](transforms.md#colorhex8android) +* [`color/UIColor`](transforms.md#coloruicolor) +* [`color/UIColorSwift`](transforms.md#coloruicolorswift) +* [`color/css`](transforms.md#colorcss) +* [`color/sketch`](transforms.md#colorsketch) +* [`color/hex8flutter`](transforms.md#colorhex8flutter) + +#### Category: size +Most platforms any type of size is treated the same. On Android it is common to use SP for font sizes and DP for paddings and dimensions. +* [`size/sp`](transforms.md#sizesp) +* [`size/dp`](transforms.md#sizedp) +* [`size/object`](transforms.md#sizeobject) +* [`size/remToSp`](transforms.md#sizeremtosp) +* [`size/remToDp`](transforms.md#sizeremtodp) +* [`size/px`](transforms.md#sizepx) +* [`size/rem`](transforms.md#sizerem) +* [`size/remToPt`](transforms.md#sizeremtopt) +* [`size/swift/remToCGFloat`](transforms.md#sizeswiftremtocgfloat) +* [`size/remToPx`](transforms.md#sizeremtopx) +* [`size/pxToRem`](transforms.md#sizepxtorem) +* [`size/flutter/remToDouble`](transforms.md#sizeflutterremtodouble) + +#### Category: time +* [`time/seconds`](transforms.md#timeseconds) + +#### Category: asset +These should be file paths used for images and font files +* [`asset/base64`](transforms.md#assetbase64) +* [`asset/path`](transforms.md#assetpath) +* [`asset/objC/literal`](transforms.md#assetobjcliteral) +* [`asset/swift/literal`](transforms.md#assetswiftliteral) +* [`asset/flutter/literal`](transforms.md#assetflutterliteral) + +#### Category: content +These should be strings +* [`content/icon`](transforms.md#contenticon) +* [`content/quote`](transforms.md#contentquote) +* [`content/objC/literal`](transforms.md#contentobjcliteral) +* [`content/swift/literal`](transforms.md#contentswiftliteral) +* [`content/flutter/literal`](transforms.md#contentflutterliteral) diff --git a/docs/transform_groups.md b/docs/transform_groups.md index e6e738a9c..2b13eda73 100644 --- a/docs/transform_groups.md +++ b/docs/transform_groups.md @@ -10,7 +10,7 @@ You use transformGroups in your config file under platforms > [platform] > trans ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transformGroup": "android" @@ -23,7 +23,7 @@ You use transformGroups in your config file under platforms > [platform] > trans ## Pre-defined Transform groups -[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/transformGroups.js) +[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transformGroups.js) ### web @@ -182,7 +182,7 @@ Transforms: [size/swift/remToCGFloat](transforms.md#sizeswiftremtocgfloat) [font/swift/literal](transforms.md#fontswiftliteral) -This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the property (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). +This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). * * * @@ -226,7 +226,7 @@ Transforms: [asset/flutter/literal](transforms.md#assetflutterliteral) [font/flutter/literal](transforms.md#fontflutterliteral) -This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the property (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). +This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). * * * diff --git a/docs/transforms.md b/docs/transforms.md index d793a23a1..58b232dd3 100644 --- a/docs/transforms.md +++ b/docs/transforms.md @@ -4,14 +4,14 @@ EDIT scripts/handlebars/templates/api.hbs OR JSDOC COMMENT INSTEAD! --> # Transforms -Transforms are functions that transform a property - this enables each platform to consume the property in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. Transforms are applied in a non-destructive way thus each platform can transform the properties. Transforms are performed sequentially, therfore the order you use transforms matters. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=defining-custom-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). +Transforms are functions that modify a [token](tokens.md) so that it can be understood by a specific platform. It can modify the name, value, or attributes of a token - enabling each platform to use the design token in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. Transforms are isolated per platform; each platform begins with the same design token and makes the modifications it needs without affecting other platforms. The order you use transforms matters because transforms are performed sequentially. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=defining-custom-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). ## Using Transforms You use transforms in your config file under platforms > [platform] > transforms ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transforms": ["attribute/cti", "name/cti/kebab", "color/hex", "size/rem"] @@ -20,25 +20,73 @@ You use transforms in your config file under platforms > [platform] > transforms } ``` -A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all properties where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all properties.* +A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all design tokens where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all tokens.* ## Transform Types There are 3 types of transforms: attribute, name, and value. -**Attribute:** An attribute transform adds to the attributes object on a property. This is for including any meta-data about a property such as it's CTI or other information. +**Attribute:** An attribute transform adds to the attributes object on a design token. This is for including any meta-data about a design token such as it's CTI or other information. -**Name:** A name transform transform the name of a property. You should really only be apply one name transformer because they will override each other if you use more than one. +**Name:** A name transform transform the name of a design token. You should really only be apply one name transformer because they will override each other if you use more than one. -**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which properties that transform runs on. This allows us to only run a color transform on only the colors and not every property. +**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which tokens that transform runs on. This allows us to only run a color transform on only the colors and not every design token. ## Defining Custom Transforms -You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](properties.md?id=default-property-metadata) to each property/token to provide context that may be useful for some transforms. +You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](tokens.md?id=default-design-token-metadata) to each design token to provide context that may be useful for some transforms. + +## Transitive Transforms +Starting in version 3.0, you can define transitive transforms which allow you to transform a referenced value. Normally, value transforms only transform non-referenced values and because transforms happen before references are resolved, the transformed value is then used to resolve references. + +```javascript +const StyleDictionary = require('style-dictionary'); + +StyleDictionary.registerTransform({ + type: `value`, + transitive: true, + name: `myTransitiveTransform`, + matcher: (token) => {}, + transformer: (token) => { + // token.value will be resolved and transformed at this point + } +}) +``` + +There is one thing to be mindful of with transitive transforms. The token's value will be resolved and *transformed* already at the time the transitive transform. What happens is Style Dictionary will transform and resolve values iteratively. First it will transform any non-referenced values, then it will resolve any references to non-referenced values, then it will try to transform any non-referenced values, and so on. Let's take a look at an example: + +```json +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}" }, + "error": { "value": "{color.danger}" } + } +} +``` + +Style dictionary will first transform the value of `color.red`, then resolve `color.danger` to the transformed `color.red` value. Then it will transform `color.danger` and resolve `color.error` to the transformed `color.danger`. Finally, it will transform `color.error` and see that there is nothing left to transform or resolve. + +This allows you to modify a reference that modifies another reference. For example: + +```json +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}", "darken": 0.75 }, + "error": { "value": "{color.danger}", "darken": 0.5 } + } +} +``` + +Using a custom transitive transform you could have `color.danger` darken `color.red` and `color.error` darken `color.danger`. The pre-defined transforms are *not transitive* to be backwards compatible with Style Dictionary v2 - an upgrade should not cause breaking changes. + +If you want to learn more about transitive transforms, take a look at the [transitive transforms example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms). + ## Pre-defined Transforms -[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/transforms.js) +[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transforms.js) -> All the pre-defined transforms included use the [CTI structure](properties.md?id=category-type-item) for the match properties. If you structure your style properties differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the property CTIs are on the attributes of your properties. +> All the pre-defined transforms included use the [CTI structure](tokens.md?id=category-type-item) for matching tokens. If you structure your design tokens differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the proper CTIs are on the attributes of your design tokens. ### attribute/cti @@ -66,7 +114,7 @@ Adds: category, type, item, subitem, and state on the attributes object based on Adds: hex, hsl, hsv, rgb, red, blue, green. ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns { "hex": "009688", @@ -158,7 +206,7 @@ Creates a snake case name. If you define a prefix on the platform in your config ### name/cti/constant -Creates a constant-style name based on the full CTI of the property. If you define a prefix on the platform in your config, it will prepend with your prefix +Creates a constant-style name based on the full CTI of the token. If you define a prefix on the platform in your config, it will prepend with your prefix ```js // Matches: all @@ -173,7 +221,7 @@ Creates a constant-style name based on the full CTI of the property. If you defi ### name/ti/constant -Creates a constant-style name on the type and item of the property. This is useful if you want to create different static classes/files for categories like `Color.BACKGROUND_BASE`. If you define a prefix on the platform in your config, it will prepend with your prefix. +Creates a constant-style name on the type and item of the token. This is useful if you want to create different static classes/files for categories like `Color.BACKGROUND_BASE`. If you define a prefix on the platform in your config, it will prepend with your prefix. ```js // Matches: all @@ -206,7 +254,7 @@ Creates a Pascal case name. If you define a prefix on the platform in your confi Transforms the value into an RGB string ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "rgb(0, 150, 136)" ``` @@ -220,7 +268,7 @@ Transforms the value into an RGB string Transforms the value into an HSL string or HSLA if alpha is present. Better browser support than color/hsl-4 ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "hsl(174, 100%, 29%)" "hsl(174, 100%, 29%, .5)" @@ -235,7 +283,7 @@ Transforms the value into an HSL string or HSLA if alpha is present. Better brow Transforms the value into an HSL string, using fourth argument if alpha is present. ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "hsl(174 100% 29%)" "hsl(174 100% 29% / .5)" @@ -250,7 +298,7 @@ Transforms the value into an HSL string, using fourth argument if alpha is prese Transforms the value into an 6-digit hex string ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "#009688" ``` @@ -264,7 +312,7 @@ Transforms the value into an 6-digit hex string Transforms the value into an 8-digit hex string ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "#009688ff" ``` @@ -278,7 +326,7 @@ Transforms the value into an 8-digit hex string Transforms the value into an 8-digit hex string for Android because they put the alpha channel first ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: "#ff009688" ``` @@ -306,7 +354,7 @@ Color(0xFF009688) Transforms the value into an UIColor class for iOS ```objectivec -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: [UIColor colorWithRed:0.114f green:0.114f blue:0.114f alpha:1.000f] ``` @@ -320,7 +368,7 @@ Transforms the value into an UIColor class for iOS Transforms the value into an UIColor swift class for iOS ```swift -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha:0.6) ``` @@ -334,7 +382,7 @@ UIColor(red: 0.667, green: 0.667, blue: 0.667, alpha:0.6) Transforms the value into a hex or rgb string depending on if it has transparency ```css -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: #000000 rgba(0,0,0,0.5) @@ -351,7 +399,7 @@ attributes that are floats from 0 - 1. This object is how Sketch stores colors. ```js -// Matches: prop.attributes.category === 'color' +// Matches: token.attributes.category === 'color' // Returns: { red: 0.5, @@ -370,7 +418,7 @@ colors. Transforms the value into a scale-independent pixel (sp) value for font sizes on Android. It will not scale the number. ```js -// Matches: prop.attributes.category === 'size' && prop.attributes.type === 'font' +// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' // Returns: "10.0sp" ``` @@ -384,7 +432,7 @@ Transforms the value into a scale-independent pixel (sp) value for font sizes on Transforms the value into a density-independent pixel (dp) value for non-font sizes on Android. It will not scale the number. ```js -// Matches: prop.attributes.category === 'size' && prop.attributes.type !== 'font' +// Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' // Returns: "10.0dp" ``` @@ -398,7 +446,7 @@ Transforms the value into a density-independent pixel (dp) value for non-font si Transforms the value into a usefull object ( for React Native support ) ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: { original: "10px", @@ -417,7 +465,7 @@ Transforms the value into a usefull object ( for React Native support ) Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes on Android. It WILL scale the number by a factor of 16 (common base font size on web). ```js -// Matches: prop.attributes.category === 'size' && prop.attributes.type === 'font' +// Matches: token.attributes.category === 'size' && token.attributes.type === 'font' // Returns: "16.0sp" ``` @@ -431,7 +479,7 @@ Transforms the value from a REM size on web into a scale-independent pixel (sp) Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). ```js -// Matches: prop.attributes.category === 'size' && prop.attributes.type !== 'font' +// Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' // Returns: "16.0dp" ``` @@ -445,7 +493,7 @@ Transforms the value from a REM size on web into a density-independent pixel (dp Adds 'px' to the end of the number. Does not scale the number ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: "10px" ``` @@ -459,7 +507,7 @@ Adds 'px' to the end of the number. Does not scale the number Adds 'rem' to the end of the number. Does not scale the number ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: "10rem" ``` @@ -473,7 +521,7 @@ Adds 'rem' to the end of the number. Does not scale the number Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'pt' to the end. ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: "16pt" ``` @@ -529,7 +577,7 @@ Adds the .em Compose extension to the end of a number. Does not scale the value Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Swift and initializes a CGFloat ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: "CGFloat(16.00)"" ``` @@ -542,7 +590,7 @@ Scales the number by 16 (or the value of 'basePxFontSize' on the platform in you Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'px' to the end. ```js -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: "16px" ``` @@ -556,7 +604,7 @@ Scales the number by 16 (or the value of 'basePxFontSize' on the platform in you Takes a unicode point and transforms it into a form CSS can use. ```js -// Matches: prop.attributes.category === 'content' && prop.attributes.type === 'icon' +// Matches: token.attributes.category === 'content' && token.attributes.type === 'icon' // Returns: "'\\E001'" ``` @@ -570,7 +618,7 @@ Takes a unicode point and transforms it into a form CSS can use. Wraps the value in a single quoted string ```js -// Matches: prop.attributes.category === 'content' +// Matches: token.attributes.category === 'content' // Returns: "'string'" ``` @@ -584,7 +632,7 @@ Wraps the value in a single quoted string Wraps the value in a double-quoted string and prepends an '@' to make a string literal. ```objectivec -// Matches: prop.attributes.category === 'content' +// Matches: token.attributes.category === 'content' // Returns: **"string"**: ``` @@ -597,7 +645,7 @@ Wraps the value in a double-quoted string and prepends an '@' to make a string l Wraps the value in a double-quoted string to make a string literal. ```swift -// Matches: prop.attributes.category === 'content' +// Matches: token.attributes.category === 'content' // Returns: "string" ``` @@ -611,7 +659,7 @@ Wraps the value in a double-quoted string to make a string literal. Wraps the value in a double-quoted string and prepends an '@' to make a string literal. ```objectivec -// Matches: prop.attributes.category === 'font' +// Matches: token.attributes.category === 'font' // Returns: @"string" ``` @@ -624,7 +672,7 @@ Wraps the value in a double-quoted string and prepends an '@' to make a string l Wraps the value in a double-quoted string to make a string literal. ```swift -// Matches: prop.attributes.category === 'font' +// Matches: token.attributes.category === 'font' // Returns: "string" ``` @@ -637,7 +685,7 @@ Wraps the value in a double-quoted string to make a string literal. Assumes a time in miliseconds and transforms it into a decimal ```js -// Matches: prop.attributes.category === 'time' +// Matches: token.attributes.category === 'time' // Returns: "0.5s" ``` @@ -651,7 +699,7 @@ Assumes a time in miliseconds and transforms it into a decimal Wraps the value in a double-quoted string and prepends an '@' to make a string literal. ```js -// Matches: prop.attributes.category === 'asset' +// Matches: token.attributes.category === 'asset' // Returns: 'IyBlZGl0b3Jjb25maWcub3JnCnJvb3QgPSB0cnVlCgpbKl0KaW5kZW50X3N0eWxlID0gc3BhY2UKaW5kZW50X3NpemUgPSAyCmVuZF9vZl9saW5lID0gbGYKY2hhcnNldCA9IHV0Zi04CnRyaW1fdHJhaWxpbmdfd2hpdGVzcGFjZSA9IHRydWUKaW5zZXJ0X2ZpbmFsX25ld2xpbmUgPSB0cnVlCgpbKi5tZF0KdHJpbV90cmFpbGluZ193aGl0ZXNwYWNlID0gZmFsc2U=' ``` @@ -665,7 +713,7 @@ Wraps the value in a double-quoted string and prepends an '@' to make a string l Prepends the local file path ```js -// Matches: prop.attributes.category === 'asset' +// Matches: token.attributes.category === 'asset' // Returns: "path/to/file/asset.png" ``` @@ -679,7 +727,7 @@ Prepends the local file path Wraps the value in a double-quoted string and prepends an '@' to make a string literal. ```objectivec -// Matches: prop.attributes.category === 'asset' +// Matches: token.attributes.category === 'asset' // Returns: @"string" ``` @@ -692,7 +740,7 @@ Wraps the value in a double-quoted string and prepends an '@' to make a string l Wraps the value in a double-quoted string to make a string literal. ```swift -// Matches: prop.attributes.category === 'asset' +// Matches: token.attributes.category === 'asset' // Returns: "string" ``` @@ -704,7 +752,7 @@ Wraps the value in a double-quoted string to make a string literal. Transforms the value into a Flutter Color object using 8-digit hex with the alpha chanel on start ```js - // Matches: prop.attributes.category === 'color' + // Matches: token.attributes.category === 'color' // Returns: Color(0xFF00FF5F) ``` @@ -718,7 +766,7 @@ Transforms the value into a Flutter Color object using 8-digit hex with the alph Wraps the value in a double-quoted string to make a string literal. ```dart -// Matches: prop.attributes.category === 'content' +// Matches: token.attributes.category === 'content' // Returns: "string" ``` @@ -731,7 +779,7 @@ Wraps the value in a double-quoted string to make a string literal. Wraps the value in a double-quoted string to make a string literal. ```dart -// Matches: prop.attributes.category === 'asset' +// Matches: token.attributes.category === 'asset' // Returns: "string" ``` @@ -744,7 +792,7 @@ Wraps the value in a double-quoted string to make a string literal. Wraps the value in a double-quoted string to make a string literal. ```dart -// Matches: prop.attributes.category === 'font' +// Matches: token.attributes.category === 'font' // Returns: "string" ``` @@ -757,7 +805,7 @@ Wraps the value in a double-quoted string to make a string literal. Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Flutter ```dart -// Matches: prop.attributes.category === 'size' +// Matches: token.attributes.category === 'size' // Returns: 16.00 ``` diff --git a/docs/using_the_cli.md b/docs/using_the_cli.md index 37ba9e143..692ec7b51 100644 --- a/docs/using_the_cli.md +++ b/docs/using_the_cli.md @@ -4,74 +4,104 @@ The Style Dictionary command line interface (CLI) provides an executable system # Installation + To use the CLI, you can install it globally via npm: + ```bash $ npm install -g style-dictionary ``` +Most of the time you will want to install Style Dictionary as a dev dependency in your NPM package. The reason to have it as a dev dependency rather than a regular dependency is that Style Dictionary is a build tool rather than a runtime tool because it is used to *generate* files rather than used directly in an application. + +```bash +$ npm install --save-dev style-dictionary +``` + +In your `package.json` file you can add an NPM script that runs Style Dictionary: + +```json + "scripts": { + "build": "style-dictionary build" + } +``` + # CLI Quick Start -This will create a new folder called 'quick-start' and populate it with a Style Dictionary configuration and properties. + +This will create a new folder called 'quick-start' and populate it with a Style Dictionary configuration and tokens. + ```bash $ mkdir quick-start && cd quick-start $ style-dictionary init basic ``` -You can then modify the properties in the properties directory and run the build command below. See the changes in the output generated in the build folder. + +You can then modify the design tokens in the tokens directory and run the build command below. See the changes in the output generated in the build folder. + ```bash $ style-dictionary build ``` - # Commands + The CLI provides three basic commands: -* [build](using_the_cli.md?id=build) Builds a style dictionary package from the current directory. -* [clean](using_the_cli.md?id=clean) Removes files specified in the config of the style dictionary package of the current directory. -* [init](using_the_cli.md?id=init) Generates a starter style dictionary + +* [build](using_the_cli.md?id=build) Builds a style dictionary package from the current directory. +* [clean](using_the_cli.md?id=clean) Removes files specified in the config of the style dictionary package of the current directory. +* [init](using_the_cli.md?id=init) Generates a starter style dictionary These commands can be run using: + ```bash $ style-dictionary [command] [options] ``` +## build -# build Builds a style dictionary package from the current directory. Usage: + ```bash $ style-dictionary build [options] ``` + Options: + | Name | Usage | Description | | :--- | :--- | :--- | | Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | | Platform | -p , --platform | Only build a specific platform. If not supplied, builds all platform found in the configuration file. | +## clean -# clean Removes files and folders generated by a previously run 'build' command. Usage: + ```bash $ style-dictionary clean [options] ``` + Options: + | Name | Usage | Description | | :--- | :--- | :--- | | Configuration Path | -c , --config | Set the path to the configuration file. Defaults to './config.json'. | | Platform | -p , --platform | Only clean a specific platform. If not supplied, cleans all platform found in the configuration file. | +## init -# init Generates a starter style dictionary, based on the supplied example type. Usage: + ```bash $ style-dictionary init ``` + Where example-type is one of: * `basic` * `complete` - +## version -# Version To see what version of Style Dictionary you have, run this command: + ```bash $ style-dictionary --version ``` diff --git a/docs/using_the_npm_module.md b/docs/using_the_npm_module.md index 2b138af17..de69fec8a 100644 --- a/docs/using_the_npm_module.md +++ b/docs/using_the_npm_module.md @@ -2,28 +2,52 @@ The Style Dictionary npm module exposes an [API](api.md) to interact with style dictionaries. +## Installation -# Installation To use the npm module, install it like a normal npm dependency. You are most likely going to want to save it as a dev dependency (The -D option) because it's a build tool: + ```bash $ npm install -D style-dictionary ``` +## NPM Module Quick Start -# NPM Module Quick Start To use the style dictionary build system in node, there are generally three steps: + 1. Require/import the StyleDictionary module 1. Extend the module with a configuration, creating the fully defined dictionary (importing all properties and intended outputs) 1. Call one or more build calls for various platforms +To use the NPM module you will need to update your NPM script that runs Style Dictionary from using the CLI command to running Node on the file you are using. + +```json5 +// package.json + "scripts": { + "build": "style-dictionary build" + } +``` + +becomes + +```json5 +// package.json + "scripts": { + "build": "node build.js" + } +``` + +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'); StyleDictionary.buildAllPlatforms(); ``` -Alternatively, you can pass in a [configuration](config.md) object to the extend call. The buildAllPlatforms call is the same. +Alternatively, you can pass in a [configuration](config.md) object to the extend call. The `buildAllPlatforms` call is the same. + ```javascript const StyleDictionary = require('style-dictionary').extend({ source: ['properties/**/*.json'], @@ -43,6 +67,43 @@ const StyleDictionary = require('style-dictionary').extend({ 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'); + +const styleDictionary = StyleDictionary.extend({ + // add custom formats/transforms +}); + +styleDictionary.extend({ + // ... +}).buildAllPlatforms(); + +styleDictionary.extend({ + // ... +}).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'); + +const brands = [`brand-1`, `brand-2`, `brand-3`]; +brands.forEach(brand => { + StyleDictionary.extend({ + include: [`tokens/default/**/*.json`], + source: [`tokens/${brand}/**/*.json`], + // ... + }).buildAllPlatforms(); +}); +``` + +The [multi-brand-multi-platform example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) uses this method. + +---- + +## NPM Module API -# NPM Module API The [complete npm module API is documented here](api.md). diff --git a/examples/README.md b/examples/README.md index ef992a711..79eeee952 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,14 +1,8 @@ -Style Dictionary logo +Style Dictionary logo # Examples -Here you can find some sample projects to get started, or to find inspiration on how to customise and extend the Style Dictionary framework to create the files you need. - -## Setup - -To use one of these examples, clone (or [download](https://github.com/amzn/style-dictionary/archive/master.zip)) from GitHub the project and copy the folder of the example that you want to use. Inside the folder you will find a `README.md` file with the instructions on how to do the initial setup and run the `build` process. - -You can alternatively start a new project from one of the `basic` or `complete` examples using the CLI: +To get you started, there are some example packages included that you can use. You can [take a look at the code on Github](https://github.com/amzn/style-dictionary/tree/main/examples/) or you can use the CLI included to generate a new package using some of these examples. Here is how you can do that: ```bash $ mkdir MyFolder @@ -18,32 +12,42 @@ $ style-dictionary init [example] Where `[example]` is one of: `basic`, `complete`. -This will create a copy of the example in `MyFolder` and start the build process, running `style-dictionary build` for the first time to generate the artifacts. - ## Basic -[View the example](https://github.com/amzn/style-dictionary/tree/master/examples/basic) +[View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/basic) This example code is bare-bones to show you what this framework can do. Use this if you want to play around with what the Style Dictionary can do. ## Complete -[View the example](https://github.com/amzn/style-dictionary/tree/master/examples/complete) +[View on Github](https://github.com/amzn/style-dictionary/tree/main/examples/complete) This is a more complete package and should have everything you need to get started. This package can be consumed as a Cocoapod on iOS, as a node module for web, and as a local library for Android. ## Advanced -[View the folder](https://github.com/amzn/style-dictionary/tree/master/examples/advanced) - -If you want to look at more advanced examples of possible applications and customisations of Style Dictionary, the `examples/advanced` folder on GitHub contains these extra folders: - -* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. -* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the properties. -* [**custom-templates**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/custom-templates/custom-templates) shows how to use "custom" templates to generate design tokens files with custom formats, useful when you need to distribute your design tokens and integrate them with custom pipelines or scripts. -* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/custom-templates/custom-transforms) shows how to use custom tranforms (and transformGroups) to apply custom "tranformations" to the properties when converted to design tokens. -* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with property values depending on brand and plaforms. -* [**npm-module**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. -* [**s3**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. -* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/master/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a property and assign it to the value –or attribute– of another property. +[View the folder](https://github.com/amzn/style-dictionary/tree/main/examples/advanced) + +If you want to look at more advanced examples of possible applications and customizations of Style Dictionary, the [`examples/advanced`](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/) folder on GitHub contains these extra folders: + +* [**assets-base64-embed**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/assets-base64-embed) shows how it's possible to embed and distribute assets – like images, icons and fonts – directly as design tokens. +* [**auto-rebuild-watcher**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/auto-rebuild-watcher) shows how to setup a "watcher" that auto-rebuilds the tokens every time there is a change in the tokens. +* [**component-cti**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/component-cti) shows how to write component tokens and still use the CTI structure. +* [**create-react-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-app) shows how to integrate Style Dictionary into a React application. +* [**create-react-native-app**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/create-react-native-app) shows how to integrate Style Dictionary into a React Native application. +* [**custom-file-header**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) shows how to define custom file headers and use them in output files. +* [**custom-formats-with-templates**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-formats-with-templates) shows how to generate custom output formats using templates, useful when you need to distribute your design tokens into your own pipelines or scripts. +* [**custom-parser**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-parser) shows how to use custom parsers for token files. +* [**custom-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-transforms) shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. +* [**flutter**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/flutter) shows how to integrate with Flutter applications. +* [**matching-build-files**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/matching-build-files) shows how to output files 1-to-1 with source files. +* [**multi-brand-multi-platform**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/multi-brand-multi-platform) shows how to set up Style Dictionary to support a multi-brand (for brand theming) and multi-platform (web, iOS, Android) solution, with token values depending on brand and platforms. +* [**node-modules-as-config-and-properties**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/node-modules-as-config-and-properties) shows how to use Javascript rather than JSON for configuration and token files. +* [**npm-module**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/npm-module) shows how to set up a style dictionary as an npm module, either to publish to a local npm service or to publish externally. +* [**referencing_aliasing**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/referencing_aliasing) shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. +* [**s3**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/s3) shows how to set up a style dictionary to build files for different platforms (web, iOS, Android) and upload those build artifacts, together with a group of assets, to an S3 bucket. +* [**tokens-deprecation**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/tokens-deprecation) shows one way to deprecate tokens by adding metadata to tokens and using custom formats to output comments in the generated files. +* [**transitive-transforms**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms) shows how to use transitive transforms to transform references +* [**variables-in-outputs**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/variables-in-outputs) shows you how to use the `outputReferences` option to generate files variable references in them. +* [**yaml-tokens**](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/yaml-tokens) shows how to use a custom parser to define your source files in YAML rather than JSON. --- diff --git a/examples/advanced/assets-base64-embed/README.md b/examples/advanced/assets-base64-embed/README.md index 60ba36783..ba6c63d07 100644 --- a/examples/advanced/assets-base64-embed/README.md +++ b/examples/advanced/assets-base64-embed/README.md @@ -2,7 +2,7 @@ This example shows how it's possible to embed and distribute assets – like **images, icons and fonts** – directly as design tokens. -This means that you can centralise all your "core" design values in one single place and one single format, and make their distribution (and consumption) much easier. +This means that you can centralize all your "core" design values in one single place and one single format, and make their distribution (and consumption) much easier. #### Running the example @@ -12,7 +12,7 @@ At this point, run `npm run build`. This command will generate the files in the #### How does it work -In Style Dictionary it is possible to associate to the `value` of a property the path of a file. During the build process, the property is processed and the asset converted to a **base64 string**. In this way the asset can be distributed **embedded** in an output file that has a pre-defined format of your choice (JSON, JS, Sass, XML, PLIST, etc), and this can be then later consumed directly in your application or website. +In Style Dictionary it is possible to associate to the `value` of a token the path of a file. During the build process, the token is processed and the asset converted to a **base64 string**. In this way the asset can be distributed **embedded** in an output file that has a pre-defined format of your choice (JSON, JS, Sass, XML, PLIST, etc), and this can be then later consumed directly in your application or website. For example, in **JavaScript** this code: @@ -54,7 +54,7 @@ Open the `config.json` file and see how all the "assets/embed/*" platform blocks ... ``` -Here there are **three specific transforms**: *attribute/cti* to assign the Category/Type/Item attributes to the tokens, *name/cti/kebab* to assign them the correct name, and finally *asset/base64* to take the path declared in the "value" of the properties, convert the file at that path in base64 format, and assign the output of the base64 conversion to the "value" of the property. +Here there are **three specific transforms**: *attribute/cti* to assign the Category/Type/Item attributes to the tokens, *name/cti/kebab* to assign them the correct name, and finally *asset/base64* to take the path declared in the "value" of the tokens, convert the file at that path in base64 format, and assign the output of the base64 conversion to the "value" of the token. If you take for example the file `assets/icons.json` you will see this declaration: @@ -64,7 +64,7 @@ If you take for example the file `assets/icons.json` you will see this declarati "alert-circle": { "value": "assets/icons/alert-circle.svg" } ``` -where the value of the `alert-circle` property is a path that points to the `alert-circle.svg` file in the `assets/icons/` folder. +where the value of the `alert-circle` token is a path that points to the `alert-circle.svg` file in the `assets/icons/` folder. Now, `build` the dictionary and open the generated file `build/scss/assets_icons.scss`, and you will see this result: diff --git a/examples/advanced/assets-base64-embed/config.json b/examples/advanced/assets-base64-embed/config.json index f93e9a52d..0bc364192 100644 --- a/examples/advanced/assets-base64-embed/config.json +++ b/examples/advanced/assets-base64-embed/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", diff --git a/examples/advanced/assets-base64-embed/properties/assets/fonts.json b/examples/advanced/assets-base64-embed/tokens/assets/fonts.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/assets/fonts.json rename to examples/advanced/assets-base64-embed/tokens/assets/fonts.json diff --git a/examples/advanced/assets-base64-embed/properties/assets/icons.json b/examples/advanced/assets-base64-embed/tokens/assets/icons.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/assets/icons.json rename to examples/advanced/assets-base64-embed/tokens/assets/icons.json diff --git a/examples/advanced/assets-base64-embed/properties/assets/images.json b/examples/advanced/assets-base64-embed/tokens/assets/images.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/assets/images.json rename to examples/advanced/assets-base64-embed/tokens/assets/images.json diff --git a/examples/advanced/assets-base64-embed/properties/color/base.json b/examples/advanced/assets-base64-embed/tokens/color/base.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/color/base.json rename to examples/advanced/assets-base64-embed/tokens/color/base.json diff --git a/examples/advanced/assets-base64-embed/properties/color/font.json b/examples/advanced/assets-base64-embed/tokens/color/font.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/color/font.json rename to examples/advanced/assets-base64-embed/tokens/color/font.json diff --git a/examples/advanced/assets-base64-embed/properties/size/font.json b/examples/advanced/assets-base64-embed/tokens/size/font.json similarity index 100% rename from examples/advanced/assets-base64-embed/properties/size/font.json rename to examples/advanced/assets-base64-embed/tokens/size/font.json diff --git a/examples/advanced/auto-rebuild-watcher/README.md b/examples/advanced/auto-rebuild-watcher/README.md index 18f71d32a..215484ba6 100644 --- a/examples/advanced/auto-rebuild-watcher/README.md +++ b/examples/advanced/auto-rebuild-watcher/README.md @@ -1,6 +1,6 @@ ## How to use a watcher to auto-rebuild -This example shows how to use a "watcher" to rebuild automatically the files every time a property file is updated. +This example shows how to use a "watcher" to rebuild automatically the files every time a token file is updated. This is quite handy when there are continuous changes to the token values (e.g. during development) and we want to avoid to run the "build" command at every update. @@ -10,11 +10,11 @@ First of all, set up the required dependencies running the command `npm install` At this point, if you want to build once the tokens you can run `npm run build`. This command will generate the files in the `build` folder. -If instead you want to automatically build the tokens every time a property file is updated, run the command `npm run watch` in your CLI. +If instead you want to automatically build the tokens every time a token file is updated, run the command `npm run watch` in your CLI. -This will start to watch the files in the "properties" folder, and whenever a file is updated and saved, the files in `build` are re-generated with the new/updated values. +This will start to watch the files in the "tokens" folder, and whenever a file is updated and saved, the files in `build` are re-generated with the new/updated values. -If you want to see it in action, open one of the files generated in "build", open a property file and update one of the values: you will see immediately updated also the generated file. +If you want to see it in action, open one of the files generated in "build", open a token file and update one of the values: you will see immediately updated also the generated file. **Important**: when in "watch" mode, to interrupt and exit the process and get back to your command line, use the `ctrl-c` command in your terminal. @@ -22,7 +22,7 @@ If you want to see it in action, open one of the files generated in "build", ope The "watch" runner will start a process (using a special filesystem watcher called [Chokidar](https://github.com/paulmillr/chokidar)) that will listen to changes to a list of "watched" files. Whenever one of this file is changed/updated (more precisely, is saved to disk) the watch process will trigger a command specified by the user (as an argument passed to the watcher). -In this example, we have selected all the JSON files in the `props` folder (using the glob pattern `properties/**/*.json`) but you can specify your own path of watched files. +In this example, we have selected all the JSON files in the `tokens` folder (using the glob pattern `tokens/**/*.json`) but you can specify your own path of watched files. The command that we automatically run at every update is the `npm run build` command, passed as parameter to the watcher via `-c 'npm run build'`. diff --git a/examples/advanced/auto-rebuild-watcher/config.json b/examples/advanced/auto-rebuild-watcher/config.json index 942e328ac..6710fad62 100644 --- a/examples/advanced/auto-rebuild-watcher/config.json +++ b/examples/advanced/auto-rebuild-watcher/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", diff --git a/examples/advanced/auto-rebuild-watcher/properties/color/base.json b/examples/advanced/auto-rebuild-watcher/tokens/color/base.json similarity index 100% rename from examples/advanced/auto-rebuild-watcher/properties/color/base.json rename to examples/advanced/auto-rebuild-watcher/tokens/color/base.json diff --git a/examples/advanced/auto-rebuild-watcher/properties/color/font.json b/examples/advanced/auto-rebuild-watcher/tokens/color/font.json similarity index 100% rename from examples/advanced/auto-rebuild-watcher/properties/color/font.json rename to examples/advanced/auto-rebuild-watcher/tokens/color/font.json diff --git a/examples/advanced/auto-rebuild-watcher/properties/size/font.json b/examples/advanced/auto-rebuild-watcher/tokens/size/font.json similarity index 100% rename from examples/advanced/auto-rebuild-watcher/properties/size/font.json rename to examples/advanced/auto-rebuild-watcher/tokens/size/font.json diff --git a/examples/advanced/custom-file-header/README.md b/examples/advanced/custom-file-header/README.md index a04932f8d..7fb21736f 100644 --- a/examples/advanced/custom-file-header/README.md +++ b/examples/advanced/custom-file-header/README.md @@ -33,7 +33,7 @@ You can reference the file header in a custom format as well by using the `fileH const {fileHeader} = StyleDictionary.formatHelpers; const myCustomFormat = ({ dictionary, file }) => { - return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allProperties.map(token => { + return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allTokens.map(token => { return `--${token.name}: ${token.value};` }).join(`\n`)}` } diff --git a/examples/advanced/custom-file-header/build.js b/examples/advanced/custom-file-header/build.js index 8eec99556..70c4f2518 100644 --- a/examples/advanced/custom-file-header/build.js +++ b/examples/advanced/custom-file-header/build.js @@ -8,7 +8,7 @@ const version = require('./package.json').version; const {fileHeader} = StyleDictionary.formatHelpers; const myCustomFormat = ({ dictionary, file }) => { - return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allProperties.map(token => { + return `${fileHeader({file, commentStyle: 'short'})}${dictionary.allTokens.map(token => { return `--${token.name}: ${token.value};` }).join(`\n`)}` } @@ -101,9 +101,9 @@ const styleDictionary = StyleDictionary.extend({ } }); -// Create a hash of style dictionary properties object to use in a file header +// Create a hash of style dictionary tokens object to use in a file header const hash = crypto.createHash('md5') - .update(JSON.stringify(styleDictionary.properties)) + .update(JSON.stringify(styleDictionary.tokens)) .digest('hex'); // Adding a custom file header with the `.registerFileHeader` diff --git a/examples/advanced/custom-formats-with-templates/build.js b/examples/advanced/custom-formats-with-templates/build.js index e7bc05e18..2a5d541e8 100644 --- a/examples/advanced/custom-formats-with-templates/build.js +++ b/examples/advanced/custom-formats-with-templates/build.js @@ -35,13 +35,13 @@ const templateCustomXml = handlebars.compile(fs.readFileSync(__dirname + '/templ StyleDictionary.registerFormat({ name: 'custom/format/android-xml-alt', - formatter: function(dictionary, platform) { + formatter: function({dictionary, platform}) { return templateCustomXml({ // this is to show that the formatter function only takes a "dictionary" and "platform" parameters - // (and dictionary has a "properties" and "allProperties" attributes) + // (and dictionary has "tokens" and "allTokens" attributes) // and returns a string. for more details about the "formatter" function refer to the documentation - allProperties: dictionary.allProperties, - properties: dictionary.properties, + allTokens: dictionary.allTokens, + tokens: dictionary.tokens, options: platform }); } @@ -53,9 +53,9 @@ const templateCustomPlist = pug.compileFile(__dirname + '/templates/ios-plist_al StyleDictionary.registerFormat({ name: 'custom/format/ios-plist-alt', - formatter: function(dictionary) { + formatter: function({dictionary}) { return templateCustomPlist({ - allProperties: dictionary.allProperties + allTokens: dictionary.allTokens }); } }); diff --git a/examples/advanced/custom-formats-with-templates/templates/android-xml.template b/examples/advanced/custom-formats-with-templates/templates/android-xml.template index 013273c61..f00a17f73 100644 --- a/examples/advanced/custom-formats-with-templates/templates/android-xml.template +++ b/examples/advanced/custom-formats-with-templates/templates/android-xml.template @@ -1,5 +1,5 @@ <% -var allProperties = _.each(allProperties, function(prop) { +var allTokens = _.each(allTokens, function(prop) { if(prop.attributes.category === 'color') { prop.tag = 'color'; } else if(prop.attributes.category === 'size') { @@ -13,7 +13,7 @@ var allProperties = _.each(allProperties, function(prop) { } }); %> -<% _.each(allProperties, function(prop) { +<% _.each(allTokens, function(prop) { // Notice: this is an alternative way to use Lodash templating syntax, // that uses string concatenation and the print() function to have // more control over the indentation, whitespace, newlines, etc. diff --git a/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs b/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs index 7b9a44063..c2ebf22b9 100644 --- a/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs +++ b/examples/advanced/custom-formats-with-templates/templates/android-xml_alt.hbs @@ -1,4 +1,4 @@ -{{#each allProperties}} +{{#each allTokens}} {{value}} {{/each}} diff --git a/examples/advanced/custom-formats-with-templates/templates/ios-plist.template b/examples/advanced/custom-formats-with-templates/templates/ios-plist.template index 3344a70fc..e62f75ae6 100644 --- a/examples/advanced/custom-formats-with-templates/templates/ios-plist.template +++ b/examples/advanced/custom-formats-with-templates/templates/ios-plist.template @@ -2,7 +2,7 @@ <% -var allProperties = _.each(allProperties, function(prop) { +var allTokens = _.each(allTokens, function(prop) { if(prop.type === 'color') { prop.tag = 'string'; } else if(prop.type === 'size') { @@ -17,7 +17,7 @@ var allProperties = _.each(allProperties, function(prop) { }); %> - <% _.each(allProperties, function(prop) { + <% _.each(allTokens, function(prop) { %><%= prop.name %><<%= prop.tag %>><%= prop.value %>><% if (prop.comment) { %><% } %> <% }); %> diff --git a/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug b/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug index 9a7659b09..f6cc4cf8a 100644 --- a/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug +++ b/examples/advanced/custom-formats-with-templates/templates/ios-plist_alt.pug @@ -1,6 +1,6 @@ -each prop in allProperties - case prop.attributes.category +each token in allTokens + case token.attributes.category when 'color' - var tag = 'string' when 'size' @@ -13,12 +13,12 @@ each prop in allProperties - var tag = 'string' default - var tag = 'string' - key #{prop.name} + key #{token.name} dict - if prop.comment - // #{prop.comment} - if prop.type + if token.comment + // #{token.comment} + if token.type key type - string #{prop.type} + string #{token.type} key value - #{tag}(name=prop.name) #{prop.value} + #{tag}(name=token.name) #{token.value} diff --git a/examples/advanced/custom-formats-with-templates/templates/web-scss.template b/examples/advanced/custom-formats-with-templates/templates/web-scss.template index f24364c8d..546acdb42 100644 --- a/examples/advanced/custom-formats-with-templates/templates/web-scss.template +++ b/examples/advanced/custom-formats-with-templates/templates/web-scss.template @@ -1,3 +1,3 @@ -<% _.each(allProperties, function(prop) { +<% _.each(allTokens, function(prop) { %>$<%= prop.name %>: <%= prop.value %>;<% if (prop.comment) { %> // <%= prop.comment %><% } %> <% }); %> \ No newline at end of file diff --git a/examples/advanced/custom-transforms/README.md b/examples/advanced/custom-transforms/README.md index bfd2afcb7..ff43d779a 100644 --- a/examples/advanced/custom-transforms/README.md +++ b/examples/advanced/custom-transforms/README.md @@ -1,15 +1,15 @@ ## Custom transforms (and transformGroups) -This example shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the properties when converted to design tokens. +This example shows how to use custom transforms (and transformGroups) to apply custom "transformations" to the design tokens. -Transforms are functions that transform a property (in a non-destructive way). The reason for *transforms* is that in this way each platform can consume the property in different ways (eg. changing *pixel* values to *pt* values for iOS, and *dp* or *sp* for Android). +Transforms are functions that modify a design token (in a non-destructive way). The reason for *transforms* is that in this way each platform can consume the token in different ways (eg. changing *pixel* values to *pt* values for iOS, and *dp* or *sp* for Android). **Remember**: transforms are performed sequentially, hence the order you use transforms matters. -The need for custom transforms is that Style Dictionary expects the properties to be declared according to certain criteria, to use the pre-defined transforms and formats/templates. For example, the *web* transformGroup consists of the *attribute/cti*, *name/cti/kebab*, *size/px* and *color/css* transforms. -The *size/px* adds 'px' to the end of the number, and is applied only if `prop.attributes.category === 'size'`. This means that your property needs to be expressed without units, and be under the *'size'* "category. If you need a different logic or you want to organise your properties differently, probably you can't use the out-of-the-box transformation groups, but you have to declare your custom ones. +The need for custom transforms is that Style Dictionary expects the tokens to be declared according to certain criteria, to use the pre-defined transforms and formats/templates. For example, the *web* transformGroup consists of the *attribute/cti*, *name/cti/kebab*, *size/px* and *color/css* transforms. +The *size/px* adds 'px' to the end of the number, and is applied only if `token.attributes.category === 'size'`. This means that your token needs to be expressed without units, and be under the *'size'* "category. If you need a different logic or you want to organize your tokens differently, probably you can't use the out-of-the-box transformation groups, but you have to declare your custom ones. -If [custom formats](../custom-formats-with-templates/) are the way to allow users to customise the format of the *output* of Style Dictionary, custom transforms are the way to allow them to customise both the *input* (the property names/values/attributes) and the *output* (the actual values expressed in the design tokens). For this reasons, custom transforms are probably one of the **most powerful features** of Style Dictionary: they make it extremely versatile, allowing limitless possibilities of extension and customisation of the entire pipeline from properties to design tokens. +If [custom formats](../custom-formats-with-templates/) are the way to allow users to customize the format of the *output* of Style Dictionary, custom transforms are the way to allow them to customise both the *input* (the token names/values/attributes) and the *output* (the actual values expressed in the design tokens). For this reasons, custom transforms are probably one of the **most powerful features** of Style Dictionary: they make it extremely versatile, allowing limitless possibilities of extension and customization of the entire design token pipeline. #### Running the example @@ -25,11 +25,11 @@ To declare a custom **transform**, you have to call the `registerTransform` meth StyleDictionary.registerTransform({ name: 'ratio/%', type: 'value', - matcher: function(prop) { - return prop.group === 'ratio'; + matcher: function(token) { + return token.group === 'ratio'; }, - transformer: function(prop) { - return `${Math.floor(100 * prop.value)}%`; + transformer: function(token) { + return `${Math.floor(100 * token.value)}%`; } }); ``` @@ -53,7 +53,7 @@ Once registered, the custom group can be associated to one or more **platforms** ``` { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "web": { "transformGroup": "custom/web", @@ -73,18 +73,18 @@ in your code and look the array of transforms associated with the it, directly i #### What to look at -Open the `config.js` file and see how for each platform there is a `transformGroup` declaration. In this specific example, all the transformGroups applied to the platforms are custom. +Open the `config.json` file and see how for each platform there is a `transformGroup` declaration. In this specific example, all the transformGroups applied to the platforms are custom. -Now open a property file (eg. `colors/font/spacing.json`) to see how we have associated custom attributes to the properties, to be used later in the matchers functions. See also how the values are unitless, where the units are applied at build time accordingly to the destination platform. Compare the values in the input JSON files, and the values that appear in the files generated in `build`, and you will see where and how the transformations have been applied. +Now open a token file (eg. `tokens/colors|font|spacing.json`) to see how we have associated custom attributes to the tokens, to be used later in the matchers functions. See also how the values are unit-less, where the units are applied at build time accordingly to the destination platform. Compare the values in the input JSON files, and the values that appear in the files generated in `build`, and you will see where and how the transformations have been applied. Now open the `build.js` script and look at how these custom transforms/transformGroups are declared and registered via the `registerTransform` and `registerTransform` API methods. We have added as many comments as possible to make the code clear and show the interesting parts of it. A few things to notice in the file: - the name of a custom "transform" can be the same as an existing pre-defined method; in that case, the pre-defined method is overwritten -- beyond the existing attributes, you can use custom attributes to create **matcher** functions, used to filter the properties and apply the transform only to those that match the filter condition. -- if you don't specify a **matcher**, the transformation will be applied to all the properties -- the transformation can be applied not only to the **value** of a property, but also to its **name** (and also to its attributes) +- beyond the existing attributes, you can use custom attributes to create **matcher** functions, used to filter the tokens and apply the transform only to those that match the filter condition. +- if you don't specify a **matcher**, the transformation will be applied to all the tokens +- the transformation can be applied not only to the **value** of a token, but also to its **name** (and also to its attributes) **IMPORTANT**: the registration of custom transforms needs to be done _before_ applying the configuration (the methods needs to be already declared and registered in Style Dictionary to be used when extending it with the configuration). See the code in the `build.js` for more details. diff --git a/examples/advanced/custom-transforms/build.js b/examples/advanced/custom-transforms/build.js index a299ad0a6..7a363fe7b 100644 --- a/examples/advanced/custom-transforms/build.js +++ b/examples/advanced/custom-transforms/build.js @@ -9,58 +9,58 @@ console.log('\n=============================================='); StyleDictionary.registerTransform({ name: 'size/px', // notice: the name is an override of an existing predefined method (yes, you can do it) type: 'value', - matcher: function(prop) { + matcher: function(token) { // this is an example of a possible filter (based on the "cti" values) to show how a "matcher" works - return prop.attributes.category === 'font' || prop.attributes.category === 'margin'; + return token.attributes.category === 'font' || token.attributes.category === 'margin'; }, - transformer: function(prop) { - return `${prop.value}px`; + transformer: function(token) { + return `${token.value}px`; } }); StyleDictionary.registerTransform({ name: 'ratio/%', type: 'value', - matcher: function(prop) { - // here we are using a custom attribute, declared in the property, to match the values where apply the transform - return prop.group === 'ratio'; + matcher: function(token) { + // here we are using a custom attribute, declared in the token, to match the values where apply the transform + return token.group === 'ratio'; }, - transformer: function(prop) { - return `${Math.floor(100 * prop.value)}%`; + transformer: function(token) { + return `${Math.floor(100 * token.value)}%`; } }); StyleDictionary.registerTransform({ name: 'hexRGB/hexARGB', type: 'value', - matcher: function(prop) { - return prop.group === 'color'; + matcher: function(token) { + return token.group === 'color'; }, - transformer: function(prop) { + transformer: function(token) { // for sake of simplicity, in this example we assume colors are always in the format #xxxxxx - return prop.value.replace(/^#/,'#FF'); + return token.value.replace(/^#/,'#FF'); } }); StyleDictionary.registerTransform({ name: 'unitless/dp-sp', type: 'value', - matcher: function(prop) { - return prop.group === 'typography' || prop.group === 'spacing'; + matcher: function(token) { + return token.group === 'typography' || token.group === 'spacing'; }, - transformer: function(prop) { + transformer: function(token) { // in Android font sizes are expressed in "sp" units - let unit = (prop.group === 'typography') ? 'sp' : 'dp'; - return `${prop.value}${unit}`; + let unit = (token.group === 'typography') ? 'sp' : 'dp'; + return `${token.value}${unit}`; } }); StyleDictionary.registerTransform({ // this is a silly example, to show how you can apply transform to names name: 'name/squiggle', type: 'name', - // notice: if you don't specify a matcher, the transformation will be applied to all the properties - transformer: function(prop) { - return prop.path.join('~'); + // notice: if you don't specify a matcher, the transformation will be applied to all the tokens + transformer: function(token) { + return token.path.join('~'); } }); @@ -96,8 +96,8 @@ StyleDictionary.registerTransformGroup({ StyleDictionary.registerFormat({ name: 'custom/android/xml', formatter: function(dictionary) { - return dictionary.allProperties.map(function(prop) { - return `${prop.value}`; + return dictionary.allTokens.map(function(token) { + return `${token.value}`; }).join('\n'); } }); @@ -106,7 +106,7 @@ StyleDictionary.registerFormat({ // APPLY THE CONFIGURATION // IMPORTANT: the registration of custom transforms // needs to be done _before_ applying the configuration -StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/config.json'); +const StyleDictionaryExtended = StyleDictionary.extend(__dirname + '/config.json'); // FINALLY, BUILD ALL THE PLATFORMS diff --git a/examples/advanced/custom-transforms/properties/button.json b/examples/advanced/custom-transforms/tokens/button.json similarity index 100% rename from examples/advanced/custom-transforms/properties/button.json rename to examples/advanced/custom-transforms/tokens/button.json diff --git a/examples/advanced/custom-transforms/properties/colors.json b/examples/advanced/custom-transforms/tokens/colors.json similarity index 100% rename from examples/advanced/custom-transforms/properties/colors.json rename to examples/advanced/custom-transforms/tokens/colors.json diff --git a/examples/advanced/custom-transforms/properties/font.json b/examples/advanced/custom-transforms/tokens/font.json similarity index 100% rename from examples/advanced/custom-transforms/properties/font.json rename to examples/advanced/custom-transforms/tokens/font.json diff --git a/examples/advanced/custom-transforms/properties/spacing.json b/examples/advanced/custom-transforms/tokens/spacing.json similarity index 100% rename from examples/advanced/custom-transforms/properties/spacing.json rename to examples/advanced/custom-transforms/tokens/spacing.json diff --git a/examples/advanced/matching-build-files/README.md b/examples/advanced/matching-build-files/README.md index f1d72bca9..7dc140bea 100644 --- a/examples/advanced/matching-build-files/README.md +++ b/examples/advanced/matching-build-files/README.md @@ -16,10 +16,10 @@ At this point, you can run `npm run build`. This command will generate the outpu #### How does it work -The "build" command processes the JSON files in the `properties` folder. The `index.js` file adds each folder, allowing you to map through them in `config.js`. The script goes through each folder and generates a file for each folder and populates it with tokens that match the filter. +The "build" command processes the JSON files in the `tokens` folder. The `index.js` file adds each folder, allowing you to map through them in `config.js`. The script goes through each folder and generates a file for each folder and populates it with tokens that match the filter. ```sh -# properties/color/base.json +# tokens/color/base.json { "color": { "red": { @@ -30,7 +30,7 @@ The "build" command processes the JSON files in the `properties` folder. The `in ``` ```sh -# properties/size/base.json +# tokens/size/base.json { "size": { "small": { @@ -44,10 +44,10 @@ Because the folder name matches the category, the output would automatically gen #### What to look at -Open the `config.js` file and see how the script first looks within the `properties` directory to map through each folder. The destination then outputs a file that would match the name, and fill that file with the tokens that match the filter criteria. +Open the `config.js` file and see how the script first looks within the `tokens` directory to map through each folder. The destination then outputs a file that would match the name, and fill that file with the tokens that match the filter criteria. ```sh - files: properties.map(tokenCategory => ({ + files: tokens.map(tokenCategory => ({ destination: `${tokenCategory}.js`, format: "format/js", filter: { diff --git a/examples/advanced/matching-build-files/config.js b/examples/advanced/matching-build-files/config.js index d29552641..72d568d00 100644 --- a/examples/advanced/matching-build-files/config.js +++ b/examples/advanced/matching-build-files/config.js @@ -1,8 +1,8 @@ const StyleDictionary = require("style-dictionary"); -const tokens = require("./properties"); +const tokens = require("./tokens"); module.exports = { - source: ["properties/**/*.json"], + source: ["tokens/**/*.json"], platforms: { "esm/category": { buildPath: "build/js/esm/", @@ -82,8 +82,8 @@ module.exports = { StyleDictionary.registerFormat({ name: "custom/cjsmodule", formatter: function (dictionary) { - return `module.exports = {${dictionary.allProperties.map( - (prop) => `\n\t${prop.name}: "${prop.value}"` + return `module.exports = {${dictionary.allTokens.map( + (token) => `\n\t${token.name}: "${token.value}"` )}\n};`; }, }); diff --git a/examples/advanced/matching-build-files/properties/button/base.json b/examples/advanced/matching-build-files/tokens/button/base.json similarity index 100% rename from examples/advanced/matching-build-files/properties/button/base.json rename to examples/advanced/matching-build-files/tokens/button/base.json diff --git a/examples/advanced/matching-build-files/properties/color/base.json b/examples/advanced/matching-build-files/tokens/color/base.json similarity index 100% rename from examples/advanced/matching-build-files/properties/color/base.json rename to examples/advanced/matching-build-files/tokens/color/base.json diff --git a/examples/advanced/matching-build-files/properties/index.js b/examples/advanced/matching-build-files/tokens/index.js similarity index 100% rename from examples/advanced/matching-build-files/properties/index.js rename to examples/advanced/matching-build-files/tokens/index.js diff --git a/examples/advanced/matching-build-files/properties/size/base.json b/examples/advanced/matching-build-files/tokens/size/base.json similarity index 100% rename from examples/advanced/matching-build-files/properties/size/base.json rename to examples/advanced/matching-build-files/tokens/size/base.json diff --git a/examples/advanced/multi-brand-multi-platform/README.md b/examples/advanced/multi-brand-multi-platform/README.md index b2179d090..cd763dc72 100644 --- a/examples/advanced/multi-brand-multi-platform/README.md +++ b/examples/advanced/multi-brand-multi-platform/README.md @@ -1,10 +1,10 @@ ## Multi Brand & Multi Platform -While it's pretty standard to use a common set of properties to generate the same design tokens for different platforms (only in different format), this example shows how to setup a **multi-brand, multi-platform suite** of design tokens, with values that may depend on the brand (eg. a brand color) or the platform (eg. a font family). +While it's pretty standard to use a common set of tokens to generate the same design tokens for different platforms (only in different format), this example shows how to setup a **multi-brand, multi-platform suite** of design tokens, with values that may depend on the brand (eg. a brand color) or the platform (eg. a font family). -In this specific case it's necessary to use a **custom build script** to process the properties for each one of the possible brand/platform combinations. In the script the configuration used by Style Dictionary becomes parametric, with "brand" and "platform" used as arguments of a function that returns the "config" object used to extend Style Dictionary. +In this specific case it's necessary to use a **custom build script** to process the tokens for each one of the possible brand/platform combinations. In the script the configuration used by Style Dictionary becomes parametric, with "brand" and "platform" used as arguments of a function that returns the "config" object used to extend Style Dictionary. -The properties are organised in **specific folders**, depending if they are "platform" dependent, "brand" dependent or "global" (independent of platform or brand). The organisation of the files used in this example is not strictly required, but has the advantage that it's easier to see what the properties depend on, and it's easier to use global paths to include the correct files for a specific combination of "brand" and "platform" (see the "source" declaration block in the `getStyleDictionaryConfig` function of the build script). +The tokens are organized in **specific folders**, depending if they are "platform" dependent, "brand" dependent or "global" (independent of platform or brand). The organization of the files used in this example is not strictly required, but has the advantage that it's easier to see what the tokens depend on, and it's easier to use global paths to include the correct files for a specific combination of "brand" and "platform" (see the "source" declaration block in the `getStyleDictionaryConfig` function of the build script). #### Running the example @@ -26,15 +26,15 @@ The "build" command will run the custom script `build.js`. This script loops on ``` -For each combination it receives a parametric configuration object from the `getStyleDictionaryConfig` function, where the input property files to read and the output paths where to write the generaed files depend on the "platform" and "brand" values: +For each combination it receives a parametric configuration object from the `getStyleDictionaryConfig` function, where the input token files to read and the output paths where to write the generated files depend on the "platform" and "brand" values: ``` function getStyleDictionaryConfig(brand, platform) { return { "source": [ - `properties/brands/${brand}/*.json`, - "properties/globals/**/*.json", - `properties/platforms/${platform}/*.json` + `tokens/brands/${brand}/*.json`, + "tokens/globals/**/*.json", + `tokens/platforms/${platform}/*.json` ], "platforms": { "web": { @@ -50,19 +50,19 @@ function getStyleDictionaryConfig(brand, platform) { }; } ``` -The properties are stored in three different folders: +The tokens are stored in three different folders: -* **brands**: this folder contain properties that depend on the "brand", eg. the "primary" and "secondary" colors (generally these are called "brand colors", think of the blue of Facebook, the orange of Amazon, or the red of Gmail). -* **platforms**: this folder contain properties that depend on the "platform", eg. the font family used in the application or website (eg. a font stack like "Tahoma, Arial, 'Helvetica Neue', sans" on web, "San Francisco" in iOS, "Roboto" in Android). -* **global**: this folder contain properties that are common, that don't depend on the specific "platform" or "brand", eg. the base grayscale colors, the font sizes, etc. +* **brands**: this folder contain tokens that depend on the "brand", eg. the "primary" and "secondary" colors (generally these are called "brand colors", think of the blue of Facebook, the orange of Amazon, or the red of Gmail). +* **platforms**: this folder contain tokens that depend on the "platform", eg. the font family used in the application or website (eg. a font stack like "Tahoma, Arial, 'Helvetica Neue', sans" on web, "San Francisco" in iOS, "Roboto" in Android). +* **global**: this folder contain tokens that are common, that don't depend on the specific "platform" or "brand", eg. the base grayscale colors, the font sizes, etc. -Leveraging the ability of Style Dictionary to reference other properties values as "aliases", we can have generic properties like `font.family.base` or `color.primary` whose values actually depend on the "platform" and "brand" and whose values are computed dynamically at build time depending on the specific "platform/brand" files, included dynamically by the `getStyleDictionaryConfig` function. +Leveraging the ability of Style Dictionary to reference other tokens values as "aliases", we can have generic tokens like `font.family.base` or `color.primary` whose values actually depend on the "platform" and "brand" and whose values are computed dynamically at build time depending on the specific "platform/brand" files, included dynamically by the `getStyleDictionaryConfig` function. #### What to look at Open the `build.js` script and look how the `StyleDictionary.buildPlatform` function is called multiple times, looping on the combination of platform and brand, and how the configuration object is returned by the `getStyleDictionaryConfig` function. -Now look at the properties folders, and see how they are organised. Open `properties/brands/brand-1/color.json`. You will see this declaration: +Now look at the tokens folders, and see how they are organized. Open `tokens/brands/brand-1/color.json`. You will see this declaration: ``` { @@ -75,7 +75,7 @@ Now look at the properties folders, and see how they are organised. Open `proper } ``` -The actual values depend on the "brand" (compare this file with `brand-2/color.json` and `brand-3/color.json`. These values are used as "aliases" in the `properties/global/color/base.json` file: +The actual values depend on the "brand" (compare this file with `brand-2/color.json` and `brand-3/color.json`. These values are used as "aliases" in the `tokens/global/color/base.json` file: ``` { @@ -92,7 +92,7 @@ The actual values depend on the "brand" (compare this file with `brand-2/color.j Depending on the file included at build time, the actual value of `color.primary` will depend on the "brand". To see how this works out, open the file `build/web/brand-1/tokens.scss` and compare it with the similar files for "brand-2" and "brand-3": you will see how the values for `color.primary`, `color.action.primary` are different for different brands, and how they are actually the values declared in the "brands" source folders. -In the same way, now open `properties/platforms/android/font.json` and you will see: +In the same way, now open `tokens/platforms/android/font.json` and you will see: ``` { @@ -103,7 +103,7 @@ In the same way, now open `properties/platforms/android/font.json` and you will } } ``` -the value `font.platform.system` is consumed by the `properties/globals/font/index.json` file: +the value `font.platform.system` is consumed by the `tokens/globals/font/index.json` file: ``` { diff --git a/examples/advanced/multi-brand-multi-platform/build.js b/examples/advanced/multi-brand-multi-platform/build.js index e43c8d3e5..305ddfb74 100644 --- a/examples/advanced/multi-brand-multi-platform/build.js +++ b/examples/advanced/multi-brand-multi-platform/build.js @@ -5,9 +5,9 @@ const StyleDictionaryPackage = require('style-dictionary'); function getStyleDictionaryConfig(brand, platform) { return { "source": [ - `properties/brands/${brand}/*.json`, - "properties/globals/**/*.json", - `properties/platforms/${platform}/*.json` + `tokens/brands/${brand}/*.json`, + "tokens/globals/**/*.json", + `tokens/platforms/${platform}/*.json` ], "platforms": { "web": { diff --git a/examples/advanced/multi-brand-multi-platform/properties/brands/brand-1/color.json b/examples/advanced/multi-brand-multi-platform/tokens/brands/brand-1/color.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/brands/brand-1/color.json rename to examples/advanced/multi-brand-multi-platform/tokens/brands/brand-1/color.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/brands/brand-2/color.json b/examples/advanced/multi-brand-multi-platform/tokens/brands/brand-2/color.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/brands/brand-2/color.json rename to examples/advanced/multi-brand-multi-platform/tokens/brands/brand-2/color.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/brands/brand-3/color.json b/examples/advanced/multi-brand-multi-platform/tokens/brands/brand-3/color.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/brands/brand-3/color.json rename to examples/advanced/multi-brand-multi-platform/tokens/brands/brand-3/color.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/globals/button.json b/examples/advanced/multi-brand-multi-platform/tokens/globals/button.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/globals/button.json rename to examples/advanced/multi-brand-multi-platform/tokens/globals/button.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/globals/color/base.json b/examples/advanced/multi-brand-multi-platform/tokens/globals/color/base.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/globals/color/base.json rename to examples/advanced/multi-brand-multi-platform/tokens/globals/color/base.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/globals/color/font.json b/examples/advanced/multi-brand-multi-platform/tokens/globals/color/font.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/globals/color/font.json rename to examples/advanced/multi-brand-multi-platform/tokens/globals/color/font.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/globals/font/index.json b/examples/advanced/multi-brand-multi-platform/tokens/globals/font/index.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/globals/font/index.json rename to examples/advanced/multi-brand-multi-platform/tokens/globals/font/index.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/globals/size/font.json b/examples/advanced/multi-brand-multi-platform/tokens/globals/size/font.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/globals/size/font.json rename to examples/advanced/multi-brand-multi-platform/tokens/globals/size/font.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/android/button.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/android/button.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/android/button.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/android/button.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/android/font.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/android/font.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/android/font.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/android/font.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/ios/button.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/ios/button.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/ios/button.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/ios/button.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/ios/font.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/ios/font.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/ios/font.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/ios/font.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/web/button.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/web/button.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/web/button.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/web/button.json diff --git a/examples/advanced/multi-brand-multi-platform/properties/platforms/web/font.json b/examples/advanced/multi-brand-multi-platform/tokens/platforms/web/font.json similarity index 100% rename from examples/advanced/multi-brand-multi-platform/properties/platforms/web/font.json rename to examples/advanced/multi-brand-multi-platform/tokens/platforms/web/font.json diff --git a/examples/advanced/node-modules-as-config-and-properties/README.md b/examples/advanced/node-modules-as-config-and-properties/README.md index 70c24edd0..7ea288d85 100644 --- a/examples/advanced/node-modules-as-config-and-properties/README.md +++ b/examples/advanced/node-modules-as-config-and-properties/README.md @@ -1,4 +1,4 @@ -## Node Modules as Config and Property files +## Node Modules as Config and Token files This example shows some advanced features using Style Dictionary with node modules. Make sure you are familiar with Style Dictionary concepts first by reading the [docs](https://amzn.github.io/style-dictionary) or taking a look at the [basic example](../../basic) first. @@ -10,7 +10,7 @@ At this point, if you want to build the tokens you can run `npm run build`. This #### How does it work? -Style Dictionary understands node modules that export a simple object for both a config file as well as the property source files. Using node module exports allows you to do some pretty cool things like generating properties programmatically (design tokens). +Style Dictionary understands node modules that export a simple object for both a config file as well as the token source files. Using node module exports allows you to do some pretty cool things like generating tokens programmatically. The `.extend()` method on the Style Dictionary module can take an object or a path to a JSON or node module and it copies the object attributes onto a new copy of the Style Dictionary object. The Style Dictionary object stores the transforms, transformGroups, and formats as attributes on the SD object. You can override these defaults by directly adding these attributes to your config object. This allows you to add custom transforms and formats without calling `.registerTransform()`! @@ -18,8 +18,8 @@ The `.extend()` method on the Style Dictionary module can take an object or a pa The [`config.js`](config.js) file is the first thing to look at. It has a lot of comments how everything works. It shows how you can add custom transforms and formats without calling the register methods. It also shows how you can extend built-in transforms and transformGroups. -If you take a look at any of the `index.js` files in `properties/` or `components/` you can see how using node module exports can simplify the object structure. Now you don't have to copy the same top-level object paths in the JSON object. Some specific files to look at: +If you take a look at any of the `index.js` files in `tokens/` or `components/` you can see how using node module exports can simplify the object structure. Now you don't have to copy the same top-level object paths in the JSON object. Some specific files to look at: -* [`components/index.js`](components/index.js) Uses node module export/require to merge the property files together without Style Dictionary -* [`components/button/primary.js`](components/button/primary.js) Extends a default set of properties -* [`properties/color/core.js`](properties/color/core.js) Creates a color ramp programmatically based on base colors +* [`components/index.js`](components/index.js) Uses node module export/require to merge the token files together without Style Dictionary +* [`components/button/primary.js`](components/button/primary.js) Extends a default set of tokens +* [`tokens/color/core.js`](tokens/color/core.js) Creates a color ramp programmatically based on base colors diff --git a/examples/advanced/node-modules-as-config-and-properties/config.js b/examples/advanced/node-modules-as-config-and-properties/config.js index c17da6bb1..0f13b2ef4 100644 --- a/examples/advanced/node-modules-as-config-and-properties/config.js +++ b/examples/advanced/node-modules-as-config-and-properties/config.js @@ -1,9 +1,9 @@ const StyleDictionary = require('style-dictionary'); -// Rather than have Style Dictionary handle the merging of property files, +// Rather than have Style Dictionary handle the merging of token files, // you could use node module export/require to do it yourself. This will // allow you to not have to copy object namespaces like you normally would. -// Take a look at any of the .js files in components/ or properties/ -const properties = require('./properties'); +// Take a look at any of the .js files in components/ or tokens/ +const tokens = require('./tokens'); const buildPath = 'build/'; @@ -12,14 +12,14 @@ const buildPath = 'build/'; StyleDictionary.registerTransform({ name: 'myRegisteredTransform', type: 'value', - matcher: (prop) => prop.attributes.category === 'size', - transformer: (prop) => `${parseInt(prop.value) * 16}px` + matcher: (token) => token.attributes.category === 'size', + transformer: (token) => `${parseInt(token.value) * 16}px` }); StyleDictionary.registerFormat({ name: 'myRegisteredFormat', formatter: (dictionary) => { - return dictionary.allProperties.map((prop) => prop.value).join('\n'); + return dictionary.allTokens.map((token) => token.value).join('\n'); } }) @@ -29,7 +29,7 @@ module.exports = { // We are relying on node modules to merge all the objects together // thus we only want to reference top level node modules that export // the whole objects. - source: ['properties/index.js', 'components/index.js'], + source: ['tokens/index.js', 'components/index.js'], // 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 // the .extend method copies everything in the config @@ -39,20 +39,20 @@ module.exports = { // Now we can use the transform 'myTransform' below myTransform: { type: 'name', - transformer: (prop) => prop.path.join('_').toUpperCase() + transformer: (token) => token.path.join('_').toUpperCase() } }, // Same with formats, you can now write them directly to this config // object. The name of the format is the key. format: { - myFormat: (dictionary, platform) => { - return dictionary.allProperties.map(prop => `${prop.name}: ${prop.value}`).join('\n'); + myFormat: ({dictionary}) => { + return dictionary.allTokens.map(token => `${token.name}: ${token.value}`).join('\n'); } }, // You can also bypass the merging of files Style Dictionary does - // by adding a 'properties' object directly like this: + // by adding a 'tokens' object directly like this: // - // properties: properties, + // tokens: tokens, platforms: { custom: { // Using the custom transforms we defined above @@ -87,14 +87,14 @@ module.exports = { transforms: StyleDictionary.transformGroup.js.concat('myRegisteredTransform'), buildPath: buildPath, // If you want to get super fancy, you can use node modules - // to create a properties object first, and then you can + // to create a tokens object first, and then you can // reference attributes of that object. This allows you to // output 1 file per color namespace. - files: Object.keys(properties.color).map((colorType) => ({ + files: Object.keys(tokens.color).map((colorType) => ({ destination: `${colorType}.js`, format: 'javascript/es6', // Filters can be functions that return a boolean - filter: (prop) => prop.attributes.type === colorType + filter: (token) => token.attributes.type === colorType })) }, @@ -103,7 +103,7 @@ module.exports = { transformGroup: 'js', buildPath: buildPath, files: [{ - destination: 'properties.json', + destination: 'tokens.json', format: 'json' }] } diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/background.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/background.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/background.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/background.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/border.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/border.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/border.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/border.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/brand.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/brand.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/brand.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/brand.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/core.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/core.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/core.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/core.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/font.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/font.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/font.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/font.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/color/index.js b/examples/advanced/node-modules-as-config-and-properties/tokens/color/index.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/color/index.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/color/index.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/index.js b/examples/advanced/node-modules-as-config-and-properties/tokens/index.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/index.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/index.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/size/border.js b/examples/advanced/node-modules-as-config-and-properties/tokens/size/border.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/size/border.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/size/border.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/size/font.js b/examples/advanced/node-modules-as-config-and-properties/tokens/size/font.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/size/font.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/size/font.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/size/index.js b/examples/advanced/node-modules-as-config-and-properties/tokens/size/index.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/size/index.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/size/index.js diff --git a/examples/advanced/node-modules-as-config-and-properties/properties/size/padding.js b/examples/advanced/node-modules-as-config-and-properties/tokens/size/padding.js similarity index 100% rename from examples/advanced/node-modules-as-config-and-properties/properties/size/padding.js rename to examples/advanced/node-modules-as-config-and-properties/tokens/size/padding.js diff --git a/examples/advanced/npm-module/config.json b/examples/advanced/npm-module/config.json index 87e55d92c..bb24ac06f 100644 --- a/examples/advanced/npm-module/config.json +++ b/examples/advanced/npm-module/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", diff --git a/examples/advanced/npm-module/properties/color/base.json b/examples/advanced/npm-module/tokens/color/base.json similarity index 100% rename from examples/advanced/npm-module/properties/color/base.json rename to examples/advanced/npm-module/tokens/color/base.json diff --git a/examples/advanced/npm-module/properties/color/font.json b/examples/advanced/npm-module/tokens/color/font.json similarity index 100% rename from examples/advanced/npm-module/properties/color/font.json rename to examples/advanced/npm-module/tokens/color/font.json diff --git a/examples/advanced/npm-module/properties/size/font.json b/examples/advanced/npm-module/tokens/size/font.json similarity index 100% rename from examples/advanced/npm-module/properties/size/font.json rename to examples/advanced/npm-module/tokens/size/font.json diff --git a/examples/advanced/referencing_aliasing/README.md b/examples/advanced/referencing_aliasing/README.md index ba57cdc47..34bea5d2f 100644 --- a/examples/advanced/referencing_aliasing/README.md +++ b/examples/advanced/referencing_aliasing/README.md @@ -1,6 +1,6 @@ ## Referencing (Aliasing) -This example shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a property and assign it to the value –or attribute– of another property. +This example shows how to use referencing (or "aliasing") to reference a value -or an attribute– of a token and assign it to the value –or attribute– of another token. This is quite handy when you want to create a system that uses some basic design definitions (base colors, base font sizes, base scales, etc) but then exposes them in a more complex and detailed set of design tokens, typically to describe a complete UI pattern library. @@ -12,20 +12,20 @@ At this point, you can run `npm run build`. This command will generate the outpu #### How does it work -The "build" command processes the JSON files in the `properties` folder. Whenever it finds a reference declared via this syntax: +The "build" command processes the JSON files in the `tokens` folder. Whenever it finds a reference declared via this syntax: ``` - property: { + token: { "value": "{ref.to.object.value}" } ``` -the build process resolves the reference using the declared path (`ref.to.object`) to retrieve the actual value of the referenced property inside the Style Dictionary object. +the build process resolves the reference using the declared path (`ref.to.object`) to retrieve the actual value of the referenced token inside the Style Dictionary object. **Notice**: if the path is not valid, doesn't exist or is a circular reference, Style Dictionary generates an error in the console. #### What to look at -Open the JSON files in the `properties` folder and see how certain properties are referencing the values of other properties via "aliases". +Open the JSON files in the `tokens` folder and see how certain tokens are referencing the values of other tokens via "aliases". For example, open `color/base.json` and see how the value of the "primary" color is a **reference** to the value of the "green" color, declared as: @@ -35,7 +35,7 @@ For example, open `color/base.json` and see how the value of the "primary" color ``` In this case, the string `"{color.base.green.value}"` is resolved at build time, and gets its value from the value of the "green" base color, `"#00FF00"`. -The reference can point to another property in a **different JSON file**. For example open `color/font.json` and see how the value for the base/secondary font colors are references to the properties declared in `color/base.json`: +The reference can point to another token in a **different JSON file**. For example open `color/font.json` and see how the value for the base/secondary font colors are references to the tokens declared in `color/base.json`: ``` { @@ -57,7 +57,7 @@ It is also possible to create **chains of references**, where a value references ... ``` -The value associated to a property can be an **object** (eg. an RGB color). In that case, the reference still works. If you open `color/font.json` you will see that the "faded" color of text is a reference to `color.base.gray.medium.value`, but if you look in `color/base.json` you will see that the value of the "medium gray" color is not a string, but an RGB oject: +The value associated to a token can be an **object** (eg. an RGB color). In that case, the reference still works. If you open `color/font.json` you will see that the "faded" color of text is a reference to `color.base.gray.medium.value`, but if you look in `color/base.json` you will see that the value of the "medium gray" color is not a string, but an RGB object: ``` { @@ -74,7 +74,7 @@ In that case Style Dictionary still resolves correctly the alias to the corresp "color-base-gray-medium": "#9299a2" ``` -You can also reference **other attributes of a property**, not only its value. For example in `button/button.json` the value of text size is composed as concatenation (remember, it's a string, think of it as template literals) of two properties of the "global" object, declared in the `globals.json` file: +You can also reference **other attributes of a token**, not only its value. For example in `button/button.json` the value of text size is composed as concatenation (remember, it's a string, think of it as template literals) of two tokens of the "global" object, declared in the `globals.json` file: ``` "text": { diff --git a/examples/advanced/referencing_aliasing/config.json b/examples/advanced/referencing_aliasing/config.json index 51b2de809..22e5b1c75 100644 --- a/examples/advanced/referencing_aliasing/config.json +++ b/examples/advanced/referencing_aliasing/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "example": { "transformGroup": "web", diff --git a/examples/advanced/referencing_aliasing/properties/button/button.json b/examples/advanced/referencing_aliasing/tokens/button/button.json similarity index 100% rename from examples/advanced/referencing_aliasing/properties/button/button.json rename to examples/advanced/referencing_aliasing/tokens/button/button.json diff --git a/examples/advanced/referencing_aliasing/properties/color/base.json b/examples/advanced/referencing_aliasing/tokens/color/base.json similarity index 100% rename from examples/advanced/referencing_aliasing/properties/color/base.json rename to examples/advanced/referencing_aliasing/tokens/color/base.json diff --git a/examples/advanced/referencing_aliasing/properties/color/font.json b/examples/advanced/referencing_aliasing/tokens/color/font.json similarity index 100% rename from examples/advanced/referencing_aliasing/properties/color/font.json rename to examples/advanced/referencing_aliasing/tokens/color/font.json diff --git a/examples/advanced/referencing_aliasing/properties/globals.json b/examples/advanced/referencing_aliasing/tokens/globals.json similarity index 100% rename from examples/advanced/referencing_aliasing/properties/globals.json rename to examples/advanced/referencing_aliasing/tokens/globals.json diff --git a/examples/advanced/referencing_aliasing/properties/size/font.json b/examples/advanced/referencing_aliasing/tokens/size/font.json similarity index 100% rename from examples/advanced/referencing_aliasing/properties/size/font.json rename to examples/advanced/referencing_aliasing/tokens/size/font.json diff --git a/examples/advanced/tokens-deprecation/README.md b/examples/advanced/tokens-deprecation/README.md index bd6112032..bd0642057 100644 --- a/examples/advanced/tokens-deprecation/README.md +++ b/examples/advanced/tokens-deprecation/README.md @@ -16,8 +16,8 @@ Using extra attributes associated to a design token, is possible (at build time) #### What to look at -Open the `properties/color/base.json` and `properties/size/font.json` files and see how some of the properties have a custom `deprecated` attribute (and an additional `deprecated_comment` attribute). +Open the `tokens/color/base.json` and `tokens/size/font.json` files and see how some of the tokens have a custom `deprecated` attribute (and an additional `deprecated_comment` attribute). -Now open the custom template files in `templates` and see how this attributes are used to - conditionally, when a property is deprecated - add extra comments to the output files. +Now open the custom template files in `templates` and see how this attributes are used to - conditionally, when a token is deprecated - add extra comments to the output files. -Finally, once generated the output files, open the `build/scss/_variables.scss` and `build/ios/tokens.plist` files and see how the `deprecated` attributes have been converted to comments (and extra properties in the plist) in the output files. \ No newline at end of file +Finally, once generated the output files, open the `build/scss/_variables.scss` and `build/ios/tokens.plist` files and see how the `deprecated` attributes have been converted to comments (and extra tokens in the plist) in the output files. \ No newline at end of file diff --git a/examples/advanced/tokens-deprecation/config.json b/examples/advanced/tokens-deprecation/config.json index f8df60380..f48a15c9f 100644 --- a/examples/advanced/tokens-deprecation/config.json +++ b/examples/advanced/tokens-deprecation/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", diff --git a/examples/advanced/tokens-deprecation/package.json b/examples/advanced/tokens-deprecation/package.json index a0577158d..3c5b5c50d 100644 --- a/examples/advanced/tokens-deprecation/package.json +++ b/examples/advanced/tokens-deprecation/package.json @@ -5,7 +5,7 @@ "main": "build/index.js", "files": [ "build", - "properties" + "tokens" ], "scripts": { "build": "node ./build.js", diff --git a/examples/advanced/tokens-deprecation/templates/ios-plist.template b/examples/advanced/tokens-deprecation/templates/ios-plist.template index 14beec7ee..6c01c25f4 100644 --- a/examples/advanced/tokens-deprecation/templates/ios-plist.template +++ b/examples/advanced/tokens-deprecation/templates/ios-plist.template @@ -3,7 +3,7 @@ -<% _.each(allProperties, function(prop) { +<% _.each(allTokens, function(prop) { // NOTICE: this is a simplified version of a PLIST file for iOS // please refer to the documentation for a proper format // or speak with one of your iOS developers to agree on a format that works for them diff --git a/examples/advanced/tokens-deprecation/templates/web-scss.template b/examples/advanced/tokens-deprecation/templates/web-scss.template index 5a016b3d6..099d97b7c 100644 --- a/examples/advanced/tokens-deprecation/templates/web-scss.template +++ b/examples/advanced/tokens-deprecation/templates/web-scss.template @@ -1,4 +1,4 @@ -<% _.each(allProperties, function(prop) { +<% _.each(allTokens, function(prop) { var output = ""; if(prop.deprecated) { output += "// Notice: the following value is deprecated"; diff --git a/examples/advanced/tokens-deprecation/properties/color/base.json b/examples/advanced/tokens-deprecation/tokens/color/base.json similarity index 100% rename from examples/advanced/tokens-deprecation/properties/color/base.json rename to examples/advanced/tokens-deprecation/tokens/color/base.json diff --git a/examples/advanced/tokens-deprecation/properties/color/font.json b/examples/advanced/tokens-deprecation/tokens/color/font.json similarity index 100% rename from examples/advanced/tokens-deprecation/properties/color/font.json rename to examples/advanced/tokens-deprecation/tokens/color/font.json diff --git a/examples/advanced/tokens-deprecation/properties/size/font.json b/examples/advanced/tokens-deprecation/tokens/size/font.json similarity index 100% rename from examples/advanced/tokens-deprecation/properties/size/font.json rename to examples/advanced/tokens-deprecation/tokens/size/font.json diff --git a/examples/advanced/variables-in-outputs/README.md b/examples/advanced/variables-in-outputs/README.md index ac2eee9e7..00a000cda 100644 --- a/examples/advanced/variables-in-outputs/README.md +++ b/examples/advanced/variables-in-outputs/README.md @@ -25,7 +25,7 @@ Here is an example that shows how to get an alias's name within a custom format: ```javascript //... function(dictionary) { - return dictionary.allProperties.map(token => { + return dictionary.allTokens.map(token => { let value = JSON.stringify(token.value); // the `dictionary` object now has `usesReference()` and // `getReferences()` methods. `usesReference()` will return true if diff --git a/examples/advanced/variables-in-outputs/sd.config.js b/examples/advanced/variables-in-outputs/sd.config.js index b98080bb0..e93105e07 100644 --- a/examples/advanced/variables-in-outputs/sd.config.js +++ b/examples/advanced/variables-in-outputs/sd.config.js @@ -2,7 +2,7 @@ module.exports = { format: { // Adding a custom format to show how to get an alias's name. customFormat: function({dictionary, options}) { - return dictionary.allProperties.map(token => { + return dictionary.allTokens.map(token => { let value = JSON.stringify(token.value); // new option added to decide whether or not to output references if (options.outputReferences) { diff --git a/examples/basic/README.md b/examples/basic/README.md index cd02479f9..985b48fe1 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -43,7 +43,7 @@ Good for you! You have now built your first style dictionary! Moving on, take a ``` ├── README.md ├── config.json -├── properties/ +├── tokens/ │ ├── color/ │ ├── base.json │ ├── font.json @@ -170,11 +170,11 @@ $size-font-base: 1rem; ``` Pretty nifty! This shows a few things happening: -1. The build system does a deep merge of all the property JSON files defined in the `source` attribute of `config.json`. This allows you to split up the property JSON files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. -1. The build system resolves references to other style properties. `{size.font.medium.value}` gets resolved properly. -1. The build system handles references to property values in other files as well as you can see in `properties/color/font.json`. +1. The build system does a deep merge of all the token JSON files defined in the `source` attribute of `config.json`. This allows you to split up the token JSON files however you want. There are 2 JSON files with `color` as the top level key, but they get merged properly. +1. The build system resolves references to other design tokens. `{size.font.medium.value}` gets resolved properly. +1. The build system handles references to token values in other files as well as you can see in `tokens/color/font.json`. -Now let's make a change and see how that affects things. Open up `properties/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. +Now let's make a change and see how that affects things. Open up `tokens/color/base.json` and change `"#111111"` to `"#000000"`. After you make that change, save the file and re-run the build command `style-dictionary build`. Open up the build files and take a look. **Huzzah!** diff --git a/examples/basic/config.json b/examples/basic/config.json index b0faee147..968f321da 100644 --- a/examples/basic/config.json +++ b/examples/basic/config.json @@ -1,5 +1,5 @@ { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", diff --git a/examples/basic/properties/color/base.json b/examples/basic/tokens/color/base.json similarity index 100% rename from examples/basic/properties/color/base.json rename to examples/basic/tokens/color/base.json diff --git a/examples/basic/properties/color/font.json b/examples/basic/tokens/color/font.json similarity index 100% rename from examples/basic/properties/color/font.json rename to examples/basic/tokens/color/font.json diff --git a/examples/basic/properties/size/font.json b/examples/basic/tokens/size/font.json similarity index 100% rename from examples/basic/properties/size/font.json rename to examples/basic/tokens/size/font.json diff --git a/examples/complete/README.md b/examples/complete/README.md index 280697893..622511457 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -4,7 +4,7 @@ This starter project has everything you need to get started. ## How it works -All of the style properties and assets are in this package. Make any changes to suit your needs. This package has iOS, Android, and web code. +All of the design tokens and assets are in this package. Make any changes to suit your needs. This package has iOS, Android, and web code. To get started, run ``` @@ -12,7 +12,6 @@ $ npm install $ npm run build ``` -The npm build task is what performs the style dictionary build steps to generate the files for each platform. Every time you change something in the style dictionary, like changing colors or adding properties, you will have to run this command again to generate the files. +The npm build task is what performs the style dictionary build steps to generate the files for each platform. Every time you change something in the style dictionary, like changing colors or adding design tokens, you will have to run this command again to generate the files. ## iOS - diff --git a/examples/complete/config.json b/examples/complete/config.json index 3db36e2fa..19ce743de 100644 --- a/examples/complete/config.json +++ b/examples/complete/config.json @@ -1,6 +1,6 @@ { "source": [ - "properties/**/*.json" + "tokens/**/*.json" ], "platforms": { "ios": { diff --git a/examples/complete/properties/asset/font.json b/examples/complete/tokens/asset/font.json similarity index 100% rename from examples/complete/properties/asset/font.json rename to examples/complete/tokens/asset/font.json diff --git a/examples/complete/properties/color/background.json b/examples/complete/tokens/color/background.json similarity index 100% rename from examples/complete/properties/color/background.json rename to examples/complete/tokens/color/background.json diff --git a/examples/complete/properties/color/base.json b/examples/complete/tokens/color/base.json similarity index 100% rename from examples/complete/properties/color/base.json rename to examples/complete/tokens/color/base.json diff --git a/examples/complete/properties/color/border.json b/examples/complete/tokens/color/border.json similarity index 100% rename from examples/complete/properties/color/border.json rename to examples/complete/tokens/color/border.json diff --git a/examples/complete/properties/color/brand.json b/examples/complete/tokens/color/brand.json similarity index 100% rename from examples/complete/properties/color/brand.json rename to examples/complete/tokens/color/brand.json diff --git a/examples/complete/properties/color/chart.json b/examples/complete/tokens/color/chart.json similarity index 100% rename from examples/complete/properties/color/chart.json rename to examples/complete/tokens/color/chart.json diff --git a/examples/complete/properties/color/font.json b/examples/complete/tokens/color/font.json similarity index 100% rename from examples/complete/properties/color/font.json rename to examples/complete/tokens/color/font.json diff --git a/examples/complete/properties/content/icon.json b/examples/complete/tokens/content/icon.json similarity index 100% rename from examples/complete/properties/content/icon.json rename to examples/complete/tokens/content/icon.json diff --git a/examples/complete/properties/font.json b/examples/complete/tokens/font.json similarity index 100% rename from examples/complete/properties/font.json rename to examples/complete/tokens/font.json diff --git a/examples/complete/properties/size/font.json b/examples/complete/tokens/size/font.json similarity index 100% rename from examples/complete/properties/size/font.json rename to examples/complete/tokens/size/font.json diff --git a/examples/complete/properties/size/icon.json b/examples/complete/tokens/size/icon.json similarity index 100% rename from examples/complete/properties/size/icon.json rename to examples/complete/tokens/size/icon.json diff --git a/examples/complete/properties/size/padding.json b/examples/complete/tokens/size/padding.json similarity index 100% rename from examples/complete/properties/size/padding.json rename to examples/complete/tokens/size/padding.json diff --git a/examples/complete/properties/time.json b/examples/complete/tokens/time.json similarity index 100% rename from examples/complete/properties/time.json rename to examples/complete/tokens/time.json diff --git a/index.js b/index.js index a8315ce9b..78ef25fd9 100644 --- a/index.js +++ b/index.js @@ -32,6 +32,10 @@ var StyleDictionary = { VERSION: require('./package.json').version, properties: {}, allProperties: [], + // Starting in v3 we are moving towards "tokens" rather than "properties" + // keeping both for backwards compatibility + tokens: {}, + allTokens: [], options: {}, transform: require('./lib/common/transforms'), diff --git a/lib/buildFile.js b/lib/buildFile.js index 54f2e427d..73f619739 100644 --- a/lib/buildFile.js +++ b/lib/buildFile.js @@ -56,6 +56,8 @@ function buildFile(file = {}, platform = {}, dictionary = {}) { const filteredDictionary = Object.assign({}, dictionary, { properties: filteredProperties.properties, allProperties: filteredProperties.allProperties, + tokens: filteredProperties.properties, + allTokens: filteredProperties.allProperties, // keep the unfiltered properties object for reference resolution _properties: dictionary.properties }); diff --git a/lib/buildFiles.js b/lib/buildFiles.js index 3c6c68207..6f212290c 100644 --- a/lib/buildFiles.js +++ b/lib/buildFiles.js @@ -14,8 +14,8 @@ const buildFile = require('./buildFile'); /** - * Takes a platform config object and a properties - * object and builds all the files. Properties object + * Takes a platform config object and a dictionary + * object and builds all the files. Dictionary object * should have been transformed and resolved before this * point. * @memberOf StyleDictionary diff --git a/lib/buildPlatform.js b/lib/buildPlatform.js index 4795e9c41..fd00c47d4 100644 --- a/lib/buildPlatform.js +++ b/lib/buildPlatform.js @@ -18,7 +18,7 @@ const createDictionary = require('./utils/createDictionary'); /** * Takes a platform and performs all transforms to - * the properties object (non-mutative) then + * the tokens object (non-mutative) then * builds all the files and performs any actions. This is useful if you only want to * build the artifacts of one platform to speed up the build process. * diff --git a/lib/cleanFiles.js b/lib/cleanFiles.js index cc6b9f54e..89fb0db48 100644 --- a/lib/cleanFiles.js +++ b/lib/cleanFiles.js @@ -14,8 +14,8 @@ const cleanFile = require('./cleanFile'); /** - * Takes a platform config object and a properties - * object and cleans all the files. Properties object + * Takes a platform config object and a dictionary + * object and cleans all the files. Dictionary object * should have been transformed and resolved before this * point. * @memberOf StyleDictionary diff --git a/lib/cleanPlatform.js b/lib/cleanPlatform.js index 0cf006366..ee3443f7a 100644 --- a/lib/cleanPlatform.js +++ b/lib/cleanPlatform.js @@ -11,7 +11,7 @@ * and limitations under the License. */ -var flattenProperties = require('./utils/flattenProperties'), +var createDictionary = require('./utils/createDictionary'), transformConfig = require('./transform/config'), cleanFiles = require('./cleanFiles'), cleanDirs = require('./cleanDirs'), @@ -19,8 +19,8 @@ var flattenProperties = require('./utils/flattenProperties'), /** * Takes a platform and performs all transforms to - * the properties object (non-mutative) then - * cleans all the files and perfoms the undo method of any [actions](actions.md). + * the tokens object (non-mutative) then + * cleans all the files and performs the undo method of any [actions](actions.md). * * @static * @memberof module:style-dictionary @@ -47,10 +47,7 @@ function cleanPlatform(platform) { // This is the dictionary object we pass to the file // cleaning and action methods. - var dictionary = { - properties: properties, - allProperties: flattenProperties( properties ) - }; + const dictionary = createDictionary({properties}); // We clean files first, then actions, ...and then directories? cleanFiles(dictionary, platformConfig); diff --git a/lib/common/actions.js b/lib/common/actions.js index 84d4d7b38..21ad4c294 100644 --- a/lib/common/actions.js +++ b/lib/common/actions.js @@ -11,8 +11,7 @@ * and limitations under the License. */ -var _ = require('../utils/es6_'), - fs = require('fs-extra'); +const fs = require('fs-extra'); /** * @namespace Actions @@ -27,19 +26,19 @@ module.exports = { 'android/copyImages': { do: function(dictionary, config) { var imagesDir = config.buildPath + 'android/main/res/drawable-'; - _.each(dictionary.allProperties, function(prop) { - if (prop.attributes.category === 'asset' && prop.attributes.type === 'image') { - var name = prop.path.slice(2,4).join('_'); - fs.copySync(prop.value, imagesDir + prop.attributes.state + '/' + name + '.png'); + dictionary.allTokens.forEach(function(token) { + if (token.attributes.category === 'asset' && token.attributes.type === 'image') { + var name = token.path.slice(2,4).join('_'); + fs.copySync(token.value, imagesDir + token.attributes.state + '/' + name + '.png'); } }); }, undo: function(dictionary, config) { var imagesDir = config.buildPath + 'android/main/res/drawable-'; - _.each(dictionary.allProperties, function(prop) { - if (prop.attributes.category === 'asset' && prop.attributes.type === 'image') { - var name = prop.path.slice(2,4).join('_'); - fs.removeSync(imagesDir + prop.attributes.state + '/' + name + '.png'); + dictionary.allTokens.forEach(function(token) { + if (token.attributes.category === 'asset' && token.attributes.type === 'image') { + var name = token.path.slice(2,4).join('_'); + fs.removeSync(imagesDir + token.attributes.state + '/' + name + '.png'); } }); } diff --git a/lib/common/formatHelpers/createPropertyFormatter.js b/lib/common/formatHelpers/createPropertyFormatter.js index 75393252f..262693b86 100644 --- a/lib/common/formatHelpers/createPropertyFormatter.js +++ b/lib/common/formatHelpers/createPropertyFormatter.js @@ -23,7 +23,7 @@ const defaultFormatting = { /** * Creates a function that can be used to format a property. This can be useful - * to use as the function on `dictionary.allProperties.map`. The formatting + * to use as the function on `dictionary.allTokens.map`. The formatting * is configurable either by supplying a `format` option or a `formatting` object * which uses: prefix, indentation, separator, suffix, and commentStyle. * @memberof module:formatHelpers @@ -38,7 +38,7 @@ const defaultFormatting = { * dictionary, * format: 'css' * }); - * return dictionary.allProperties.map(formatProperty).join('\n'); + * return dictionary.allTokens.map(formatProperty).join('\n'); * } * }); * ``` diff --git a/lib/common/formatHelpers/fileHeader.js b/lib/common/formatHelpers/fileHeader.js index 9332a717f..9b33f5912 100644 --- a/lib/common/formatHelpers/fileHeader.js +++ b/lib/common/formatHelpers/fileHeader.js @@ -39,7 +39,7 @@ const defaultFormatting = { * name: 'myCustomFormat', * formatter: function({ dictionary, file }) { * return fileHeader({file, 'short') + - * dictionary.allProperties.map(token => `${token.name} = ${token.value}`) + * dictionary.allTokens.map(token => `${token.name} = ${token.value}`) * .join('\n'); * } * }); diff --git a/lib/common/formatHelpers/formattedVariables.js b/lib/common/formatHelpers/formattedVariables.js index 9a6326553..02830b3d0 100644 --- a/lib/common/formatHelpers/formattedVariables.js +++ b/lib/common/formatHelpers/formattedVariables.js @@ -39,7 +39,7 @@ const defaultFormatting = { * ``` */ function formattedVariables({format, dictionary, outputReferences=false, formatting={}}) { - let {allProperties} = dictionary; + let {allTokens} = dictionary; let {lineSeparator} = Object.assign({}, defaultFormatting, formatting); @@ -52,10 +52,10 @@ function formattedVariables({format, dictionary, outputReferences=false, formatt if (outputReferences) { // note: using the spread operator here so we get a new array rather than // mutating the original - allProperties = [...allProperties].sort(sortByReference(dictionary)); + allTokens = [...allTokens].sort(sortByReference(dictionary)); } - return allProperties + return allTokens .map(createPropertyFormatter({ outputReferences, dictionary, format, formatting })) .filter(function(strVal) { return !!strVal }) .join(lineSeparator); diff --git a/lib/common/formatHelpers/iconsWithPrefix.js b/lib/common/formatHelpers/iconsWithPrefix.js index bb806f4f4..61c7b0fef 100644 --- a/lib/common/formatHelpers/iconsWithPrefix.js +++ b/lib/common/formatHelpers/iconsWithPrefix.js @@ -14,12 +14,12 @@ /** * * 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 psuedo-selector to add + * using an icon font and creates helper classes with the :before pseudo-selector to add * a unicode character. * __You probably don't need this.__ * @memberof module:formatHelpers * @param {String} prefix - Character to prefix variable names, like '$' for Sass - * @param {Property[]} properties - allProperties array on the dictionary object passed to the formatter function. + * @param {Token[]} allTokens - allTokens array on the dictionary object passed to the formatter function. * @param {Object} options - options object passed to the formatter function. * @returns {String} * @example @@ -27,19 +27,19 @@ * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * formatter: function({ dictionary, options }) { - * return iconsWithPrefix('$', dictionary.allProperties, options); + * return iconsWithPrefix('$', dictionary.allTokens, options); * } * }); * ``` */ - function iconsWithPrefix(prefix, properties, options) { - return properties.filter(function(prop) { - return prop.attributes.category === 'content' && prop.attributes.type === 'icon'; + function iconsWithPrefix(prefix, allTokens, options) { + return allTokens.filter(function(token) { + return token.attributes.category === 'content' && token.attributes.type === 'icon'; }) - .map(function(prop) { - var varName = prefix + prop.name + ': ' + prop.value + ';'; - var className = '.' + options.prefix + '-icon.' + prop.attributes.item + ':before '; - var declaration = '{ content: ' + prefix + prop.name + '; }'; + .map(function(token) { + var varName = prefix + token.name + ': ' + token.value + ';'; + var className = '.' + options.prefix + '-icon.' + token.attributes.item + ':before '; + var declaration = '{ content: ' + prefix + token.name + '; }'; return varName + '\n' + className + declaration; }) .join('\n'); diff --git a/lib/common/formatHelpers/minifyDictionary.js b/lib/common/formatHelpers/minifyDictionary.js index 638ec7570..2335a77f7 100644 --- a/lib/common/formatHelpers/minifyDictionary.js +++ b/lib/common/formatHelpers/minifyDictionary.js @@ -14,14 +14,14 @@ /** * Outputs an object stripping out everything except values * @memberof module:formatHelpers - * @param {Object} obj - The object to minify. You will most likely pass `dictionary.properties` to it. + * @param {Object} obj - The object to minify. You will most likely pass `dictionary.tokens` to it. * @returns {Object} * @example * ```js * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * formatter: function({ dictionary }) { - * return JSON.stringify(minifyDictionary(dictionary.properties)); + * return JSON.stringify(minifyDictionary(dictionary.tokens)); * } * }); * ``` diff --git a/lib/common/formatHelpers/sortByName.js b/lib/common/formatHelpers/sortByName.js index b8df89916..3031e3579 100644 --- a/lib/common/formatHelpers/sortByName.js +++ b/lib/common/formatHelpers/sortByName.js @@ -12,7 +12,7 @@ */ /** - * A sorting function to be used when iterating over `dictionary.allProperties` in + * A sorting function to be used when iterating over `dictionary.allTokens` in * a format. * @memberof module:formatHelpers * @example @@ -20,7 +20,7 @@ * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * formatter: function({ dictionary, options }) { - * return dictionary.allProperties.sort(sortByName) + * return dictionary.allTokens.sort(sortByName) * .map(token => `${token.name} = ${token.value}`) * .join('\n'); * } diff --git a/lib/common/formatHelpers/sortByReference.js b/lib/common/formatHelpers/sortByReference.js index 653232b70..a69b0fe9b 100644 --- a/lib/common/formatHelpers/sortByReference.js +++ b/lib/common/formatHelpers/sortByReference.js @@ -13,13 +13,13 @@ /** * A function that returns a sorting function to be used with Array.sort that - * will sort the allProperties array based on references. This is to make sure + * 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 * defined. * @memberof module:formatHelpers * @example * ```javascript - * dictionary.allProperties.sort(sortByReference(dictionary)) + * dictionary.allTokens.sort(sortByReference(dictionary)) * ``` * @param {Dictionary} dictionary * @returns {Function} diff --git a/lib/common/formats.js b/lib/common/formats.js index dc8a9f509..8e91f8b43 100644 --- a/lib/common/formats.js +++ b/lib/common/formats.js @@ -65,8 +65,8 @@ module.exports = { */ 'scss/map-flat': function({dictionary, options, file}) { const template = _template(fs.readFileSync(__dirname + '/templates/scss/map-flat.template')); - const { allProperties } = dictionary; - return template({allProperties, file, options, fileHeader}); + const { allTokens } = dictionary; + return template({allTokens, file, options, fileHeader}); }, // This will soon be removed, is left here only for backwards compatibility @@ -111,7 +111,7 @@ module.exports = { /** * Creates a SCSS file with variable definitions based on the style dictionary. * - * Add `!default` to any variable by setting a `themeable: true` property in the token's definition. + * Add `!default` to any variable by setting a `themeable: true` attribute in the token's definition. * * @memberof Formats * @kind member @@ -142,7 +142,7 @@ module.exports = { * ``` */ 'scss/icons': function({dictionary, options, file}) { - return fileHeader({file, commentStyle: 'short'}) + iconsWithPrefix('$', dictionary.allProperties, options); + return fileHeader({file, commentStyle: 'short'}) + iconsWithPrefix('$', dictionary.allTokens, options); }, /** @@ -177,7 +177,7 @@ module.exports = { * ``` */ 'less/icons': function({dictionary, options, file}) { - return fileHeader({file, commentStyle: 'short'}) + iconsWithPrefix('@', dictionary.allProperties, options); + return fileHeader({file, commentStyle: 'short'}) + iconsWithPrefix('@', dictionary.allTokens, options); }, /** @@ -218,7 +218,7 @@ module.exports = { 'javascript/module': function({dictionary, file}) { return fileHeader({file}) + 'module.exports = ' + - JSON.stringify(dictionary.properties, null, 2) + ';'; + JSON.stringify(dictionary.tokens, null, 2) + ';'; }, /** @@ -263,7 +263,7 @@ module.exports = { 'var ' + (file.name || '_styleDictionary') + ' = ' + - JSON.stringify(dictionary.properties, null, 2) + + JSON.stringify(dictionary.tokens, null, 2) + ';'; }, @@ -311,7 +311,7 @@ module.exports = { ' root["' + name + '"] = factory();\n' + ' }\n' + '}(this, function() {\n' + - ' return ' + JSON.stringify(dictionary.properties, null, 2) + ';\n' + + ' return ' + JSON.stringify(dictionary.tokens, null, 2) + ';\n' + '}))\n' }, @@ -349,11 +349,11 @@ module.exports = { */ 'javascript/es6': function({dictionary, file}) { return fileHeader({file}) + - dictionary.allProperties.map(function(prop) { - var to_ret_prop = 'export const ' + prop.name + ' = ' + JSON.stringify(prop.value) + ';'; - if (prop.comment) - to_ret_prop = to_ret_prop.concat(' // ' + prop.comment); - return to_ret_prop; + dictionary.allTokens.map(function(token) { + var to_ret = 'export const ' + token.name + ' = ' + JSON.stringify(token.value) + ';'; + if (token.comment) + to_ret = to_ret.concat(' // ' + token.comment); + return to_ret; }).join('\n'); }, @@ -486,7 +486,7 @@ module.exports = { /** * Creates a resource xml file with all the integers in your style dictionary. It filters your - * style properties by `prop.attributes.category === 'time'` + * design tokens by `token.attributes.category === 'time'` * * It is recommended to use the 'android/resources' format with a custom filter * instead of this format: @@ -519,7 +519,7 @@ module.exports = { /** * Creates a resource xml file with all the strings in your style dictionary. Filters your - * style properties by `prop.attributes.category === 'content'` + * design tokens by `token.attributes.category === 'content'` * * It is recommended to use the 'android/resources' format with a custom filter * instead of this format: @@ -597,7 +597,7 @@ module.exports = { // iOS templates /** - * Creates an Objective-C header file with macros for style properties + * Creates an Objective-C header file with macros for design tokens * * @memberof Formats * @kind member @@ -772,7 +772,7 @@ module.exports = { const template = _template( fs.readFileSync(__dirname + '/templates/ios-swift/class.swift.template') ); - let allProperties; + let allTokens; const { outputReferences } = options; const formatProperty = createPropertyFormatter({ outputReferences, @@ -783,12 +783,12 @@ module.exports = { }); if (outputReferences) { - allProperties = [...dictionary.allProperties].sort(sortByReference(dictionary)); + allTokens = [...dictionary.allTokens].sort(sortByReference(dictionary)); } else { - allProperties = [...dictionary.allProperties].sort(sortByName); + allTokens = [...dictionary.allTokens].sort(sortByName); } - return template({allProperties, file, options, formatProperty, fileHeader}); + return template({allTokens, file, options, formatProperty, fileHeader}); }, /** @@ -802,7 +802,7 @@ module.exports = { const template = _template( fs.readFileSync(__dirname + '/templates/ios-swift/enum.swift.template') ); - let allProperties; + let allTokens; const { outputReferences } = options; const formatProperty = createPropertyFormatter({ outputReferences, @@ -813,11 +813,11 @@ module.exports = { }); if (outputReferences) { - allProperties = [...dictionary.allProperties].sort(sortByReference(dictionary)); + allTokens = [...dictionary.allTokens].sort(sortByReference(dictionary)); } else { - allProperties = [...dictionary.allProperties].sort(sortByName) + allTokens = [...dictionary.allTokens].sort(sortByName) } - return template({allProperties, file, options, formatProperty, fileHeader}); + return template({allTokens, file, options, formatProperty, fileHeader}); }, // Css templates @@ -853,7 +853,7 @@ module.exports = { * ``` */ 'json': function({dictionary}) { - return JSON.stringify(dictionary.properties, null, 2); + return JSON.stringify(dictionary.tokens, null, 2); }, /** @@ -875,7 +875,7 @@ module.exports = { * ``` */ 'json/asset': function({dictionary}) { - return JSON.stringify({asset: dictionary.properties.asset}, null, 2); + return JSON.stringify({asset: dictionary.tokens.asset}, null, 2); }, /** @@ -895,7 +895,7 @@ module.exports = { * ``` */ 'json/nested': function({dictionary}) { - return JSON.stringify(minifyDictionary(dictionary.properties), null, 2); + return JSON.stringify(minifyDictionary(dictionary.tokens), null, 2); }, /** @@ -911,8 +911,8 @@ module.exports = { * ``` */ 'json/flat': function({dictionary}) { - return '{\n' + dictionary.allProperties.map(function(prop) { - return ` "${prop.name}": ${JSON.stringify(prop.value)}`; + return '{\n' + dictionary.allTokens.map(function(token) { + return ` "${token.name}": ${JSON.stringify(token.value)}`; }).join(',\n') + '\n}'; }, @@ -939,12 +939,12 @@ module.exports = { 'compatibleVersion':'1.0', 'pluginVersion':'1.1' }; - to_ret.colors = dictionary.allProperties - .filter(function(prop) { - return prop.attributes.category === 'color' && prop.attributes.type === 'base'; + to_ret.colors = dictionary.allTokens + .filter(function(token) { + return token.attributes.category === 'color' && token.attributes.type === 'base'; }) - .map(function(prop) { - return prop.value; + .map(function(token) { + return token.value; }); return JSON.stringify(to_ret, null, 2); }, @@ -973,11 +973,11 @@ module.exports = { var to_ret = { compatibleVersion: '2.0', pluginVersion: '2.2', - colors: dictionary.allProperties.map(function(prop) { + colors: dictionary.allTokens.map(function(token) { // Merging the token's value, which should be an object with r,g,b,a channels return Object.assign({ - name: prop.name - }, prop.value) + name: token.name + }, token.value) }) }; return JSON.stringify(to_ret, null, 2); @@ -1009,7 +1009,7 @@ module.exports = { const template = _template( fs.readFileSync(__dirname + '/templates/flutter/class.dart.template') ); - let allProperties; + let allTokens; const { outputReferences } = options; const formatProperty = createPropertyFormatter({ outputReferences, @@ -1017,11 +1017,11 @@ module.exports = { }); if (outputReferences) { - allProperties = [...dictionary.allProperties].sort(sortByReference(dictionary)); + allTokens = [...dictionary.allTokens].sort(sortByReference(dictionary)); } else { - allProperties = [...dictionary.allProperties].sort(sortByName) + allTokens = [...dictionary.allTokens].sort(sortByName) } - return template({allProperties, file, options, formatProperty, fileHeader}); + return template({allTokens, file, options, formatProperty, fileHeader}); }, }; diff --git a/lib/common/templates/android/colors.template b/lib/common/templates/android/colors.template index 5fa2fed1e..7caab7c7d 100644 --- a/lib/common/templates/android/colors.template +++ b/lib/common/templates/android/colors.template @@ -14,7 +14,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category === 'color'; }); %> diff --git a/lib/common/templates/android/dimens.template b/lib/common/templates/android/dimens.template index 2e3e2b6a2..e3135133d 100644 --- a/lib/common/templates/android/dimens.template +++ b/lib/common/templates/android/dimens.template @@ -14,7 +14,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category === 'size' && prop.attributes.type !== 'font' }); %> <%= fileHeader({file, commentStyle: 'xml'}) %> diff --git a/lib/common/templates/android/fontDimens.template b/lib/common/templates/android/fontDimens.template index f2e9ff936..52c4e892d 100644 --- a/lib/common/templates/android/fontDimens.template +++ b/lib/common/templates/android/fontDimens.template @@ -14,7 +14,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category === 'size' && prop.attributes.type === 'font'; }); %> <%= fileHeader({file, commentStyle: 'xml'}) %> diff --git a/lib/common/templates/android/integers.template b/lib/common/templates/android/integers.template index b424fbb5b..10203630d 100644 --- a/lib/common/templates/android/integers.template +++ b/lib/common/templates/android/integers.template @@ -14,7 +14,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category === 'time'; }); %> <%= fileHeader({file, commentStyle: 'xml'}) %> diff --git a/lib/common/templates/android/resources.template b/lib/common/templates/android/resources.template index 6ea6cb9af..7cfac1a30 100644 --- a/lib/common/templates/android/resources.template +++ b/lib/common/templates/android/resources.template @@ -44,7 +44,7 @@ function propToValue(prop) { } %> <%= fileHeader({file, commentStyle: 'xml'}) %> - <% dictionary.allProperties.forEach(function(prop) { + <% dictionary.allTokens.forEach(function(prop) { %><<%= propToType(prop) %> name="<%= prop.name %>"><%= propToValue(prop) %>><% if (prop.comment) { %><% } %> <% }); %> diff --git a/lib/common/templates/android/strings.template b/lib/common/templates/android/strings.template index 142ea7aba..91e886b5a 100644 --- a/lib/common/templates/android/strings.template +++ b/lib/common/templates/android/strings.template @@ -14,7 +14,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category === 'content'; }); %> <%= fileHeader({file, commentStyle: 'xml'}) %> diff --git a/lib/common/templates/flutter/class.dart.template b/lib/common/templates/flutter/class.dart.template index d33711b0f..bf648bd59 100644 --- a/lib/common/templates/flutter/class.dart.template +++ b/lib/common/templates/flutter/class.dart.template @@ -20,7 +20,7 @@ import 'dart:ui'; class <%= file.className %> { <%= file.className %>._(); - <%= allProperties.map(function(prop) { + <%= allTokens.map(function(prop) { return 'static const ' + formatProperty(prop); }).join('\n ') %> } \ No newline at end of file diff --git a/lib/common/templates/ios-swift/class.swift.template b/lib/common/templates/ios-swift/class.swift.template index 8bdc5f2e8..7cef38930 100644 --- a/lib/common/templates/ios-swift/class.swift.template +++ b/lib/common/templates/ios-swift/class.swift.template @@ -20,7 +20,7 @@ import UIKit public class <%= file.className %> { - <%= allProperties.map(function(prop) { + <%= allTokens.map(function(prop) { return 'public static let ' + formatProperty(prop); }).join('\n ') %> } diff --git a/lib/common/templates/ios-swift/enum.swift.template b/lib/common/templates/ios-swift/enum.swift.template index d6ab961a6..7dac9974f 100644 --- a/lib/common/templates/ios-swift/enum.swift.template +++ b/lib/common/templates/ios-swift/enum.swift.template @@ -20,7 +20,7 @@ import UIKit public enum <%= file.className %> { - <%= allProperties.map(function(prop) { + <%= allTokens.map(function(prop) { return 'public static let ' + formatProperty(prop); }).join('\n ') %> } diff --git a/lib/common/templates/ios/colors.h.template b/lib/common/templates/ios/colors.h.template index 2a19fe88e..6fbad9fc5 100644 --- a/lib/common/templates/ios/colors.h.template +++ b/lib/common/templates/ios/colors.h.template @@ -20,7 +20,7 @@ #import typedef NS_ENUM(NSInteger, <%= file.type %>) { -<%= dictionary.allProperties.map(function(prop) { return prop.name; }).join(',\n') %> +<%= dictionary.allTokens.map(function(prop) { return prop.name; }).join(',\n') %> }; @interface <%= file.className %> : NSObject diff --git a/lib/common/templates/ios/colors.m.template b/lib/common/templates/ios/colors.m.template index 07dc35393..5fb9b6031 100644 --- a/lib/common/templates/ios/colors.m.template +++ b/lib/common/templates/ios/colors.m.template @@ -31,7 +31,7 @@ dispatch_once(&onceToken, ^{ colorArray = @[ -<%= dictionary.allProperties.map(function(prop){ return prop.value; }).join(',\n') %> +<%= dictionary.allTokens.map(function(prop){ return prop.value; }).join(',\n') %> ]; }); diff --git a/lib/common/templates/ios/macros.template b/lib/common/templates/ios/macros.template index 7c73a766b..3788a5578 100644 --- a/lib/common/templates/ios/macros.template +++ b/lib/common/templates/ios/macros.template @@ -20,6 +20,6 @@ #import #import -<% dictionary.allProperties.forEach(function(prop) { +<% dictionary.allTokens.forEach(function(prop) { %>#define <%= prop.name %> <%= prop.value %> <% }); %> diff --git a/lib/common/templates/ios/plist.template b/lib/common/templates/ios/plist.template index afb2c66fc..23bc50161 100644 --- a/lib/common/templates/ios/plist.template +++ b/lib/common/templates/ios/plist.template @@ -13,7 +13,7 @@ // express or implied. See the License for the specific language governing // permissions and limitations under the License. -var props = dictionary.allProperties.filter(function(prop) { +var props = dictionary.allTokens.filter(function(prop) { return prop.attributes.category !== 'asset' && prop.attributes.category !== 'border' && prop.attributes.category !== 'shadow' && diff --git a/lib/common/templates/ios/static.h.template b/lib/common/templates/ios/static.h.template index d5240ac65..381f53204 100644 --- a/lib/common/templates/ios/static.h.template +++ b/lib/common/templates/ios/static.h.template @@ -19,5 +19,5 @@ <%= fileHeader({ file, commentStyle: 'short' })%> #import -<% dictionary.allProperties.forEach(function(prop) { %> +<% dictionary.allTokens.forEach(function(prop) { %> extern <%= file.type %> const <%= prop.name %>;<% }); %> diff --git a/lib/common/templates/ios/static.m.template b/lib/common/templates/ios/static.m.template index 94cf20a17..b39a6fde6 100644 --- a/lib/common/templates/ios/static.m.template +++ b/lib/common/templates/ios/static.m.template @@ -19,5 +19,5 @@ <%= fileHeader({ file, commentStyle: 'short' }) %> #import "<%= file.className %>.h" -<% dictionary.allProperties.forEach(function(prop) { %> +<% dictionary.allTokens.forEach(function(prop) { %> <%= file.type %> const <%= prop.name %> = <%= prop.value %>;<% }); %> diff --git a/lib/common/templates/ios/strings.h.template b/lib/common/templates/ios/strings.h.template index 73179d125..658f41f37 100644 --- a/lib/common/templates/ios/strings.h.template +++ b/lib/common/templates/ios/strings.h.template @@ -19,7 +19,7 @@ <%= fileHeader({ file, commentStyle: 'short' })%> #import -<% dictionary.allProperties.forEach(function(prop) { %> +<% dictionary.allTokens.forEach(function(prop) { %> extern NSString * const <%= prop.name %>;<% }); %> @interface <%= file.className %> : NSObject diff --git a/lib/common/templates/ios/strings.m.template b/lib/common/templates/ios/strings.m.template index 3da68d46b..206563583 100644 --- a/lib/common/templates/ios/strings.m.template +++ b/lib/common/templates/ios/strings.m.template @@ -19,7 +19,7 @@ <%= fileHeader({ file, commentStyle: 'short' }) %> #import "<%= file.className %>.h" -<% dictionary.allProperties.forEach(function(prop) { %> +<% dictionary.allTokens.forEach(function(prop) { %> NSString * const <%= prop.name %> = <%= prop.value %>;<% }); %> @implementation <%= file.className %> @@ -30,7 +30,7 @@ NSString * const <%= prop.name %> = <%= prop.value %>;<% }); %> dispatch_once(&onceToken, ^{ array = @[ - <%= dictionary.allProperties.map(buildProperty).join(',\n') %> + <%= dictionary.allTokens.map(buildProperty).join(',\n') %> ]; }); diff --git a/lib/common/templates/scss/map-deep.template b/lib/common/templates/scss/map-deep.template index 0e5e83f83..4a2654739 100644 --- a/lib/common/templates/scss/map-deep.template +++ b/lib/common/templates/scss/map-deep.template @@ -16,7 +16,7 @@ <%= fileHeader({file, commentStyle: 'long'}) %><% // output the list of tokens as Sass variables // - dictionary.allProperties.forEach(function(prop) { + dictionary.allTokens.forEach(function(prop) { var output = ''; output += '$' + prop.name + ': ' + (prop.attributes.category==='asset' ? '"'+prop.value+'"' : prop.value) + ' !default;' if(prop.comment) { diff --git a/lib/common/templates/scss/map-flat.template b/lib/common/templates/scss/map-flat.template index 35bc03132..b6815d885 100644 --- a/lib/common/templates/scss/map-flat.template +++ b/lib/common/templates/scss/map-flat.template @@ -17,7 +17,7 @@ <%= fileHeader({file, commentStyle: 'long'}) %><% var output = ''; output += `$${file.mapName||'tokens'}: (\n`; - output += allProperties.map(function(prop){ + output += allTokens.map(function(prop){ var line = ''; if(prop.comment) { line += ' // ' + prop.comment + '\n'; diff --git a/lib/common/templates/static-style-guide/index.html.template b/lib/common/templates/static-style-guide/index.html.template index d5e0fc106..86caab74f 100644 --- a/lib/common/templates/static-style-guide/index.html.template +++ b/lib/common/templates/static-style-guide/index.html.template @@ -58,7 +58,7 @@
- <% _.each(allProperties, function(property) { %> + <% _.each(allTokens, function(property) { %>
" style="<%= checkForStyle(property) %>">
<%= property.path.join(".") %>
<%= property.name %>
diff --git a/lib/common/transformGroups.js b/lib/common/transformGroups.js index 6dcbe5eba..9a4232c9e 100644 --- a/lib/common/transformGroups.js +++ b/lib/common/transformGroups.js @@ -221,7 +221,7 @@ module.exports = { * [size/swift/remToCGFloat](transforms.md#sizeswiftremtocgfloat) * [font/swift/literal](transforms.md#fontswiftliteral) * - * This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the property (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). + * This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). * * @memberof TransformGroups */ @@ -277,7 +277,7 @@ module.exports = { * [asset/flutter/literal](transforms.md#assetflutterliteral) * [font/flutter/literal](transforms.md#fontflutterliteral) * - * This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the property (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). + * This is to be used if you want to have separate files per category and you don't want the category (e.g., color) as the lead value in the name of the token (e.g., StyleDictionaryColor.baseText instead of StyleDictionary.colorBaseText). * * @memberof TransformGroups */ diff --git a/lib/common/transforms.js b/lib/common/transforms.js index 5606909cb..d571c5d91 100644 --- a/lib/common/transforms.js +++ b/lib/common/transforms.js @@ -17,39 +17,39 @@ var Color = require('tinycolor2'), convertToBase64 = require('../utils/convertToBase64'), UNICODE_PATTERN = /&#x([^;]+);/g; -function isColor(prop) { - return prop.attributes.category === 'color'; +function isColor(token) { + return token.attributes.category === 'color'; } -function isSize(prop) { - return prop.attributes.category === 'size'; +function isSize(token) { + return token.attributes.category === 'size'; } -function isFontSize(prop) { - return prop.attributes.category === 'size' && - (prop.attributes.type === 'font' || prop.attributes.type === 'icon'); +function isFontSize(token) { + return token.attributes.category === 'size' && + (token.attributes.type === 'font' || token.attributes.type === 'icon'); } -function isNotFontSize(prop) { - return prop.attributes.category === 'size' && - prop.attributes.type !== 'font' && - prop.attributes.type !== 'icon'; +function isNotFontSize(token) { + return token.attributes.category === 'size' && + token.attributes.type !== 'font' && + token.attributes.type !== 'icon'; } -function isAsset(prop) { - return prop.attributes.category === 'asset'; +function isAsset(token) { + return token.attributes.category === 'asset'; } -function isContent(prop) { - return prop.attributes.category === 'content'; +function isContent(token) { + return token.attributes.category === 'content'; } -function wrapValueWith(character, prop) { - return `${character}${prop.value}${character}`; +function wrapValueWith(character, token) { + return `${character}${token.value}${character}`; } -function wrapValueWithDoubleQuote(prop) { - return wrapValueWith('"', prop); +function wrapValueWithDoubleQuote(token) { + return wrapValueWith('"', token); } function throwSizeError(name, value, unitType) { @@ -83,14 +83,14 @@ module.exports = { */ 'attribute/cti': { type: 'attribute', - transformer: function(prop) { + transformer: function(token) { const attrNames = ['category', 'type', 'item', 'subitem', 'state']; - const originalAttrs = prop.attributes || {}; + const originalAttrs = token.attributes || {}; const generatedAttrs = {} - for(let i=0; i prop.attributes.category === 'color', - transformer: function(prop) { - let color = Color(prop.original.value).toRgb(); + matcher: (token) => token.attributes.category === 'color', + transformer: function(token) { + let color = Color(token.original.value).toRgb(); return { red: (color.r / 255).toFixed(5), green: (color.g / 255).toFixed(5), @@ -535,7 +535,7 @@ module.exports = { * Transforms the value into a scale-independent pixel (sp) value for font sizes on Android. It will not scale the number. * * ```js - * // Matches: prop.attributes.category === 'size' && prop.attributes.type === 'font' + * // Matches: token.attributes.category === 'size' && token.attributes.type === 'font' * // Returns: * "10.0sp" * ``` @@ -545,9 +545,9 @@ module.exports = { 'size/sp': { type: 'value', matcher: isFontSize, - transformer: function(prop) { - const val = parseFloat(prop.value); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'sp'); + transformer: function(token) { + const val = parseFloat(token.value); + if (isNaN(val)) throwSizeError(token.name, token.value, 'sp'); return val.toFixed(2) + 'sp'; } }, @@ -556,7 +556,7 @@ module.exports = { * Transforms the value into a density-independent pixel (dp) value for non-font sizes on Android. It will not scale the number. * * ```js - * // Matches: prop.attributes.category === 'size' && prop.attributes.type !== 'font' + * // Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' * // Returns: * "10.0dp" * ``` @@ -566,9 +566,9 @@ module.exports = { 'size/dp': { type: 'value', matcher: isNotFontSize, - transformer: function(prop) { - const val = parseFloat(prop.value); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'dp'); + transformer: function(token) { + const val = parseFloat(token.value); + if (isNaN(val)) throwSizeError(token.name, token.value, 'dp'); return val.toFixed(2) + 'dp'; } }, @@ -577,7 +577,7 @@ module.exports = { * Transforms the value into a usefull object ( for React Native support ) * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * { * original: "10px", @@ -592,12 +592,12 @@ module.exports = { 'size/object': { type: 'value', matcher: isSize, - transformer: function (prop, options) { - var val = parseFloat(prop.value); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'object'); + transformer: function (token, options) { + var val = parseFloat(token.value); + if (isNaN(val)) throwSizeError(token.name, token.value, 'object'); return { - original: prop.value, + original: token.value, number: val, decimal: val / 100, scale: val * getBasePxFontSize(options), @@ -609,7 +609,7 @@ module.exports = { * Transforms the value from a REM size on web into a scale-independent pixel (sp) value for font sizes on Android. It WILL scale the number by a factor of 16 (common base font size on web). * * ```js - * // Matches: prop.attributes.category === 'size' && prop.attributes.type === 'font' + * // Matches: token.attributes.category === 'size' && token.attributes.type === 'font' * // Returns: * "16.0sp" * ``` @@ -619,10 +619,10 @@ module.exports = { 'size/remToSp': { type: 'value', matcher: isFontSize, - transformer: function(prop, options) { - const val = parseFloat(prop.value); + transformer: function(token, options) { + const val = parseFloat(token.value); const baseFont = getBasePxFontSize(options); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'sp'); + if (isNaN(val)) throwSizeError(token.name, token.value, 'sp'); return (val * baseFont).toFixed(2) + 'sp'; } }, @@ -632,7 +632,7 @@ module.exports = { * Transforms the value from a REM size on web into a density-independent pixel (dp) value for font sizes on Android. It WILL scale the number by a factor of 16 (or the value of 'basePxFontSize' on the platform in your config). * * ```js - * // Matches: prop.attributes.category === 'size' && prop.attributes.type !== 'font' + * // Matches: token.attributes.category === 'size' && token.attributes.type !== 'font' * // Returns: * "16.0dp" * ``` @@ -642,10 +642,10 @@ module.exports = { 'size/remToDp': { type: 'value', matcher: isNotFontSize, - transformer: function(prop, options) { - const val = parseFloat(prop.value); + transformer: function(token, options) { + const val = parseFloat(token.value); const baseFont = getBasePxFontSize(options); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'dp'); + if (isNaN(val)) throwSizeError(token.name, token.value, 'dp'); return (val * baseFont).toFixed(2) + 'dp'; } }, @@ -655,7 +655,7 @@ module.exports = { * Adds 'px' to the end of the number. Does not scale the number * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * "10px" * ``` @@ -665,9 +665,9 @@ module.exports = { 'size/px': { type: 'value', matcher: isSize, - transformer: function(prop) { - const val = parseFloat(prop.value); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'px'); + transformer: function(token) { + const val = parseFloat(token.value); + if (isNaN(val)) throwSizeError(token.name, token.value, 'px'); return val + 'px'; } }, @@ -676,7 +676,7 @@ module.exports = { * Adds 'rem' to the end of the number. Does not scale the number * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * "10rem" * ``` @@ -686,9 +686,9 @@ module.exports = { 'size/rem': { type: 'value', matcher: isSize, - transformer: function(prop) { - const val = parseFloat(prop.value); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'rem'); + transformer: function(token) { + const val = parseFloat(token.value); + if (isNaN(val)) throwSizeError(token.name, token.value, 'rem'); return val + 'rem'; } }, @@ -697,7 +697,7 @@ module.exports = { * Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'pt' to the end. * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * "16pt" * ``` @@ -707,10 +707,10 @@ module.exports = { 'size/remToPt': { type: 'value', matcher: isSize, - transformer: function(prop, options) { - const val = parseFloat(prop.value); + transformer: function(token, options) { + const val = parseFloat(token.value); const baseFont = getBasePxFontSize(options); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'pt'); + if (isNaN(val)) throwSizeError(token.name, token.value, 'pt'); return (val * baseFont).toFixed(2) + 'f'; } }, @@ -785,7 +785,7 @@ module.exports = { * Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Swift and initializes a CGFloat * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: "CGFloat(16.00)"" * ``` * @@ -794,10 +794,10 @@ module.exports = { 'size/swift/remToCGFloat': { type: 'value', matcher: isSize, - transformer: function(prop, options) { - const val = parseFloat(prop.value); + transformer: function(token, options) { + const val = parseFloat(token.value); const baseFont = getBasePxFontSize(options); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'CGFloat'); + if (isNaN(val)) throwSizeError(token.name, token.value, 'CGFloat'); return `CGFloat(${(val * baseFont).toFixed(2)})`; } }, @@ -806,7 +806,7 @@ module.exports = { * Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) and adds 'px' to the end. * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * "16px" * ``` @@ -816,10 +816,10 @@ module.exports = { 'size/remToPx': { type: 'value', matcher: isSize, - transformer: function(prop, options) { - const val = parseFloat(prop.value); + transformer: function(token, options) { + const val = parseFloat(token.value); const baseFont = getBasePxFontSize(options); - if (isNaN(val)) throwSizeError(prop.name, prop.value, 'px'); + if (isNaN(val)) throwSizeError(token.name, token.value, 'px'); return (val * baseFont).toFixed(0) + 'px'; } }, @@ -828,7 +828,7 @@ module.exports = { * Scales non-zero numbers to rem, and adds 'rem' to the end. If you define a "basePxFontSize" on the platform in your config, it will be used to scale the value, otherwise 16 (default web font size) will be used. * * ```js - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: * "0" * "1rem" @@ -837,12 +837,12 @@ module.exports = { 'size/pxToRem': { type: 'value', matcher: isSize, - transformer: (prop, options) => { + transformer: (token, options) => { const baseFont = getBasePxFontSize(options); - const floatVal = parseFloat(prop.value); + const floatVal = parseFloat(token.value); if (isNaN(floatVal)) { - throwSizeError(prop.name, prop.value, 'rem'); + throwSizeError(token.name, token.value, 'rem'); } if (floatVal === 0) { @@ -857,7 +857,7 @@ module.exports = { * Takes a unicode point and transforms it into a form CSS can use. * * ```js - * // Matches: prop.attributes.category === 'content' && prop.attributes.type === 'icon' + * // Matches: token.attributes.category === 'content' && token.attributes.type === 'icon' * // Returns: * "'\\E001'" * ``` @@ -866,11 +866,11 @@ module.exports = { */ 'content/icon': { type: 'value', - matcher: function (prop) { - return prop.attributes.category === 'content' && prop.attributes.type === 'icon'; + matcher: function (token) { + return token.attributes.category === 'content' && token.attributes.type === 'icon'; }, - transformer: function (prop) { - return prop.value.replace(UNICODE_PATTERN, function (match, variable) { + transformer: function (token) { + return token.value.replace(UNICODE_PATTERN, function (match, variable) { return "'\\" + variable + "'"; }); } @@ -880,7 +880,7 @@ module.exports = { * Wraps the value in a single quoted string * * ```js - * // Matches: prop.attributes.category === 'content' + * // Matches: token.attributes.category === 'content' * // Returns: * "'string'" * ``` @@ -890,8 +890,8 @@ module.exports = { 'content/quote': { type: 'value', matcher: isContent, - transformer: function(prop) { - return wrapValueWith('\'', prop); + transformer: function(token) { + return wrapValueWith('\'', token); } }, @@ -899,7 +899,7 @@ module.exports = { * Wraps the value in a double-quoted string and prepends an '@' to make a string literal. * * ```objectivec - * // Matches: prop.attributes.category === 'content' + * // Matches: token.attributes.category === 'content' * // Returns: * @"string" * ``` @@ -909,8 +909,8 @@ module.exports = { 'content/objC/literal': { type: 'value', matcher: isContent, - transformer: function(prop) { - return '@' + wrapValueWithDoubleQuote(prop); + transformer: function(token) { + return '@' + wrapValueWithDoubleQuote(token); } }, @@ -918,7 +918,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```swift - * // Matches: prop.attributes.category === 'content' + * // Matches: token.attributes.category === 'content' * // Returns: * "string" * ``` @@ -935,7 +935,7 @@ module.exports = { * Wraps the value in a double-quoted string and prepends an '@' to make a string literal. * * ```objectivec - * // Matches: prop.attributes.category === 'font' + * // Matches: token.attributes.category === 'font' * // Returns: @"string" * ``` * @@ -943,11 +943,11 @@ module.exports = { */ 'font/objC/literal': { type: 'value', - matcher: function(prop) { - return prop.attributes.category === 'font'; + matcher: function(token) { + return token.attributes.category === 'font'; }, - transformer: function(prop) { - return '@' + wrapValueWithDoubleQuote(prop); + transformer: function(token) { + return '@' + wrapValueWithDoubleQuote(token); } }, @@ -955,7 +955,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```swift - * // Matches: prop.attributes.category === 'font' + * // Matches: token.attributes.category === 'font' * // Returns: "string" * ``` * @@ -963,8 +963,8 @@ module.exports = { */ 'font/swift/literal': { type: 'value', - matcher: function(prop) { - return prop.attributes.category === 'font'; + matcher: function(token) { + return token.attributes.category === 'font'; }, transformer: wrapValueWithDoubleQuote }, @@ -974,7 +974,7 @@ module.exports = { * Assumes a time in miliseconds and transforms it into a decimal * * ```js - * // Matches: prop.attributes.category === 'time' + * // Matches: token.attributes.category === 'time' * // Returns: * "0.5s" * ``` @@ -983,11 +983,11 @@ module.exports = { */ 'time/seconds': { type: 'value', - matcher: function(prop) { - return prop.attributes.category === 'time'; + matcher: function(token) { + return token.attributes.category === 'time'; }, - transformer: function(prop) { - return (parseFloat(prop.value) / 1000).toFixed(2) + 's'; + transformer: function(token) { + return (parseFloat(token.value) / 1000).toFixed(2) + 's'; } }, @@ -995,7 +995,7 @@ module.exports = { * Wraps the value in a double-quoted string and prepends an '@' to make a string literal. * * ```js - * // Matches: prop.attributes.category === 'asset' + * // Matches: token.attributes.category === 'asset' * // Returns: * 'IyBlZGl0b3Jjb25maWcub3JnCnJvb3QgPSB0cnVlCgpbKl0KaW5kZW50X3N0eWxlID0gc3BhY2UKaW5kZW50X3NpemUgPSAyCmVuZF9vZl9saW5lID0gbGYKY2hhcnNldCA9IHV0Zi04CnRyaW1fdHJhaWxpbmdfd2hpdGVzcGFjZSA9IHRydWUKaW5zZXJ0X2ZpbmFsX25ld2xpbmUgPSB0cnVlCgpbKi5tZF0KdHJpbV90cmFpbGluZ193aGl0ZXNwYWNlID0gZmFsc2U=' * ``` @@ -1005,8 +1005,8 @@ module.exports = { 'asset/base64': { type: 'value', matcher: isAsset, - transformer: function(prop) { - return convertToBase64(prop.value); + transformer: function(token) { + return convertToBase64(token.value); } }, @@ -1014,7 +1014,7 @@ module.exports = { * Prepends the local file path * * ```js - * // Matches: prop.attributes.category === 'asset' + * // Matches: token.attributes.category === 'asset' * // Returns: * "path/to/file/asset.png" * ``` @@ -1024,8 +1024,8 @@ module.exports = { 'asset/path': { type: 'value', matcher: isAsset, - transformer: function(prop) { - return path.join(process.cwd(), prop.value); + transformer: function(token) { + return path.join(process.cwd(), token.value); } }, @@ -1033,7 +1033,7 @@ module.exports = { * Wraps the value in a double-quoted string and prepends an '@' to make a string literal. * * ```objectivec - * // Matches: prop.attributes.category === 'asset' + * // Matches: token.attributes.category === 'asset' * // Returns: @"string" * ``` * @@ -1042,8 +1042,8 @@ module.exports = { 'asset/objC/literal': { type: 'value', matcher: isAsset, - transformer: function(prop) { - return '@' + wrapValueWithDoubleQuote(prop); + transformer: function(token) { + return '@' + wrapValueWithDoubleQuote(token); } }, @@ -1051,7 +1051,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```swift - * // Matches: prop.attributes.category === 'asset' + * // Matches: token.attributes.category === 'asset' * // Returns: "string" * ``` * @@ -1062,23 +1062,23 @@ module.exports = { matcher: isAsset, transformer: wrapValueWithDoubleQuote }, - - + + /** * Transforms the value into a Flutter Color object using 8-digit hex with the alpha chanel on start * ```js - * // Matches: prop.attributes.category === 'color' + * // Matches: token.attributes.category === 'color' * // Returns: * Color(0xFF00FF5F) * ``` * @memberof Transforms - * + * */ 'color/hex8flutter': { type: 'value', matcher: isColor, - transformer: function (prop) { - var str = Color(prop.value).toHex8().toUpperCase(); + transformer: function (token) { + var str = Color(token.value).toHex8().toUpperCase(); return `Color(0x${str.slice(6)}${str.slice(0,6)})`; } }, @@ -1087,7 +1087,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```dart - * // Matches: prop.attributes.category === 'content' + * // Matches: token.attributes.category === 'content' * // Returns: "string" * ``` * @@ -1103,7 +1103,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```dart - * // Matches: prop.attributes.category === 'asset' + * // Matches: token.attributes.category === 'asset' * // Returns: "string" * ``` * @@ -1119,7 +1119,7 @@ module.exports = { * Wraps the value in a double-quoted string to make a string literal. * * ```dart - * // Matches: prop.attributes.category === 'font' + * // Matches: token.attributes.category === 'font' * // Returns: "string" * ``` * @@ -1127,8 +1127,8 @@ module.exports = { */ 'font/flutter/literal': { type: 'value', - matcher: function (prop) { - return prop.attributes.category === 'font'; + matcher: function (token) { + return token.attributes.category === 'font'; }, transformer: wrapValueWithDoubleQuote }, @@ -1137,7 +1137,7 @@ module.exports = { * Scales the number by 16 (or the value of 'basePxFontSize' on the platform in your config) to get to points for Flutter * * ```dart - * // Matches: prop.attributes.category === 'size' + * // Matches: token.attributes.category === 'size' * // Returns: 16.00 * ``` * @@ -1146,9 +1146,9 @@ module.exports = { 'size/flutter/remToDouble': { type: 'value', matcher: isSize, - transformer: function (prop, options) { + transformer: function (token, options) { const baseFont = getBasePxFontSize(options); - return (parseFloat(prop.value, 10) * baseFont).toFixed(2); + return (parseFloat(token.value, 10) * baseFont).toFixed(2); } } diff --git a/lib/exportPlatform.js b/lib/exportPlatform.js index 5a4427f03..8750fbbe7 100644 --- a/lib/exportPlatform.js +++ b/lib/exportPlatform.js @@ -20,7 +20,7 @@ const resolveObject = require('./utils/resolveObject'), const PROPERTY_REFERENCE_WARNINGS = GroupMessages.GROUP.PropertyReferenceWarnings; /** - * Exports a properties object with applied + * Exports a tokens object with applied * platform transforms. * * This is useful if you want to use a style diff --git a/lib/extend.js b/lib/extend.js index a15e01efb..dd2113366 100644 --- a/lib/extend.js +++ b/lib/extend.js @@ -25,12 +25,12 @@ var PROPERTY_VALUE_COLLISIONS = GroupMessages.GROUP.PropertyValueCollisions; * Either a string to a JSON file that contains configuration for the style dictionary or a plain Javascript object * that contains the configuration. * @typedef {(object|string)} Config - * @prop {String[]} source - Paths to property JSON files + * @prop {String[]} source - Paths to token files * @prop {Platform} platforms.platform - A platform * @example * ```json * { - * "source": ["properties/*.json"], + * "source": ["tokens/*.json"], * "platforms": { * "scss": { * "transformGroup": "scss", @@ -67,7 +67,7 @@ var PROPERTY_VALUE_COLLISIONS = GroupMessages.GROUP.PropertyValueCollisions; * const StyleDictionary = require('style-dictionary').extend('config.json'); * * const StyleDictionary = require('style-dictionary').extend({ - * source: ['properties/*.json'], + * source: ['tokens/*.json'], * platforms: { * scss: { * transformGroup: 'scss', @@ -83,7 +83,10 @@ var PROPERTY_VALUE_COLLISIONS = GroupMessages.GROUP.PropertyValueCollisions; * ``` */ function extend(opts) { - var options, to_ret; + let options, to_ret; + let inlineTokens = {}; + let includeTokens = {}; + let sourceTokens = {}; // Overloaded method, can accept a string as a path that points to a JS or // JSON file or a plain object. Potentially refactor. @@ -97,23 +100,28 @@ function extend(opts) { // Also keeping an options object in case to_ret = deepExtend([{}, this, {options: options}, options]); - // Update properties with includes from dependencies + // grab the inline tokens, ones either defined in the configuration object + // or that already exist from extending another style dictionary instance + // with `properties` or `tokens` keys + inlineTokens = deepExtend([{}, (to_ret.tokens||{}), (to_ret.properties||{})]); + + // Update tokens with includes from dependencies if (options.include) { if (!_.isArray(options.include)) throw new Error('include must be an array'); - to_ret.properties = combineJSON(options.include, true, null, false, to_ret.parsers); + includeTokens = combineJSON(options.include, true, null, false, to_ret.parsers); to_ret.include = null; // We don't want to carry over include references } - // Update properties with current package's source + // Update tokens with current package's source // These highest precedence if (options.source) { if (!_.isArray(options.source)) throw new Error('source must be an array'); - var props = combineJSON(options.source, true, function Collision(prop) { + sourceTokens = combineJSON(options.source, true, function Collision(prop) { GroupMessages.add( PROPERTY_VALUE_COLLISIONS, `Collision detected at: ${prop.path.join('.')}! Original value: ${prop.target[prop.key]}, New value: ${prop.copy[prop.key]}` @@ -128,11 +136,16 @@ function extend(opts) { } } - to_ret.properties = deepExtend([{}, to_ret.properties, props]); - to_ret.source = null; // We don't want to carry over the source references } + // Merge inline, include, and source tokens + const tokens = deepExtend([{}, inlineTokens, includeTokens, sourceTokens]); + + // Add tokens to both .tokens and .properties + to_ret.tokens = tokens; + to_ret.properties = tokens; + return to_ret; } diff --git a/lib/filterProperties.js b/lib/filterProperties.js index 5fd252d73..2155f872e 100644 --- a/lib/filterProperties.js +++ b/lib/filterProperties.js @@ -69,9 +69,9 @@ function filterPropertyArray(properties, filter) { * object using a function provided by the user. * * @param {Object} dictionary - * @param {Function} filter - A function that receives a property object - * and returns `true` if the property should be included in the output - * or `false` if the property should be excluded from the output + * @param {Function} filter - A function that receives a token object + * and returns `true` if the token should be included in the output + * or `false` if the token should be excluded from the output * @returns {Object} dictionary - A new dictionary containing only the * properties that matched the filter (or the original dictionary if no filter * function was provided). diff --git a/lib/register/action.js b/lib/register/action.js index 45c004813..b2c8664b2 100644 --- a/lib/register/action.js +++ b/lib/register/action.js @@ -12,7 +12,7 @@ */ /** - * Adds a custom action to the style property builder. Custom + * Adds a custom action to Style Dictionary. Custom * actions can do whatever you need, such as: copying files, * base64'ing files, running other build scripts, etc. * After you register a custom action, you then use that diff --git a/lib/register/filter.js b/lib/register/filter.js index 21b26e758..d4573a37c 100644 --- a/lib/register/filter.js +++ b/lib/register/filter.js @@ -17,14 +17,14 @@ * @memberof module:style-dictionary * @param {Object} filter * @param {String} filter.name - Name of the filter to be referenced in your config.json - * @param {Function} filter.matcher - Matcher function, return boolean if the property should be included. + * @param {Function} filter.matcher - Matcher function, return boolean if the token should be included. * @returns {module:style-dictionary} * @example * ```js * StyleDictionary.registerFilter({ * name: 'isColor', - * matcher: function(prop) { - * return prop.attributes.category === 'color'; + * matcher: function(token) { + * return token.attributes.category === 'color'; * } * }) * ``` diff --git a/lib/register/format.js b/lib/register/format.js index 8fdd2b539..7b823db17 100644 --- a/lib/register/format.js +++ b/lib/register/format.js @@ -22,10 +22,10 @@ * @memberof module:format * @param {Object} args - A single argument to support named parameters and destructuring. * @param {Object} args.dictionary - The transformed and resolved dictionary object - * @param {Object} args.dictionary.properties - Object structure of the tokens/properties that has been transformed and references resolved. - * @param {Array} args.dictionary.allProperties - Flattened array of all the tokens/properties. This makes it easy to output a list, like a list of SCSS variables. + * @param {Object} args.dictionary.tokens - Object structure of the tokens that has been transformed and references resolved. + * @param {Array} args.dictionary.allTokens - Flattened array of all the tokens. This makes it easy to output a list, like a list of SCSS variables. * @param {function(value): Boolean} args.dictionary.usesReference - Use this function to see if a token's value uses a reference. This is the same function style dictionary uses internally to detect a reference. - * @param {function(value): Value} args.dictionary.getReferences - Use this function to get the tokens/properties that it references. You can use this to output a reference in your custom format. For example: `dictionary.getReferences(token.original.value) // returns an array of the referenced token objects` + * @param {function(value): Value} args.dictionary.getReferences - Use this function to get the tokens that it references. You can use this to output a reference in your custom format. For example: `dictionary.getReferences(token.original.value) // returns an array of the referenced token objects` * @param {Object} args.platform - The platform configuration this format is being called in. * @param {Object} args.file - The file configuration this format is being called in. * @param {Object} args.options - Merged options object that combines platform level configuration and file level configuration. File options take precedence. @@ -35,7 +35,7 @@ * StyleDictionary.registerFormat({ * name: 'myCustomFormat', * formatter: function({dictionary, platform, options, file}) { - * return JSON.stringify(dictionary.properties, null, 2); + * return JSON.stringify(dictionary.tokens, null, 2); * } * }) * ``` @@ -55,7 +55,7 @@ * StyleDictionary.registerFormat({ * name: 'json', * formatter: function({dictionary, platform, options, file}) { - * return JSON.stringify(dictionary.properties, null, 2); + * return JSON.stringify(dictionary.tokens, null, 2); * } * }) * ``` diff --git a/lib/register/parser.js b/lib/register/parser.js index 63cd4e0cb..ef5d66c8a 100644 --- a/lib/register/parser.js +++ b/lib/register/parser.js @@ -15,7 +15,7 @@ * Adds a custom parser to parse style dictionary files * @static * @memberof module:style-dictionary - * @param {Regex} pattern - + * @param {Regex} pattern - A file path regular expression to match which files this parser should be be used on. This is similar to how webpack loaders work. `/\.json$/` will match any file ending in '.json', for example. * @param {Function} parse - Function to parse the file contents. Takes 1 argument, which is an object with 2 attributes: contents wich is the string of the file contents and filePath. The function should return a plain Javascript object. * @returns {module:style-dictionary} * @example diff --git a/lib/register/transform.js b/lib/register/transform.js index 05f08d0a3..5ca10d4ef 100644 --- a/lib/register/transform.js +++ b/lib/register/transform.js @@ -15,7 +15,7 @@ var transformTypes = ['name', 'value', 'attribute']; /** * Add a custom transform to the Style Dictionary - * Transforms can manipulate a property's name, value, or attributes + * Transforms can manipulate a token's name, value, or attributes * * @static * @name registerTransform @@ -25,22 +25,22 @@ var transformTypes = ['name', 'value', 'attribute']; * @param {String} transform.type - Type of transform, can be: name, attribute, or value * @param {String} transform.name - Name of the transformer (used by transformGroup to call a list of transforms). * @param {Boolean} transform.transitive - If the value transform should be applied transitively, i.e. should be applied to referenced values as well as absolute values. - * @param {Function} [transform.matcher] - Matcher function, return boolean if transform should be applied. If you omit the matcher function, it will match all properties. - * @param {Function} transform.transformer Performs a transform on a property object, should return a string or object depending on the type. Will only update certain properties by which you can't mess up property objects on accident. + * @param {Function} [transform.matcher] - Matcher function, return boolean if transform should be applied. If you omit the matcher function, it will match all tokens. + * @param {Function} transform.transformer Modifies a design token object. The transformer function will receive the token and the platform configuration as its arguments. The transformer function should return a string for name transforms, an object for attribute transforms, and same type of value for a value transform. * @returns {module:style-dictionary} * @example * ```js * StyleDictionary.registerTransform({ * name: 'time/seconds', * type: 'value', - * matcher: function(prop) { - * return prop.attributes.category === 'time'; + * matcher: function(token) { + * return token.attributes.category === 'time'; * }, - * transformer: function(prop) { + * transformer: function(token) { * // Note the use of prop.original.value, * // before any transforms are performed, the build system - * // clones the original property to the 'original' attribute. - * return (parseInt(prop.original.value) / 1000).toString() + 's'; + * // clones the original token to the 'original' attribute. + * return (parseInt(token.original.value) / 1000).toString() + 's'; * } * }); * ``` diff --git a/lib/transform/object.js b/lib/transform/object.js index aaa8c0cd6..6d25b1171 100644 --- a/lib/transform/object.js +++ b/lib/transform/object.js @@ -18,7 +18,7 @@ var _ = require('../utils/es6_'), propertySetup = require('./propertySetup'); /** - * Applies transforms on all properties. This + * Applies transforms on all tokens. This * does not happen inline, rather it is functional * and returns a new object. By doing this, * we can perform transforms for different platforms diff --git a/lib/utils/createDictionary.js b/lib/utils/createDictionary.js index 5dd5f249e..a38e78e8f 100644 --- a/lib/utils/createDictionary.js +++ b/lib/utils/createDictionary.js @@ -18,8 +18,10 @@ const usesReference = require('./references/usesReference'); /** * * @typedef Dictionary - * @property {Object} properties - * @property {Array} allProperties + * @property {Object} properties - Deprecated + * @property {Array} allProperties - Deprecated + * @property {Object} tokens - Replacement for `properties` + * @property {Array} allTokens - Replacement for `allProperties` * @property {Dictionary.getReferences} getReferences * @property {Dictionary.usesReference} usesReference */ @@ -31,9 +33,14 @@ const usesReference = require('./references/usesReference'); * @returns {Dictionary} */ function createDictionary({ properties }) { + const allProperties = flattenProperties( properties ); return { - properties: properties, - allProperties: flattenProperties( properties ), + properties, + allProperties, + // adding tokens and allTokens as the new way starting in v3, + // keeping properties and allProperties around for backwards-compatibility + tokens: properties, + allTokens: allProperties, getReferences: getReferences, usesReference: usesReference } diff --git a/scripts/handlebars/templates/actions.hbs b/scripts/handlebars/templates/actions.hbs index 5a73a4a21..3eccc0e51 100644 --- a/scripts/handlebars/templates/actions.hbs +++ b/scripts/handlebars/templates/actions.hbs @@ -2,13 +2,13 @@ Actions provide a way to run custom build code such as generating binary assets like images. -Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/master/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). +Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). You use actions in your config file under platforms > [platform] > actions ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transformGroup": "android", @@ -24,7 +24,7 @@ You use actions in your config file under platforms > [platform] > actions ## Pre-defined Actions -[lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/actions.js) +[lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/actions.js) {{#namespace name="Actions"}} {{>members~}} diff --git a/scripts/handlebars/templates/formats.hbs b/scripts/handlebars/templates/formats.hbs index 2ac2bd9e8..035df7b09 100644 --- a/scripts/handlebars/templates/formats.hbs +++ b/scripts/handlebars/templates/formats.hbs @@ -10,7 +10,7 @@ You use formats in your config file under platforms > [platform] > files > [file ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "css": { "transformGroup": "css", @@ -33,7 +33,7 @@ Formats can take configuration to make them more flexible. This allows you to re ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "scss": { "transformGroup": "scss", @@ -55,7 +55,7 @@ A special file configuration is `filter`, which will filter the tokens before th * 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 if you are defining your configuration in Javascript rather than JSON. The filter function takes a token as the property and should return a boolean if the token should be included (true) or excluded (false). +* 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.** ```javascript { @@ -67,7 +67,7 @@ A special file configuration is `filter`, which will filter the tokens before th } ``` -The token/property that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](properties.md?id=default-property-metadata) added by Style Dictionary. +The design token that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](tokens.md?id=default-design-token-metadata) added by Style Dictionary. ## References in output files @@ -250,7 +250,7 @@ To take advantage of outputting references in your custom formats there are 2 he StyleDictionary.registerFormat({ name: `es6WithReferences`, formatter: function({dictionary}) { - return dictionary.allProperties.map(token => { + return dictionary.allTokens.map(token => { let value = JSON.stringify(token.value); // the `dictionary` object now has `usesReference()` and // `getReferences()` methods. `usesReference()` will return true if @@ -300,7 +300,7 @@ Here are the available format helper methods: Formatters are functions and created easily with most templating engines. Formats can be built using templates if there is a lot of boilerplate code to insert (e.g. ObjectiveC files). If the output consists of only the values (e.g. a flat SCSS variables file), writing a formatter function directly may be easier. -Any templating language can work as there is a node module for it. All you need to do is register a format that calls your template and returns a string. +Any templating language can work as long as there is a node module for it. All you need to do is register a format that calls your template and returns a string. Here is a quick example for Lodash. @@ -330,7 +330,7 @@ styleDictionary.registerFormat({ name: 'my/format', formatter: function({dictionary, platform}) { return template({ - properties: dictionary.properties, + tokens: dictionary.tokens, options: platform }); } @@ -343,7 +343,7 @@ styleDictionary.registerFormat({ ## Pre-defined Formats -These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/formats.js) +These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/formats.js) Want a format? [You can request it here](https://github.com/amzn/style-dictionary/issues). diff --git a/scripts/handlebars/templates/transform_groups.hbs b/scripts/handlebars/templates/transform_groups.hbs index 03c34a6ac..ad38050aa 100644 --- a/scripts/handlebars/templates/transform_groups.hbs +++ b/scripts/handlebars/templates/transform_groups.hbs @@ -6,7 +6,7 @@ You use transformGroups in your config file under platforms > [platform] > trans ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transformGroup": "android" @@ -19,7 +19,7 @@ You use transformGroups in your config file under platforms > [platform] > trans ## Pre-defined Transform groups -[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/transformGroups.js) +[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transformGroups.js) {{#namespace name="TransformGroups"}} {{>members~}} diff --git a/scripts/handlebars/templates/transforms.hbs b/scripts/handlebars/templates/transforms.hbs index b5b50047d..cf8fc975e 100644 --- a/scripts/handlebars/templates/transforms.hbs +++ b/scripts/handlebars/templates/transforms.hbs @@ -1,13 +1,13 @@ # Transforms -Transforms are functions that transform a property - this enables each platform to consume the property in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. Transforms are applied in a non-destructive way thus each platform can transform the properties. Transforms are performed sequentially, therfore the order you use transforms matters. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=defining-custom-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). +Transforms are functions that modify a [token](tokens.md) so that it can be understood by a specific platform. It can modify the name, value, or attributes of a token - enabling each platform to use the design token in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. Transforms are isolated per platform; each platform begins with the same design token and makes the modifications it needs without affecting other platforms. The order you use transforms matters because transforms are performed sequentially. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=defining-custom-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). ## Using Transforms You use transforms in your config file under platforms > [platform] > transforms ```json { - "source": ["properties/**/*.json"], + "source": ["tokens/**/*.json"], "platforms": { "android": { "transforms": ["attribute/cti", "name/cti/kebab", "color/hex", "size/rem"] @@ -16,25 +16,73 @@ You use transforms in your config file under platforms > [platform] > transforms } ``` -A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all properties where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all properties.* +A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all design tokens where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all tokens.* ## Transform Types There are 3 types of transforms: attribute, name, and value. -**Attribute:** An attribute transform adds to the attributes object on a property. This is for including any meta-data about a property such as it's CTI or other information. +**Attribute:** An attribute transform adds to the attributes object on a design token. This is for including any meta-data about a design token such as it's CTI or other information. -**Name:** A name transform transform the name of a property. You should really only be apply one name transformer because they will override each other if you use more than one. +**Name:** A name transform transform the name of a design token. You should really only be apply one name transformer because they will override each other if you use more than one. -**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which properties that transform runs on. This allows us to only run a color transform on only the colors and not every property. +**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which tokens that transform runs on. This allows us to only run a color transform on only the colors and not every design token. ## Defining Custom Transforms -You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](properties.md?id=default-property-metadata) to each property/token to provide context that may be useful for some transforms. +You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](tokens.md?id=default-design-token-metadata) to each design token to provide context that may be useful for some transforms. + +## Transitive Transforms +Starting in version 3.0, you can define transitive transforms which allow you to transform a referenced value. Normally, value transforms only transform non-referenced values and because transforms happen before references are resolved, the transformed value is then used to resolve references. + +```javascript +const StyleDictionary = require('style-dictionary'); + +StyleDictionary.registerTransform({ + type: `value`, + transitive: true, + name: `myTransitiveTransform`, + matcher: (token) => {}, + transformer: (token) => { + // token.value will be resolved and transformed at this point + } +}) +``` + +There is one thing to be mindful of with transitive transforms. The token's value will be resolved and *transformed* already at the time the transitive transform. What happens is Style Dictionary will transform and resolve values iteratively. First it will transform any non-referenced values, then it will resolve any references to non-referenced values, then it will try to transform any non-referenced values, and so on. Let's take a look at an example: + +```json +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}" }, + "error": { "value": "{color.danger}" } + } +} +``` + +Style dictionary will first transform the value of `color.red`, then resolve `color.danger` to the transformed `color.red` value. Then it will transform `color.danger` and resolve `color.error` to the transformed `color.danger`. Finally, it will transform `color.error` and see that there is nothing left to transform or resolve. + +This allows you to modify a reference that modifies another reference. For example: + +```json +{ + "color": { + "red": { "value": "#f00" }, + "danger": { "value": "{color.red}", "darken": 0.75 }, + "error": { "value": "{color.danger}", "darken": 0.5 } + } +} +``` + +Using a custom transitive transform you could have `color.danger` darken `color.red` and `color.error` darken `color.danger`. The pre-defined transforms are *not transitive* to be backwards compatible with Style Dictionary v2 - an upgrade should not cause breaking changes. + +If you want to learn more about transitive transforms, take a look at the [transitive transforms example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms). + ## Pre-defined Transforms -[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/master/lib/common/transforms.js) +[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transforms.js) -> All the pre-defined transforms included use the [CTI structure](properties.md?id=category-type-item) for the match properties. If you structure your style properties differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the property CTIs are on the attributes of your properties. +> All the pre-defined transforms included use the [CTI structure](tokens.md?id=category-type-item) for matching tokens. If you structure your design tokens differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the proper CTIs are on the attributes of your design tokens. {{#namespace name="Transforms"}} {{>members~}}