Skip to content

Commit

Permalink
chore(format): add format helpers for custom formats (#547)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanksdesign authored Feb 27, 2021
1 parent 0042354 commit 53053a1
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 148 deletions.
176 changes: 169 additions & 7 deletions docs/formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Formats define the output of your created files. For example, to use your styles
you use the `css/variables` format. This will create a CSS file containing the variables from
your style dictionary.

### Using formats
## Using formats

You use formats in your config file under platforms > [platform] > files > [file] > format

Expand All @@ -31,7 +31,7 @@ You use formats in your config file under platforms > [platform] > files > [file

There is an extensive (but not exhaustive) list of [included formats](#pre-defined-formats) available in Style Dictionary.

### Format configuration
## Format configuration

Formats can take configuration to make them more flexible. This allows you to re-use the same format multiple times with different configurations or to allow the format to use data not defined in the tokens themselves. To configure a format, add extra attributes on the file object in your configuration like the following:

Expand All @@ -53,7 +53,7 @@ Formats can take configuration to make them more flexible. This allows you to re

In this example we are adding the `mapName` configuration to the `scss/map-deep` format. This will change the name of the SCSS map in the output. Not all formats have the configuration options; format configuration is defined by the format itself. To see the configurtion options of a format, take a look at the documentation of the [specific format](#pre-defined-formats)

### Filtering tokens
## Filtering tokens

A special file configuration is `filter`, which will filter the tokens before they get to the format. This allows you to re-use the same format to generate multiple files with different sets of tokens. Filtering tokens works by adding a `filter` attribute on the file object, where `filter` is:

Expand All @@ -73,7 +73,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.

### References in output files
## References in output files

Starting with version 3.0, some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens:

Expand Down Expand Up @@ -143,7 +143,7 @@ Not all formats use the `outputReferences` option because that file format might

You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section.

### Creating formats
## Custom formats

You can create custom formats using the [`registerFormat`](api.md#registerformat) function or by directly including them in your [configuration](config.md). A format has a name and a formatter function, which takes an object as the argument and should return a string which is then written to a file.

Expand Down Expand Up @@ -231,7 +231,7 @@ It is recommended for any configuration needed for your custom format to use the
Note: to support legacy ways of defining custom formats, <code>this</code> in the formatter function is bound to the file object and when Style Dictionary calls the formatter function it passes 3 arguments: dictionary, platform, and file. Starting in 3.0 all data the formatter needs is in the first argument as shown above to make it easier to grab the arguments by name rather than by position. We recommend not using <code>this</code> or the positional arguments in your custom format.
</div>

#### Custom format with output references
## Custom format with output references

To take advantage of outputting references in your custom formats there are 2 helper methods in the `dictionary` argument passed to your formatter function: `usesReference(value)` and `getReference(value)`. Here is an example using those:

Expand All @@ -258,7 +258,169 @@ StyleDictionary.registerFormat({
});
```

### Using a template / templating engine to create a format
## Custom format helpers

We provide some helper methods we use internally in some of the built-in formats to make building custom formats a bit easier. They are accessible at `StyleDictionary.formatHelpers`.

```javascript
const StyleDictionary = require('style-dictionary');

const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers;

StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: function({dictionary, options}) {
return fileHeader(options.showFileHeader) +
':root {\n' +
formattedVariables('css', dictionary, options.outputReferences) +
'\n}\n';
}
});
```

Here are the available format helper methods:

### fileHeader
> formatHelpers.fileHeader(showFileHeader, commentStyle) ⇒ <code>String</code>
This is for creating the comment at the top of generated files with the generated at date.

<table>
<thead>
<tr>
<th>Param</th><th>Type</th><th>Default</th><th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>showFileHeader</td><td><code>Boolean</code></td><td><code>true</code></td><td><p>Whether or not to show the file header. If false will return an empty string.</p>
</td>
</tr><tr>
<td>commentStyle</td><td><code>String</code></td><td></td><td><p>The only option is &#39;short&#39;, which will use the // style comments. Anything else will use /* style comments.</p>
</td>
</tr> </tbody>
</table>

**Example**
```js
StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: function({ dictionary, options }) {
return fileHeader(true, 'short') +
dictionary.allProperties.map(token => `${token.name} = ${token.value}`);
}
});
```

* * *

### formattedVariables
> formatHelpers.formattedVariables(format, dictionary, outputReferences) ⇒ <code>String</code>
This is used to create lists of variables like Sass variables or CSS custom properties

<table>
<thead>
<tr>
<th>Param</th><th>Type</th><th>Default</th><th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>format</td><td><code>String</code></td><td></td><td><p>What type of variables to output. Options are: css, sass, less, and stylus</p>
</td>
</tr><tr>
<td>dictionary</td><td><code>Object</code></td><td></td><td><p>The dictionary object that gets passed to the formatter method.</p>
</td>
</tr><tr>
<td>outputReferences</td><td><code>Boolean</code></td><td><code>false</code></td><td><p>Whether or not to output references</p>
</td>
</tr> </tbody>
</table>

**Example**
```js
StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: function({ dictionary, options }) {
return formattedVariables('less', dictionary, options.outputReferences);
}
});
```

* * *

### iconsWithPrefix
> formatHelpers.iconsWithPrefix(prefix, properties, platform) ⇒ <code>String</code>
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
a unicode character.
__You probably don't need this.__

<table>
<thead>
<tr>
<th>Param</th><th>Type</th><th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>prefix</td><td><code>String</code></td><td><p>Character to prefix variable names, like &#39;$&#39; for Sass</p>
</td>
</tr><tr>
<td>properties</td><td><code>Array.&lt;Property&gt;</code></td><td><p>allProperties array on the dictionary object passed to the formatter function.</p>
</td>
</tr><tr>
<td>platform</td><td><code>Platform</code></td><td><p>options object passed to the formatter function.</p>
</td>
</tr> </tbody>
</table>

**Example**
```js
StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: function({ dictionary, options }) {
return iconsWithPrefix('$', dictionary.allProperties, options);
}
});
```

* * *

### minifyDictionary
> formatHelpers.minifyDictionary(obj) ⇒ <code>Object</code>
Outputs an object stripping out everything except values

<table>
<thead>
<tr>
<th>Param</th><th>Type</th><th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>obj</td><td><code>Object</code></td><td><p>The object to minify. You will most likely pass <code>dictionary.properties</code> to it.</p>
</td>
</tr> </tbody>
</table>

**Example**
```js
StyleDictionary.registerFormat({
name: 'myCustomFormat',
formatter: function({ dictionary, options }) {
return JSON.stringify(minifyDictionary(dictionary.properties));
}
});
```

* * *


## Using a template / templating engine to create a format

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.

Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var StyleDictionary = {
transformGroup: require('./lib/common/transformGroups'),
format: require('./lib/common/formats'),
action: require('./lib/common/actions'),
formatHelpers: require('./lib/common/formatHelpers'),
filter: {}, // we need to initialise the object, since we don't have built-in filters
parsers: [], // ditto ^

Expand Down
Loading

0 comments on commit 53053a1

Please sign in to comment.