Skip to content

Commit 990c361

Browse files
committed
feat(design-tokens): ✨ build several token-sets for different themes
1 parent c8a3659 commit 990c361

5 files changed

Lines changed: 144 additions & 44 deletions

File tree

packages/design-tokens/package.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,28 @@
22
"name": "@3jane/design-tokens",
33
"version": "0.0.0",
44
"type": "module",
5+
"main": "dist/index.cjs.js",
6+
"module": "dist/index.js",
7+
"types": "dist/index.d.ts",
8+
"files": [
9+
"dist"
10+
],
11+
"exports": {
12+
".": {
13+
"types": "dist/index.d.ts",
14+
"default": "./dist/index.js"
15+
}
16+
},
517
"scripts": {
6-
"build": "node ./scripts/build.mjs --input './src/**/*.json' --output './dist/tokens.json'",
18+
"build": "node ./scripts/build.mjs --input src/\\$themes.json --output ./dist",
719
"test": "glob -c \"tsx --test --no-warnings\" \"./tests/**/*.test.ts\""
820
},
921
"devDependencies": {
1022
"@tokens-studio/sd-transforms": "^0.14.2",
1123
"ajv": "^8.16.0",
1224
"commander": "^12.1.0",
1325
"glob": "^10.4.2",
26+
"lodash.camelcase": "^4.3.0",
1427
"lodash.setwith": "^4.3.2",
1528
"style-dictionary": "4.0.0-prerelease.13",
1629
"tsx": "^4.16.0",
Lines changed: 111 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,124 @@
1+
import { readFile, writeFile } from "fs/promises";
2+
import { resolve, join, dirname, relative } from "path";
3+
import { Command } from "commander";
14
import StyleDictionary from "style-dictionary";
25
import { registerTransforms } from "@tokens-studio/sd-transforms";
3-
import { Command } from "commander";
4-
import path from "path";
56
import setWith from "lodash.setwith";
7+
import camelCase from "lodash.camelcase";
68

79
const program = new Command();
810

911
program
10-
.option("--input <path>", "Input path for tokens")
11-
.option("--output <path>", "Output path for generated file")
12+
.option("--input <path>", "input path to $themes.json")
13+
.option("--output <directory>", "output directory")
1214
.parse(process.argv);
1315

1416
const options = program.opts();
1517

16-
const inputPath = options.input || "./src/**/*.json";
17-
const outputPath = options.output || "./dist/tokens.json";
18-
19-
const outputDir = path.dirname(outputPath);
20-
const outputFile = path.basename(outputPath);
21-
22-
await registerTransforms(StyleDictionary, {});
23-
24-
StyleDictionary.registerFormat({
25-
name: "minimalJSON",
26-
formatter: ({ dictionary }) => {
27-
const out = {};
28-
dictionary.allTokens.map((t) => setWith(out, t.path, t.value, Object));
29-
return JSON.stringify(out, null, 4);
30-
},
31-
});
32-
33-
const sd = new StyleDictionary({
34-
source: [inputPath],
35-
platforms: {
36-
js: {
37-
buildPath: path.join(outputDir, "/"),
38-
transformGroup: "tokens-studio",
39-
files: [
40-
{
41-
destination: outputFile,
42-
format: "minimalJSON",
43-
},
44-
],
18+
if (!options.input || !options.output) {
19+
console.error("Both --input and --output options are required.");
20+
process.exit(1);
21+
}
22+
23+
const inputPath = resolve(process.cwd(), options.input);
24+
const outputDir = resolve(process.cwd(), options.output);
25+
26+
(async () => {
27+
StyleDictionary.registerTransform({
28+
name: "name/cti/custom",
29+
type: "name",
30+
transformer: function (token, config) {
31+
return camelCase(
32+
[config.prefix]
33+
.concat(token.path.map((it) => it.replace("-", "Minus")))
34+
.join(" ")
35+
);
4536
},
46-
},
47-
});
37+
});
38+
39+
StyleDictionary.registerFormat({
40+
name: "minimalJSON",
41+
formatter: ({ dictionary }) =>
42+
JSON.stringify(
43+
dictionary.allTokens.reduce((out, t) => {
44+
// if (["semantics", "composites"].includes(t.path[0]) === false) {
45+
// return out;
46+
// }
47+
48+
return setWith(out, t.path, t.value, Object);
49+
}, {}),
50+
null,
51+
2
52+
),
53+
});
54+
55+
registerTransforms(StyleDictionary, { casing: "custom" });
56+
57+
try {
58+
const blob = await readFile(inputPath, "utf8");
59+
const data = JSON.parse(blob);
60+
61+
const result = data.map((item) => {
62+
const name = item.name;
63+
const selectedTokenSets = item.selectedTokenSets || {};
64+
65+
const sources = Object.keys(selectedTokenSets).map((key) =>
66+
relative(process.cwd(), join(dirname(inputPath), `${key}.json`))
67+
);
68+
69+
return {
70+
name,
71+
sources,
72+
};
73+
});
74+
75+
const modules = await Promise.all(
76+
result.map(async ({ name, sources }) => {
77+
const exportedName = camelCase(name);
78+
const sd = new StyleDictionary({
79+
source: sources,
80+
platforms: {
81+
js: {
82+
buildPath: join(relative(process.cwd(), outputDir), "/"),
83+
transformGroup: "tokens-studio",
84+
transform: ["name/with-minus"],
85+
files: [
86+
{
87+
destination: `${name}.json`,
88+
format: "minimalJSON",
89+
},
90+
],
91+
},
92+
},
93+
});
94+
95+
await sd.cleanAllPlatforms();
96+
await sd.buildAllPlatforms();
97+
98+
return {
99+
name: exportedName,
100+
file: `./${name}.json`,
101+
};
102+
})
103+
);
104+
105+
const es = modules.map(
106+
({ name, file }) => `export { default as ${name} } from "${file}";`
107+
);
108+
const cjs = modules.map(
109+
({ name, file }) => `exports.${name} = require("${file}");`
110+
);
111+
const types = modules.map(
112+
({ name, file }) =>
113+
`export declare const ${name}: typeof import("${file}");`
114+
);
48115

49-
await sd.cleanAllPlatforms();
50-
await sd.buildAllPlatforms();
116+
await Promise.all([
117+
writeFile(join(outputDir, "index.js"), es.join("\n"), "utf8"),
118+
writeFile(join(outputDir, "index.cjs.js"), cjs.join("\n"), "utf8"),
119+
writeFile(join(outputDir, "index.d.ts"), types.join("\n"), "utf8"),
120+
]);
121+
} catch (error) {
122+
console.error("Error processing the files:", error);
123+
}
124+
})();

packages/design-tokens/tests/validate-tokens.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ import { test } from "node:test";
22
import { equal } from "node:assert";
33
import Ajv from "ajv";
44

5-
import tokens from "../dist/tokens.json";
65
import schema from "./tokens-schema.json";
76

8-
test("tokens should be valid structure", () => {
9-
const ajv = new Ajv();
10-
const validate = ajv.compile(schema);
7+
import * as tokens from "../dist";
118

12-
equal(validate(tokens), true);
9+
const ajv = new Ajv();
10+
const validate = ajv.compile(schema);
11+
12+
test("light tokens should be valid structure", () => {
13+
equal(validate(tokens.light), true);
14+
});
15+
16+
test("light tokens should be valid structure", () => {
17+
equal(validate(tokens.dark), true);
1318
});

packages/mui-themes/src/semantic/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import tokens from "@3jane/design-tokens/dist/tokens.json";
1+
import * as tokens from "@3jane/design-tokens";
22

33
export const semantic = {
44
color: {

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)