Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): add matching build files example #481

Merged
merged 15 commits into from
Nov 14, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/advanced/custom-filters/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/
node_modules/
61 changes: 61 additions & 0 deletions examples/advanced/custom-filters/README.md
Original file line number Diff line number Diff line change
@@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about changing the name of this example? This example is showing how to generate output files 1:1 based on category/folder. I don't have a good name in mind right now...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Darn, I was hoping you had a suggestion haha. I was thinking maybe something like matching-build-files ? Open to whatever makes it easier to understand what this example does. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll think about it today..

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about "Custom Build", or "Custom Output Structure"?

I'm so excited to see this work, I'm creating a multi-brand design system that has shared global styles among the brands, and specific brand styles for each site. I'd love to output tokens as two separate files, like global.scss and brand.scss


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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this 'common use cases' section. I think this is something we should start adding to examples.


#### 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!
115 changes: 115 additions & 0 deletions examples/advanced/custom-filters/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
const StyleDictionary = require("style-dictionary");
const tokens = require("./properties");

module.exports = {
source: ["properties/**/*.json"],
platforms: {
"esm/category": {
transformGroup: "js",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you are defining both transforms and a transformGroup. I think the transforms will override anything in transformGroup so we might be able to remove this line (and the other transformGroup lines below)

buildPath: "build/js/esm/",
transforms: ["attribute/cti", "name/cti/camel", "size/px", "color/hex"],
files: tokens.map((tokenCategory) => ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super cool 😎

destination: `${tokenCategory}.js`,
format: "javascript/es6",
filter: {
attributes: {
category: tokenCategory,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome that it uses the built-in filter mechanism!

},
},
})),
},
"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({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't appear that this transform or the next one are being used?

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};`;
},
});
5 changes: 5 additions & 0 deletions examples/advanced/custom-filters/foundations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file can be deleted?

* Do not edit directly
* Generated on Sat, 07 Nov 2020 21:21:52 GMT
*/

Loading