From f95c4202e93dcc00b47e595c4910f435a57d1987 Mon Sep 17 00:00:00 2001 From: Kelly Harrop Date: Sat, 7 Nov 2020 17:36:54 -0600 Subject: [PATCH] feat(examples): add custom filters example --- examples/advanced/custom-filters/.gitignore | 2 + examples/advanced/custom-filters/README.md | 61 +++++ examples/advanced/custom-filters/config.js | 115 ++++++++ .../advanced/custom-filters/foundations.js | 5 + .../advanced/custom-filters/package-lock.json | 248 ++++++++++++++++++ examples/advanced/custom-filters/package.json | 21 ++ .../properties/button/base.json | 14 + .../custom-filters/properties/color/base.json | 10 + .../custom-filters/properties/index.js | 5 + .../custom-filters/properties/size/base.json | 13 + 10 files changed, 494 insertions(+) create mode 100644 examples/advanced/custom-filters/.gitignore create mode 100644 examples/advanced/custom-filters/README.md create mode 100644 examples/advanced/custom-filters/config.js create mode 100644 examples/advanced/custom-filters/foundations.js create mode 100644 examples/advanced/custom-filters/package-lock.json create mode 100644 examples/advanced/custom-filters/package.json create mode 100644 examples/advanced/custom-filters/properties/button/base.json create mode 100644 examples/advanced/custom-filters/properties/color/base.json create mode 100644 examples/advanced/custom-filters/properties/index.js create mode 100644 examples/advanced/custom-filters/properties/size/base.json diff --git a/examples/advanced/custom-filters/.gitignore b/examples/advanced/custom-filters/.gitignore new file mode 100644 index 000000000..3e2e84b08 --- /dev/null +++ b/examples/advanced/custom-filters/.gitignore @@ -0,0 +1,2 @@ +build/ +node_modules/ diff --git a/examples/advanced/custom-filters/README.md b/examples/advanced/custom-filters/README.md new file mode 100644 index 000000000..cef322064 --- /dev/null +++ b/examples/advanced/custom-filters/README.md @@ -0,0 +1,61 @@ +## Customize token output using filters + +This example shows how you can manage what tokens are generated and how they are organized. This is useful when you want to generate a 1:1 relationship between files and token categories. + +Common use cases include: + +- Each token category as its own Sass partial (_colors.scss) +- Separate component files (button.css, input.css, etc) +- Tree shaking (only import what you need) + +#### Running the example + +First of all, set up the required dependencies running the command `npm install` in your local CLI environment (if you prefer to use *yarn*, update the commands accordingly). + +At this point, you can run `npm run build`. This command will generate the output file in the `build` folder. + +#### 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. + +```sh +# properties/color/base.json +{ + "color": { + "red": { + "value": "#FF0000" + } + } +} +``` + +```sh +# properties/size/base.json +{ + "size": { + "small": { + "value": "2px" + } + } +} +``` + +Because the folder name matches the category, the output would automatically generate separate `color` and `size` files. + +#### What to look at + +Open the `config.json` 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. + +```sh + files: properties.map(tokenCategory => ({ + destination: `${tokenCategory}.js`, + format: "format/js", + filter: { + attributes: { + category: tokenCategory + } + } + })) +``` + +Now each new folder that gets added will automatically generate a corresponding file filled with tokens that match the category! diff --git a/examples/advanced/custom-filters/config.js b/examples/advanced/custom-filters/config.js new file mode 100644 index 000000000..5586b3dc1 --- /dev/null +++ b/examples/advanced/custom-filters/config.js @@ -0,0 +1,115 @@ +const StyleDictionary = require("style-dictionary"); +const tokens = require("./properties"); + +module.exports = { + source: ["properties/**/*.json"], + platforms: { + "esm/category": { + transformGroup: "js", + buildPath: "build/js/esm/", + transforms: ["attribute/cti", "name/cti/camel", "size/px", "color/hex"], + files: tokens.map((tokenCategory) => ({ + destination: `${tokenCategory}.js`, + format: "javascript/es6", + filter: { + attributes: { + category: tokenCategory, + }, + }, + })), + }, + "esm/index": { + transformGroup: "js", + buildPath: "build/js/esm/", + transforms: ["attribute/cti", "name/cti/camel", "size/px", "color/hex"], + files: [ + { + destination: `index.js`, + format: "javascript/es6", + }, + ], + }, + "cjs/category": { + transformGroup: "js", + buildPath: "build/js/cjs/", + transforms: ["attribute/cti", "name/cti/camel", "size/px", "color/hex"], + files: tokens.map((tokenCategory) => ({ + destination: `${tokenCategory}.js`, + format: "custom/cjsmodule", + filter: { + attributes: { + category: tokenCategory, + }, + }, + })), + }, + "cjs/index": { + transformGroup: "js", + buildPath: "build/js/cjs/", + transforms: ["attribute/cti", "name/cti/camel", "size/px", "color/hex"], + files: [ + { + destination: `index.js`, + format: "custom/cjsmodule", + }, + ], + }, + + // Web output in scss format + scss: { + transformGroup: "scss", + buildPath: `build/scss/`, + files: [ + { + destination: `tokens.scss`, + format: "scss/variables", + }, + ], + }, + // Web output in scss partialformat + "scss/category": { + transformGroup: "scss", + buildPath: `build/scss/`, + files: tokens.map((tokenCategory) => ({ + destination: `_${tokenCategory}.scss`, + format: "scss/variables", + filter: { + attributes: { + category: tokenCategory, + }, + }, + })), + }, + }, +}; + +StyleDictionary.registerTransform({ + name: "size/pxToPt", + type: "value", + matcher: function (prop) { + return prop.value.match(/[\d.]+px/g); + }, + transformer: function (prop) { + return prop.value.replace(/px/g, "pt"); + }, +}); + +StyleDictionary.registerTransform({ + name: "size/pxToDp", + type: "value", + matcher: function (prop) { + return prop.value.match(/[\d.]+px/g); + }, + transformer: function (prop) { + return prop.value.replace(/px/g, "dp"); + }, +}); + +StyleDictionary.registerFormat({ + name: "custom/cjsmodule", + formatter: function (dictionary) { + return `module.exports = {${dictionary.allProperties.map( + (prop) => `\n\t${prop.name}: "${prop.value}"` + )}\n};`; + }, +}); diff --git a/examples/advanced/custom-filters/foundations.js b/examples/advanced/custom-filters/foundations.js new file mode 100644 index 000000000..110beff28 --- /dev/null +++ b/examples/advanced/custom-filters/foundations.js @@ -0,0 +1,5 @@ +/** + * Do not edit directly + * Generated on Sat, 07 Nov 2020 21:21:52 GMT + */ + diff --git a/examples/advanced/custom-filters/package-lock.json b/examples/advanced/custom-filters/package-lock.json new file mode 100644 index 000000000..75cac0023 --- /dev/null +++ b/examples/advanced/custom-filters/package-lock.json @@ -0,0 +1,248 @@ +{ + "name": "style-dictionary-custom-filters", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/commander/-/commander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha1-irwSj3lG4xATXdyTuYvdtBDno0s=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/glob/-/glob-7.1.6.tgz", + "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/json5/-/json5-2.1.3.tgz", + "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "style-dictionary": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/style-dictionary/-/style-dictionary-2.8.2.tgz", + "integrity": "sha1-babNxUdhD+Lw9dnwYVaLYIwaBvQ=", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "commander": "^2.9.0", + "fs-extra": "^6.0.1", + "glob": "^7.1.1", + "json5": "^2.1.0", + "lodash": "^4.17.15", + "resolve-cwd": "^2.0.0", + "tinycolor2": "^1.4.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha1-P2pNEHGtB2dtf6Ry4frECnGdiAM=", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/examples/advanced/custom-filters/package.json b/examples/advanced/custom-filters/package.json new file mode 100644 index 000000000..b294765f6 --- /dev/null +++ b/examples/advanced/custom-filters/package.json @@ -0,0 +1,21 @@ +{ + "name": "style-dictionary-custom-filters", + "version": "1.0.0", + "description": "An example to show custom filters", + "main": "dist/js/cjs/index.js", + "module": "dist/js/esm/index.js", + "files": [ + "build", + "properties" + ], + "scripts": { + "build": "style-dictionary build --config ./config.js", + "clean": "rm -rf build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Kelly Harrop ", + "license": "Apache-2.0", + "devDependencies": { + "style-dictionary": "2.8.2" + } +} diff --git a/examples/advanced/custom-filters/properties/button/base.json b/examples/advanced/custom-filters/properties/button/base.json new file mode 100644 index 000000000..b6c780698 --- /dev/null +++ b/examples/advanced/custom-filters/properties/button/base.json @@ -0,0 +1,14 @@ +{ + "button": { + "background": { + "color": { + "value": "{color.blue.value}" + } + }, + "text": { + "color": { + "value": "#FFFFFF" + } + } + } +} \ No newline at end of file diff --git a/examples/advanced/custom-filters/properties/color/base.json b/examples/advanced/custom-filters/properties/color/base.json new file mode 100644 index 000000000..d8b83723d --- /dev/null +++ b/examples/advanced/custom-filters/properties/color/base.json @@ -0,0 +1,10 @@ +{ + "color": { + "red": { + "value": "#FF0000" + }, + "blue": { + "value": "#0000FF" + } + } + } \ No newline at end of file diff --git a/examples/advanced/custom-filters/properties/index.js b/examples/advanced/custom-filters/properties/index.js new file mode 100644 index 000000000..4a2e37f27 --- /dev/null +++ b/examples/advanced/custom-filters/properties/index.js @@ -0,0 +1,5 @@ +const { readdirSync, statSync } = require("fs"); +const { join } = require("path"); +const dirs = (p) => + readdirSync(p).filter((f) => statSync(join(p, f)).isDirectory()); +module.exports = dirs(__dirname); diff --git a/examples/advanced/custom-filters/properties/size/base.json b/examples/advanced/custom-filters/properties/size/base.json new file mode 100644 index 000000000..76ffc555e --- /dev/null +++ b/examples/advanced/custom-filters/properties/size/base.json @@ -0,0 +1,13 @@ +{ + "size": { + "small": { + "value": "2px" + }, + "medium": { + "value": "8px" + }, + "large": { + "value": "16px" + } + } +} \ No newline at end of file