Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions style-dictionary/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build/
json/
node_modules/
70 changes: 70 additions & 0 deletions style-dictionary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Style Dictionary example

This repository contains an example script that uses [Style Dictionary](https://amzn.github.io/style-dictionary/) to manage design tokens. The script pulls a token set generated by syncing a Figma file with zeroheight. For more details on how to sync Figma files with zeroheight, see [this guide](https://zeroheight.com/help/article/documenting-figma-color-variables).

## Token Set Overview

The token set used in this example contains two collections, each with two modes:

1. **Primitives**
- Modern Theme
- Brutal Theme
2. **Tokens**
- Light Mode
- Dark Mode

## Prerequisites

- Node.js >= 20

## Getting Started

To get started, follow these steps:

1. **Install Dependencies**
Run the following command in your CLI to install the required dependencies:

```sh
npm install
```

2. **Build the Tokens**
Once dependencies are installed, you can build the tokens by running:

```sh
npm run build
```

## How It Works

The build process is driven by a custom script (index.js) that performs the following steps:

1. **Fetching Style Dictionary Links**
The script first fetches links from the token set’s Style Dictionary URL. Each link corresponds to a JSON file that is saved locally.

```js
async function fetchLinks() {
// Logic to fetch links
}

async function saveFiles(links) {
// Logic to save JSON files locally
}
```

2. **Generating Style Dictionary Configuration**
Next, the script dynamically generates a Style Dictionary configuration for each mode in the Tokens collection.

```js
function getStyleDictionaryConfig(mode1, mode2) {
// Logic to generate Style Dictionary config
}
```

3. **Building for Multiple Platforms**
Finally, the script runs the build process for two platforms: `web` and `ios`.

## Additional Notes

Ensure that your Figma file is properly synced with zeroheight to avoid issues with token generation.
You can customize the build process by modifying the index.js script or the generated Style Dictionary configurations.
129 changes: 129 additions & 0 deletions style-dictionary/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { promises as fs } from "fs";
import fetch from "node-fetch";
import path from "path";
import { fileURLToPath } from "url";
import StyleDictionary from "style-dictionary";
import { extractCollectionAndMode, extractCollectionModes } from "./utils.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const styleDictionaryURL =
"https://zeroheight.zeroheight.com/api/token_management/token_set/7770/style_dictionary_links";

/**
* Fetches links for each collection and mode
*
* @returns {string[]} list of URLs for each collection and mode
*/
async function fetchLinks() {
try {
/** styleDictionaryURL value is generated per a token set at zeroheight.
*
* If you generate a private link, you need to generate access token and add additional headers to the request
* X-API-CLIENT
* X-API-KEY
*
* Learn more: https://zeroheight.com/help/article/documenting-figma-color-variables/
*/
const response = await fetch(styleDictionaryURL);
const textResponse = await response.text();
const links = textResponse.split("\n");

return links;
} catch (error) {
console.error("❗️Error fetching links:", error);
}
}

/**
* Iterates links, fetches Style Dictionary JSON files and saves them
*
* @param {string[]} links
*/
async function saveFiles(links) {
try {
for (const link of links) {
const response = await fetch(link);

if (!response.ok) {
throw new Error(`Failed to fetch from ${link}: ${response.statusText}`);
}

const jsonData = await response.json();

const [collection, mode] = extractCollectionAndMode(link);
const directory = path.join(__dirname, "json", collection);

await fs.mkdir(directory, { recursive: true });

const fileName = `${mode}.json`;
const filePath = path.join(directory, fileName);

await fs.writeFile(filePath, JSON.stringify(jsonData, null, 2));
}
} catch (error) {
console.error("❗️Error:", error);
}
}

/**
* Returns Style Dictionary config
*
* @param {string} mode1
* @param {string} mode2
* @returns {json} Style Dictionary config
*/
function getStyleDictionaryConfig(mode1, mode2) {
const buildDir = [mode1, mode2].join("_");

return {
source: [`json/tokens/${mode1}.json`, `json/primitives/${mode2}.json`],
platforms: {
web: {
transformGroup: "web",
buildPath: `build/web/${buildDir}/`,
files: [
{
destination: "tokens.css",
format: "css/variables",
},
],
},
ios: {
transformGroup: "ios",
buildPath: `build/ios/${buildDir}/`,
files: [
{
destination: "tokens.h",
format: "ios/macros",
},
],
},
},
};
}

/**
* Main function that builds tokens
*/
(async () => {
const links = await fetchLinks();
await saveFiles(links);

const collectionModes = extractCollectionModes(links);
const tokensCollectionModes = collectionModes.tokens;
const primitivesCollectionModes = collectionModes.primitives;
const platforms = ["web", "ios"];

console.log("\n🚀 Build started...");

tokensCollectionModes.forEach((m1) => {
primitivesCollectionModes.forEach((m2) => {
platforms.forEach((platform) => {
const sd = new StyleDictionary(getStyleDictionaryConfig(m1, m2));
sd.buildPlatform(platform);
});
});
});
})();
Loading