@interactivethings/scripts 2.0.2 → 2.0.4

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.
@@ -1,155 +0,0 @@
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
- if (typeof value === "string" &&
108
- value.startsWith("{") &&
109
- value.endsWith("}")) {
110
- const key = value.slice(1, -1);
111
- return map.get(key) ?? value;
112
- }
113
- return value;
114
- };
115
- const traverse = (obj, currentPath = []) => {
116
- for (const key in obj) {
117
- const newPath = [...currentPath, key];
118
- if (obj[key] && typeof obj[key] === "object") {
119
- const maybeToken = obj[key];
120
- if ((0, exports.isToken)(maybeToken)) {
121
- const fullPath = newPath.join(".");
122
- map.set(fullPath, maybeToken.value);
123
- maybeToken.value = resolveValue(maybeToken.value);
124
- }
125
- else {
126
- traverse(maybeToken, newPath);
127
- }
128
- }
129
- }
130
- };
131
- traverse(obj);
132
- };
133
- exports.resolveReferences = resolveReferences;
134
- /**
135
- * Formats token values by extracting the value property
136
- */
137
- const formatValues = (v) => {
138
- return v.value;
139
- };
140
- exports.formatValues = formatValues;
141
- const flattenTokens = (v, depth = 0, transformKey) => {
142
- if (typeof v === "object") {
143
- if ((0, exports.isToken)(v)) {
144
- return (0, exports.formatValues)(v);
145
- }
146
- return (0, exports.mapEntries)(v, (k, v) => {
147
- return [
148
- transformKey(k, depth + 1),
149
- (0, exports.flattenTokens)(v, depth + 1, transformKey),
150
- ];
151
- });
152
- }
153
- return v;
154
- };
155
- exports.flattenTokens = flattenTokens;
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CLI entry point for tokens-studio transformations
4
- * Supports different transformer handlers via --handler argument
5
- */
6
- import { ArgumentParser } from "argparse";
7
- export declare const configParser: (parser: ArgumentParser) => void;
8
- export declare const run: (parser: ArgumentParser) => Promise<void>;
@@ -1,14 +0,0 @@
1
- /**
2
- * Tokens Studio module for @interactivethings/scripts
3
- *
4
- * This module provides utilities and transformers for working with
5
- * tokens exported from Tokens Studio (Figma plugin).
6
- */
7
- export { simplifyValues, kebabCase, mapEntries, maybeParseToNumber, maybeParseToPx, isToken, deepMerge, resolveReferences, formatValues, flattenTokens, } from "./utils";
8
- export interface TransformInput {
9
- metadata: {
10
- tokenSetOrder: string[];
11
- };
12
- tokenData: any;
13
- }
14
- export * as cli from "./cli";
@@ -1,212 +0,0 @@
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
- }
@@ -1,211 +0,0 @@
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();
@@ -1,49 +0,0 @@
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;
package/dist/types.d.ts DELETED
@@ -1 +0,0 @@
1
- export type $IntentionalAny = any;
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { ArgumentParser } from "argparse";
3
- export declare const configParser: (parser: ArgumentParser) => void;
4
- export declare const run: (parser: ArgumentParser) => Promise<void>;