@interactivethings/scripts 0.0.9 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +208 -12
- package/codemods/__testfixtures__/sx-to-use-styles.input.js +50 -0
- package/codemods/__testfixtures__/sx-to-use-styles.output.js +59 -0
- package/codemods/__tests__/defineTest.ts +9 -0
- package/codemods/__tests__/sx-to-use-styles.test.js +3 -0
- package/codemods/sx-to-use-styles.js +162 -0
- package/dist/__tests__/figma-cli.test.js +189 -0
- package/dist/__tests__/tokens-studio-cli.test.js +197 -0
- package/dist/__tests__/vercel-cli.test.js +86 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +103 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.js +167 -0
- package/dist/figma/api.d.ts +71 -0
- package/dist/figma/api.js +175 -0
- package/dist/figma/cli.d.ts +20 -0
- package/dist/figma/cli.js +163 -0
- package/dist/figma/cli.test.js +197 -0
- package/dist/figma/images.js +63 -0
- package/dist/figma/optimizeImage.js +53 -0
- package/dist/figma/utils.d.ts +10 -0
- package/dist/figma/utils.js +26 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +53 -0
- package/dist/init/cli.d.ts +3 -0
- package/dist/init/cli.js +320 -0
- package/dist/mui-tokens-studio.js +0 -0
- package/dist/plugins/figma/index.js +653 -0
- package/dist/plugins/tokens-studio/utils.js +155 -0
- package/dist/tokens-studio/__tests__/fixtures/invalid-transformer.js +12 -0
- package/dist/tokens-studio/__tests__/fixtures/test-transformer.js +18 -0
- package/dist/tokens-studio/cli.d.ts +8 -0
- package/dist/tokens-studio/cli.js +153 -0
- package/dist/tokens-studio/cli.test.js +160 -0
- package/dist/tokens-studio/index.d.ts +14 -0
- package/dist/tokens-studio/index.js +56 -0
- package/dist/tokens-studio/mui.js +212 -0
- package/dist/tokens-studio/require.js +17 -0
- package/dist/tokens-studio/tailwind.js +211 -0
- package/dist/tokens-studio/types.js +2 -0
- package/dist/tokens-studio/utils.d.ts +49 -0
- package/dist/tokens-studio/utils.js +156 -0
- package/dist/types.d.ts +1 -0
- package/dist/vercel/cli.d.ts +4 -0
- package/dist/vercel/cli.js +70 -0
- package/dist/vercel/cli.test.js +86 -0
- package/dist/vercel/deployments.js +41 -0
- package/dist/vercel/waitForDeploymentReady.js +43 -0
- package/package.json +46 -6
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* This script transforms tokens exported with tokens-studio in Figma into
|
|
5
|
+
* a format that is easier to work with when using MUI.
|
|
6
|
+
* You can run it via `pnpm run design:tokens`
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
25
|
+
if (mod && mod.__esModule) return mod;
|
|
26
|
+
var result = {};
|
|
27
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
28
|
+
__setModuleDefault(result, mod);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.run = exports.configParser = void 0;
|
|
33
|
+
const fs = __importStar(require("fs"));
|
|
34
|
+
const argparse_1 = require("argparse");
|
|
35
|
+
const remeda_1 = require("remeda");
|
|
36
|
+
const simplifyValues = (x) => {
|
|
37
|
+
if (typeof x === "string") {
|
|
38
|
+
return x;
|
|
39
|
+
}
|
|
40
|
+
else if (typeof x === "object" && !!x) {
|
|
41
|
+
if ("value" in x) {
|
|
42
|
+
return x.value;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return (0, remeda_1.mapValues)(x, simplifyValues);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const kebabCase = (x) => {
|
|
50
|
+
return x
|
|
51
|
+
.split(" ")
|
|
52
|
+
.map((t, i) => {
|
|
53
|
+
if (i === 0) {
|
|
54
|
+
return t.toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return `${t[0].toUpperCase()}${t.substring(1).toLowerCase()}`;
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
.join("");
|
|
61
|
+
};
|
|
62
|
+
const renameColorKeys = (k) => {
|
|
63
|
+
return kebabCase(k
|
|
64
|
+
.replace(/-[a-zA-Z0-9]+/, "")
|
|
65
|
+
.replace(" - ", " ")
|
|
66
|
+
.replace(",", "")
|
|
67
|
+
.replace(/^\d+\s+/, ""));
|
|
68
|
+
};
|
|
69
|
+
const renameColorKeysEntries = (obj) => {
|
|
70
|
+
const visitor = (k, v) => {
|
|
71
|
+
if (typeof v === "object") {
|
|
72
|
+
return [renameColorKeys(k), mapEntries(v, visitor)];
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
return [renameColorKeys(k), v];
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
return mapEntries(obj, visitor);
|
|
79
|
+
};
|
|
80
|
+
const mapEntries = (x, mapper) => {
|
|
81
|
+
return Object.fromEntries(Object.entries(x).map(([k, v]) => mapper(k, v)));
|
|
82
|
+
};
|
|
83
|
+
const getPalette = (tokensData) => {
|
|
84
|
+
const data = tokensData.global;
|
|
85
|
+
const colorKeys = ["Base", "Functional"];
|
|
86
|
+
let palette = (0, remeda_1.pick)(data, colorKeys);
|
|
87
|
+
palette = (0, remeda_1.mapValues)(palette, simplifyValues);
|
|
88
|
+
palette = renameColorKeysEntries(palette);
|
|
89
|
+
palette = {
|
|
90
|
+
...palette.base,
|
|
91
|
+
...(0, remeda_1.pick)(palette, ["functional"]),
|
|
92
|
+
};
|
|
93
|
+
return palette;
|
|
94
|
+
};
|
|
95
|
+
const getTypography = (tokensData) => {
|
|
96
|
+
const sizes = ["Desktop", "Mobile"];
|
|
97
|
+
const res = {};
|
|
98
|
+
const index = {};
|
|
99
|
+
for (const k of [
|
|
100
|
+
"fontFamilies",
|
|
101
|
+
"lineHeights",
|
|
102
|
+
"fontWeights",
|
|
103
|
+
"fontSize",
|
|
104
|
+
"letterSpacing",
|
|
105
|
+
"textDecoration",
|
|
106
|
+
]) {
|
|
107
|
+
for (const [vName, value] of Object.entries(tokensData.global[k])) {
|
|
108
|
+
index[`${k}.${vName}`] = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const maybeParseToNumber = (x) => {
|
|
112
|
+
const parsed = Number(x);
|
|
113
|
+
if (Number.isNaN(x)) {
|
|
114
|
+
return x;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return parsed;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const maybeParseToPx = (x) => {
|
|
121
|
+
if (typeof x === "number") {
|
|
122
|
+
return `${x}px`;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return x;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const cleanupFns = {
|
|
129
|
+
fontWeight: (x) => {
|
|
130
|
+
const lowered = x.toLowerCase();
|
|
131
|
+
if (lowered == "regular") {
|
|
132
|
+
return 400;
|
|
133
|
+
}
|
|
134
|
+
return lowered;
|
|
135
|
+
},
|
|
136
|
+
fontSize: maybeParseToNumber,
|
|
137
|
+
lineHeight: (x) => maybeParseToPx(maybeParseToNumber(x)),
|
|
138
|
+
paragraphSpacing: maybeParseToNumber,
|
|
139
|
+
letterSpacing: maybeParseToNumber,
|
|
140
|
+
};
|
|
141
|
+
const cleanup = (k, v) => {
|
|
142
|
+
if (k in cleanupFns) {
|
|
143
|
+
return [k, cleanupFns[k](v)];
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return [k, v];
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const resolve = (str) => {
|
|
150
|
+
if (str[0] === "{" && str[str.length - 1] === "}") {
|
|
151
|
+
const path = str.substring(1, str.length - 1);
|
|
152
|
+
return index[path]?.value;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
return str;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
for (const size of sizes) {
|
|
159
|
+
const typographies = tokensData.global[size];
|
|
160
|
+
for (const [typo, typoDataRaw] of Object.entries(typographies)) {
|
|
161
|
+
const typoData = typoDataRaw;
|
|
162
|
+
const typoKey = kebabCase(typo.toLowerCase());
|
|
163
|
+
res[typoKey] = res[typoKey] || {};
|
|
164
|
+
res[typoKey][size.toLowerCase()] = mapEntries((0, remeda_1.mapValues)(typoData.value, resolve), cleanup);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return res;
|
|
168
|
+
};
|
|
169
|
+
const getShadows = (tokenData) => {
|
|
170
|
+
const transformShadow = (shadowData) => {
|
|
171
|
+
const { color, x, y, blur, spread } = shadowData;
|
|
172
|
+
return `${x}px ${y}px ${blur}px ${spread}px ${color}`;
|
|
173
|
+
};
|
|
174
|
+
const shadows = mapEntries(tokenData.global.Elevation, (k, v) => [
|
|
175
|
+
`${Number(k.replace("dp", "").replace("pd", ""))}`,
|
|
176
|
+
Array.isArray(v.value)
|
|
177
|
+
? v.value.map(transformShadow).join(", ")
|
|
178
|
+
: transformShadow(v.value),
|
|
179
|
+
]);
|
|
180
|
+
return shadows;
|
|
181
|
+
};
|
|
182
|
+
const transform = (tokenData) => {
|
|
183
|
+
const palette = getPalette(tokenData);
|
|
184
|
+
const typography = getTypography(tokenData);
|
|
185
|
+
const shadows = getShadows(tokenData);
|
|
186
|
+
return {
|
|
187
|
+
palette,
|
|
188
|
+
typography,
|
|
189
|
+
shadows,
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
const configParser = (parser) => {
|
|
193
|
+
parser.add_argument("input");
|
|
194
|
+
parser.add_argument("output");
|
|
195
|
+
};
|
|
196
|
+
exports.configParser = configParser;
|
|
197
|
+
const run = (parser) => {
|
|
198
|
+
const args = parser.parse_args();
|
|
199
|
+
const content = JSON.parse(fs.readFileSync(args.input).toString());
|
|
200
|
+
const transformed = transform(content);
|
|
201
|
+
fs.writeFileSync(args.output === "-" ? process.stdout.fd : args.output, JSON.stringify(transformed, null, 2));
|
|
202
|
+
};
|
|
203
|
+
exports.run = run;
|
|
204
|
+
const main = () => {
|
|
205
|
+
const parser = new argparse_1.ArgumentParser();
|
|
206
|
+
(0, exports.configParser)(parser);
|
|
207
|
+
(0, exports.run)(parser);
|
|
208
|
+
};
|
|
209
|
+
// Only run main if this file is being executed directly
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
main();
|
|
212
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ourRequire = void 0;
|
|
4
|
+
const jiti_1 = require("jiti");
|
|
5
|
+
const jiti = (0, jiti_1.createJiti)(__filename);
|
|
6
|
+
// A simple wrapper around require to make it easier to mock in tests
|
|
7
|
+
const ourRequire = async (modulePath) => {
|
|
8
|
+
const transformerModule = await jiti.import(modulePath);
|
|
9
|
+
if (!(typeof transformerModule === "object" &&
|
|
10
|
+
transformerModule &&
|
|
11
|
+
"transform" in transformerModule) ||
|
|
12
|
+
typeof transformerModule.transform !== "function") {
|
|
13
|
+
throw new Error(`Module does not export a 'transform' function: ${modulePath}`);
|
|
14
|
+
}
|
|
15
|
+
return transformerModule;
|
|
16
|
+
};
|
|
17
|
+
exports.ourRequire = ourRequire;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const fs = __importStar(require("fs"));
|
|
27
|
+
const path = __importStar(require("path"));
|
|
28
|
+
const remeda_1 = require("remeda");
|
|
29
|
+
const isToken = (obj) => {
|
|
30
|
+
return typeof obj === "object" && "value" in obj && "type" in obj;
|
|
31
|
+
};
|
|
32
|
+
const tokensDir = path.join(__dirname, "tokens");
|
|
33
|
+
const readJsonFile = (filePath) => {
|
|
34
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
35
|
+
};
|
|
36
|
+
const resolveReferences = (obj, map) => {
|
|
37
|
+
const resolveValue = (value) => {
|
|
38
|
+
if (typeof value === "string" &&
|
|
39
|
+
value.startsWith("{") &&
|
|
40
|
+
value.endsWith("}")) {
|
|
41
|
+
const key = value.slice(1, -1);
|
|
42
|
+
return map.get(key) ?? value;
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
};
|
|
46
|
+
const traverse = (obj, currentPath = []) => {
|
|
47
|
+
for (const key in obj) {
|
|
48
|
+
const newPath = [...currentPath, key];
|
|
49
|
+
if (obj[key] && typeof obj[key] === "object") {
|
|
50
|
+
const maybeToken = obj[key];
|
|
51
|
+
if (isToken(maybeToken)) {
|
|
52
|
+
const fullPath = newPath.join(".");
|
|
53
|
+
map.set(fullPath, maybeToken.value);
|
|
54
|
+
maybeToken.value = resolveValue(maybeToken.value);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
traverse(maybeToken, newPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
traverse(obj);
|
|
63
|
+
};
|
|
64
|
+
const deepMerge = function (mergedTokens, tokenData) {
|
|
65
|
+
for (const key in tokenData) {
|
|
66
|
+
if (tokenData.hasOwnProperty(key)) {
|
|
67
|
+
if (typeof tokenData[key] === "object" &&
|
|
68
|
+
!Array.isArray(tokenData[key]) &&
|
|
69
|
+
tokenData[key] !== null) {
|
|
70
|
+
if (!mergedTokens[key]) {
|
|
71
|
+
mergedTokens[key] = {};
|
|
72
|
+
}
|
|
73
|
+
deepMerge(mergedTokens[key], tokenData[key]);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
mergedTokens[key] = tokenData[key];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const main = () => {
|
|
82
|
+
const metadata = readJsonFile(path.join(tokensDir, "$metadata.json"));
|
|
83
|
+
const mergedTokens = {};
|
|
84
|
+
metadata.tokenSetOrder.forEach((tokenFile) => {
|
|
85
|
+
const tokenFilePath = path.join(tokensDir, `${tokenFile}.json`);
|
|
86
|
+
const tokenData = readJsonFile(tokenFilePath);
|
|
87
|
+
deepMerge(mergedTokens, tokenData);
|
|
88
|
+
});
|
|
89
|
+
const valueMap = new Map();
|
|
90
|
+
resolveReferences(mergedTokens, valueMap);
|
|
91
|
+
const theme = {
|
|
92
|
+
colors: {
|
|
93
|
+
...(0, remeda_1.pick)(mergedTokens.core, [
|
|
94
|
+
"amber",
|
|
95
|
+
"blue",
|
|
96
|
+
"brand",
|
|
97
|
+
"cyan",
|
|
98
|
+
"emerald",
|
|
99
|
+
"fuchsia",
|
|
100
|
+
"green",
|
|
101
|
+
"indigo",
|
|
102
|
+
"light-blue",
|
|
103
|
+
"lime",
|
|
104
|
+
"midnight",
|
|
105
|
+
"monochrome",
|
|
106
|
+
"orange",
|
|
107
|
+
"pink",
|
|
108
|
+
"purple",
|
|
109
|
+
"red",
|
|
110
|
+
"rose",
|
|
111
|
+
"teal",
|
|
112
|
+
"violet",
|
|
113
|
+
"yellow",
|
|
114
|
+
]),
|
|
115
|
+
...(0, remeda_1.pick)(mergedTokens.functional, [
|
|
116
|
+
"primary",
|
|
117
|
+
"secondary",
|
|
118
|
+
"tertiary",
|
|
119
|
+
"error",
|
|
120
|
+
"success",
|
|
121
|
+
"warning",
|
|
122
|
+
"link",
|
|
123
|
+
"surface",
|
|
124
|
+
"on-surface",
|
|
125
|
+
"surface-inverted",
|
|
126
|
+
"on-surface-inverted",
|
|
127
|
+
"border",
|
|
128
|
+
"input",
|
|
129
|
+
"accent",
|
|
130
|
+
"qualitative",
|
|
131
|
+
"pathways",
|
|
132
|
+
]),
|
|
133
|
+
},
|
|
134
|
+
borderWidth: {
|
|
135
|
+
...mergedTokens.functional["border-width"],
|
|
136
|
+
},
|
|
137
|
+
borderRadius: {
|
|
138
|
+
...mergedTokens.functional["border-radius"],
|
|
139
|
+
},
|
|
140
|
+
fontSize: mergedTokens.core["font-size"],
|
|
141
|
+
fontWeight: mergedTokens.core["font-weight"],
|
|
142
|
+
lineHeight: mergedTokens.core["line-height"],
|
|
143
|
+
spacing: mergedTokens.functional.spacing,
|
|
144
|
+
};
|
|
145
|
+
const formatValues = (v) => {
|
|
146
|
+
return v.value;
|
|
147
|
+
};
|
|
148
|
+
const transformKey = (key, depth) => {
|
|
149
|
+
if (key.startsWith("on-")) {
|
|
150
|
+
if (depth === 1) {
|
|
151
|
+
return key.replace("on-", "foreground-");
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
return "foreground";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (key === "default") {
|
|
158
|
+
return "DEFAULT";
|
|
159
|
+
}
|
|
160
|
+
return key;
|
|
161
|
+
};
|
|
162
|
+
const flattenTokens = (v, depth = 0) => {
|
|
163
|
+
if (typeof v === "object") {
|
|
164
|
+
if (isToken(v)) {
|
|
165
|
+
return formatValues(v);
|
|
166
|
+
}
|
|
167
|
+
return mapEntries(v, (k, v) => {
|
|
168
|
+
return [
|
|
169
|
+
transformKey(k, depth + 1),
|
|
170
|
+
flattenTokens(v, depth + 1),
|
|
171
|
+
];
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return v;
|
|
175
|
+
};
|
|
176
|
+
const flattenedTheme = (0, remeda_1.mapValues)(theme, (x) => flattenTokens(x, 0));
|
|
177
|
+
const lineHeights = flattenedTheme.lineHeight;
|
|
178
|
+
const fontWeights = flattenedTheme.fontWeight;
|
|
179
|
+
const finalTheme = {
|
|
180
|
+
...flattenedTheme,
|
|
181
|
+
borderWidth: (0, remeda_1.mapValues)(flattenedTheme.borderWidth, (x) => `${x}px`),
|
|
182
|
+
borderRadius: (0, remeda_1.mapValues)(flattenedTheme.borderRadius, (x) => `${x}px`),
|
|
183
|
+
fontSize: mapEntries(flattenedTheme.fontSize["mobile-large"], (k, value) => {
|
|
184
|
+
return [
|
|
185
|
+
k.replace(",", ""),
|
|
186
|
+
[
|
|
187
|
+
`${value}px`,
|
|
188
|
+
{
|
|
189
|
+
lineHeight: lineHeights["mobile-large"][k]
|
|
190
|
+
? `${lineHeights["mobile-large"][k]}px`
|
|
191
|
+
: undefined,
|
|
192
|
+
fontWeight: fontWeights[k],
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
];
|
|
196
|
+
}),
|
|
197
|
+
fontWeight: flattenedTheme.fontWeight,
|
|
198
|
+
lineHeight: mapEntries(flattenedTheme.lineHeight["mobile-large"], (k, value) => {
|
|
199
|
+
return [k.replace(",", ""), `${value}px`];
|
|
200
|
+
}),
|
|
201
|
+
backgroundImage: {
|
|
202
|
+
"gradient-2": "var(--Gradient-2, linear-gradient(135deg, var(--core-brand-electricblue500, #48A1C7) 20.83%, var(--core-brand-nocturne700, #336476) 87.96%))",
|
|
203
|
+
},
|
|
204
|
+
spacing: mapEntries(flattenedTheme.spacing, (k, v) => [k.replace("spacing-", ""), `${v}px`]),
|
|
205
|
+
};
|
|
206
|
+
fs.writeFileSync("./theme.json", JSON.stringify(finalTheme, null, 2));
|
|
207
|
+
};
|
|
208
|
+
const mapEntries = (obj, mapper) => {
|
|
209
|
+
return Object.fromEntries(Object.entries(obj).map(([key, value]) => mapper(key, value)));
|
|
210
|
+
};
|
|
211
|
+
main();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { $IntentionalAny } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Shared utility functions for tokens-studio transformations
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Simplifies nested token values by extracting the 'value' property
|
|
7
|
+
*/
|
|
8
|
+
export declare const simplifyValues: (x: {
|
|
9
|
+
value: unknown;
|
|
10
|
+
} | string | null) => $IntentionalAny;
|
|
11
|
+
/**
|
|
12
|
+
* Converts space-separated strings to camelCase
|
|
13
|
+
*/
|
|
14
|
+
export declare const kebabCase: (x: string) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Maps over object entries with a custom mapper function
|
|
17
|
+
*/
|
|
18
|
+
export declare const mapEntries: <K extends string | number | symbol, V, K2 extends string | number | symbol, V2>(obj: Record<K, V>, mapper: (key: K, value: V) => [K2, V2]) => Record<K2, V2>;
|
|
19
|
+
/**
|
|
20
|
+
* Attempts to parse a string or number to a number, returns original if not possible
|
|
21
|
+
*/
|
|
22
|
+
export declare const maybeParseToNumber: (x: string | number) => string | number;
|
|
23
|
+
/**
|
|
24
|
+
* Converts a value to pixels (adds 'px' suffix if it's a number)
|
|
25
|
+
*/
|
|
26
|
+
export declare const maybeParseToPx: (x: string | number) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Type guard to check if an object is a token with value and type properties
|
|
29
|
+
*/
|
|
30
|
+
export declare const isToken: (obj: any) => obj is {
|
|
31
|
+
value: string;
|
|
32
|
+
type: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Deep merge utility for combining token objects
|
|
36
|
+
*/
|
|
37
|
+
export declare const deepMerge: (mergedTokens: any, tokenData: any) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves token references (strings like "{path.to.token}") using a value map
|
|
40
|
+
*/
|
|
41
|
+
export declare const resolveReferences: (obj: any, map: Map<string, string>) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Formats token values by extracting the value property
|
|
44
|
+
*/
|
|
45
|
+
export declare const formatValues: (v: {
|
|
46
|
+
type: string;
|
|
47
|
+
value: string | number;
|
|
48
|
+
}) => string | number;
|
|
49
|
+
export declare const flattenTokens: (v: any, depth: number | undefined, transformKey: (key: string, depth: number) => string) => unknown;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flattenTokens = exports.formatValues = exports.resolveReferences = exports.deepMerge = exports.isToken = exports.maybeParseToPx = exports.maybeParseToNumber = exports.mapEntries = exports.kebabCase = exports.simplifyValues = void 0;
|
|
4
|
+
const remeda_1 = require("remeda");
|
|
5
|
+
/**
|
|
6
|
+
* Shared utility functions for tokens-studio transformations
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Simplifies nested token values by extracting the 'value' property
|
|
10
|
+
*/
|
|
11
|
+
const simplifyValues = (x) => {
|
|
12
|
+
if (typeof x === "string") {
|
|
13
|
+
return x;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof x === "object" && !!x) {
|
|
16
|
+
if ("value" in x) {
|
|
17
|
+
return x.value;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return (0, remeda_1.mapValues)(x, exports.simplifyValues);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.simplifyValues = simplifyValues;
|
|
25
|
+
/**
|
|
26
|
+
* Converts space-separated strings to camelCase
|
|
27
|
+
*/
|
|
28
|
+
const kebabCase = (x) => {
|
|
29
|
+
return x
|
|
30
|
+
.split(" ")
|
|
31
|
+
.map((t, i) => {
|
|
32
|
+
if (i === 0) {
|
|
33
|
+
return t.toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return `${t[0].toUpperCase()}${t.substring(1).toLowerCase()}`;
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
.join("");
|
|
40
|
+
};
|
|
41
|
+
exports.kebabCase = kebabCase;
|
|
42
|
+
/**
|
|
43
|
+
* Maps over object entries with a custom mapper function
|
|
44
|
+
*/
|
|
45
|
+
const mapEntries = (obj, mapper) => {
|
|
46
|
+
return Object.fromEntries(Object.entries(obj).map(([key, value]) => mapper(key, value)));
|
|
47
|
+
};
|
|
48
|
+
exports.mapEntries = mapEntries;
|
|
49
|
+
/**
|
|
50
|
+
* Attempts to parse a string or number to a number, returns original if not possible
|
|
51
|
+
*/
|
|
52
|
+
const maybeParseToNumber = (x) => {
|
|
53
|
+
const parsed = Number(x);
|
|
54
|
+
if (Number.isNaN(parsed)) {
|
|
55
|
+
return x;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return parsed;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.maybeParseToNumber = maybeParseToNumber;
|
|
62
|
+
/**
|
|
63
|
+
* Converts a value to pixels (adds 'px' suffix if it's a number)
|
|
64
|
+
*/
|
|
65
|
+
const maybeParseToPx = (x) => {
|
|
66
|
+
if (typeof x === "number") {
|
|
67
|
+
return `${x}px`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
return x;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
exports.maybeParseToPx = maybeParseToPx;
|
|
74
|
+
/**
|
|
75
|
+
* Type guard to check if an object is a token with value and type properties
|
|
76
|
+
*/
|
|
77
|
+
const isToken = (obj) => {
|
|
78
|
+
return typeof obj === "object" && "value" in obj && "type" in obj;
|
|
79
|
+
};
|
|
80
|
+
exports.isToken = isToken;
|
|
81
|
+
/**
|
|
82
|
+
* Deep merge utility for combining token objects
|
|
83
|
+
*/
|
|
84
|
+
const deepMerge = (mergedTokens, tokenData) => {
|
|
85
|
+
for (const key in tokenData) {
|
|
86
|
+
if (tokenData.hasOwnProperty(key)) {
|
|
87
|
+
if (typeof tokenData[key] === "object" &&
|
|
88
|
+
!Array.isArray(tokenData[key]) &&
|
|
89
|
+
tokenData[key] !== null) {
|
|
90
|
+
if (!mergedTokens[key]) {
|
|
91
|
+
mergedTokens[key] = {};
|
|
92
|
+
}
|
|
93
|
+
(0, exports.deepMerge)(mergedTokens[key], tokenData[key]);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
mergedTokens[key] = tokenData[key];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
exports.deepMerge = deepMerge;
|
|
102
|
+
/**
|
|
103
|
+
* Resolves token references (strings like "{path.to.token}") using a value map
|
|
104
|
+
*/
|
|
105
|
+
const resolveReferences = (obj, map) => {
|
|
106
|
+
const resolveValue = (value) => {
|
|
107
|
+
var _a;
|
|
108
|
+
if (typeof value === "string" &&
|
|
109
|
+
value.startsWith("{") &&
|
|
110
|
+
value.endsWith("}")) {
|
|
111
|
+
const key = value.slice(1, -1);
|
|
112
|
+
return (_a = map.get(key)) !== null && _a !== void 0 ? _a : value;
|
|
113
|
+
}
|
|
114
|
+
return value;
|
|
115
|
+
};
|
|
116
|
+
const traverse = (obj, currentPath = []) => {
|
|
117
|
+
for (const key in obj) {
|
|
118
|
+
const newPath = [...currentPath, key];
|
|
119
|
+
if (obj[key] && typeof obj[key] === "object") {
|
|
120
|
+
const maybeToken = obj[key];
|
|
121
|
+
if ((0, exports.isToken)(maybeToken)) {
|
|
122
|
+
const fullPath = newPath.join(".");
|
|
123
|
+
map.set(fullPath, maybeToken.value);
|
|
124
|
+
maybeToken.value = resolveValue(maybeToken.value);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
traverse(maybeToken, newPath);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
traverse(obj);
|
|
133
|
+
};
|
|
134
|
+
exports.resolveReferences = resolveReferences;
|
|
135
|
+
/**
|
|
136
|
+
* Formats token values by extracting the value property
|
|
137
|
+
*/
|
|
138
|
+
const formatValues = (v) => {
|
|
139
|
+
return v.value;
|
|
140
|
+
};
|
|
141
|
+
exports.formatValues = formatValues;
|
|
142
|
+
const flattenTokens = (v, depth = 0, transformKey) => {
|
|
143
|
+
if (typeof v === "object") {
|
|
144
|
+
if ((0, exports.isToken)(v)) {
|
|
145
|
+
return (0, exports.formatValues)(v);
|
|
146
|
+
}
|
|
147
|
+
return (0, exports.mapEntries)(v, (k, v) => {
|
|
148
|
+
return [
|
|
149
|
+
transformKey(k, depth + 1),
|
|
150
|
+
(0, exports.flattenTokens)(v, depth + 1, transformKey),
|
|
151
|
+
];
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return v;
|
|
155
|
+
};
|
|
156
|
+
exports.flattenTokens = flattenTokens;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type $IntentionalAny = any;
|