@terrazzo/cli 2.0.0-beta.2 → 2.0.0-beta.3
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +318 -90
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/terrazzo.config.ts +0 -12
- package/tokens-example.json +0 -50
- package/vite.config.ts +0 -18
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"mappings":";;;cASa,GAAA,EAAG,GAAA;AAAA,cACH,mBAAA,EAAmB,GAAA;AAAA,cACnB,mBAAA,EAAmB,GAAA;AAAA,KAEpB,OAAA;AAAA,cAEC,WAAA;AAAA,UAEI,KAAA;EAR6C;EAU5D,MAAA;EATqE;EAWrE,GAAA;EAX8B;EAa9B,IAAA;EAZW;EAcX,KAAA;;EAEA,OAAA;AAAA;AAAA,UAGe,iBAAA;EACf,GAAA,EAAK,OAAA;EACL,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,MAAA;AAAA;AAlBV;AAAA,iBAsBsB,UAAA,CAAA;EAAa,GAAA;EAAK,KAAA;EAAO;AAAA,GAAU,iBAAA,GAAiB,OAAA;;;;AApB1E;AAAA,iBA2GsB,UAAA,CAAW,UAAA,EAAY,GAAA;EAAS;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,OAAA;;;;;iBAiGlE,UAAA,CAAW,OAAA;;iBAKX,YAAA,CAAa,OAAA,UAAiB,SAAA;AApM9C;AAAA,iBAyMgB,aAAA,CAAc,QAAA;;iBAgBd,gBAAA,CAAiB,QAAA;EAAoB;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,GAAA;;iBAWjE,IAAA,CAAK,KAAA;;;UChPJ,YAAA;EACf,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,UAAA;EACR,UAAA;EACA,MAAA,EAAQ,MAAA;AAAA;ADZV;AAAA,iBCgBsB,QAAA,CAAA;EAAW,MAAA;EAAQ,UAAA;EAAY,KAAA;EAAO;AAAA,GAAU,YAAA,GAAY,OAAA;;iBAoFlE,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;EAAQ;AAAA;EAAY,MAAA,EAAQ,UAAA;EAAY,MAAA,EAAQ,MAAA;AAAA;;;UC1GvF,YAAA;;EAEf,WAAA;EACA,MAAA,EAAQ,UAAA;EACR,MAAA,EAAQ,MAAA;AAAA;;iBAIY,QAAA,CAAA;EAAW,MAAA;EAAQ,MAAA;EAAQ;AAAA,GAAe,YAAA,GAAY,OAAA;;;;iBCX5D,OAAA,CAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"mappings":";;;cASa,GAAA,EAAG,GAAA;AAAA,cACH,mBAAA,EAAmB,GAAA;AAAA,cACnB,mBAAA,EAAmB,GAAA;AAAA,KAEpB,OAAA;AAAA,cAEC,WAAA;AAAA,UAEI,KAAA;EAR6C;EAU5D,MAAA;EATqE;EAWrE,GAAA;EAX8B;EAa9B,IAAA;EAZW;EAcX,KAAA;;EAEA,OAAA;AAAA;AAAA,UAGe,iBAAA;EACf,GAAA,EAAK,OAAA;EACL,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,MAAA;AAAA;AAlBV;AAAA,iBAsBsB,UAAA,CAAA;EAAa,GAAA;EAAK,KAAA;EAAO;AAAA,GAAU,iBAAA,GAAiB,OAAA;;;;AApB1E;AAAA,iBA2GsB,UAAA,CAAW,UAAA,EAAY,GAAA;EAAS;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,OAAA;;;;;iBAiGlE,UAAA,CAAW,OAAA;;iBAKX,YAAA,CAAa,OAAA,UAAiB,SAAA;AApM9C;AAAA,iBAyMgB,aAAA,CAAc,QAAA;;iBAgBd,gBAAA,CAAiB,QAAA;EAAoB;AAAA;EAAY,MAAA,EAAQ,MAAA;AAAA,IAAQ,GAAA;;iBAWjE,IAAA,CAAK,KAAA;;;UChPJ,YAAA;EACf,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,UAAA;EACR,UAAA;EACA,MAAA,EAAQ,MAAA;AAAA;ADZV;AAAA,iBCgBsB,QAAA,CAAA;EAAW,MAAA;EAAQ,UAAA;EAAY,KAAA;EAAO;AAAA,GAAU,YAAA,GAAY,OAAA;;iBAoFlE,UAAA,CAAW,MAAA,EAAQ,iBAAA;EAAqB,MAAA;EAAQ;AAAA;EAAY,MAAA,EAAQ,UAAA;EAAY,MAAA,EAAQ,MAAA;AAAA;;;UC1GvF,YAAA;;EAEf,WAAA;EACA,MAAA,EAAQ,UAAA;EACR,MAAA,EAAQ,MAAA;AAAA;;iBAIY,QAAA,CAAA;EAAW,MAAA;EAAQ,MAAA;EAAQ;AAAA,GAAe,YAAA,GAAY,OAAA;;;;iBCX5D,OAAA,CAAA;;;UCoFC,WAAA;EACf,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAGY,OAAA,CAAA;EAAU;AAAA,GAAU,WAAA,GAAW,OAAA;;;UChFpC,eAAA;EACf,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,UAAA;EACR,UAAA;EACA,MAAA,EAAQ,MAAA;AAAA;AAAA,iBAGY,MAAA,CAAA;EAAS,MAAA;EAAQ;AAAA,GAAU,eAAA,GAAe,OAAA;;;UCR/C,gBAAA;EACf,MAAA,EAAQ,MAAA;EACR,MAAA,EAAQ,GAAA;AAAA;AAAA,iBASY,YAAA,CAAa,QAAA;EAAoB,MAAA;EAAQ;AAAA,GAAU,gBAAA,GAAgB,OAAA;;;iBCjBzE,UAAA,CAAA;;;iBCeA,YAAA,CAAa,MAAA,EAAQ,MAAA,GAAS,UAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import { build, defineConfig as defineConfig$1, parse } from "@terrazzo/parser";
|
|
4
|
-
import fs
|
|
4
|
+
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pc from "picocolors";
|
|
7
7
|
import { createServer } from "vite";
|
|
@@ -10,12 +10,12 @@ import { ViteNodeServer } from "vite-node/server";
|
|
|
10
10
|
import chokidar from "chokidar";
|
|
11
11
|
import yamlToMomoa from "yaml-to-momoa";
|
|
12
12
|
import { spawn } from "node:child_process";
|
|
13
|
+
import fs$1 from "node:fs/promises";
|
|
13
14
|
import { confirm, intro, multiselect, outro, select, spinner } from "@clack/prompts";
|
|
14
15
|
import { isAlias, pluralize } from "@terrazzo/token-tools";
|
|
15
16
|
import { detect } from "detect-package-manager";
|
|
16
17
|
import { generate } from "escodegen";
|
|
17
18
|
import { parseModule } from "meriyah";
|
|
18
|
-
import { readdir } from "node:fs/promises";
|
|
19
19
|
import { Readable, Writable } from "node:stream";
|
|
20
20
|
import { serve } from "@hono/node-server";
|
|
21
21
|
import mime from "mime";
|
|
@@ -400,6 +400,12 @@ const INSTALL_COMMAND = {
|
|
|
400
400
|
pnpm: "add -D --silent",
|
|
401
401
|
bun: "install -D --silent"
|
|
402
402
|
};
|
|
403
|
+
const SYNTAX_SETTINGS = { format: {
|
|
404
|
+
indent: { style: " " },
|
|
405
|
+
quotes: "single",
|
|
406
|
+
semicolons: true
|
|
407
|
+
} };
|
|
408
|
+
const EXAMPLE_TOKENS_PATH = "my-tokens.tokens.json";
|
|
403
409
|
const DESIGN_SYSTEMS = {
|
|
404
410
|
"adobe-spectrum": {
|
|
405
411
|
name: "Spectrum",
|
|
@@ -441,19 +447,19 @@ async function initCmd({ logger }) {
|
|
|
441
447
|
try {
|
|
442
448
|
intro("⛋ Welcome to Terrazzo");
|
|
443
449
|
const packageManager = await detect({ cwd: fileURLToPath(cwd) });
|
|
444
|
-
const { config, configPath } = await loadConfig({
|
|
450
|
+
const { config, configPath = "terrazzo.config.ts" } = await loadConfig({
|
|
445
451
|
cmd: "init",
|
|
446
452
|
flags: {},
|
|
447
453
|
logger
|
|
448
454
|
});
|
|
449
|
-
const
|
|
450
|
-
|
|
455
|
+
const tokensPath = config.tokens[0];
|
|
456
|
+
const hasExistingConfig = fs.existsSync(configPath);
|
|
451
457
|
let startFromDS = !(tokensPath && fs.existsSync(tokensPath));
|
|
452
458
|
if (tokensPath && fs.existsSync(tokensPath)) {
|
|
453
459
|
if (await confirm({ message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?` })) startFromDS = true;
|
|
454
|
-
}
|
|
460
|
+
}
|
|
455
461
|
if (startFromDS) {
|
|
456
|
-
|
|
462
|
+
const ds = DESIGN_SYSTEMS[await select({
|
|
457
463
|
message: "Start from existing design system?",
|
|
458
464
|
options: [...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({
|
|
459
465
|
value: id,
|
|
@@ -462,7 +468,8 @@ async function initCmd({ logger }) {
|
|
|
462
468
|
value: "none",
|
|
463
469
|
label: "None"
|
|
464
470
|
}]
|
|
465
|
-
})]
|
|
471
|
+
})];
|
|
472
|
+
if (ds) {
|
|
466
473
|
const s = spinner();
|
|
467
474
|
s.start("Downloading");
|
|
468
475
|
await new Promise((resolve, reject) => {
|
|
@@ -470,8 +477,14 @@ async function initCmd({ logger }) {
|
|
|
470
477
|
subprocess.on("error", reject);
|
|
471
478
|
subprocess.on("exit", resolve);
|
|
472
479
|
});
|
|
473
|
-
|
|
474
|
-
|
|
480
|
+
s.stop("Download complete");
|
|
481
|
+
if (hasExistingConfig) await updateConfigTokens(configPath, ds.tokens);
|
|
482
|
+
else await newConfigFile(configPath, ds.tokens);
|
|
483
|
+
} else startFromDS = false;
|
|
484
|
+
}
|
|
485
|
+
if (!hasExistingConfig) {
|
|
486
|
+
await newConfigFile(configPath, [EXAMPLE_TOKENS_PATH]);
|
|
487
|
+
await fs$1.writeFile(EXAMPLE_TOKENS_PATH, JSON.stringify(EXAMPLE_TOKENS, void 0, 2));
|
|
475
488
|
}
|
|
476
489
|
const existingPlugins = config.plugins.map((p) => p.name);
|
|
477
490
|
const pluginSelection = await multiselect({
|
|
@@ -500,7 +513,7 @@ async function initCmd({ logger }) {
|
|
|
500
513
|
if (newPlugins?.length) {
|
|
501
514
|
const plugins = newPlugins.map((p) => ({
|
|
502
515
|
specifier: p.replace("@terrazzo/plugin-", ""),
|
|
503
|
-
|
|
516
|
+
path: p
|
|
504
517
|
}));
|
|
505
518
|
const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, "plugin", "plugins")}`;
|
|
506
519
|
const s = spinner();
|
|
@@ -511,77 +524,27 @@ async function initCmd({ logger }) {
|
|
|
511
524
|
subprocess.on("exit", resolve);
|
|
512
525
|
});
|
|
513
526
|
s.message("Updating config");
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
attributes: []
|
|
531
|
-
})));
|
|
532
|
-
if (!astExport) {
|
|
533
|
-
logger.error({
|
|
534
|
-
group: "config",
|
|
535
|
-
message: `SyntaxError: ${relConfigPath} does not have default export.`
|
|
536
|
-
});
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
const astConfig = astExport.declaration.type === "CallExpression" ? astExport.declaration.arguments[0] : astExport.declaration;
|
|
540
|
-
if (astConfig.type !== "ObjectExpression") {
|
|
541
|
-
logger.error({
|
|
542
|
-
group: "config",
|
|
543
|
-
message: `Config: expected object default export, received ${astConfig.type}`
|
|
544
|
-
});
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
const pluginsArray = astConfig.properties.find((property) => property.type === "Property" && property.key.type === "Identifier" && property.key.name === "plugins")?.value;
|
|
548
|
-
const pluginsAst = plugins.map((p) => ({
|
|
549
|
-
type: "CallExpression",
|
|
550
|
-
callee: {
|
|
551
|
-
type: "Identifier",
|
|
552
|
-
name: p.specifier
|
|
553
|
-
},
|
|
554
|
-
arguments: [],
|
|
555
|
-
optional: false
|
|
556
|
-
}));
|
|
557
|
-
if (pluginsArray) pluginsArray.elements.push(...pluginsAst);
|
|
558
|
-
else astConfig.properties.push({
|
|
559
|
-
type: "Property",
|
|
560
|
-
key: {
|
|
561
|
-
type: "Identifier",
|
|
562
|
-
name: "plugins"
|
|
563
|
-
},
|
|
564
|
-
value: {
|
|
565
|
-
type: "ArrayExpression",
|
|
566
|
-
elements: pluginsAst
|
|
567
|
-
},
|
|
568
|
-
kind: "init",
|
|
569
|
-
computed: false,
|
|
570
|
-
method: false,
|
|
571
|
-
shorthand: false
|
|
572
|
-
});
|
|
573
|
-
fs.writeFileSync(configPath, generate(ast, { format: {
|
|
574
|
-
indent: { style: " " },
|
|
575
|
-
quotes: "single",
|
|
576
|
-
semicolons: true
|
|
577
|
-
} }));
|
|
578
|
-
} else fs.writeFileSync(DEFAULT_CONFIG_PATH, `import { defineConfig } from '@terrazzo/cli';
|
|
579
|
-
${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join("\n")}
|
|
527
|
+
await updateConfigPlugins(configPath, plugins);
|
|
528
|
+
s.stop(`Installed ${pluginCount}`);
|
|
529
|
+
}
|
|
530
|
+
if (!startFromDS && !newPlugins?.length) {
|
|
531
|
+
outro("Nothing to do. Exiting.");
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
outro("⛋ Done! 🎉");
|
|
535
|
+
} catch (err) {
|
|
536
|
+
printError(err.message);
|
|
537
|
+
process.exit(1);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
async function newConfigFile(configPath, tokens, imports = []) {
|
|
541
|
+
await fs$1.writeFile(configPath, `import { defineConfig } from '@terrazzo/cli';
|
|
542
|
+
${imports.map((p) => `import ${p.specifier} from '${p.path}';`).join("\n")}
|
|
580
543
|
|
|
581
544
|
export default defineConfig({
|
|
582
|
-
tokens: ['
|
|
545
|
+
tokens: ['${tokens.join("', '")}'],
|
|
583
546
|
plugins: [
|
|
584
|
-
${
|
|
547
|
+
${imports.length ? imports.map((p) => `${p.specifier}(),`).join("\n ") : "/** @see https://terrazzo.app/docs */"}
|
|
585
548
|
],
|
|
586
549
|
outDir: './dist/',
|
|
587
550
|
lint: {
|
|
@@ -610,14 +573,279 @@ export default defineConfig({
|
|
|
610
573
|
},
|
|
611
574
|
},
|
|
612
575
|
});`);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
576
|
+
}
|
|
577
|
+
function getConfigObjFromAst(ast, configPath) {
|
|
578
|
+
const astExport = ast.body.find((node) => node.type === "ExportDefaultDeclaration");
|
|
579
|
+
if (!astExport) {
|
|
580
|
+
const relConfigPath = configPath ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath))) : void 0;
|
|
581
|
+
throw new Error(`SyntaxError: ${relConfigPath} does not have default export.`);
|
|
619
582
|
}
|
|
583
|
+
const astConfig = astExport.declaration.type === "CallExpression" ? astExport.declaration.arguments[0] : astExport.declaration;
|
|
584
|
+
if (astConfig.type !== "ObjectExpression") throw new Error(`Config: expected object default export, received ${astConfig.type}.`);
|
|
585
|
+
return astConfig;
|
|
620
586
|
}
|
|
587
|
+
async function updateConfigTokens(configPath, tokens) {
|
|
588
|
+
const ast = parseModule(await fs$1.readFile(configPath, "utf8"));
|
|
589
|
+
const astConfig = getConfigObjFromAst(ast, configPath);
|
|
590
|
+
let tokensKey = astConfig.properties.find((p) => p.type === "Property" && p.key.type === "Identifier" && p.key.name === "tokens");
|
|
591
|
+
if (!tokensKey) {
|
|
592
|
+
tokensKey = {
|
|
593
|
+
type: "Property",
|
|
594
|
+
key: {
|
|
595
|
+
type: "Identifier",
|
|
596
|
+
name: "tokens"
|
|
597
|
+
},
|
|
598
|
+
method: false,
|
|
599
|
+
computed: false,
|
|
600
|
+
shorthand: false,
|
|
601
|
+
value: {
|
|
602
|
+
type: "ArrayExpression",
|
|
603
|
+
elements: tokens.map((value) => ({
|
|
604
|
+
type: "Literal",
|
|
605
|
+
value,
|
|
606
|
+
raw: `'${value}'`
|
|
607
|
+
}))
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
astConfig.properties.unshift(tokensKey);
|
|
611
|
+
}
|
|
612
|
+
await fs$1.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Add plugin imports
|
|
616
|
+
* note: this has the potential to duplicate plugins, but we tried our
|
|
617
|
+
* best to filter already, and this may be the user’s fault if they
|
|
618
|
+
* selected to install a plugin already installed. But also, this is
|
|
619
|
+
* easily-fixable, so let’s not waste too much time here (and possibly
|
|
620
|
+
* introduce bugs).
|
|
621
|
+
*/
|
|
622
|
+
async function updateConfigPlugins(configPath, plugins) {
|
|
623
|
+
const ast = parseModule(await fs$1.readFile(configPath, "utf8"));
|
|
624
|
+
ast.body.push(...plugins.map((p) => ({
|
|
625
|
+
type: "ImportDeclaration",
|
|
626
|
+
source: {
|
|
627
|
+
type: "Literal",
|
|
628
|
+
value: p.path
|
|
629
|
+
},
|
|
630
|
+
specifiers: [{
|
|
631
|
+
type: "ImportDefaultSpecifier",
|
|
632
|
+
local: {
|
|
633
|
+
type: "Identifier",
|
|
634
|
+
name: p.specifier
|
|
635
|
+
}
|
|
636
|
+
}],
|
|
637
|
+
attributes: []
|
|
638
|
+
})));
|
|
639
|
+
const astConfig = getConfigObjFromAst(ast, configPath);
|
|
640
|
+
const pluginsArray = astConfig.properties.find((property) => property.type === "Property" && property.key.type === "Identifier" && property.key.name === "plugins")?.value;
|
|
641
|
+
const pluginsAst = plugins.map((p) => ({
|
|
642
|
+
type: "CallExpression",
|
|
643
|
+
callee: {
|
|
644
|
+
type: "Identifier",
|
|
645
|
+
name: p.specifier
|
|
646
|
+
},
|
|
647
|
+
arguments: [],
|
|
648
|
+
optional: false
|
|
649
|
+
}));
|
|
650
|
+
if (pluginsArray) pluginsArray.elements.push(...pluginsAst);
|
|
651
|
+
else astConfig.properties.push({
|
|
652
|
+
type: "Property",
|
|
653
|
+
key: {
|
|
654
|
+
type: "Identifier",
|
|
655
|
+
name: "plugins"
|
|
656
|
+
},
|
|
657
|
+
value: {
|
|
658
|
+
type: "ArrayExpression",
|
|
659
|
+
elements: pluginsAst
|
|
660
|
+
},
|
|
661
|
+
kind: "init",
|
|
662
|
+
computed: false,
|
|
663
|
+
method: false,
|
|
664
|
+
shorthand: false
|
|
665
|
+
});
|
|
666
|
+
await fs$1.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));
|
|
667
|
+
}
|
|
668
|
+
const EXAMPLE_TOKENS = {
|
|
669
|
+
color: {
|
|
670
|
+
$description: "Color tokens",
|
|
671
|
+
black: {
|
|
672
|
+
"100": {
|
|
673
|
+
$type: "color",
|
|
674
|
+
$value: {
|
|
675
|
+
colorSpace: "srgb",
|
|
676
|
+
components: [
|
|
677
|
+
.047,
|
|
678
|
+
.047,
|
|
679
|
+
.047
|
|
680
|
+
],
|
|
681
|
+
alpha: .05,
|
|
682
|
+
hex: "#0c0c0d"
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
"200": {
|
|
686
|
+
$type: "color",
|
|
687
|
+
$value: {
|
|
688
|
+
colorSpace: "srgb",
|
|
689
|
+
components: [
|
|
690
|
+
.047,
|
|
691
|
+
.047,
|
|
692
|
+
.047
|
|
693
|
+
],
|
|
694
|
+
alpha: .1,
|
|
695
|
+
hex: "#0c0c0d"
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
"300": {
|
|
699
|
+
$type: "color",
|
|
700
|
+
$value: {
|
|
701
|
+
colorSpace: "srgb",
|
|
702
|
+
components: [
|
|
703
|
+
.047,
|
|
704
|
+
.047,
|
|
705
|
+
.047
|
|
706
|
+
],
|
|
707
|
+
alpha: .2,
|
|
708
|
+
hex: "#0c0c0d"
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
"400": {
|
|
712
|
+
$type: "color",
|
|
713
|
+
$value: {
|
|
714
|
+
colorSpace: "srgb",
|
|
715
|
+
components: [
|
|
716
|
+
.047,
|
|
717
|
+
.047,
|
|
718
|
+
.047
|
|
719
|
+
],
|
|
720
|
+
alpha: .34,
|
|
721
|
+
hex: "#0c0c04"
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
"500": {
|
|
725
|
+
$type: "color",
|
|
726
|
+
$value: {
|
|
727
|
+
colorSpace: "srgb",
|
|
728
|
+
components: [
|
|
729
|
+
.047,
|
|
730
|
+
.047,
|
|
731
|
+
.047
|
|
732
|
+
],
|
|
733
|
+
alpha: .7,
|
|
734
|
+
hex: "#0c0c0d"
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
"600": {
|
|
738
|
+
$type: "color",
|
|
739
|
+
$value: {
|
|
740
|
+
colorSpace: "srgb",
|
|
741
|
+
components: [
|
|
742
|
+
.047,
|
|
743
|
+
.047,
|
|
744
|
+
.047
|
|
745
|
+
],
|
|
746
|
+
alpha: .8,
|
|
747
|
+
hex: "#0c0c0d"
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
"700": {
|
|
751
|
+
$type: "color",
|
|
752
|
+
$value: {
|
|
753
|
+
colorSpace: "srgb",
|
|
754
|
+
components: [
|
|
755
|
+
.047,
|
|
756
|
+
.047,
|
|
757
|
+
.047
|
|
758
|
+
],
|
|
759
|
+
alpha: .85,
|
|
760
|
+
hex: "#0c0c0d"
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
"800": {
|
|
764
|
+
$type: "color",
|
|
765
|
+
$value: {
|
|
766
|
+
colorSpace: "srgb",
|
|
767
|
+
components: [
|
|
768
|
+
.047,
|
|
769
|
+
.047,
|
|
770
|
+
.047
|
|
771
|
+
],
|
|
772
|
+
alpha: .9,
|
|
773
|
+
hex: "#0c0c0d"
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
"900": {
|
|
777
|
+
$type: "color",
|
|
778
|
+
$value: {
|
|
779
|
+
colorSpace: "srgb",
|
|
780
|
+
components: [
|
|
781
|
+
.047,
|
|
782
|
+
.047,
|
|
783
|
+
.047
|
|
784
|
+
],
|
|
785
|
+
alpha: .95,
|
|
786
|
+
hex: "#0c0c0d"
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
"1000": {
|
|
790
|
+
$type: "color",
|
|
791
|
+
$value: {
|
|
792
|
+
colorSpace: "srgb",
|
|
793
|
+
components: [
|
|
794
|
+
.047,
|
|
795
|
+
.047,
|
|
796
|
+
.047
|
|
797
|
+
],
|
|
798
|
+
alpha: 0,
|
|
799
|
+
hex: "#0c0c0d"
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
border: {
|
|
805
|
+
$description: "Border tokens",
|
|
806
|
+
default: {
|
|
807
|
+
type: "border",
|
|
808
|
+
$value: {
|
|
809
|
+
color: "{color.black.900}",
|
|
810
|
+
style: "solid",
|
|
811
|
+
width: {
|
|
812
|
+
value: 1,
|
|
813
|
+
unit: "px"
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
radius: {
|
|
819
|
+
$description: "Corner radius tokens",
|
|
820
|
+
"100": { $value: {
|
|
821
|
+
value: .25,
|
|
822
|
+
unit: "rem"
|
|
823
|
+
} }
|
|
824
|
+
},
|
|
825
|
+
space: {
|
|
826
|
+
$description: "Dimension tokens",
|
|
827
|
+
"100": { $value: {
|
|
828
|
+
value: .25,
|
|
829
|
+
unit: "rem"
|
|
830
|
+
} }
|
|
831
|
+
},
|
|
832
|
+
typography: {
|
|
833
|
+
$description: "Typography tokens",
|
|
834
|
+
body: {
|
|
835
|
+
$type: "typography",
|
|
836
|
+
$value: {
|
|
837
|
+
fontFamily: "{typography.family.sans}",
|
|
838
|
+
fontSize: "{typography.scale.03}",
|
|
839
|
+
fontWeight: "{typography.weight.regular}",
|
|
840
|
+
letterSpacing: {
|
|
841
|
+
value: 0,
|
|
842
|
+
unit: "em"
|
|
843
|
+
},
|
|
844
|
+
lineHeight: 1
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
};
|
|
621
849
|
|
|
622
850
|
//#endregion
|
|
623
851
|
//#region src/lab.ts
|
|
@@ -625,7 +853,7 @@ async function labCmd({ config, logger }) {
|
|
|
625
853
|
/** TODO: handle multiple files */
|
|
626
854
|
const [tokenFileUrl] = config.tokens;
|
|
627
855
|
const staticFiles = /* @__PURE__ */ new Set();
|
|
628
|
-
const dirEntries = await readdir(fileURLToPath(import.meta.resolve("./lab")), {
|
|
856
|
+
const dirEntries = await fs$1.readdir(fileURLToPath(import.meta.resolve("./lab")), {
|
|
629
857
|
withFileTypes: true,
|
|
630
858
|
recursive: true
|
|
631
859
|
});
|
|
@@ -639,18 +867,18 @@ async function labCmd({ config, logger }) {
|
|
|
639
867
|
overrideGlobalObjects: false,
|
|
640
868
|
async fetch(request) {
|
|
641
869
|
const pathname = new URL(request.url).pathname;
|
|
642
|
-
if (pathname === "/") return new Response(Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve("./lab/index.html")))), { headers: { "Content-Type": "text/html" } });
|
|
870
|
+
if (pathname === "/") return new Response(Readable.toWeb(fs.createReadStream(fileURLToPath(import.meta.resolve("./lab/index.html")))), { headers: { "Content-Type": "text/html" } });
|
|
643
871
|
if (pathname === "/api/tokens") {
|
|
644
|
-
if (request.method === "GET") return new Response(Readable.toWeb(createReadStream(tokenFileUrl)), { headers: {
|
|
872
|
+
if (request.method === "GET") return new Response(Readable.toWeb(fs.createReadStream(tokenFileUrl)), { headers: {
|
|
645
873
|
"Content-Type": "application/json",
|
|
646
874
|
"Cache-Control": "no-cache"
|
|
647
875
|
} });
|
|
648
876
|
else if (request.method === "POST" && request.body) {
|
|
649
|
-
await request.body.pipeTo(Writable.toWeb(createWriteStream(tokenFileUrl)));
|
|
877
|
+
await request.body.pipeTo(Writable.toWeb(fs.createWriteStream(tokenFileUrl)));
|
|
650
878
|
return new Response(JSON.stringify({ success: true }), { headers: { "Content-Type": "application/json" } });
|
|
651
879
|
}
|
|
652
880
|
}
|
|
653
|
-
if (staticFiles.has(pathname)) return new Response(Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))), { headers: { "Content-Type": mime.getType(pathname) ?? "application/octet-stream" } });
|
|
881
|
+
if (staticFiles.has(pathname)) return new Response(Readable.toWeb(fs.createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))), { headers: { "Content-Type": mime.getType(pathname) ?? "application/octet-stream" } });
|
|
654
882
|
return new Response("Not found", { status: 404 });
|
|
655
883
|
}
|
|
656
884
|
}, (info) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["defineConfig","defineConfig","defineConfigCore"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\nimport { createServer, type ViteDevServer } from 'vite';\nimport { ViteNodeRunner } from 'vite-node/client';\nimport { ViteNodeServer } from 'vite-node/server';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.ts', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n /**\n * Vite server for loading .ts config files\n * TODO: remove me when Node 24 is the oldest-supported Node version\n */\n let viteServer: ViteDevServer | undefined;\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: {\n build: { enabled: true },\n rules: {},\n },\n alphabetize: false,\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n if (!configPath) {\n logger.error({ group: 'config', message: `Could not locate ${flags.config}` });\n }\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n // Note: we create a vite-node instance only when resolving the config,\n // because in most scenarios we only ever need this once and never again.\n // even in watch mode we don’t reload the config, so keeping a vite-node\n // “hot” instance doesn’t provide obvious benefits (only potential memory leaks)\n viteServer = await createServer({ mode: 'development' });\n const viteNodeServer = new ViteNodeServer(viteServer);\n const viteNodeRunner = new ViteNodeRunner({\n root: viteServer.config.root,\n base: viteServer.config.base,\n fetchModule(...args) {\n return viteNodeServer.fetchModule(...args);\n },\n resolveId(...args) {\n return viteNodeServer.resolveId(...args);\n },\n });\n const mod = await viteNodeRunner.executeFile(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${resolvedConfigPath.replace(fileURLToPath(cwd), '')}. See https://terrazzo.dev/docs for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n // clean up\n if (viteServer) {\n await viteServer?.close();\n }\n\n return {\n config,\n configPath: resolvedConfigPath!,\n };\n } catch (err) {\n printError((err as Error).message);\n\n // clean up\n if (viteServer) {\n await viteServer.close();\n }\n\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string): string | undefined {\n // --config [configpath]\n if (filename && fs.existsSync(new URL(filename, cwd))) {\n return filename;\n }\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple config files with different extensions that’s their fault\n for (const ext of ['.ts', '.js', '.mts', '.cts', '.mjs', '.cjs']) {\n const maybeFilename = `terrazzo.config${ext}`;\n if (fs.existsSync(new URL(maybeFilename, cwd))) {\n return fileURLToPath(new URL(maybeFilename, cwd));\n }\n }\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.ts'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, resolver, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { resolver, sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n resolver = parseResult.resolver;\n result = await build(tokens, { resolver, sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.ts)\n --quiet Suppress warnings\n`);\n}\n","import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, DEFAULT_CONFIG_PATH, DEFAULT_TOKENS_PATH, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'shopify-polaris';\n\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['dtcg-examples/adobe-spectrum.resolver.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['dtcg-examples/apple-hig.resolver.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['dtcg-examples/figma-sds.resolver.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['dtcg-examples/github-primer.resolver.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['dtcg-examples/ibm-carbon.resolver.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['dtcg-examples/microsoft-fluent.resolver.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['dtcg-examples/shopify-polaris.resolver.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n\n let tokensPath = config.tokens[0]!;\n let startFromDS = !(tokensPath && fs.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fs.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n } else {\n tokensPath = DEFAULT_TOKENS_PATH;\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n if (ds) {\n const s = spinner();\n s.start('Downloading');\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], 'dtcg-examples'], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n await s.stop('Download complete');\n }\n }\n\n // 2. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), package: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: thi sis async to show the spinner\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], newPlugins.join(' ')], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n if (configPath) {\n const ast = parseModule(fs.readFileSync(configPath, 'utf8'));\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n\n // 2a. add plugin imports\n // note: this has the potential to duplicate plugins, but we tried our\n // best to filter already, and this may be the user’s fault if they\n // selected to install a plugin already installed. But also, this is\n // easily-fixable, so let’s not waste too much time here (and possibly\n // introduce bugs).\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration',\n source: { type: 'Literal', value: p.package },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // 2b. add plugins to config.plugins\n if (!astExport) {\n logger.error({ group: 'config', message: `SyntaxError: ${relConfigPath} does not have default export.` });\n return;\n }\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n if (astConfig.type !== 'ObjectExpression') {\n logger.error({\n group: 'config',\n message: `Config: expected object default export, received ${astConfig.type}`,\n });\n return;\n }\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression' as const,\n callee: {\n type: 'Identifier' as const,\n name: p.specifier,\n },\n arguments: [],\n optional: false,\n }) as ESTree.CallExpression,\n );\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n // 2c. update new file (and we’ll probably format it wrong but hey)\n fs.writeFileSync(\n configPath,\n generate(ast, {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n }),\n );\n } else {\n // 2a. write new config file (easy)\n fs.writeFileSync(\n DEFAULT_CONFIG_PATH,\n `import { defineConfig } from '@terrazzo/cli';\n${plugins.map((p) => `import ${p.specifier} from '${p.package}';`).join('\\n')}\n\nexport default defineConfig({\n tokens: ['./tokens.json'],\n plugins: [\n ${plugins.map((p) => `${p.specifier}(),`).join('\\n ')}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/linting */\n build: {\n enabled: true,\n },\n rules: {\n 'core/valid-color': 'error',\n 'core/valid-dimension': 'error',\n 'core/valid-font-family': 'error',\n 'core/valid-font-weight': 'error',\n 'core/valid-duration': 'error',\n 'core/valid-cubic-bezier': 'error',\n 'core/valid-number': 'error',\n 'core/valid-link': 'error',\n 'core/valid-boolean': 'error',\n 'core/valid-string': 'error',\n 'core/valid-stroke-style': 'error',\n 'core/valid-border': 'error',\n 'core/valid-transition': 'error',\n 'core/valid-shadow': 'error',\n 'core/valid-gradient': 'error',\n 'core/valid-typography': 'error',\n 'core/consistent-naming': 'warn',\n },\n },\n});`,\n );\n }\n s.stop(`Installed ${pluginCount}`);\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","import { createReadStream, createWriteStream, type PathLike } from 'node:fs';\nimport { readdir } from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html')))) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(Readable.toWeb(createReadStream(tokenFileUrl as PathLike)) as ReadableStream, {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n });\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(createWriteStream(tokenFileUrl as PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`)))) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport * as momoa from '@humanwhocodes/momoa';\nimport { getObjMember, getObjMembers, traverse } from '@terrazzo/json-schema-tools';\nimport { defineConfig, type Logger, parse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: momoa.MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = momoa.parse(sourceData, { mode: 'jsonc' });\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig(\n {\n lint: {\n rules: {\n 'core/valid-color': 'off',\n 'core/valid-dimension': 'off',\n 'core/valid-duration': 'off',\n 'core/valid-typography': 'off',\n },\n },\n },\n { cwd },\n ),\n logger,\n });\n\n traverse(document, {\n enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n const hex = (node.value.members[$valueI]!.value as momoa.StringNode).value;\n node.value.members[$valueI]!.value = momoa.parse(\n JSON.stringify({\n ...token.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as momoa.StringNode).value;\n const hex = (mode.members[i]!.value as momoa.StringNode).value;\n mode.members[i]!.value = momoa.parse(\n JSON.stringify({\n ...token.mode[modeName]!.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n }\n }\n }\n }\n break;\n }\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n node.value.members[$valueI]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n }\n }\n }\n }\n break;\n }\n case 'typography': {\n if (node.value.members[$valueI]?.value.type !== 'Object') {\n return;\n }\n node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeTypography(mode.members[i]!.value as momoa.ObjectNode);\n }\n }\n }\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nfunction normalizeDurationDimension(node: momoa.StringNode) {\n const value = Number.parseFloat(node.value);\n if (!Number.isFinite(value)) {\n return node;\n }\n (node as any).type = 'Object';\n (node as any).members = (\n momoa.parse(JSON.stringify({ value, unit: node.value.replace(String(value), '') })).body as momoa.ObjectNode\n ).members;\n delete (node as any).value;\n return node;\n}\n\nfunction normalizeTypography(node: momoa.ObjectNode) {\n const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);\n if (!fontFamily) {\n node.members.push((momoa.parse('{\"fontFamily\":[\"inherit\"]}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontSize) {\n node.members.push((momoa.parse('{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontWeight) {\n node.members.push((momoa.parse('{\"fontWeight\":400}').body as momoa.ObjectNode).members[0]!);\n }\n if (!letterSpacing) {\n node.members.push((momoa.parse('{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!lineHeight) {\n node.members.push((momoa.parse('{\"lineHeight\":1}').body as momoa.ObjectNode).members[0]!);\n }\n return node;\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["defineConfig","fsSync","fs","fs","fsSync","defineConfig","defineConfigCore"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\nimport { createServer, type ViteDevServer } from 'vite';\nimport { ViteNodeRunner } from 'vite-node/client';\nimport { ViteNodeServer } from 'vite-node/server';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.ts', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n /**\n * Vite server for loading .ts config files\n * TODO: remove me when Node 24 is the oldest-supported Node version\n */\n let viteServer: ViteDevServer | undefined;\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: {\n build: { enabled: true },\n rules: {},\n },\n alphabetize: false,\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n if (!configPath) {\n logger.error({ group: 'config', message: `Could not locate ${flags.config}` });\n }\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n // Note: we create a vite-node instance only when resolving the config,\n // because in most scenarios we only ever need this once and never again.\n // even in watch mode we don’t reload the config, so keeping a vite-node\n // “hot” instance doesn’t provide obvious benefits (only potential memory leaks)\n viteServer = await createServer({ mode: 'development' });\n const viteNodeServer = new ViteNodeServer(viteServer);\n const viteNodeRunner = new ViteNodeRunner({\n root: viteServer.config.root,\n base: viteServer.config.base,\n fetchModule(...args) {\n return viteNodeServer.fetchModule(...args);\n },\n resolveId(...args) {\n return viteNodeServer.resolveId(...args);\n },\n });\n const mod = await viteNodeRunner.executeFile(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${resolvedConfigPath.replace(fileURLToPath(cwd), '')}. See https://terrazzo.dev/docs for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n // clean up\n if (viteServer) {\n await viteServer?.close();\n }\n\n return {\n config,\n configPath: resolvedConfigPath,\n };\n } catch (err) {\n printError((err as Error).message);\n\n // clean up\n if (viteServer) {\n await viteServer.close();\n }\n\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string): string | undefined {\n // --config [configpath]\n if (filename && fs.existsSync(new URL(filename, cwd))) {\n return filename;\n }\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple config files with different extensions that’s their fault\n for (const ext of ['.ts', '.js', '.mts', '.cts', '.mjs', '.cjs']) {\n const maybeFilename = `terrazzo.config${ext}`;\n if (fs.existsSync(new URL(maybeFilename, cwd))) {\n return fileURLToPath(new URL(maybeFilename, cwd));\n }\n }\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.ts'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, resolver, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { resolver, sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n resolver = parseResult.resolver;\n result = await build(tokens, { resolver, sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.ts)\n --quiet Suppress warnings\n`);\n}\n","import { spawn } from 'node:child_process';\nimport fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\nconst SYNTAX_SETTINGS = {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n};\n\nconst EXAMPLE_TOKENS_PATH = 'my-tokens.tokens.json';\n\ninterface ImportSpec {\n specifier: string;\n path: string;\n}\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'shopify-polaris';\n\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['dtcg-examples/adobe-spectrum.resolver.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['dtcg-examples/apple-hig.resolver.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['dtcg-examples/figma-sds.resolver.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['dtcg-examples/github-primer.resolver.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['dtcg-examples/ibm-carbon.resolver.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['dtcg-examples/microsoft-fluent.resolver.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['dtcg-examples/shopify-polaris.resolver.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath = 'terrazzo.config.ts' } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const tokensPath = config.tokens[0]!;\n const hasExistingConfig = fsSync.existsSync(configPath);\n let startFromDS = !(tokensPath && fsSync.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fsSync.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n\n if (ds) {\n const s = spinner();\n s.start('Downloading');\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], 'dtcg-examples'], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.stop('Download complete');\n\n if (hasExistingConfig) {\n await updateConfigTokens(configPath, ds.tokens);\n } else {\n await newConfigFile(configPath, ds.tokens);\n }\n } else {\n startFromDS = false; // we’ll use this later in the final check\n }\n }\n\n // 2. If a user selected no DS, and doesn’t have a config file, create one\n if (!hasExistingConfig) {\n await newConfigFile(configPath, [EXAMPLE_TOKENS_PATH]);\n await fs.writeFile(EXAMPLE_TOKENS_PATH, JSON.stringify(EXAMPLE_TOKENS, undefined, 2));\n }\n\n // 3. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins: ImportSpec[] = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), path: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: this is async to show the spinner\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], newPlugins.join(' ')], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n\n await updateConfigPlugins(configPath, plugins);\n\n s.stop(`Installed ${pluginCount}`);\n }\n\n // 4. No tokens, no plugins\n if (!startFromDS && !newPlugins?.length) {\n outro('Nothing to do. Exiting.');\n return;\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nasync function newConfigFile(configPath: string, tokens: string[], imports: ImportSpec[] = []) {\n await fs.writeFile(\n configPath,\n `import { defineConfig } from '@terrazzo/cli';\n${imports.map((p) => `import ${p.specifier} from '${p.path}';`).join('\\n')}\n\nexport default defineConfig({\n tokens: ['${tokens.join(\"', '\")}'],\n plugins: [\n ${imports.length ? imports.map((p) => `${p.specifier}(),`).join('\\n ') : '/** @see https://terrazzo.app/docs */'}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/linting */\n build: {\n enabled: true,\n },\n rules: {\n 'core/valid-color': 'error',\n 'core/valid-dimension': 'error',\n 'core/valid-font-family': 'error',\n 'core/valid-font-weight': 'error',\n 'core/valid-duration': 'error',\n 'core/valid-cubic-bezier': 'error',\n 'core/valid-number': 'error',\n 'core/valid-link': 'error',\n 'core/valid-boolean': 'error',\n 'core/valid-string': 'error',\n 'core/valid-stroke-style': 'error',\n 'core/valid-border': 'error',\n 'core/valid-transition': 'error',\n 'core/valid-shadow': 'error',\n 'core/valid-gradient': 'error',\n 'core/valid-typography': 'error',\n 'core/consistent-naming': 'warn',\n },\n },\n});`,\n );\n}\n\nfunction getConfigObjFromAst(ast: ESTree.Program, configPath: string) {\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n if (!astExport) {\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n throw new Error(`SyntaxError: ${relConfigPath} does not have default export.`);\n }\n\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n\n if (astConfig.type !== 'ObjectExpression') {\n throw new Error(`Config: expected object default export, received ${astConfig.type}.`);\n }\n\n return astConfig;\n}\n\nasync function updateConfigTokens(configPath: string, tokens: string[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n const astConfig = getConfigObjFromAst(ast, configPath);\n\n let tokensKey = astConfig.properties.find(\n (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'tokens',\n ) as ESTree.Property | undefined;\n if (!tokensKey) {\n tokensKey = {\n type: 'Property' as const,\n key: { type: 'Identifier', name: 'tokens' },\n method: false,\n computed: false,\n shorthand: false,\n value: {\n type: 'ArrayExpression',\n elements: tokens.map((value) => ({ type: 'Literal', value, raw: `'${value}'` })),\n },\n } as ESTree.Property;\n astConfig.properties.unshift(tokensKey); // inject into first position\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\n/**\n * Add plugin imports\n * note: this has the potential to duplicate plugins, but we tried our\n * best to filter already, and this may be the user’s fault if they\n * selected to install a plugin already installed. But also, this is\n * easily-fixable, so let’s not waste too much time here (and possibly\n * introduce bugs).\n */\nasync function updateConfigPlugins(configPath: string, plugins: ImportSpec[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration' as const,\n source: { type: 'Literal', value: p.path },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // add plugins to config.plugins\n const astConfig = getConfigObjFromAst(ast, configPath);\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression' as const,\n callee: { type: 'Identifier' as const, name: p.specifier },\n arguments: [],\n optional: false,\n }) as ESTree.CallExpression,\n );\n\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\nconst EXAMPLE_TOKENS = {\n color: {\n $description: 'Color tokens',\n black: {\n '100': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.05, hex: '#0c0c0d' },\n },\n '200': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.1, hex: '#0c0c0d' },\n },\n '300': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.2, hex: '#0c0c0d' },\n },\n '400': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.34, hex: '#0c0c04' },\n },\n '500': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.7, hex: '#0c0c0d' },\n },\n '600': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.8, hex: '#0c0c0d' },\n },\n '700': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.85, hex: '#0c0c0d' },\n },\n '800': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.9, hex: '#0c0c0d' },\n },\n '900': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.95, hex: '#0c0c0d' },\n },\n '1000': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0, hex: '#0c0c0d' },\n },\n },\n },\n border: {\n $description: 'Border tokens',\n default: {\n type: 'border',\n $value: {\n color: '{color.black.900}',\n style: 'solid',\n width: { value: 1, unit: 'px' },\n },\n },\n },\n radius: {\n $description: 'Corner radius tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n space: {\n $description: 'Dimension tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n typography: {\n $description: 'Typography tokens',\n body: {\n $type: 'typography',\n $value: {\n fontFamily: '{typography.family.sans}',\n fontSize: '{typography.scale.03}',\n fontWeight: '{typography.weight.regular}',\n letterSpacing: { value: 0, unit: 'em' },\n lineHeight: 1,\n },\n },\n },\n};\n","import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await fs.readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html'))),\n ) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(\n Readable.toWeb(fsSync.createReadStream(tokenFileUrl as fsSync.PathLike)) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n },\n );\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(fsSync.createWriteStream(tokenFileUrl as fsSync.PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`))),\n ) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport * as momoa from '@humanwhocodes/momoa';\nimport { getObjMember, getObjMembers, traverse } from '@terrazzo/json-schema-tools';\nimport { defineConfig, type Logger, parse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: momoa.MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = momoa.parse(sourceData, { mode: 'jsonc' });\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig(\n {\n lint: {\n rules: {\n 'core/valid-color': 'off',\n 'core/valid-dimension': 'off',\n 'core/valid-duration': 'off',\n 'core/valid-typography': 'off',\n },\n },\n },\n { cwd },\n ),\n logger,\n });\n\n traverse(document, {\n enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n const hex = (node.value.members[$valueI]!.value as momoa.StringNode).value;\n node.value.members[$valueI]!.value = momoa.parse(\n JSON.stringify({\n ...token.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as momoa.StringNode).value;\n const hex = (mode.members[i]!.value as momoa.StringNode).value;\n mode.members[i]!.value = momoa.parse(\n JSON.stringify({\n ...token.mode[modeName]!.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n }\n }\n }\n }\n break;\n }\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n node.value.members[$valueI]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n }\n }\n }\n }\n break;\n }\n case 'typography': {\n if (node.value.members[$valueI]?.value.type !== 'Object') {\n return;\n }\n node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeTypography(mode.members[i]!.value as momoa.ObjectNode);\n }\n }\n }\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nfunction normalizeDurationDimension(node: momoa.StringNode) {\n const value = Number.parseFloat(node.value);\n if (!Number.isFinite(value)) {\n return node;\n }\n (node as any).type = 'Object';\n (node as any).members = (\n momoa.parse(JSON.stringify({ value, unit: node.value.replace(String(value), '') })).body as momoa.ObjectNode\n ).members;\n delete (node as any).value;\n return node;\n}\n\nfunction normalizeTypography(node: momoa.ObjectNode) {\n const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);\n if (!fontFamily) {\n node.members.push((momoa.parse('{\"fontFamily\":[\"inherit\"]}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontSize) {\n node.members.push((momoa.parse('{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontWeight) {\n node.members.push((momoa.parse('{\"fontWeight\":400}').body as momoa.ObjectNode).members[0]!);\n }\n if (!letterSpacing) {\n node.members.push((momoa.parse('{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!lineHeight) {\n node.members.push((momoa.parse('{\"lineHeight\":1}').body as momoa.ObjectNode).members[0]!);\n }\n return node;\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrazzo/cli",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.3",
|
|
4
4
|
"description": "CLI for managing design tokens using the Design Tokens Community Group (DTCG) standard and generating code for any platform via plugins.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"terrazzo": "bin/cli.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@clack/prompts": "^0.
|
|
39
|
+
"@clack/prompts": "^1.0.0",
|
|
40
40
|
"@hono/node-server": "^1.19.9",
|
|
41
41
|
"@humanwhocodes/momoa": "^3.3.10",
|
|
42
42
|
"@types/escodegen": "^0.0.10",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"vite-node": "^5.3.0",
|
|
54
54
|
"yaml-to-momoa": "0.0.8",
|
|
55
55
|
"@terrazzo/json-schema-tools": "^0.2.0",
|
|
56
|
-
"@terrazzo/parser": "^2.0.0-beta.
|
|
57
|
-
"@terrazzo/token-tools": "^2.0.0-beta.
|
|
56
|
+
"@terrazzo/parser": "^2.0.0-beta.3",
|
|
57
|
+
"@terrazzo/token-tools": "^2.0.0-beta.3"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@swc/core": "1.13.19",
|
package/terrazzo.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from '@terrazzo/cli';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
tokens: ['tokens-example.json'],
|
|
5
|
-
outDir: './tokens/',
|
|
6
|
-
plugins: [
|
|
7
|
-
/** @see https://terrazzo.app/docs/integrations */
|
|
8
|
-
],
|
|
9
|
-
lint: {
|
|
10
|
-
/** @see https://terrazzo.app/docs/linting */
|
|
11
|
-
},
|
|
12
|
-
});
|
package/tokens-example.json
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"color": {
|
|
3
|
-
"$description": "Color tokens",
|
|
4
|
-
"$type": "color",
|
|
5
|
-
"black": {
|
|
6
|
-
"100": {
|
|
7
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.05, "hex": "#0c0c0d" }
|
|
8
|
-
},
|
|
9
|
-
"200": {
|
|
10
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.1, "hex": "#0c0c0d" }
|
|
11
|
-
},
|
|
12
|
-
"300": {
|
|
13
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.2, "hex": "#0c0c0d" }
|
|
14
|
-
},
|
|
15
|
-
"400": {
|
|
16
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.34, "hex": "#0c0c04" }
|
|
17
|
-
},
|
|
18
|
-
"500": {
|
|
19
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.7, "hex": "#0c0c0d" }
|
|
20
|
-
},
|
|
21
|
-
"600": {
|
|
22
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.8, "hex": "#0c0c0d" }
|
|
23
|
-
},
|
|
24
|
-
"700": {
|
|
25
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.85, "hex": "#0c0c0d" }
|
|
26
|
-
},
|
|
27
|
-
"800": {
|
|
28
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.9, "hex": "#0c0c0d" }
|
|
29
|
-
},
|
|
30
|
-
"900": {
|
|
31
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0.95, "hex": "#0c0c0d" }
|
|
32
|
-
},
|
|
33
|
-
"1000": {
|
|
34
|
-
"$value": { "colorSpace": "srgb", "components": [0.047, 0.047, 0.047], "alpha": 0, "hex": "#0c0c0d" }
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
"border": {
|
|
39
|
-
"$description": "Border tokens",
|
|
40
|
-
"$type": "border"
|
|
41
|
-
},
|
|
42
|
-
"space": {
|
|
43
|
-
"$description": "Dimension tokens",
|
|
44
|
-
"$type": "dimension"
|
|
45
|
-
},
|
|
46
|
-
"typography": {
|
|
47
|
-
"$description": "Typography tokens",
|
|
48
|
-
"$type": "typography"
|
|
49
|
-
}
|
|
50
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import react from '@vitejs/plugin-react-swc';
|
|
2
|
-
import { defineConfig } from 'vitest/config';
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
plugins: [react({ devTarget: 'esnext' })],
|
|
6
|
-
build: {
|
|
7
|
-
outDir: 'dist/lab',
|
|
8
|
-
rollupOptions: {
|
|
9
|
-
external: ['@terrazzo/tiles', '@terrazzo/token-lab'],
|
|
10
|
-
},
|
|
11
|
-
emptyOutDir: true,
|
|
12
|
-
sourcemap: true,
|
|
13
|
-
target: 'es2024',
|
|
14
|
-
},
|
|
15
|
-
test: {
|
|
16
|
-
testTimeout: 15_000,
|
|
17
|
-
},
|
|
18
|
-
});
|