bdsg-cli 0.1.0
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 +277 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +176 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +125 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +63 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/files.d.ts +12 -0
- package/dist/utils/files.d.ts.map +1 -0
- package/dist/utils/files.js +190 -0
- package/dist/utils/files.js.map +1 -0
- package/package.json +25 -0
- package/src/commands/generate.ts +236 -0
- package/src/commands/init.ts +132 -0
- package/src/commands/validate.ts +89 -0
- package/src/index.ts +18 -0
- package/src/utils/files.ts +249 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { adjustColorForContrast, calculateContrast, meetsWCAG } from "bdsg";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
export const validateCommand = new Command("validate")
|
|
5
|
+
.description("Validate WCAG contrast between colors")
|
|
6
|
+
.argument("<foreground>", "Foreground color in hex format")
|
|
7
|
+
.argument("<background>", "Background color in hex format")
|
|
8
|
+
.option("-l, --level <level>", "Target WCAG level (AA, AAA)", "AA")
|
|
9
|
+
.option("-s, --size <size>", "Text size (normal, large)", "normal")
|
|
10
|
+
.action((foreground, background, options) => {
|
|
11
|
+
console.log(chalk.bold("\n Contrast Analysis\n"));
|
|
12
|
+
// Calculate contrast
|
|
13
|
+
const ratio = calculateContrast(foreground, background);
|
|
14
|
+
// Check each combination
|
|
15
|
+
const AANormal = meetsWCAG(ratio, "AA", "normal");
|
|
16
|
+
const AALarge = meetsWCAG(ratio, "AA", "large");
|
|
17
|
+
const AAANormal = meetsWCAG(ratio, "AAA", "normal");
|
|
18
|
+
const AAALarge = meetsWCAG(ratio, "AAA", "large");
|
|
19
|
+
// Display colors
|
|
20
|
+
console.log(chalk.dim("Colors"));
|
|
21
|
+
console.log(chalk.dim("──────────────────"));
|
|
22
|
+
console.log(` Foreground: ${chalk.hex(foreground)(foreground)}`);
|
|
23
|
+
console.log(` Background: ${chalk.hex(background)("████")} ${background}`);
|
|
24
|
+
console.log(` Ratio: ${chalk.bold(ratio.toFixed(2))}:1`);
|
|
25
|
+
console.log();
|
|
26
|
+
// WCAG Results
|
|
27
|
+
console.log(chalk.dim("WCAG Results"));
|
|
28
|
+
console.log(chalk.dim("──────────────────"));
|
|
29
|
+
const passSymbol = chalk.green("✓ Pass");
|
|
30
|
+
const failSymbol = chalk.red("✗ Fail");
|
|
31
|
+
console.log(` AA Normal Text: ${AANormal ? passSymbol : failSymbol} (needs 4.5:1)`);
|
|
32
|
+
console.log(` AA Large Text: ${AALarge ? passSymbol : failSymbol} (needs 3.0:1)`);
|
|
33
|
+
console.log(` AAA Normal Text: ${AAANormal ? passSymbol : failSymbol} (needs 7.0:1)`);
|
|
34
|
+
console.log(` AAA Large Text: ${AAALarge ? passSymbol : failSymbol} (needs 4.5:1)`);
|
|
35
|
+
console.log();
|
|
36
|
+
// Suggest fix if failing target level
|
|
37
|
+
const targetLevel = options.level;
|
|
38
|
+
const textSize = options.size;
|
|
39
|
+
const targetMet = meetsWCAG(ratio, targetLevel, textSize);
|
|
40
|
+
if (!targetMet) {
|
|
41
|
+
console.log(chalk.dim("Suggestion"));
|
|
42
|
+
console.log(chalk.dim("──────────────────"));
|
|
43
|
+
try {
|
|
44
|
+
const adjusted = adjustColorForContrast(foreground, background, targetLevel, textSize);
|
|
45
|
+
if (adjusted.adjusted !== foreground) {
|
|
46
|
+
console.log(` For ${targetLevel} ${textSize} text compliance:`);
|
|
47
|
+
console.log(` Try: ${chalk.hex(adjusted.adjusted)(adjusted.adjusted)} (ratio: ${adjusted.ratio.toFixed(2)}:1)`);
|
|
48
|
+
console.log(` Strategy: ${adjusted.strategy}`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(chalk.yellow(" Could not find a suitable adjustment."));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
console.log(chalk.yellow(" Could not calculate adjustment."));
|
|
56
|
+
}
|
|
57
|
+
console.log();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log(chalk.green(`✓ Colors meet ${targetLevel} ${textSize} text requirements!\n`));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { generateCommand } from "./commands/generate.js";
|
|
4
|
+
import { initCommand } from "./commands/init.js";
|
|
5
|
+
import { validateCommand } from "./commands/validate.js";
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name("bdsg")
|
|
9
|
+
.description("Design system generation CLI")
|
|
10
|
+
.version("0.1.0");
|
|
11
|
+
program.addCommand(initCommand);
|
|
12
|
+
program.addCommand(generateCommand);
|
|
13
|
+
program.addCommand(validateCommand);
|
|
14
|
+
program.parse();
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACL,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,8BAA8B,CAAC;KAC3C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AAEpC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ColorPalette, ShadowScale, SpacingScale, TypographyScale } from "bdsg";
|
|
2
|
+
interface TokensToWrite {
|
|
3
|
+
palette: ColorPalette;
|
|
4
|
+
typography: TypographyScale;
|
|
5
|
+
spacing: SpacingScale;
|
|
6
|
+
shadows: ShadowScale;
|
|
7
|
+
format: "css" | "json" | "tailwind-v4" | "shadcn";
|
|
8
|
+
outputDir: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function writeTokensToFile(tokens: TokensToWrite): Promise<void>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,MAAM,MAAM,CAAC;AAEd,UAAU,aAAa;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5E"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export async function writeTokensToFile(tokens) {
|
|
4
|
+
await mkdir(tokens.outputDir, { recursive: true });
|
|
5
|
+
if (tokens.format === "json") {
|
|
6
|
+
await writeJsonTokens(tokens);
|
|
7
|
+
}
|
|
8
|
+
else if (tokens.format === "tailwind-v4") {
|
|
9
|
+
await writeTailwindV4Tokens(tokens);
|
|
10
|
+
}
|
|
11
|
+
else if (tokens.format === "shadcn") {
|
|
12
|
+
await writeShadcnTokens(tokens);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
await writeCssTokens(tokens);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function writeCssTokens(tokens) {
|
|
19
|
+
// Colors CSS
|
|
20
|
+
const colorsContent = generateColorsCss(tokens.palette);
|
|
21
|
+
await writeFile(join(tokens.outputDir, "colors.css"), colorsContent);
|
|
22
|
+
// Typography CSS
|
|
23
|
+
await writeFile(join(tokens.outputDir, "typography.css"), tokens.typography.cssVariables);
|
|
24
|
+
// Spacing CSS
|
|
25
|
+
await writeFile(join(tokens.outputDir, "spacing.css"), tokens.spacing.cssVariables);
|
|
26
|
+
// Shadows CSS
|
|
27
|
+
await writeFile(join(tokens.outputDir, "shadows.css"), tokens.shadows.cssVariables);
|
|
28
|
+
}
|
|
29
|
+
async function writeJsonTokens(tokens) {
|
|
30
|
+
// Colors JSON
|
|
31
|
+
const colors = {};
|
|
32
|
+
for (const [shade, data] of Object.entries(tokens.palette.shades)) {
|
|
33
|
+
colors[`primary-${shade}`] = data.value;
|
|
34
|
+
}
|
|
35
|
+
await writeFile(join(tokens.outputDir, "colors.json"), JSON.stringify({ colors }, null, 2));
|
|
36
|
+
// Typography JSON
|
|
37
|
+
const typography = {};
|
|
38
|
+
for (const token of tokens.typography.tokens) {
|
|
39
|
+
typography[token.name] = {
|
|
40
|
+
fontSize: token.fontSize,
|
|
41
|
+
lineHeight: token.lineHeight,
|
|
42
|
+
letterSpacing: token.letterSpacing,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
await writeFile(join(tokens.outputDir, "typography.json"), JSON.stringify({ typography }, null, 2));
|
|
46
|
+
// Spacing JSON
|
|
47
|
+
const spacing = {};
|
|
48
|
+
for (const token of tokens.spacing.tokens) {
|
|
49
|
+
spacing[token.name] = {
|
|
50
|
+
value: token.formatted,
|
|
51
|
+
px: token.value,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
await writeFile(join(tokens.outputDir, "spacing.json"), JSON.stringify({ spacing }, null, 2));
|
|
55
|
+
// Shadows JSON
|
|
56
|
+
const shadows = {};
|
|
57
|
+
for (const token of tokens.shadows.tokens) {
|
|
58
|
+
shadows[token.name] = token.value;
|
|
59
|
+
}
|
|
60
|
+
await writeFile(join(tokens.outputDir, "shadows.json"), JSON.stringify({ shadows }, null, 2));
|
|
61
|
+
}
|
|
62
|
+
async function writeTailwindV4Tokens(tokens) {
|
|
63
|
+
let content = '@import "tailwindcss";\n\n@theme {\n';
|
|
64
|
+
// Colors
|
|
65
|
+
for (const [shade, data] of Object.entries(tokens.palette.shades)) {
|
|
66
|
+
content += ` --color-primary-${shade}: ${data.value};\n`;
|
|
67
|
+
}
|
|
68
|
+
content += "\n";
|
|
69
|
+
// Typography
|
|
70
|
+
for (const token of tokens.typography.tokens) {
|
|
71
|
+
const remValue = token.fontSize / 16;
|
|
72
|
+
content += ` --font-size-${token.name}: ${remValue}rem;\n`;
|
|
73
|
+
}
|
|
74
|
+
content += "\n";
|
|
75
|
+
// Spacing
|
|
76
|
+
for (const token of tokens.spacing.tokens) {
|
|
77
|
+
content += ` --spacing-${token.name}: ${token.formatted};\n`;
|
|
78
|
+
}
|
|
79
|
+
content += "\n";
|
|
80
|
+
// Shadows
|
|
81
|
+
for (const token of tokens.shadows.tokens) {
|
|
82
|
+
content += ` --shadow-${token.name}: ${token.value};\n`;
|
|
83
|
+
}
|
|
84
|
+
content += "}\n";
|
|
85
|
+
await writeFile(join(tokens.outputDir, "theme.css"), content);
|
|
86
|
+
}
|
|
87
|
+
function generateColorsCss(palette) {
|
|
88
|
+
let css = ":root {\n";
|
|
89
|
+
for (const [shade, data] of Object.entries(palette.shades)) {
|
|
90
|
+
css += ` --color-primary-${shade}: ${data.value};\n`;
|
|
91
|
+
}
|
|
92
|
+
css += "}\n";
|
|
93
|
+
return css;
|
|
94
|
+
}
|
|
95
|
+
async function writeShadcnTokens(tokens) {
|
|
96
|
+
const shades = tokens.palette.shades;
|
|
97
|
+
// Light mode tokens (using palette shades)
|
|
98
|
+
const lightTokens = {
|
|
99
|
+
background: "#ffffff",
|
|
100
|
+
foreground: shades[900].value,
|
|
101
|
+
card: "#ffffff",
|
|
102
|
+
"card-foreground": shades[900].value,
|
|
103
|
+
popover: "#ffffff",
|
|
104
|
+
"popover-foreground": shades[900].value,
|
|
105
|
+
primary: shades[500].value,
|
|
106
|
+
"primary-foreground": shades[50].value,
|
|
107
|
+
secondary: shades[100].value,
|
|
108
|
+
"secondary-foreground": shades[900].value,
|
|
109
|
+
muted: shades[100].value,
|
|
110
|
+
"muted-foreground": shades[500].value,
|
|
111
|
+
accent: shades[100].value,
|
|
112
|
+
"accent-foreground": shades[900].value,
|
|
113
|
+
destructive: "#ef4444",
|
|
114
|
+
border: shades[200].value,
|
|
115
|
+
input: shades[200].value,
|
|
116
|
+
ring: shades[500].value,
|
|
117
|
+
};
|
|
118
|
+
// Dark mode tokens (inverted)
|
|
119
|
+
const darkTokens = {
|
|
120
|
+
background: shades[900].value,
|
|
121
|
+
foreground: shades[50].value,
|
|
122
|
+
card: shades[800].value,
|
|
123
|
+
"card-foreground": shades[50].value,
|
|
124
|
+
popover: shades[800].value,
|
|
125
|
+
"popover-foreground": shades[50].value,
|
|
126
|
+
primary: shades[400].value,
|
|
127
|
+
"primary-foreground": shades[900].value,
|
|
128
|
+
secondary: shades[700].value,
|
|
129
|
+
"secondary-foreground": shades[50].value,
|
|
130
|
+
muted: shades[700].value,
|
|
131
|
+
"muted-foreground": shades[400].value,
|
|
132
|
+
accent: shades[700].value,
|
|
133
|
+
"accent-foreground": shades[50].value,
|
|
134
|
+
destructive: "#dc2626",
|
|
135
|
+
border: shades[700].value,
|
|
136
|
+
input: shades[700].value,
|
|
137
|
+
ring: shades[400].value,
|
|
138
|
+
};
|
|
139
|
+
let content = '@import "tailwindcss";\n\n';
|
|
140
|
+
// @theme block for Tailwind v4 mapping
|
|
141
|
+
content += "@custom-variant dark (&:is(.dark *));\n\n";
|
|
142
|
+
content += "@theme inline {\n";
|
|
143
|
+
content += " --color-background: var(--background);\n";
|
|
144
|
+
content += " --color-foreground: var(--foreground);\n";
|
|
145
|
+
content += " --color-card: var(--card);\n";
|
|
146
|
+
content += " --color-card-foreground: var(--card-foreground);\n";
|
|
147
|
+
content += " --color-popover: var(--popover);\n";
|
|
148
|
+
content += " --color-popover-foreground: var(--popover-foreground);\n";
|
|
149
|
+
content += " --color-primary: var(--primary);\n";
|
|
150
|
+
content += " --color-primary-foreground: var(--primary-foreground);\n";
|
|
151
|
+
content += " --color-secondary: var(--secondary);\n";
|
|
152
|
+
content += " --color-secondary-foreground: var(--secondary-foreground);\n";
|
|
153
|
+
content += " --color-muted: var(--muted);\n";
|
|
154
|
+
content += " --color-muted-foreground: var(--muted-foreground);\n";
|
|
155
|
+
content += " --color-accent: var(--accent);\n";
|
|
156
|
+
content += " --color-accent-foreground: var(--accent-foreground);\n";
|
|
157
|
+
content += " --color-destructive: var(--destructive);\n";
|
|
158
|
+
content += " --color-border: var(--border);\n";
|
|
159
|
+
content += " --color-input: var(--input);\n";
|
|
160
|
+
content += " --color-ring: var(--ring);\n";
|
|
161
|
+
content += " --radius-sm: calc(var(--radius) - 4px);\n";
|
|
162
|
+
content += " --radius-md: calc(var(--radius) - 2px);\n";
|
|
163
|
+
content += " --radius-lg: var(--radius);\n";
|
|
164
|
+
content += " --radius-xl: calc(var(--radius) + 4px);\n";
|
|
165
|
+
content += "}\n\n";
|
|
166
|
+
// :root with light mode tokens
|
|
167
|
+
content += ":root {\n";
|
|
168
|
+
content += " --radius: 0.625rem;\n";
|
|
169
|
+
for (const [name, value] of Object.entries(lightTokens)) {
|
|
170
|
+
content += ` --${name}: ${value};\n`;
|
|
171
|
+
}
|
|
172
|
+
content += "}\n\n";
|
|
173
|
+
// .dark with dark mode tokens
|
|
174
|
+
content += ".dark {\n";
|
|
175
|
+
for (const [name, value] of Object.entries(darkTokens)) {
|
|
176
|
+
content += ` --${name}: ${value};\n`;
|
|
177
|
+
}
|
|
178
|
+
content += "}\n\n";
|
|
179
|
+
// Base layer
|
|
180
|
+
content += "@layer base {\n";
|
|
181
|
+
content += " * {\n";
|
|
182
|
+
content += " @apply border-border outline-ring/50;\n";
|
|
183
|
+
content += " }\n";
|
|
184
|
+
content += " body {\n";
|
|
185
|
+
content += " @apply bg-background text-foreground;\n";
|
|
186
|
+
content += " }\n";
|
|
187
|
+
content += "}\n";
|
|
188
|
+
await writeFile(join(tokens.outputDir, "globals.css"), content);
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bdsg-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for design system generation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"bdsg": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"bdsg": "workspace:*",
|
|
15
|
+
"commander": "^12.0.0",
|
|
16
|
+
"inquirer": "^9.2.0",
|
|
17
|
+
"chalk": "^5.3.0",
|
|
18
|
+
"ora": "^8.0.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@bdsg/config": "workspace:*",
|
|
22
|
+
"@types/inquirer": "^9.0.9",
|
|
23
|
+
"@types/node": "^25.0.6"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
generatePalette,
|
|
5
|
+
generateShadows,
|
|
6
|
+
generateSpacingScale,
|
|
7
|
+
generateTypographyScale,
|
|
8
|
+
} from "bdsg";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import ora from "ora";
|
|
12
|
+
|
|
13
|
+
export const generateCommand = new Command("generate")
|
|
14
|
+
.description("Generate specific design tokens")
|
|
15
|
+
.addCommand(
|
|
16
|
+
new Command("palette")
|
|
17
|
+
.description("Generate a color palette from a base color")
|
|
18
|
+
.argument("<color>", "Base color in hex format (e.g., #3B82F6)")
|
|
19
|
+
.option("-n, --name <name>", "Palette name", "primary")
|
|
20
|
+
.option("-o, --output <dir>", "Output directory", "./tokens")
|
|
21
|
+
.option("-f, --format <format>", "Output format (css, json)", "css")
|
|
22
|
+
.action(async (color, options) => {
|
|
23
|
+
const spinner = ora("Generating palette...").start();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const palette = generatePalette(color, options.name);
|
|
27
|
+
await mkdir(options.output, { recursive: true });
|
|
28
|
+
|
|
29
|
+
if (options.format === "json") {
|
|
30
|
+
const colors: Record<string, string> = {};
|
|
31
|
+
for (const [shade, data] of Object.entries(palette.shades)) {
|
|
32
|
+
colors[`${options.name}-${shade}`] = data.value;
|
|
33
|
+
}
|
|
34
|
+
await writeFile(
|
|
35
|
+
join(options.output, `${options.name}.json`),
|
|
36
|
+
JSON.stringify({ colors }, null, 2),
|
|
37
|
+
);
|
|
38
|
+
} else {
|
|
39
|
+
let css = ":root {\n";
|
|
40
|
+
for (const [shade, data] of Object.entries(palette.shades)) {
|
|
41
|
+
css += ` --color-${options.name}-${shade}: ${data.value};\n`;
|
|
42
|
+
}
|
|
43
|
+
css += "}\n";
|
|
44
|
+
await writeFile(join(options.output, `${options.name}.css`), css);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
spinner.succeed(chalk.green("Palette generated!"));
|
|
48
|
+
console.log(
|
|
49
|
+
chalk.dim(
|
|
50
|
+
`\nFile: ${options.output}/${options.name}.${options.format}`,
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
console.log();
|
|
54
|
+
|
|
55
|
+
// Show preview
|
|
56
|
+
console.log(chalk.bold("Color shades:"));
|
|
57
|
+
for (const [shade, data] of Object.entries(palette.shades)) {
|
|
58
|
+
console.log(` ${shade}: ${data.value}`);
|
|
59
|
+
}
|
|
60
|
+
console.log();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
spinner.fail(chalk.red("Failed to generate palette"));
|
|
63
|
+
console.error(error);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
.addCommand(
|
|
69
|
+
new Command("typography")
|
|
70
|
+
.description("Generate a typography scale")
|
|
71
|
+
.option("-r, --ratio <ratio>", "Scale ratio", "perfect-fourth")
|
|
72
|
+
.option("-b, --base <size>", "Base font size in px", "16")
|
|
73
|
+
.option("-o, --output <dir>", "Output directory", "./tokens")
|
|
74
|
+
.option("-f, --format <format>", "Output format (css, json)", "css")
|
|
75
|
+
.action(async (options) => {
|
|
76
|
+
const spinner = ora("Generating typography scale...").start();
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const typography = generateTypographyScale({
|
|
80
|
+
ratio: options.ratio,
|
|
81
|
+
base: Number.parseInt(options.base, 10),
|
|
82
|
+
});
|
|
83
|
+
await mkdir(options.output, { recursive: true });
|
|
84
|
+
|
|
85
|
+
if (options.format === "json") {
|
|
86
|
+
const tokens: Record<string, unknown> = {};
|
|
87
|
+
for (const token of typography.tokens) {
|
|
88
|
+
tokens[token.name] = {
|
|
89
|
+
fontSize: token.fontSize,
|
|
90
|
+
lineHeight: token.lineHeight,
|
|
91
|
+
letterSpacing: token.letterSpacing,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
await writeFile(
|
|
95
|
+
join(options.output, "typography.json"),
|
|
96
|
+
JSON.stringify({ typography: tokens }, null, 2),
|
|
97
|
+
);
|
|
98
|
+
} else {
|
|
99
|
+
await writeFile(
|
|
100
|
+
join(options.output, "typography.css"),
|
|
101
|
+
typography.cssVariables,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
spinner.succeed(chalk.green("Typography scale generated!"));
|
|
106
|
+
console.log(
|
|
107
|
+
chalk.dim(`\nFile: ${options.output}/typography.${options.format}`),
|
|
108
|
+
);
|
|
109
|
+
console.log();
|
|
110
|
+
|
|
111
|
+
// Show preview
|
|
112
|
+
console.log(chalk.bold("Font sizes:"));
|
|
113
|
+
for (const token of typography.tokens) {
|
|
114
|
+
console.log(` ${token.name}: ${token.fontSize}px`);
|
|
115
|
+
}
|
|
116
|
+
console.log();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
spinner.fail(chalk.red("Failed to generate typography"));
|
|
119
|
+
console.error(error);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}),
|
|
123
|
+
)
|
|
124
|
+
.addCommand(
|
|
125
|
+
new Command("spacing")
|
|
126
|
+
.description("Generate a spacing scale")
|
|
127
|
+
.option(
|
|
128
|
+
"-m, --method <method>",
|
|
129
|
+
"Spacing method (fibonacci, linear, t-shirt)",
|
|
130
|
+
"fibonacci",
|
|
131
|
+
)
|
|
132
|
+
.option("-b, --base <size>", "Base spacing in px", "8")
|
|
133
|
+
.option("-o, --output <dir>", "Output directory", "./tokens")
|
|
134
|
+
.option("-f, --format <format>", "Output format (css, json)", "css")
|
|
135
|
+
.action(async (options) => {
|
|
136
|
+
const spinner = ora("Generating spacing scale...").start();
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const spacing = generateSpacingScale({
|
|
140
|
+
method: options.method,
|
|
141
|
+
base: Number.parseInt(options.base, 10),
|
|
142
|
+
});
|
|
143
|
+
await mkdir(options.output, { recursive: true });
|
|
144
|
+
|
|
145
|
+
if (options.format === "json") {
|
|
146
|
+
const tokens: Record<string, unknown> = {};
|
|
147
|
+
for (const token of spacing.tokens) {
|
|
148
|
+
tokens[token.name] = {
|
|
149
|
+
value: token.formatted,
|
|
150
|
+
px: token.value,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
await writeFile(
|
|
154
|
+
join(options.output, "spacing.json"),
|
|
155
|
+
JSON.stringify({ spacing: tokens }, null, 2),
|
|
156
|
+
);
|
|
157
|
+
} else {
|
|
158
|
+
await writeFile(
|
|
159
|
+
join(options.output, "spacing.css"),
|
|
160
|
+
spacing.cssVariables,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
spinner.succeed(chalk.green("Spacing scale generated!"));
|
|
165
|
+
console.log(
|
|
166
|
+
chalk.dim(`\nFile: ${options.output}/spacing.${options.format}`),
|
|
167
|
+
);
|
|
168
|
+
console.log();
|
|
169
|
+
|
|
170
|
+
// Show preview
|
|
171
|
+
console.log(chalk.bold("Spacing values:"));
|
|
172
|
+
for (const token of spacing.tokens) {
|
|
173
|
+
console.log(` ${token.name}: ${token.formatted}`);
|
|
174
|
+
}
|
|
175
|
+
console.log();
|
|
176
|
+
} catch (error) {
|
|
177
|
+
spinner.fail(chalk.red("Failed to generate spacing"));
|
|
178
|
+
console.error(error);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
}),
|
|
182
|
+
)
|
|
183
|
+
.addCommand(
|
|
184
|
+
new Command("shadows")
|
|
185
|
+
.description("Generate shadow tokens")
|
|
186
|
+
.option(
|
|
187
|
+
"-s, --style <style>",
|
|
188
|
+
"Shadow style (material, soft, hard)",
|
|
189
|
+
"material",
|
|
190
|
+
)
|
|
191
|
+
.option("-o, --output <dir>", "Output directory", "./tokens")
|
|
192
|
+
.option("-f, --format <format>", "Output format (css, json)", "css")
|
|
193
|
+
.action(async (options) => {
|
|
194
|
+
const spinner = ora("Generating shadows...").start();
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const shadows = generateShadows({
|
|
198
|
+
style: options.style,
|
|
199
|
+
});
|
|
200
|
+
await mkdir(options.output, { recursive: true });
|
|
201
|
+
|
|
202
|
+
if (options.format === "json") {
|
|
203
|
+
const tokens: Record<string, string> = {};
|
|
204
|
+
for (const token of shadows.tokens) {
|
|
205
|
+
tokens[token.name] = token.value;
|
|
206
|
+
}
|
|
207
|
+
await writeFile(
|
|
208
|
+
join(options.output, "shadows.json"),
|
|
209
|
+
JSON.stringify({ shadows: tokens }, null, 2),
|
|
210
|
+
);
|
|
211
|
+
} else {
|
|
212
|
+
await writeFile(
|
|
213
|
+
join(options.output, "shadows.css"),
|
|
214
|
+
shadows.cssVariables,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
spinner.succeed(chalk.green("Shadows generated!"));
|
|
219
|
+
console.log(
|
|
220
|
+
chalk.dim(`\nFile: ${options.output}/shadows.${options.format}`),
|
|
221
|
+
);
|
|
222
|
+
console.log();
|
|
223
|
+
|
|
224
|
+
// Show preview
|
|
225
|
+
console.log(chalk.bold("Shadow levels:"));
|
|
226
|
+
for (const token of shadows.tokens) {
|
|
227
|
+
console.log(` ${token.name}: elevation ${token.elevation}`);
|
|
228
|
+
}
|
|
229
|
+
console.log();
|
|
230
|
+
} catch (error) {
|
|
231
|
+
spinner.fail(chalk.red("Failed to generate shadows"));
|
|
232
|
+
console.error(error);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}),
|
|
236
|
+
);
|