@digdir/designsystemet 1.12.1 → 1.13.1
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/bin/config.d.ts +4 -4
- package/dist/bin/config.d.ts.map +1 -1
- package/dist/bin/config.js +133 -28
- package/dist/bin/designsystemet.d.ts.map +1 -1
- package/dist/bin/designsystemet.js +279 -238
- package/dist/src/config.d.ts +2 -2
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +4 -4
- package/dist/src/index.js +5 -5
- package/dist/src/migrations/beta-to-v1.js +122 -16
- package/dist/src/migrations/codemods/css/run.d.ts.map +1 -1
- package/dist/src/migrations/codemods/css/run.js +122 -16
- package/dist/src/migrations/color-rename-next49.js +122 -16
- package/dist/src/migrations/index.js +122 -16
- package/dist/src/scripts/update-preview-tokens.d.ts.map +1 -1
- package/dist/src/scripts/update-preview-tokens.js +122 -45
- package/dist/src/tokens/build.d.ts +2 -1
- package/dist/src/tokens/build.d.ts.map +1 -1
- package/dist/src/tokens/build.js +128 -62
- package/dist/src/tokens/create/files.d.ts +11 -0
- package/dist/src/tokens/create/files.d.ts.map +1 -0
- package/dist/src/tokens/create/{write.js → files.js} +143 -83
- package/dist/src/tokens/create/generators/$designsystemet.js +5 -5
- package/dist/src/tokens/format.js +5 -5
- package/dist/src/tokens/generate-config.d.ts +0 -1
- package/dist/src/tokens/generate-config.d.ts.map +1 -1
- package/dist/src/tokens/generate-config.js +145 -26
- package/dist/src/tokens/index.js +5 -5
- package/dist/src/tokens/process/output/declarations.js +5 -5
- package/dist/src/tokens/process/output/theme.js +5 -5
- package/dist/src/tokens/process/platform.d.ts +0 -4
- package/dist/src/tokens/process/platform.d.ts.map +1 -1
- package/dist/src/tokens/types.d.ts +2 -0
- package/dist/src/tokens/types.d.ts.map +1 -1
- package/dist/src/utils/filesystem.d.ts +40 -0
- package/dist/src/utils/filesystem.d.ts.map +1 -0
- package/dist/src/utils/filesystem.js +127 -0
- package/package.json +6 -6
- package/dist/src/tokens/create/write.d.ts +0 -12
- package/dist/src/tokens/create/write.d.ts.map +0 -1
- package/dist/src/utils.d.ts +0 -18
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/utils.js +0 -70
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// bin/designsystemet.ts
|
|
4
|
+
import path4 from "path";
|
|
4
5
|
import { Argument, createCommand, program } from "@commander-js/extra-typings";
|
|
5
|
-
import
|
|
6
|
-
import * as
|
|
6
|
+
import pc11 from "picocolors";
|
|
7
|
+
import * as R28 from "ramda";
|
|
7
8
|
|
|
8
9
|
// src/colors/colorMetadata.ts
|
|
9
10
|
import * as R from "ramda";
|
|
@@ -392,7 +393,7 @@ var cssClassRename = (dictionary) => ({
|
|
|
392
393
|
var cssVarRename = (dictionary) => ({
|
|
393
394
|
postcssPlugin: `Replaces CSS variables ${hash(dictionary)}`,
|
|
394
395
|
Declaration(decl) {
|
|
395
|
-
const { value, prop:
|
|
396
|
+
const { value, prop: prop3 } = decl;
|
|
396
397
|
const deleted = /* @__PURE__ */ new Set();
|
|
397
398
|
for (const [from, to] of Object.entries(dictionary)) {
|
|
398
399
|
if (R4.isNotEmpty(to)) {
|
|
@@ -403,8 +404,8 @@ var cssVarRename = (dictionary) => ({
|
|
|
403
404
|
decl.value = value.replace(from, to);
|
|
404
405
|
continue;
|
|
405
406
|
}
|
|
406
|
-
if (R4.includes(from,
|
|
407
|
-
decl.prop =
|
|
407
|
+
if (R4.includes(from, prop3) && decl.variable) {
|
|
408
|
+
decl.prop = prop3.replace(from, to);
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
411
|
}
|
|
@@ -415,58 +416,133 @@ var cssVarRename = (dictionary) => ({
|
|
|
415
416
|
});
|
|
416
417
|
|
|
417
418
|
// src/migrations/codemods/css/run.ts
|
|
418
|
-
import fs2 from "fs";
|
|
419
419
|
import glob from "fast-glob";
|
|
420
420
|
import postcss from "postcss";
|
|
421
421
|
|
|
422
|
-
// src/utils.ts
|
|
422
|
+
// src/utils/filesystem.ts
|
|
423
423
|
import fs from "fs/promises";
|
|
424
|
+
import path from "path";
|
|
424
425
|
import pc2 from "picocolors";
|
|
425
|
-
var
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return Promise.resolve();
|
|
426
|
+
var FileSystem = class {
|
|
427
|
+
isInitialized = false;
|
|
428
|
+
dry = false;
|
|
429
|
+
verbose = false;
|
|
430
|
+
/** Default working directory is where the process was started */
|
|
431
|
+
workingDir = process.cwd();
|
|
432
|
+
outDir = this.workingDir;
|
|
433
|
+
/** Initialize the file system */
|
|
434
|
+
init({ dry, outdir, verbose }) {
|
|
435
|
+
if (this.isInitialized) {
|
|
436
|
+
console.warn(pc2.yellow("FileSystem is already initialized. Ignoring subsequent init call."));
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (dry) {
|
|
440
|
+
console.log(pc2.blue("Initializing FileSystem in dry-run mode. No files will be written."));
|
|
441
|
+
}
|
|
442
|
+
this.dry = dry ?? false;
|
|
443
|
+
this.verbose = verbose ?? false;
|
|
444
|
+
this.outDir = outdir ? path.isAbsolute(outdir) ? outdir : path.join(this.workingDir, outdir) : this.workingDir;
|
|
445
|
+
if (this.verbose) {
|
|
446
|
+
console.log(
|
|
447
|
+
`FileSystem initialized with workingDir: ${pc2.green(this.workingDir)}, outDir: ${pc2.green(this.outDir)}`
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
this.isInitialized = true;
|
|
451
451
|
}
|
|
452
|
-
|
|
452
|
+
/**
|
|
453
|
+
* Creates a directory if it does not already exist.
|
|
454
|
+
*
|
|
455
|
+
* @param dir - The path of the directory to create.
|
|
456
|
+
*
|
|
457
|
+
* @returns A promise that resolves when the operation is complete.
|
|
458
|
+
* If the directory already exists or `dry` is `true`, the promise resolves immediately.
|
|
459
|
+
*/
|
|
460
|
+
mkdir = async (dir) => {
|
|
461
|
+
if (this.dry) {
|
|
462
|
+
console.log(`${pc2.blue("mkdir")} ${dir}`);
|
|
463
|
+
return Promise.resolve();
|
|
464
|
+
}
|
|
465
|
+
const exists = await fs.access(dir, fs.constants.F_OK).then(() => true).catch(() => false);
|
|
466
|
+
if (exists) {
|
|
467
|
+
return Promise.resolve();
|
|
468
|
+
}
|
|
469
|
+
return fs.mkdir(dir, { recursive: true });
|
|
470
|
+
};
|
|
471
|
+
writeFile = async (path5, data) => {
|
|
472
|
+
if (this.dry) {
|
|
473
|
+
console.log(`${pc2.blue("writeFile")} ${path5}`);
|
|
474
|
+
return Promise.resolve();
|
|
475
|
+
}
|
|
476
|
+
return fs.writeFile(path5, data, { encoding: "utf-8" }).catch((error) => {
|
|
477
|
+
console.error(pc2.red(`Error writing file: ${path5}`));
|
|
478
|
+
console.error(pc2.red(error));
|
|
479
|
+
throw error;
|
|
480
|
+
});
|
|
481
|
+
};
|
|
482
|
+
cp = async (src, dest, filter) => {
|
|
483
|
+
if (this.dry) {
|
|
484
|
+
console.log(`${pc2.blue("cp")} ${src} ${dest}`);
|
|
485
|
+
return Promise.resolve();
|
|
486
|
+
}
|
|
487
|
+
return fs.cp(src, dest, { recursive: true, filter });
|
|
488
|
+
};
|
|
489
|
+
copyFile = async (src, dest) => {
|
|
490
|
+
if (this.dry) {
|
|
491
|
+
console.log(`${pc2.blue("copyFile")} ${src} to ${dest}`);
|
|
492
|
+
return Promise.resolve();
|
|
493
|
+
}
|
|
494
|
+
return fs.copyFile(src, dest);
|
|
495
|
+
};
|
|
496
|
+
cleanDir = async (dir) => {
|
|
497
|
+
if (this.dry) {
|
|
498
|
+
console.log(`${pc2.blue("cleanDir")} ${dir}`);
|
|
499
|
+
return Promise.resolve();
|
|
500
|
+
}
|
|
501
|
+
console.log(`
|
|
453
502
|
\u{1F525} Cleaning dir ${pc2.red(`${dir.trim()}`)} `);
|
|
454
|
-
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return Promise.resolve("");
|
|
460
|
-
}
|
|
461
|
-
try {
|
|
462
|
-
return await fs.readFile(path6, "utf-8");
|
|
463
|
-
} catch (error) {
|
|
464
|
-
if (allowFileNotFound && error.code === "ENOENT") {
|
|
465
|
-
return "";
|
|
503
|
+
return fs.rm(dir, { recursive: true, force: true });
|
|
504
|
+
};
|
|
505
|
+
readFile = async (path5, allowFileNotFound) => {
|
|
506
|
+
if (this.dry) {
|
|
507
|
+
console.log(`${pc2.blue("readFile")} ${path5}`);
|
|
466
508
|
}
|
|
467
|
-
|
|
468
|
-
|
|
509
|
+
try {
|
|
510
|
+
return await fs.readFile(path5, "utf-8");
|
|
511
|
+
} catch (error) {
|
|
512
|
+
if (allowFileNotFound && error.code === "ENOENT") {
|
|
513
|
+
return "";
|
|
514
|
+
}
|
|
515
|
+
throw error;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
readdir = async (path5) => {
|
|
519
|
+
if (this.dry) {
|
|
520
|
+
console.log(`${pc2.blue("readdir")} ${path5}`);
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
return await fs.readdir(path5);
|
|
524
|
+
} catch (error) {
|
|
525
|
+
if (error.code === "ENOENT") {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
writeFiles = async (files, outDir, log) => {
|
|
532
|
+
for (const { destination: filename, output } of files) {
|
|
533
|
+
if (filename) {
|
|
534
|
+
const filePath = path.join(outDir, filename);
|
|
535
|
+
const fileDir = path.dirname(filePath);
|
|
536
|
+
if (log) {
|
|
537
|
+
console.log(filename);
|
|
538
|
+
}
|
|
539
|
+
await this.mkdir(fileDir);
|
|
540
|
+
await this.writeFile(filePath, output);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
};
|
|
469
544
|
};
|
|
545
|
+
var dsfs = new FileSystem();
|
|
470
546
|
|
|
471
547
|
// src/migrations/codemods/css/run.ts
|
|
472
548
|
var runCssCodemod = async ({ plugins = [], globPattern = "./**/*.css" }) => {
|
|
@@ -482,9 +558,9 @@ var runCssCodemod = async ({ plugins = [], globPattern = "./**/*.css" }) => {
|
|
|
482
558
|
if (file.includes("node_modules") || file.includes("dist")) {
|
|
483
559
|
return;
|
|
484
560
|
}
|
|
485
|
-
const contents = readFile(file)
|
|
486
|
-
const result = await processor.process(contents, { from: file });
|
|
487
|
-
|
|
561
|
+
const contents = await dsfs.readFile(file);
|
|
562
|
+
const result = await processor.process(contents.toString(), { from: file });
|
|
563
|
+
await dsfs.writeFile(file, result.css);
|
|
488
564
|
});
|
|
489
565
|
await Promise.all(filePromises);
|
|
490
566
|
};
|
|
@@ -874,7 +950,6 @@ var migrations_default = {
|
|
|
874
950
|
};
|
|
875
951
|
|
|
876
952
|
// src/tokens/build.ts
|
|
877
|
-
import path from "path";
|
|
878
953
|
import pc7 from "picocolors";
|
|
879
954
|
import * as R22 from "ramda";
|
|
880
955
|
|
|
@@ -884,11 +959,11 @@ import pc5 from "picocolors";
|
|
|
884
959
|
// package.json
|
|
885
960
|
var package_default = {
|
|
886
961
|
name: "@digdir/designsystemet",
|
|
887
|
-
version: "1.
|
|
962
|
+
version: "1.13.1",
|
|
888
963
|
description: "CLI for Designsystemet",
|
|
889
964
|
author: "Designsystemet team",
|
|
890
965
|
engines: {
|
|
891
|
-
node: ">=20
|
|
966
|
+
node: ">=20.20.1"
|
|
892
967
|
},
|
|
893
968
|
repository: {
|
|
894
969
|
type: "git",
|
|
@@ -952,16 +1027,16 @@ var package_default = {
|
|
|
952
1027
|
hsluv: "^1.0.1",
|
|
953
1028
|
"object-hash": "^3.0.0",
|
|
954
1029
|
picocolors: "^1.1.1",
|
|
955
|
-
postcss: "^8.5.
|
|
1030
|
+
postcss: "^8.5.8",
|
|
956
1031
|
ramda: "^0.32.0",
|
|
957
|
-
"style-dictionary": "^5.3.
|
|
1032
|
+
"style-dictionary": "^5.3.3",
|
|
958
1033
|
zod: "^4.3.6",
|
|
959
1034
|
"zod-validation-error": "^5.0.0"
|
|
960
1035
|
},
|
|
961
1036
|
devDependencies: {
|
|
962
1037
|
"@tokens-studio/types": "0.5.2",
|
|
963
1038
|
"@types/chroma-js": "^3.1.2",
|
|
964
|
-
"@types/node": "^24.
|
|
1039
|
+
"@types/node": "^24.12.0",
|
|
965
1040
|
"@types/object-hash": "^3.0.6",
|
|
966
1041
|
"@types/ramda": "^0.31.1",
|
|
967
1042
|
tsup: "^8.5.1",
|
|
@@ -1007,8 +1082,8 @@ var pathStartsWithOneOf = R6.curry(
|
|
|
1007
1082
|
}
|
|
1008
1083
|
const tokenPath = mapToLowerCase(token.path);
|
|
1009
1084
|
const matchPathsStartingWith = R6.map((pathOrString) => {
|
|
1010
|
-
const
|
|
1011
|
-
return R6.startsWith(mapToLowerCase(
|
|
1085
|
+
const path5 = typeof pathOrString === "string" ? [pathOrString] : pathOrString;
|
|
1086
|
+
return R6.startsWith(mapToLowerCase(path5), tokenPath);
|
|
1012
1087
|
}, paths);
|
|
1013
1088
|
return hasAnyTruth(matchPathsStartingWith);
|
|
1014
1089
|
}
|
|
@@ -1033,11 +1108,11 @@ function isColorCategoryToken(token, category) {
|
|
|
1033
1108
|
var isDigit = (s) => /^\d+$/.test(s);
|
|
1034
1109
|
function traverseObj(obj, fn) {
|
|
1035
1110
|
for (const key in obj) {
|
|
1036
|
-
const
|
|
1037
|
-
if (
|
|
1038
|
-
fn.apply(null, [obj, key,
|
|
1039
|
-
if (typeof
|
|
1040
|
-
traverseObj(
|
|
1111
|
+
const prop3 = obj[key];
|
|
1112
|
+
if (prop3 != null) {
|
|
1113
|
+
fn.apply(null, [obj, key, prop3]);
|
|
1114
|
+
if (typeof prop3 === "object") {
|
|
1115
|
+
traverseObj(prop3, fn);
|
|
1041
1116
|
}
|
|
1042
1117
|
}
|
|
1043
1118
|
}
|
|
@@ -2449,8 +2524,8 @@ ${dynamicColors}`;
|
|
|
2449
2524
|
import pc6 from "picocolors";
|
|
2450
2525
|
import * as R21 from "ramda";
|
|
2451
2526
|
var defaultFileHeader2 = `build: v${package_default.version}`;
|
|
2452
|
-
var getFileNameWithoutExtension = (
|
|
2453
|
-
const pathSegments =
|
|
2527
|
+
var getFileNameWithoutExtension = (path5) => {
|
|
2528
|
+
const pathSegments = path5.split("/");
|
|
2454
2529
|
return pathSegments[pathSegments.length - 1].split(".").slice(0, -1).join(".");
|
|
2455
2530
|
};
|
|
2456
2531
|
var createThemeCSSFiles = ({
|
|
@@ -2530,25 +2605,13 @@ ${fileHeader}
|
|
|
2530
2605
|
};
|
|
2531
2606
|
|
|
2532
2607
|
// src/tokens/build.ts
|
|
2533
|
-
async function write(files, outDir, dry) {
|
|
2534
|
-
for (const { destination, output } of files) {
|
|
2535
|
-
if (destination) {
|
|
2536
|
-
const filePath = path.join(outDir, destination);
|
|
2537
|
-
const fileDir = path.dirname(filePath);
|
|
2538
|
-
console.log(destination);
|
|
2539
|
-
await mkdir(fileDir, dry);
|
|
2540
|
-
await writeFile(filePath, output, dry);
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
2608
|
var buildTokens = async (options) => {
|
|
2545
|
-
const
|
|
2546
|
-
const
|
|
2547
|
-
const $themes = JSON.parse(await readFile(`${tokensDir}/$themes.json`));
|
|
2609
|
+
const tokensDir = options.tokensDir;
|
|
2610
|
+
const $themes = JSON.parse(await dsfs.readFile(`${tokensDir}/$themes.json`));
|
|
2548
2611
|
const processed$themes = $themes.map(processThemeObject);
|
|
2549
2612
|
let $designsystemet;
|
|
2550
2613
|
try {
|
|
2551
|
-
const $designsystemetContent = await readFile(`${tokensDir}/$designsystemet.jsonc`);
|
|
2614
|
+
const $designsystemetContent = await dsfs.readFile(`${tokensDir}/$designsystemet.jsonc`);
|
|
2552
2615
|
$designsystemet = JSON.parse($designsystemetContent);
|
|
2553
2616
|
} catch (_error) {
|
|
2554
2617
|
}
|
|
@@ -2556,7 +2619,6 @@ var buildTokens = async (options) => {
|
|
|
2556
2619
|
\u{1F3D7}\uFE0F Start building tokens in ${pc7.green(tokensDir)}`);
|
|
2557
2620
|
const processedBuilds = await processPlatform({
|
|
2558
2621
|
...options,
|
|
2559
|
-
outDir,
|
|
2560
2622
|
tokensDir,
|
|
2561
2623
|
type: "build",
|
|
2562
2624
|
processed$themes,
|
|
@@ -2575,19 +2637,9 @@ design-tokens: v${$designsystemet.version}` : ""
|
|
|
2575
2637
|
const tailwindFiles = createTailwindCSSFiles(cssFiles);
|
|
2576
2638
|
files = files.concat(tailwindFiles.filter(Boolean));
|
|
2577
2639
|
}
|
|
2578
|
-
|
|
2579
|
-
\u{1F4BE} Writing build to ${pc7.green(outDir)}`);
|
|
2580
|
-
await write(files, outDir, options.dry);
|
|
2581
|
-
console.log(`
|
|
2582
|
-
\u2705 Finished building tokens!`);
|
|
2583
|
-
return processedBuilds;
|
|
2640
|
+
return files;
|
|
2584
2641
|
};
|
|
2585
2642
|
|
|
2586
|
-
// src/tokens/create/write.ts
|
|
2587
|
-
import path2 from "path";
|
|
2588
|
-
import pc8 from "picocolors";
|
|
2589
|
-
import * as R23 from "ramda";
|
|
2590
|
-
|
|
2591
2643
|
// src/tokens/create/generators/$designsystemet.ts
|
|
2592
2644
|
function generate$Designsystemet() {
|
|
2593
2645
|
return {
|
|
@@ -2783,56 +2835,36 @@ function generateTypographyGroup(themes) {
|
|
|
2783
2835
|
];
|
|
2784
2836
|
}
|
|
2785
2837
|
|
|
2786
|
-
// src/tokens/create/
|
|
2838
|
+
// src/tokens/create/files.ts
|
|
2787
2839
|
var stringify = (data) => JSON.stringify(data, null, 2);
|
|
2788
|
-
var
|
|
2840
|
+
var createTokenFiles = async (options) => {
|
|
2789
2841
|
const {
|
|
2790
2842
|
outDir,
|
|
2791
2843
|
tokenSets,
|
|
2792
|
-
theme: {
|
|
2793
|
-
|
|
2844
|
+
theme: { colors: colors2 },
|
|
2845
|
+
themeNames
|
|
2794
2846
|
} = options;
|
|
2795
|
-
const
|
|
2796
|
-
const $
|
|
2797
|
-
const $
|
|
2798
|
-
const $designsystemetPath = path2.join(targetDir, "$designsystemet.jsonc");
|
|
2799
|
-
let themeObjects = [];
|
|
2847
|
+
const $themesPath = "$themes.json";
|
|
2848
|
+
const $metadataPath = "$metadata.json";
|
|
2849
|
+
const $designsystemetPath = "$designsystemet.jsonc";
|
|
2800
2850
|
const sizeModes2 = ["small", "medium", "large"];
|
|
2801
|
-
await mkdir(
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
if ($themes2) {
|
|
2805
|
-
themeObjects = JSON.parse($themes2);
|
|
2806
|
-
}
|
|
2807
|
-
} catch (_error) {
|
|
2808
|
-
}
|
|
2809
|
-
const concatThemeNames = R23.pipe(
|
|
2810
|
-
R23.filter((obj) => R23.toLower(obj.group || "") === "theme"),
|
|
2811
|
-
R23.map(R23.prop("name")),
|
|
2812
|
-
// New theme is added to the end of the list so we keep the same order from config and Token Studio
|
|
2813
|
-
R23.append(themeName),
|
|
2814
|
-
R23.uniq
|
|
2815
|
-
);
|
|
2816
|
-
const themes = concatThemeNames(themeObjects);
|
|
2817
|
-
console.log(`
|
|
2818
|
-
Themes: ${pc8.blue(themes.join(", "))}`);
|
|
2819
|
-
const $themes = await generate$Themes(["dark", "light"], themes, colors2, sizeModes2);
|
|
2820
|
-
const $metadata = generate$Metadata(["dark", "light"], themes, colors2, sizeModes2);
|
|
2851
|
+
await dsfs.mkdir(outDir);
|
|
2852
|
+
const $themes = await generate$Themes(["dark", "light"], themeNames, colors2, sizeModes2);
|
|
2853
|
+
const $metadata = generate$Metadata(["dark", "light"], themeNames, colors2, sizeModes2);
|
|
2821
2854
|
const $designsystemet = generate$Designsystemet();
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2855
|
+
const files = [];
|
|
2856
|
+
files.push({ destination: $themesPath, output: stringify($themes) });
|
|
2857
|
+
files.push({ destination: $metadataPath, output: stringify($metadata) });
|
|
2858
|
+
files.push({ destination: $designsystemetPath, output: stringify($designsystemet) });
|
|
2825
2859
|
for (const [set4, tokens] of tokenSets) {
|
|
2826
|
-
const
|
|
2827
|
-
|
|
2828
|
-
const filePath = path2.join(targetDir, `${set4}.json`);
|
|
2829
|
-
await writeFile(filePath, stringify(tokens), dry);
|
|
2860
|
+
const filePath = `${set4}.json`;
|
|
2861
|
+
files.push({ destination: filePath, output: stringify(tokens) });
|
|
2830
2862
|
}
|
|
2831
|
-
|
|
2863
|
+
return files;
|
|
2832
2864
|
};
|
|
2833
2865
|
|
|
2834
2866
|
// src/tokens/create/generators/primitives/color-scheme.ts
|
|
2835
|
-
import * as
|
|
2867
|
+
import * as R23 from "ramda";
|
|
2836
2868
|
var generateColor = (colorArray, overrides) => {
|
|
2837
2869
|
const obj = {};
|
|
2838
2870
|
const $type = "color";
|
|
@@ -2869,11 +2901,11 @@ var generateColorScheme = (themeName, colorScheme2, colors2, overrides) => {
|
|
|
2869
2901
|
});
|
|
2870
2902
|
return Object.keys(positionOverrides).length > 0 ? positionOverrides : void 0;
|
|
2871
2903
|
};
|
|
2872
|
-
const main =
|
|
2904
|
+
const main = R23.mapObjIndexed(
|
|
2873
2905
|
(color, colorName) => generateColor(generateColorScale(color, colorScheme2), createColorOverrides(colorName)),
|
|
2874
2906
|
colors2.main
|
|
2875
2907
|
);
|
|
2876
|
-
const support =
|
|
2908
|
+
const support = R23.mapObjIndexed(
|
|
2877
2909
|
(color, colorName) => generateColor(generateColorScale(color, colorScheme2), createColorOverrides(colorName)),
|
|
2878
2910
|
colors2.support
|
|
2879
2911
|
);
|
|
@@ -2883,7 +2915,7 @@ var generateColorScheme = (themeName, colorScheme2, colors2, overrides) => {
|
|
|
2883
2915
|
...baseColors,
|
|
2884
2916
|
...overrides?.severity
|
|
2885
2917
|
};
|
|
2886
|
-
const globalColors =
|
|
2918
|
+
const globalColors = R23.mapObjIndexed(
|
|
2887
2919
|
(color, colorName) => generateColor(generateColorScale(color, colorScheme2), createColorOverrides(colorName)),
|
|
2888
2920
|
baseColorsWithOverrides
|
|
2889
2921
|
);
|
|
@@ -3435,7 +3467,7 @@ var fontSizes = {
|
|
|
3435
3467
|
};
|
|
3436
3468
|
|
|
3437
3469
|
// src/tokens/create/generators/semantic/color.ts
|
|
3438
|
-
import * as
|
|
3470
|
+
import * as R24 from "ramda";
|
|
3439
3471
|
var generateSemanticColors = (colors2, _themeName) => {
|
|
3440
3472
|
const mainColorNames = Object.keys(colors2.main);
|
|
3441
3473
|
const supportColorNames = Object.keys(colors2.support);
|
|
@@ -3474,7 +3506,7 @@ var baseColorTemplate = {
|
|
|
3474
3506
|
};
|
|
3475
3507
|
var generateColorScaleTokens = (colorName) => {
|
|
3476
3508
|
const colorScale = {};
|
|
3477
|
-
for (const [colorSemantic, colorNumber] of
|
|
3509
|
+
for (const [colorSemantic, colorNumber] of R24.toPairs(semanticColorMap)) {
|
|
3478
3510
|
colorScale[colorSemantic] = {
|
|
3479
3511
|
$type: "color",
|
|
3480
3512
|
$value: `{color.${colorName}.${colorNumber}}`
|
|
@@ -3902,7 +3934,7 @@ function generateSemanticStyle() {
|
|
|
3902
3934
|
}
|
|
3903
3935
|
|
|
3904
3936
|
// src/tokens/create/generators/themes/theme.ts
|
|
3905
|
-
import * as
|
|
3937
|
+
import * as R25 from "ramda";
|
|
3906
3938
|
var generateTheme = (colors2, themeName, borderRadius) => {
|
|
3907
3939
|
const mainColorNames = Object.keys(colors2.main);
|
|
3908
3940
|
const supportColorNames = Object.keys(colors2.support);
|
|
@@ -3934,8 +3966,8 @@ var generateTheme = (colors2, themeName, borderRadius) => {
|
|
|
3934
3966
|
},
|
|
3935
3967
|
...remainingThemeFile
|
|
3936
3968
|
};
|
|
3937
|
-
const baseBorderRadius =
|
|
3938
|
-
const updatedThemeFile =
|
|
3969
|
+
const baseBorderRadius = R25.lensPath(["border-radius", "base", "$value"]);
|
|
3970
|
+
const updatedThemeFile = R25.set(baseBorderRadius, String(borderRadius), themeFile);
|
|
3939
3971
|
const token = JSON.parse(
|
|
3940
3972
|
JSON.stringify(
|
|
3941
3973
|
updatedThemeFile,
|
|
@@ -4007,7 +4039,7 @@ var generateBase = (themeName) => ({
|
|
|
4007
4039
|
});
|
|
4008
4040
|
var generateColorScaleTokens3 = (colorName, themeName) => {
|
|
4009
4041
|
const colorScale = {};
|
|
4010
|
-
for (const [_, colorNumber] of
|
|
4042
|
+
for (const [_, colorNumber] of R25.toPairs(semanticColorMap)) {
|
|
4011
4043
|
colorScale[colorNumber] = {
|
|
4012
4044
|
$type: "color",
|
|
4013
4045
|
$value: `{${themeName}.${colorName}.${colorNumber}}`
|
|
@@ -4062,12 +4094,11 @@ var createTokens = async (theme) => {
|
|
|
4062
4094
|
};
|
|
4063
4095
|
|
|
4064
4096
|
// src/tokens/generate-config.ts
|
|
4065
|
-
import
|
|
4066
|
-
import
|
|
4067
|
-
import pc9 from "picocolors";
|
|
4097
|
+
import path2 from "path";
|
|
4098
|
+
import pc8 from "picocolors";
|
|
4068
4099
|
async function readJsonFile(filePath) {
|
|
4069
4100
|
try {
|
|
4070
|
-
const content = await
|
|
4101
|
+
const content = await dsfs.readFile(filePath);
|
|
4071
4102
|
return JSON.parse(content);
|
|
4072
4103
|
} catch (err) {
|
|
4073
4104
|
throw new Error(`Failed to read token file at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -4083,21 +4114,21 @@ function extractBaseColor(colorScale) {
|
|
|
4083
4114
|
return null;
|
|
4084
4115
|
}
|
|
4085
4116
|
async function discoverThemes(tokensDir) {
|
|
4086
|
-
const lightModePath =
|
|
4117
|
+
const lightModePath = path2.join(tokensDir, "themes");
|
|
4087
4118
|
try {
|
|
4088
|
-
const files = await
|
|
4119
|
+
const files = await dsfs.readdir(lightModePath);
|
|
4089
4120
|
const themes = files.filter((file) => file.endsWith(".json")).map((file) => file.replace(".json", ""));
|
|
4090
4121
|
return themes;
|
|
4091
4122
|
} catch {
|
|
4092
|
-
throw new Error(`Could not find themes. Make sure ${
|
|
4123
|
+
throw new Error(`Could not find themes. Make sure ${pc8.blue(lightModePath)} exists and contains theme JSON files.`);
|
|
4093
4124
|
}
|
|
4094
4125
|
}
|
|
4095
4126
|
async function readThemeTokens(tokensDir, themeName) {
|
|
4096
|
-
const themePath =
|
|
4127
|
+
const themePath = path2.join(tokensDir, "primitives", "modes", "color-scheme", "light", `${themeName}.json`);
|
|
4097
4128
|
return readJsonFile(themePath);
|
|
4098
4129
|
}
|
|
4099
4130
|
async function readThemeConfig(tokensDir, themeName) {
|
|
4100
|
-
const themeConfigPath =
|
|
4131
|
+
const themeConfigPath = path2.join(tokensDir, "themes", `${themeName}.json`);
|
|
4101
4132
|
try {
|
|
4102
4133
|
return await readJsonFile(themeConfigPath);
|
|
4103
4134
|
} catch {
|
|
@@ -4131,7 +4162,7 @@ function extractFontFamily(themeConfig) {
|
|
|
4131
4162
|
return void 0;
|
|
4132
4163
|
}
|
|
4133
4164
|
async function readTypographyConfig(tokensDir, themeName) {
|
|
4134
|
-
const typographyConfigPath =
|
|
4165
|
+
const typographyConfigPath = path2.join(
|
|
4135
4166
|
tokensDir,
|
|
4136
4167
|
"primitives",
|
|
4137
4168
|
"modes",
|
|
@@ -4191,33 +4222,33 @@ function categorizeColors(themeTokens, themeName) {
|
|
|
4191
4222
|
return { main, support, neutral };
|
|
4192
4223
|
}
|
|
4193
4224
|
async function generateConfigFromTokens(options) {
|
|
4194
|
-
const { tokensDir
|
|
4225
|
+
const { tokensDir } = options;
|
|
4195
4226
|
console.log(`
|
|
4196
|
-
Reading tokens from ${
|
|
4227
|
+
Reading tokens from ${pc8.blue(tokensDir)}`);
|
|
4197
4228
|
const themes = await discoverThemes(tokensDir);
|
|
4198
4229
|
if (themes.length === 0) {
|
|
4199
4230
|
throw new Error(`
|
|
4200
|
-
No themes found in ${
|
|
4231
|
+
No themes found in ${pc8.blue(tokensDir)}`);
|
|
4201
4232
|
}
|
|
4202
4233
|
console.log(`
|
|
4203
|
-
Found ${
|
|
4234
|
+
Found ${pc8.green(String(themes.length))} theme(s): ${themes.map((t) => pc8.cyan(t)).join(", ")}`);
|
|
4204
4235
|
const config = {
|
|
4205
4236
|
outDir: tokensDir,
|
|
4206
4237
|
themes: {}
|
|
4207
4238
|
};
|
|
4208
4239
|
for (const themeName of themes) {
|
|
4209
4240
|
console.log(`
|
|
4210
|
-
Processing theme ${
|
|
4241
|
+
Processing theme ${pc8.cyan(themeName)}...`);
|
|
4211
4242
|
const themeTokens = await readThemeTokens(tokensDir, themeName);
|
|
4212
4243
|
const themeConfig = await readThemeConfig(tokensDir, themeName);
|
|
4213
4244
|
const typographyConfig = await readTypographyConfig(tokensDir, themeName);
|
|
4214
4245
|
const { main, support, neutral } = categorizeColors(themeTokens, themeName);
|
|
4215
4246
|
if (Object.keys(main).length === 0) {
|
|
4216
|
-
console.warn(
|
|
4247
|
+
console.warn(pc8.yellow(`
|
|
4217
4248
|
Warning: No main colors found for theme ${themeName}`));
|
|
4218
4249
|
}
|
|
4219
4250
|
if (!neutral) {
|
|
4220
|
-
console.warn(
|
|
4251
|
+
console.warn(pc8.yellow(`
|
|
4221
4252
|
Warning: No neutral color found for theme ${themeName}`));
|
|
4222
4253
|
continue;
|
|
4223
4254
|
}
|
|
@@ -4234,46 +4265,38 @@ Warning: No neutral color found for theme ${themeName}`));
|
|
|
4234
4265
|
};
|
|
4235
4266
|
console.log(
|
|
4236
4267
|
`
|
|
4237
|
-
\u2705 Main colors: ${Object.keys(main).map((c) =>
|
|
4268
|
+
\u2705 Main colors: ${Object.keys(main).map((c) => pc8.cyan(c)).join(", ") || pc8.dim("none")}`
|
|
4238
4269
|
);
|
|
4239
4270
|
console.log(
|
|
4240
4271
|
`
|
|
4241
|
-
\u2705 Support colors: ${Object.keys(support).map((c) =>
|
|
4272
|
+
\u2705 Support colors: ${Object.keys(support).map((c) => pc8.cyan(c)).join(", ") || pc8.dim("none")}`
|
|
4242
4273
|
);
|
|
4243
4274
|
console.log(`
|
|
4244
|
-
\u2705 Neutral: ${
|
|
4275
|
+
\u2705 Neutral: ${pc8.cyan(neutral)}`);
|
|
4245
4276
|
if (borderRadius !== void 0) {
|
|
4246
4277
|
console.log(`
|
|
4247
|
-
\u2705 Border radius: ${
|
|
4278
|
+
\u2705 Border radius: ${pc8.cyan(String(borderRadius))}`);
|
|
4248
4279
|
}
|
|
4249
4280
|
if (fontFamily) {
|
|
4250
4281
|
console.log(`
|
|
4251
|
-
\u2705 Font family: ${
|
|
4282
|
+
\u2705 Font family: ${pc8.cyan(fontFamily)}`);
|
|
4252
4283
|
}
|
|
4253
4284
|
}
|
|
4254
|
-
if (!dry && options.outFile) {
|
|
4255
|
-
const configJson = JSON.stringify(config, null, 2);
|
|
4256
|
-
await fs3.writeFile(options.outFile, configJson, "utf-8");
|
|
4257
|
-
console.log();
|
|
4258
|
-
console.log(`
|
|
4259
|
-
\u2705 Config file written to ${pc9.blue(options.outFile)}`);
|
|
4260
|
-
}
|
|
4261
4285
|
return config;
|
|
4262
4286
|
}
|
|
4263
4287
|
|
|
4264
4288
|
// bin/config.ts
|
|
4265
|
-
import path5 from "path";
|
|
4266
|
-
import pc11 from "picocolors";
|
|
4267
|
-
import * as R28 from "ramda";
|
|
4268
|
-
|
|
4269
|
-
// src/config.ts
|
|
4270
4289
|
import pc10 from "picocolors";
|
|
4271
4290
|
import * as R27 from "ramda";
|
|
4291
|
+
|
|
4292
|
+
// src/config.ts
|
|
4293
|
+
import pc9 from "picocolors";
|
|
4294
|
+
import * as R26 from "ramda";
|
|
4272
4295
|
import { z } from "zod";
|
|
4273
4296
|
import { fromError } from "zod-validation-error";
|
|
4274
|
-
function mapPathToOptionName(
|
|
4275
|
-
const normalisedPath =
|
|
4276
|
-
const option =
|
|
4297
|
+
function mapPathToOptionName(path5) {
|
|
4298
|
+
const normalisedPath = path5[0] === "themes" ? ["theme", ...R26.drop(2, path5)] : path5;
|
|
4299
|
+
const option = R26.path(normalisedPath, cliOptions);
|
|
4277
4300
|
if (typeof option !== "string") {
|
|
4278
4301
|
return;
|
|
4279
4302
|
}
|
|
@@ -4287,33 +4310,33 @@ function makeFriendlyError(err) {
|
|
|
4287
4310
|
const optionName = mapPathToOptionName(issue.path);
|
|
4288
4311
|
const errorCode = `(error code: ${issue.code})`;
|
|
4289
4312
|
const optionMessage = optionName ? ` or CLI option --${optionName}` : "";
|
|
4290
|
-
return ` - Error in JSON value ${
|
|
4291
|
-
${issue.message} ${
|
|
4313
|
+
return ` - Error in JSON value ${pc9.red(issuePath)}${optionMessage}:
|
|
4314
|
+
${issue.message} ${pc9.dim(errorCode)}`;
|
|
4292
4315
|
}).join("\n")
|
|
4293
4316
|
});
|
|
4294
4317
|
} catch (_err2) {
|
|
4295
|
-
console.error(
|
|
4318
|
+
console.error(pc9.red(err instanceof Error ? err.message : "Unknown error occurred while parsing config file"));
|
|
4296
4319
|
console.error(err instanceof Error ? err.stack : "No stack trace available");
|
|
4297
4320
|
}
|
|
4298
4321
|
}
|
|
4299
|
-
function validateConfig(schema, unvalidatedConfig,
|
|
4322
|
+
function validateConfig(schema, unvalidatedConfig, configFilePath) {
|
|
4300
4323
|
try {
|
|
4301
4324
|
return schema.parse(unvalidatedConfig);
|
|
4302
4325
|
} catch (err) {
|
|
4303
|
-
console.error(
|
|
4326
|
+
console.error(pc9.redBright(`Invalid config file at ${pc9.red(configFilePath)}`));
|
|
4304
4327
|
const validationError = makeFriendlyError(err);
|
|
4305
4328
|
console.error(validationError?.toString());
|
|
4306
4329
|
process.exit(1);
|
|
4307
4330
|
}
|
|
4308
4331
|
}
|
|
4309
|
-
function parseConfig(configFile,
|
|
4332
|
+
function parseConfig(configFile, configFilePath) {
|
|
4310
4333
|
if (!configFile) {
|
|
4311
4334
|
return {};
|
|
4312
4335
|
}
|
|
4313
4336
|
try {
|
|
4314
4337
|
return JSON.parse(configFile);
|
|
4315
4338
|
} catch (err) {
|
|
4316
|
-
console.error(
|
|
4339
|
+
console.error(pc9.redBright(`Failed parsing config file at ${pc9.red(configFilePath)}`));
|
|
4317
4340
|
const validationError = makeFriendlyError(err);
|
|
4318
4341
|
console.error(validationError?.toString());
|
|
4319
4342
|
process.exit(1);
|
|
@@ -4404,32 +4427,31 @@ var getDefaultCliOption = getOptionIfMatchingSource("default");
|
|
|
4404
4427
|
var getCliOption = getOptionIfMatchingSource("cli", "default");
|
|
4405
4428
|
|
|
4406
4429
|
// bin/config.ts
|
|
4407
|
-
async function readConfigFile(
|
|
4408
|
-
const resolvedPath = path5.resolve(process.cwd(), configPath);
|
|
4430
|
+
async function readConfigFile(configFilePath, allowFileNotFound = true) {
|
|
4409
4431
|
let configFile;
|
|
4410
4432
|
try {
|
|
4411
|
-
configFile = await readFile(
|
|
4433
|
+
configFile = await dsfs.readFile(configFilePath, allowFileNotFound);
|
|
4412
4434
|
} catch (err) {
|
|
4413
4435
|
if (allowFileNotFound) {
|
|
4414
4436
|
return "";
|
|
4415
4437
|
}
|
|
4416
|
-
console.error(
|
|
4438
|
+
console.error(pc10.redBright(`Could not read config file at ${pc10.blue(configFilePath)}`));
|
|
4417
4439
|
throw err;
|
|
4418
4440
|
}
|
|
4419
4441
|
if (configFile) {
|
|
4420
|
-
console.log(`Found config file: ${
|
|
4442
|
+
console.log(`Found config file: ${pc10.green(configFilePath)}`);
|
|
4421
4443
|
}
|
|
4422
4444
|
return configFile;
|
|
4423
4445
|
}
|
|
4424
4446
|
async function parseCreateConfig(configFile, options) {
|
|
4425
|
-
const { cmd, theme = "theme",
|
|
4426
|
-
const configParsed = parseConfig(configFile,
|
|
4447
|
+
const { cmd, theme = "theme", configFilePath } = options;
|
|
4448
|
+
const configParsed = parseConfig(configFile, configFilePath);
|
|
4427
4449
|
const themeColors = Object.values(configParsed?.themes ?? {}).map(
|
|
4428
|
-
(x) => /* @__PURE__ */ new Set([...
|
|
4450
|
+
(x) => /* @__PURE__ */ new Set([...R27.keys(x.colors.main), ...R27.keys(x.colors.support)])
|
|
4429
4451
|
);
|
|
4430
|
-
if (!
|
|
4431
|
-
console.error(
|
|
4432
|
-
const themeNames =
|
|
4452
|
+
if (!R27.all(R27.equals(R27.__, themeColors[0]), themeColors)) {
|
|
4453
|
+
console.error(pc10.redBright(`In config, all themes must have the same custom color names, but we found:`));
|
|
4454
|
+
const themeNames = R27.keys(configParsed.themes ?? {});
|
|
4433
4455
|
themeColors.forEach((colors2, index) => {
|
|
4434
4456
|
const colorNames2 = Array.from(colors2);
|
|
4435
4457
|
console.log(` - ${themeNames[index]}: ${colorNames2.join(", ")}`);
|
|
@@ -4437,7 +4459,7 @@ async function parseCreateConfig(configFile, options) {
|
|
|
4437
4459
|
console.log();
|
|
4438
4460
|
process.exit(1);
|
|
4439
4461
|
}
|
|
4440
|
-
const noUndefined =
|
|
4462
|
+
const noUndefined = R27.reject(R27.isNil);
|
|
4441
4463
|
const getThemeOptions = (optionGetter) => noUndefined({
|
|
4442
4464
|
colors: noUndefined({
|
|
4443
4465
|
main: optionGetter(cmd, "mainColors"),
|
|
@@ -4453,10 +4475,10 @@ async function parseCreateConfig(configFile, options) {
|
|
|
4453
4475
|
const unvalidatedConfig = noUndefined({
|
|
4454
4476
|
outDir: configParsed?.outDir ?? getCliOption(cmd, "outDir"),
|
|
4455
4477
|
clean: configParsed?.clean ?? getCliOption(cmd, "clean"),
|
|
4456
|
-
themes: configParsed?.themes ?
|
|
4478
|
+
themes: configParsed?.themes ? R27.map((jsonThemeValues) => {
|
|
4457
4479
|
const defaultThemeValues = getThemeOptions(getDefaultCliOption);
|
|
4458
4480
|
const cliThemeValues = getThemeOptions(getSuppliedCliOption);
|
|
4459
|
-
const mergedConfigs =
|
|
4481
|
+
const mergedConfigs = R27.mergeDeepRight(defaultThemeValues, R27.mergeDeepRight(jsonThemeValues, cliThemeValues));
|
|
4460
4482
|
return mergedConfigs;
|
|
4461
4483
|
}, configParsed.themes) : (
|
|
4462
4484
|
// If there are no themes specified in the JSON config, we use both explicit
|
|
@@ -4466,11 +4488,7 @@ async function parseCreateConfig(configFile, options) {
|
|
|
4466
4488
|
}
|
|
4467
4489
|
)
|
|
4468
4490
|
});
|
|
4469
|
-
return validateConfig(configFileCreateSchema, unvalidatedConfig,
|
|
4470
|
-
}
|
|
4471
|
-
async function parseBuildConfig(configFile, { configPath }) {
|
|
4472
|
-
const configParsed = parseConfig(configFile, configPath);
|
|
4473
|
-
return validateConfig(commonConfig, configParsed, configPath);
|
|
4491
|
+
return validateConfig(configFileCreateSchema, unvalidatedConfig, configFilePath);
|
|
4474
4492
|
}
|
|
4475
4493
|
|
|
4476
4494
|
// bin/designsystemet.ts
|
|
@@ -4489,81 +4507,104 @@ var DEFAULT_TOKENS_CREATE_DIR = "./design-tokens";
|
|
|
4489
4507
|
var DEFAULT_TOKENS_BUILD_DIR = "./design-tokens-build";
|
|
4490
4508
|
var DEFAULT_FONT = "Inter";
|
|
4491
4509
|
var DEFAULT_THEME_NAME = "theme";
|
|
4492
|
-
var
|
|
4510
|
+
var DEFAULT_CONFIG_FILEPATH = "designsystemet.config.json";
|
|
4493
4511
|
function makeTokenCommands() {
|
|
4494
4512
|
const tokenCmd = createCommand("tokens");
|
|
4495
|
-
tokenCmd.command("build").description("Build Designsystemet tokens").option("-t, --tokens <string>", `Path to ${
|
|
4513
|
+
tokenCmd.command("build").description("Build Designsystemet tokens").option("-t, --tokens <string>", `Path to ${pc11.blue("design-tokens")}`, DEFAULT_TOKENS_CREATE_DIR).option(
|
|
4496
4514
|
"-o, --out-dir <string>",
|
|
4497
|
-
`Output directory for built ${
|
|
4515
|
+
`Output directory for built ${pc11.blue("design-tokens")}`,
|
|
4498
4516
|
DEFAULT_TOKENS_BUILD_DIR
|
|
4499
|
-
).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before building tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for built ${
|
|
4517
|
+
).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before building tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for built ${pc11.blue("design-tokens")}`, parseBoolean, false).option("--verbose", "Enable verbose output", false).option("--config <string>", `Path to config file (default: "${DEFAULT_CONFIG_FILEPATH}")`).option("--experimental-tailwind", "Generate Tailwind CSS classes for tokens", false).action(async (opts) => {
|
|
4500
4518
|
console.log(figletAscii);
|
|
4501
|
-
const { verbose, clean, dry, experimentalTailwind } = opts;
|
|
4502
|
-
|
|
4503
|
-
const outDir =
|
|
4504
|
-
const { configFile, configPath } = await getConfigFile(opts.config);
|
|
4505
|
-
const config = await parseBuildConfig(configFile, { configPath });
|
|
4506
|
-
if (dry) {
|
|
4507
|
-
console.log(`Performing dry run, no files will be written`);
|
|
4508
|
-
}
|
|
4519
|
+
const { verbose, clean, dry, experimentalTailwind, tokens } = opts;
|
|
4520
|
+
dsfs.init({ dry, outdir: opts.outDir, verbose });
|
|
4521
|
+
const outDir = dsfs.outDir;
|
|
4509
4522
|
if (clean) {
|
|
4510
|
-
await cleanDir(outDir
|
|
4523
|
+
await dsfs.cleanDir(outDir);
|
|
4511
4524
|
}
|
|
4512
|
-
await buildTokens({
|
|
4525
|
+
const files = await buildTokens({
|
|
4526
|
+
tokensDir: tokens,
|
|
4527
|
+
verbose,
|
|
4528
|
+
tailwind: experimentalTailwind
|
|
4529
|
+
});
|
|
4530
|
+
console.log(`
|
|
4531
|
+
\u{1F4BE} Writing build to ${pc11.green(outDir)}`);
|
|
4532
|
+
await dsfs.writeFiles(files, outDir, true);
|
|
4533
|
+
console.log(`
|
|
4534
|
+
\u2705 Finished building tokens in ${pc11.green(outDir)}`);
|
|
4513
4535
|
return Promise.resolve();
|
|
4514
4536
|
});
|
|
4515
4537
|
tokenCmd.command("create").description("Create Designsystemet tokens").option(`-m, --${cliOptions.theme.colors.main} <name:hex...>`, `Main colors`, parseColorValues).option(`-s, --${cliOptions.theme.colors.support} <name:hex...>`, `Support colors`, parseColorValues).option(`-n, --${cliOptions.theme.colors.neutral} <hex>`, `Neutral hex color`, convertToHex).option(
|
|
4516
4538
|
`-o, --${cliOptions.outDir} <string>`,
|
|
4517
|
-
`Output directory for created ${
|
|
4539
|
+
`Output directory for created ${pc11.blue("design-tokens")}`,
|
|
4518
4540
|
DEFAULT_TOKENS_CREATE_DIR
|
|
4519
|
-
).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before creating tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for created ${
|
|
4541
|
+
).option(`--${cliOptions.clean} [boolean]`, "Clean output directory before creating tokens", parseBoolean, false).option("--dry [boolean]", `Dry run for created ${pc11.blue("design-tokens")}`, parseBoolean, false).option(`-f, --${cliOptions.theme.typography.fontFamily} <string>`, `Font family (experimental)`, DEFAULT_FONT).option(
|
|
4520
4542
|
`-b, --${cliOptions.theme.borderRadius} <number>`,
|
|
4521
4543
|
`Unitless base border-radius in px`,
|
|
4522
4544
|
(radiusAsString) => Number(radiusAsString),
|
|
4523
4545
|
4
|
|
4524
|
-
).option("--theme <string>", "Theme name (ignored when using JSON config file)", DEFAULT_THEME_NAME).option("--config <string>", `Path to config file (default: "${
|
|
4546
|
+
).option("--theme <string>", "Theme name (ignored when using JSON config file)", DEFAULT_THEME_NAME).option("--config <string>", `Path to config file (default: "${DEFAULT_CONFIG_FILEPATH}")`).action(async (opts, cmd) => {
|
|
4525
4547
|
console.log(figletAscii);
|
|
4526
4548
|
if (opts.dry) {
|
|
4527
4549
|
console.log(`Performing dry run, no files will be written`);
|
|
4528
4550
|
}
|
|
4529
|
-
const
|
|
4551
|
+
const themeName = opts.theme;
|
|
4552
|
+
const { configFile, configFilePath } = await getConfigFile(opts.config);
|
|
4530
4553
|
const config = await parseCreateConfig(configFile, {
|
|
4531
|
-
theme:
|
|
4554
|
+
theme: themeName,
|
|
4532
4555
|
cmd,
|
|
4533
|
-
|
|
4556
|
+
configFilePath
|
|
4534
4557
|
});
|
|
4558
|
+
const themeNames = Object.keys(config.themes);
|
|
4559
|
+
if (themeNames.length > 0) {
|
|
4560
|
+
console.log(`Using themes from config file: ${pc11.blue(themeNames.join(", "))}`);
|
|
4561
|
+
}
|
|
4562
|
+
dsfs.init({ dry: opts.dry, outdir: config.outDir });
|
|
4563
|
+
const outDir = dsfs.outDir;
|
|
4535
4564
|
if (config.clean) {
|
|
4536
|
-
await cleanDir(
|
|
4565
|
+
await dsfs.cleanDir(outDir);
|
|
4537
4566
|
}
|
|
4567
|
+
let files = [];
|
|
4538
4568
|
if (config.themes) {
|
|
4539
4569
|
for (const [name, themeWithoutName] of Object.entries(config.themes)) {
|
|
4540
4570
|
const theme = { name, ...themeWithoutName };
|
|
4541
4571
|
const { tokenSets } = await createTokens(theme);
|
|
4542
|
-
await
|
|
4572
|
+
files = files.concat(await createTokenFiles({ outDir, theme, tokenSets, themeNames }));
|
|
4543
4573
|
}
|
|
4544
4574
|
}
|
|
4575
|
+
await dsfs.writeFiles(files, outDir);
|
|
4576
|
+
console.log(`
|
|
4577
|
+
\u2705 Finished creating tokens in ${pc11.green(outDir)} for themes: ${pc11.blue(themeNames.join(", "))}`);
|
|
4578
|
+
return Promise.resolve();
|
|
4545
4579
|
});
|
|
4546
4580
|
return tokenCmd;
|
|
4547
4581
|
}
|
|
4548
4582
|
program.addCommand(makeTokenCommands());
|
|
4549
|
-
program.command("generate-config-from-tokens").description("Generate a config file from existing design tokens. Will not include overrides.").option("-d, --dir <string>", "Path to design tokens directory", DEFAULT_TOKENS_CREATE_DIR).option("-o, --out <string>", "Output path for config file",
|
|
4583
|
+
program.command("generate-config-from-tokens").description("Generate a config file from existing design tokens. Will not include overrides.").option("-d, --dir <string>", "Path to design tokens directory", DEFAULT_TOKENS_CREATE_DIR).option("-o, --out <string>", "Output path for config file", DEFAULT_CONFIG_FILEPATH).option("--dry [boolean]", "Dry run - show config without writing file", parseBoolean, false).action(async (opts) => {
|
|
4550
4584
|
console.log(figletAscii);
|
|
4551
4585
|
const { dry } = opts;
|
|
4552
|
-
const tokensDir =
|
|
4553
|
-
const
|
|
4586
|
+
const tokensDir = path4.resolve(opts.dir);
|
|
4587
|
+
const configFilePath = path4.resolve(opts.out);
|
|
4588
|
+
dsfs.init({ dry, outdir: path4.dirname(configFilePath) });
|
|
4554
4589
|
try {
|
|
4555
4590
|
const config = await generateConfigFromTokens({
|
|
4556
4591
|
tokensDir,
|
|
4557
|
-
outFile:
|
|
4558
|
-
dry
|
|
4592
|
+
outFile: configFilePath
|
|
4559
4593
|
});
|
|
4560
4594
|
if (dry) {
|
|
4561
4595
|
console.log();
|
|
4562
4596
|
console.log("Generated config (dry run):");
|
|
4563
4597
|
console.log(JSON.stringify(config, null, 2));
|
|
4564
4598
|
}
|
|
4599
|
+
if (configFilePath) {
|
|
4600
|
+
const configJson = JSON.stringify(config, null, 2);
|
|
4601
|
+
await dsfs.writeFile(configFilePath, configJson);
|
|
4602
|
+
console.log();
|
|
4603
|
+
console.log(`
|
|
4604
|
+
\u2705 Config file written to ${pc11.blue(configFilePath)}`);
|
|
4605
|
+
}
|
|
4565
4606
|
} catch (error) {
|
|
4566
|
-
console.error(
|
|
4607
|
+
console.error(pc11.redBright("Error generating config:"));
|
|
4567
4608
|
console.error(error instanceof Error ? error.message : String(error));
|
|
4568
4609
|
process.exit(1);
|
|
4569
4610
|
}
|
|
@@ -4581,8 +4622,8 @@ program.command("migrate").description("run a Designsystemet migration").addArgu
|
|
|
4581
4622
|
console.error("Migration not found!");
|
|
4582
4623
|
throw "Aborting";
|
|
4583
4624
|
}
|
|
4584
|
-
console.log(`Applying migration ${
|
|
4585
|
-
migration?.(glob2).then(() => console.log(`Migration ${
|
|
4625
|
+
console.log(`Applying migration ${pc11.blue(migrationKey)} with glob: ${pc11.green(glob2)}`);
|
|
4626
|
+
migration?.(glob2).then(() => console.log(`Migration ${pc11.blue(migrationKey)} finished`)).catch((error) => console.log(error));
|
|
4586
4627
|
} else {
|
|
4587
4628
|
console.log("Migrate: please specify a migration name or --list");
|
|
4588
4629
|
}
|
|
@@ -4596,11 +4637,11 @@ function parseColorValues(value, previous = {}) {
|
|
|
4596
4637
|
function parseBoolean(value) {
|
|
4597
4638
|
return value === "true" || value === true;
|
|
4598
4639
|
}
|
|
4599
|
-
async function getConfigFile(
|
|
4600
|
-
const allowFileNotFound =
|
|
4601
|
-
const
|
|
4602
|
-
const configFile = await readConfigFile(
|
|
4603
|
-
return { configFile,
|
|
4640
|
+
async function getConfigFile(userConfigFilePath) {
|
|
4641
|
+
const allowFileNotFound = R28.isNil(userConfigFilePath) || userConfigFilePath === DEFAULT_CONFIG_FILEPATH;
|
|
4642
|
+
const configFilePath = userConfigFilePath ?? DEFAULT_CONFIG_FILEPATH;
|
|
4643
|
+
const configFile = await readConfigFile(configFilePath, allowFileNotFound);
|
|
4644
|
+
return { configFile, configFilePath };
|
|
4604
4645
|
}
|
|
4605
4646
|
export {
|
|
4606
4647
|
figletAscii
|