tokvista 1.9.0 → 1.10.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 +17 -0
- package/dist/bin/tokvista.js +88 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -147,6 +147,22 @@ npx tokvista convert tokens.json --to supernova --output tokens-sn.json
|
|
|
147
147
|
npx tokvista convert tokens.json --to w3c
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
### Build All Formats
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Build everything in one command
|
|
154
|
+
npx tokvista build tokens.json --output-dir ./dist
|
|
155
|
+
|
|
156
|
+
# Creates:
|
|
157
|
+
# - tokens.css
|
|
158
|
+
# - tokens.scss
|
|
159
|
+
# - tokens.js
|
|
160
|
+
# - tailwind.config.js
|
|
161
|
+
|
|
162
|
+
# Skip validation for faster builds
|
|
163
|
+
npx tokvista build tokens.json --output-dir ./dist --skip-validation
|
|
164
|
+
```
|
|
165
|
+
|
|
150
166
|
### Interactive Setup
|
|
151
167
|
|
|
152
168
|
```bash
|
|
@@ -179,6 +195,7 @@ Then run `npx tokvista` to use your config.
|
|
|
179
195
|
| `tokvista validate <file>` | Validate token structure and values |
|
|
180
196
|
| `tokvista diff <old> <new>` | Compare two token files |
|
|
181
197
|
| `tokvista convert <file> --to <format>` | Convert between token formats |
|
|
198
|
+
| `tokvista build <file> --output-dir <dir>` | Build all formats (validate + export) |
|
|
182
199
|
| `--config`, `-c` | Config file path |
|
|
183
200
|
| `--port`, `-p` | Server port (default: `3000`) |
|
|
184
201
|
| `--format` | Export format (export only) |
|
package/dist/bin/tokvista.js
CHANGED
|
@@ -1122,6 +1122,7 @@ Usage:
|
|
|
1122
1122
|
tokvista validate <tokens.json>
|
|
1123
1123
|
tokvista diff <old.json> <new.json>
|
|
1124
1124
|
tokvista convert <tokens.json> --to <w3c|style-dictionary|supernova> [--output <file>]
|
|
1125
|
+
tokvista build <tokens.json> --output-dir <dir> [--skip-validation]
|
|
1125
1126
|
|
|
1126
1127
|
Arguments:
|
|
1127
1128
|
tokens.json Path to your tokens file (overrides config.tokens)
|
|
@@ -1257,6 +1258,9 @@ function parseArgs(args) {
|
|
|
1257
1258
|
if (args[0] === "convert") {
|
|
1258
1259
|
return parseConvertArgs(args.slice(1));
|
|
1259
1260
|
}
|
|
1261
|
+
if (args[0] === "build") {
|
|
1262
|
+
return parseBuildArgs(args.slice(1));
|
|
1263
|
+
}
|
|
1260
1264
|
return parseServeArgs(args);
|
|
1261
1265
|
}
|
|
1262
1266
|
function parseValidateArgs(args) {
|
|
@@ -1353,6 +1357,43 @@ function parseConvertArgs(args) {
|
|
|
1353
1357
|
if (!to) throw new Error("--to is required (w3c, style-dictionary, supernova, or token-studio)");
|
|
1354
1358
|
return { command: "convert", tokenFileArg, to, output };
|
|
1355
1359
|
}
|
|
1360
|
+
function parseBuildArgs(args) {
|
|
1361
|
+
let tokenFileArg;
|
|
1362
|
+
let outputDir;
|
|
1363
|
+
let skipValidation = false;
|
|
1364
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1365
|
+
const arg = args[index];
|
|
1366
|
+
if (arg === "-h" || arg === "--help") {
|
|
1367
|
+
printHelp();
|
|
1368
|
+
process.exit(0);
|
|
1369
|
+
}
|
|
1370
|
+
if (arg === "--output-dir" || arg === "-o") {
|
|
1371
|
+
const next = args[index + 1];
|
|
1372
|
+
if (!next) throw new Error("Missing value for --output-dir");
|
|
1373
|
+
outputDir = next;
|
|
1374
|
+
index += 1;
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
if (arg.startsWith("--output-dir=")) {
|
|
1378
|
+
outputDir = arg.slice("--output-dir=".length);
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
if (arg === "--skip-validation") {
|
|
1382
|
+
skipValidation = true;
|
|
1383
|
+
continue;
|
|
1384
|
+
}
|
|
1385
|
+
if (arg.startsWith("-")) {
|
|
1386
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
1387
|
+
}
|
|
1388
|
+
if (tokenFileArg) {
|
|
1389
|
+
throw new Error(`Only one token file is supported. Unexpected value: "${arg}"`);
|
|
1390
|
+
}
|
|
1391
|
+
tokenFileArg = arg;
|
|
1392
|
+
}
|
|
1393
|
+
if (!tokenFileArg) throw new Error("Token file is required for build");
|
|
1394
|
+
if (!outputDir) throw new Error("--output-dir is required");
|
|
1395
|
+
return { command: "build", tokenFileArg, outputDir, skipValidation };
|
|
1396
|
+
}
|
|
1356
1397
|
function parseExportArgs(args) {
|
|
1357
1398
|
let tokenFileArg;
|
|
1358
1399
|
let format;
|
|
@@ -2125,6 +2166,49 @@ async function runConvertCommand(cwd, options) {
|
|
|
2125
2166
|
console.log(output);
|
|
2126
2167
|
}
|
|
2127
2168
|
}
|
|
2169
|
+
async function runBuildCommand(cwd, options) {
|
|
2170
|
+
const resolvedTokenPath = path.resolve(cwd, options.tokenFileArg);
|
|
2171
|
+
const outputDir = path.resolve(cwd, options.outputDir);
|
|
2172
|
+
if (!existsSync(resolvedTokenPath)) {
|
|
2173
|
+
throw new Error(`Token file not found: ${resolvedTokenPath}`);
|
|
2174
|
+
}
|
|
2175
|
+
if (!existsSync(outputDir)) {
|
|
2176
|
+
await import("fs/promises").then((fs) => fs.mkdir(outputDir, { recursive: true }));
|
|
2177
|
+
}
|
|
2178
|
+
const tokens = await readTokens(resolvedTokenPath);
|
|
2179
|
+
if (!options.skipValidation) {
|
|
2180
|
+
console.log("\nValidating tokens...");
|
|
2181
|
+
const result = validateTokens(tokens);
|
|
2182
|
+
if (!result.valid) {
|
|
2183
|
+
console.log(`\u274C Found ${result.errors.length} errors`);
|
|
2184
|
+
result.errors.slice(0, 5).forEach((err) => {
|
|
2185
|
+
console.log(` ${err.path}: ${err.message}`);
|
|
2186
|
+
});
|
|
2187
|
+
if (result.errors.length > 5) {
|
|
2188
|
+
console.log(` ... and ${result.errors.length - 5} more errors`);
|
|
2189
|
+
}
|
|
2190
|
+
throw new Error("Validation failed. Fix errors or use --skip-validation");
|
|
2191
|
+
}
|
|
2192
|
+
console.log("\u2705 Validation passed\n");
|
|
2193
|
+
}
|
|
2194
|
+
console.log("Building tokens...");
|
|
2195
|
+
const formats = [
|
|
2196
|
+
{ name: "CSS", ext: "css", generator: generateCSS },
|
|
2197
|
+
{ name: "SCSS", ext: "scss", generator: generateSCSS },
|
|
2198
|
+
{ name: "JavaScript", ext: "js", generator: generateJS },
|
|
2199
|
+
{ name: "Tailwind", ext: "tailwind.config.js", generator: generateTailwind }
|
|
2200
|
+
];
|
|
2201
|
+
for (const format of formats) {
|
|
2202
|
+
const content = format.generator(tokens);
|
|
2203
|
+
const filename = format.ext.includes(".") ? format.ext : `tokens.${format.ext}`;
|
|
2204
|
+
const outputPath = path.join(outputDir, filename);
|
|
2205
|
+
await writeFile(outputPath, content, "utf8");
|
|
2206
|
+
console.log(` \u2713 ${format.name} \u2192 ${filename}`);
|
|
2207
|
+
}
|
|
2208
|
+
console.log(`
|
|
2209
|
+
\u2705 Build complete: ${outputDir}
|
|
2210
|
+
`);
|
|
2211
|
+
}
|
|
2128
2212
|
async function main() {
|
|
2129
2213
|
try {
|
|
2130
2214
|
const options = parseArgs(process.argv.slice(2));
|
|
@@ -2152,6 +2236,10 @@ async function main() {
|
|
|
2152
2236
|
await runConvertCommand(cwd, options);
|
|
2153
2237
|
return;
|
|
2154
2238
|
}
|
|
2239
|
+
if (options.command === "build") {
|
|
2240
|
+
await runBuildCommand(cwd, options);
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2155
2243
|
await runServeCommand(cwd, options);
|
|
2156
2244
|
} catch (error) {
|
|
2157
2245
|
console.error(error.message);
|