From 2f94b73c0ec121f5b8c6701d34d810d0fcd353ba Mon Sep 17 00:00:00 2001 From: Michael Marszalek Date: Wed, 11 Dec 2024 16:14:06 +0100 Subject: [PATCH] refactor: :recycle: Conform cli arguments for output (#2884) - `tokens create|build` will now by default write tokens - Removed: - `-o, --out` on `tokens build` - `-w, --write` on `tokens create` - New: - `-o, --out-dir` for defining which folder `tokens create|build` will be outputted to. - `--dry` option for ommiting writing/building tokens to test which token configuration would be generated Notes: - Used postcss and typescript cli as inspiration for cli commands --- .changeset/gorgeous-geese-boil.md | 5 +++ .changeset/lazy-wolves-provide.md | 5 +++ .changeset/wicked-pots-allow.md | 5 +++ .../components/TokenModal/TokenModal.tsx | 3 +- packages/cli/bin/designsystemet.ts | 39 +++++++++++------- packages/cli/package.json | 10 ++--- packages/cli/src/tokens/build.ts | 37 ++++++++++------- packages/cli/src/tokens/build/actions.ts | 40 ------------------- packages/cli/src/tokens/build/configs.ts | 2 +- packages/cli/src/tokens/build/formats/css.ts | 2 +- .../cli/src/tokens/build/formats/js-tokens.ts | 2 +- packages/cli/src/tokens/build/transformers.ts | 2 +- packages/cli/src/tokens/build/types.ts | 1 + .../cli/src/tokens/build/utils/entryfile.ts | 6 ++- .../cli/src/tokens/{build/utils => }/utils.ts | 38 ++++++++++++++++++ packages/cli/src/tokens/write.ts | 37 +++++++++-------- 16 files changed, 136 insertions(+), 98 deletions(-) create mode 100644 .changeset/gorgeous-geese-boil.md create mode 100644 .changeset/lazy-wolves-provide.md create mode 100644 .changeset/wicked-pots-allow.md delete mode 100644 packages/cli/src/tokens/build/actions.ts rename packages/cli/src/tokens/{build/utils => }/utils.ts (68%) diff --git a/.changeset/gorgeous-geese-boil.md b/.changeset/gorgeous-geese-boil.md new file mode 100644 index 0000000000..6e989ba031 --- /dev/null +++ b/.changeset/gorgeous-geese-boil.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet": minor +--- + +Added option dry run using `--dry` on `tokens create` & `tokens build` diff --git a/.changeset/lazy-wolves-provide.md b/.changeset/lazy-wolves-provide.md new file mode 100644 index 0000000000..28883e4141 --- /dev/null +++ b/.changeset/lazy-wolves-provide.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet": minor +--- + +`tokens create` now writes by default diff --git a/.changeset/wicked-pots-allow.md b/.changeset/wicked-pots-allow.md new file mode 100644 index 0000000000..d5ed47981b --- /dev/null +++ b/.changeset/wicked-pots-allow.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet": minor +--- + +Changed `-w, --write` to `-o, --out-dir` on `tokens create` & `tokens build` for defining output dir diff --git a/apps/theme/components/TokenModal/TokenModal.tsx b/apps/theme/components/TokenModal/TokenModal.tsx index e71e8e01d7..f37859d298 100644 --- a/apps/theme/components/TokenModal/TokenModal.tsx +++ b/apps/theme/components/TokenModal/TokenModal.tsx @@ -35,8 +35,7 @@ export const TokenModal = () => { --${colorCliOptions.main} ${setCliColors(colors.main)} \\ --${colorCliOptions.neutral} "${colors.neutral[0]?.colors.light[8].hex}" \\ --${colorCliOptions.support} ${setCliColors(colors.support)} \\ - --theme "${themeName}" \\ - --write`; + --theme "${themeName}"`; type InfoBoxType = { title: string; diff --git a/packages/cli/bin/designsystemet.ts b/packages/cli/bin/designsystemet.ts index da6a959cd5..49a57d2a9a 100644 --- a/packages/cli/bin/designsystemet.ts +++ b/packages/cli/bin/designsystemet.ts @@ -13,22 +13,30 @@ program.name('designsystemet').description('CLI for working with Designsystemet' function makeTokenCommands() { const tokenCmd = createCommand('tokens'); - const DEFAULT_TOKENSDIR = './design-tokens'; + const DEFAULT_TOKENS_DIR = './design-tokens'; + const DEFAULT_BUILD_DIR = './design-tokens-build'; tokenCmd .command('build') .description('Build Designsystemet tokens') - .option('-t, --tokens ', `Path to ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR) - .option('-o, --out ', `Output directory for built ${chalk.blue('design-tokens')}`, './build') + .option('-t, --tokens ', `Path to ${chalk.blue('design-tokens')}`, DEFAULT_TOKENS_DIR) + .option('-o, --out-dir ', `Output directory for built ${chalk.blue('design-tokens')}`, DEFAULT_BUILD_DIR) + .option('--dry [boolean]', `Dry run for built ${chalk.blue('design-tokens')}`, false) .option('-p, --preview', 'Generate preview token.ts files', false) .option('--verbose', 'Enable verbose output', false) .action((opts) => { - const tokens = typeof opts.tokens === 'string' ? opts.tokens : DEFAULT_TOKENSDIR; - const out = typeof opts.out === 'string' ? opts.out : './dist/tokens'; - const preview = opts.preview; - const verbose = opts.verbose; + const { preview, verbose } = opts; + const tokens = typeof opts.tokens === 'string' ? opts.tokens : DEFAULT_TOKENS_DIR; + const outDir = typeof opts.outDir === 'string' ? opts.outDir : './dist/tokens'; + const dry = Boolean(opts.dry); + console.log(`Building tokens in ${chalk.green(tokens)}`); - return buildTokens({ tokens, out, preview, verbose }); + + if (dry) { + console.log(`Performing dry run, no files will be written`); + } + + return buildTokens({ tokens, outDir, preview, verbose, dry }); }); tokenCmd .command('create') @@ -36,13 +44,14 @@ function makeTokenCommands() { .requiredOption(`-m, --${colorCliOptions.main} `, `Main colors`, parseColorValues) .requiredOption(`-s, --${colorCliOptions.support} `, `Support colors`, parseColorValues) .requiredOption(`-n, --${colorCliOptions.neutral} `, `Neutral hex color`, convertToHex) - .option('-w, --write [string]', `Output directory for created ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR) + .option('-o, --out-dir ', `Output directory for created ${chalk.blue('design-tokens')}`, DEFAULT_TOKENS_DIR) + .option('--dry [boolean]', `Dry run for created ${chalk.blue('design-tokens')}`, false) .option('-f, --font-family ', `Font family`, 'Inter') .option('--theme ', `Theme name`, 'theme') .action(async (opts) => { - const { theme, fontFamily } = opts; + const { theme, fontFamily, outDir } = opts; + const dry = Boolean(opts.dry); console.log(`Creating tokens with options ${chalk.green(JSON.stringify(opts, null, 2))}`); - const write = typeof opts.write === 'boolean' ? DEFAULT_TOKENSDIR : opts.write; const props = { themeName: theme, @@ -56,11 +65,13 @@ function makeTokenCommands() { }, }; + if (dry) { + console.log(`Performing dry run, no files will be written`); + } + const tokens = createTokens(props); - if (write) { - await writeTokens({ writeDir: write, tokens, themeName: theme, colors: props.colors }); - } + await writeTokens({ outDir, tokens, themeName: theme, colors: props.colors, dry }); return Promise.resolve(); }); diff --git a/packages/cli/package.json b/packages/cli/package.json index 1c1b49944b..a85e28dc97 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -35,17 +35,17 @@ "build:tokens:debug": "yarn clean:theme && tsx --inspect-brk ./bin/designsystemet.ts tokens build -p -t ../../design-tokens -o ../../packages/theme/brand", "build": "tsup && yarn build:types", "build:types": "tsc --emitDeclarationOnly --declaration", - "test:tokens-create": "yarn designsystemet tokens create -m dominant:#007682 secondary:#ff0000 -n #003333 -s support1:#12404f support2:#0054a6 support3:#942977 -w ./test-tokens-create", + "test:tokens-create": "yarn designsystemet tokens create -m dominant:#007682 secondary:#ff0000 -n #003333 -s support1:#12404f support2:#0054a6 support3:#942977 -o ./test-tokens-create", "test:tokens-build": "yarn designsystemet tokens build -t ./test-tokens-create -o ./test-tokens-build", "test:tokens-create-and-build": "rimraf test-tokens-create && rimraf test-tokens-build && yarn test:tokens-create && yarn test:tokens-build", "test": "yarn test:tokens-create-and-build", "clean": "rimraf dist", "clean:theme": "yarn workspace @digdir/designsystemet-theme clean", "update:template": "tsx ./src/tokens/template.ts", - "internal:tokens-create-digdir": "yarn designsystemet tokens create --theme theme -m accent:#0062BA -n #1E2B3C -s brand1:#F45F63 brand2:#E5AA20 brand3:#1E98F5 -w ./internal/design-tokens", - "internal:tokens-create-altinn": "yarn designsystemet tokens create --theme theme2 -m accent:#0162BA -n #1E2B3C -s brand1:#0162BA brand2:#3F3161 brand3:#E02F4A -w ./internal/design-tokens", - "internal:tokens-create-uutilsynet": "yarn designsystemet tokens create --theme theme3 -m accent:#0162BA -n #1E2B3C -s brand1:#5B60D1 brand2:#FEA769 brand3:#5DA290 -w ./internal/design-tokens", - "internal:tokens-create-portal": "yarn designsystemet tokens create --theme theme4 -m accent:#4D107D -n #1E2B3C -s brand1:#A259DC brand2:#DF73E4 brand3:#E86ABF -w ./internal/design-tokens", + "internal:tokens-create-digdir": "yarn designsystemet tokens create --theme theme -m accent:#0062BA -n #1E2B3C -s brand1:#F45F63 brand2:#E5AA20 brand3:#1E98F5 -o ./internal/design-tokens", + "internal:tokens-create-altinn": "yarn designsystemet tokens create --theme theme2 -m accent:#0162BA -n #1E2B3C -s brand1:#0162BA brand2:#3F3161 brand3:#E02F4A -o ./internal/design-tokens", + "internal:tokens-create-uutilsynet": "yarn designsystemet tokens create --theme theme3 -m accent:#0162BA -n #1E2B3C -s brand1:#5B60D1 brand2:#FEA769 brand3:#5DA290 -o ./internal/design-tokens", + "internal:tokens-create-portal": "yarn designsystemet tokens create --theme theme4 -m accent:#4D107D -n #1E2B3C -s brand1:#A259DC brand2:#DF73E4 brand3:#E86ABF -o ./internal/design-tokens", "internal:tokens-create-all": "yarn internal:tokens-create-digdir && yarn internal:tokens-create-altinn && yarn internal:tokens-create-uutilsynet && yarn internal:tokens-create-portal" }, "dependencies": { diff --git a/packages/cli/src/tokens/build.ts b/packages/cli/src/tokens/build.ts index 82755fd390..36ae111110 100644 --- a/packages/cli/src/tokens/build.ts +++ b/packages/cli/src/tokens/build.ts @@ -10,6 +10,7 @@ import { configs, getConfigsForThemeDimensions } from './build/configs.js'; import { type BuildConfig, type ThemePermutation, colorCategories } from './build/types.js'; import { makeEntryFile } from './build/utils/entryfile.js'; import { type ProcessedThemeObject, processThemeObject } from './build/utils/getMultidimensionalThemes.js'; +import { copyFile, writeFile } from './utils.js'; export const DEFAULT_COLOR = 'accent'; @@ -17,13 +18,15 @@ type Options = { /** Design tokens path */ tokens: string; /** Output directory for built tokens */ - out: string; + outDir: string; /** Generate preview tokens */ preview: boolean; /** Enable verbose output */ verbose: boolean; /** Set the default "accent" color, if not overridden with data-color */ accentColor?: string; + /** Dry run */ + dry?: boolean; }; export let buildOptions: Options | undefined; @@ -50,26 +53,26 @@ const buildConfigs = { name: 'CSS entry files', getConfig: configs.semanticVariables, dimensions: ['semantic'], - build: async (sdConfigs, { outPath }) => { + build: async (sdConfigs, { outPath, dry }) => { await Promise.all( sdConfigs.map(async ({ permutation: { theme } }) => { console.log(`šŸ‘· ${theme}.css`); const builtinColorsFilename = 'builtin-colors.css'; const builtinColors = path.resolve(import.meta.dirname, 'build', builtinColorsFilename); - await fs.copyFile(builtinColors, path.resolve(outPath, theme, builtinColorsFilename)); + await copyFile(builtinColors, path.resolve(outPath, theme, builtinColorsFilename), dry); - return makeEntryFile({ theme, outPath, buildPath: path.resolve(outPath, theme) }); + return makeEntryFile({ theme, outPath, buildPath: path.resolve(outPath, theme), dry }); }), ); }, }, } satisfies Record; -export async function buildTokens(options: Options): Promise { - buildOptions = options; - const tokensDir = options.tokens; - const outPath = path.resolve(options.out); +export async function buildTokens(buildOptions: Options): Promise { + const { dry } = buildOptions; + const tokensDir = buildOptions.tokens; + const targetDir = path.resolve(buildOptions.outDir); /* * Build the themes @@ -97,7 +100,7 @@ export async function buildTokens(options: Options): Promise { (val: BuildConfig) => ({ buildConfig: val, sdConfigs: getConfigsForThemeDimensions(val.getConfig, relevant$themes, val.dimensions, { - outPath, + outPath: targetDir, tokensDir, ...val.options, }), @@ -114,15 +117,20 @@ export async function buildTokens(options: Options): Promise { console.log(`\nšŸ± Building ${chalk.green(buildConfig.name ?? key)}`); if (buildConfig.build) { - await buildConfig.build(sdConfigs, { outPath, tokensDir, ...buildConfig.options }); + await buildConfig.build(sdConfigs, { outPath: targetDir, tokensDir, ...buildConfig.options, dry }); } + await Promise.all( sdConfigs.map(async ({ config, permutation }) => { const modes: Array = ['theme', ...buildConfig.dimensions]; const modeMessage = modes.map((x) => permutation[x]).join(' - '); console.log(modeMessage); - return (await sd.extend(config)).buildAllPlatforms(); + if (!dry) { + return (await sd.extend(config)).buildAllPlatforms(); + } + + return Promise.resolve(); }), ); } @@ -138,10 +146,10 @@ export async function buildTokens(options: Options): Promise { throw err; } - await writeColorTypeDeclaration($themes, outPath); + await writeColorTypeDeclaration($themes, targetDir, dry); } -async function writeColorTypeDeclaration($themes: ProcessedThemeObject[], outPath: string) { +async function writeColorTypeDeclaration($themes: ProcessedThemeObject[], outPath: string, dry?: boolean) { const colorsFileName = 'colors.d.ts'; console.log(`\nšŸ± Building ${chalk.green('type declarations')}`); console.log(colorsFileName); @@ -159,5 +167,6 @@ ${mainAndSupportColors.map((color) => ` ${color}: never;`).join('\n')} } } `.trimStart(); - await fs.writeFile(path.resolve(outPath, colorsFileName), typeDeclaration, 'utf-8'); + + await writeFile(path.resolve(outPath, colorsFileName), typeDeclaration, dry); } diff --git a/packages/cli/src/tokens/build/actions.ts b/packages/cli/src/tokens/build/actions.ts deleted file mode 100644 index c308c8124d..0000000000 --- a/packages/cli/src/tokens/build/actions.ts +++ /dev/null @@ -1,40 +0,0 @@ -import chalk from 'chalk'; -import glob from 'fast-glob'; -import fs from 'fs-extra'; -import * as R from 'ramda'; -import type { Action } from 'style-dictionary/types'; - -const sortLightmodeFirst = R.sortWith([R.descend(R.includes('light')), R.descend(R.includes('secondary'))]); - -const header = `@charset "UTF-8"; - -@layer ds.reset, ds.theme, ds.base, ds.utilities, ds.components; -\n`; - -/** - * Creates a CSS entry file that imports base CSS files for a theme - */ -export const makeEntryFile: Action = { - name: 'make_entryfile', - do: async (dictionary, platform) => { - const { outPath, theme, log } = platform; - - const writePath = `${outPath}/${theme}.css`; - - if (log?.verbosity !== 'silent') { - console.log(chalk.green(`Creating entry file: ${writePath}`)); - } - - const generateImportUrls = R.pipe( - sortLightmodeFirst, - R.map((file): string => `@import url('${theme}/${file.toString()}');`), - R.join('\n'), - ); - - const files = await glob(`**/*`, { cwd: platform.buildPath }); - const content = header + generateImportUrls(files); - - await fs.writeFile(writePath, content); - }, - undo: async function noOp() {}, -}; diff --git a/packages/cli/src/tokens/build/configs.ts b/packages/cli/src/tokens/build/configs.ts index 8b3721ec0e..415e327974 100644 --- a/packages/cli/src/tokens/build/configs.ts +++ b/packages/cli/src/tokens/build/configs.ts @@ -5,6 +5,7 @@ import type { Config as StyleDictionaryConfig, TransformedToken } from 'style-di import { outputReferencesFilter } from 'style-dictionary/utils'; import { DEFAULT_COLOR, buildOptions } from '../build.js'; +import { isColorCategoryToken, pathStartsWithOneOf, typeEquals } from '../utils.js'; import { formats } from './formats/css.js'; import { jsTokens } from './formats/js-tokens.js'; import { nameKebab, resolveMath, sizeRem, typographyName } from './transformers.js'; @@ -17,7 +18,6 @@ import type { ThemePermutation, } from './types.js'; import { type ProcessedThemeObject, getMultidimensionalThemes } from './utils/getMultidimensionalThemes.js'; -import { isColorCategoryToken, pathStartsWithOneOf, typeEquals } from './utils/utils.js'; void register(StyleDictionary, { withSDBuiltins: false }); /** Use official W3C design token format diff --git a/packages/cli/src/tokens/build/formats/css.ts b/packages/cli/src/tokens/build/formats/css.ts index 03a5ca9063..ed3d80f77a 100644 --- a/packages/cli/src/tokens/build/formats/css.ts +++ b/packages/cli/src/tokens/build/formats/css.ts @@ -3,8 +3,8 @@ import type { TransformedToken } from 'style-dictionary'; import type { Format } from 'style-dictionary/types'; import { createPropertyFormatter, fileHeader, usesReferences } from 'style-dictionary/utils'; +import { getValue, isColorCategoryToken, isGlobalColorToken, isSemanticToken } from '../../utils.js'; import { type IsCalculatedToken, colorCategories } from '../types.js'; -import { getValue, isColorCategoryToken, isGlobalColorToken, isSemanticToken } from '../utils/utils.js'; const prefersColorScheme = (colorScheme: string, content: string) => ` @media (prefers-color-scheme: ${colorScheme}) { diff --git a/packages/cli/src/tokens/build/formats/js-tokens.ts b/packages/cli/src/tokens/build/formats/js-tokens.ts index e0416a1a2e..c56fdafa2f 100644 --- a/packages/cli/src/tokens/build/formats/js-tokens.ts +++ b/packages/cli/src/tokens/build/formats/js-tokens.ts @@ -2,7 +2,7 @@ import * as R from 'ramda'; import type { Format, TransformedToken } from 'style-dictionary/types'; import { createPropertyFormatter, fileHeader } from 'style-dictionary/utils'; -import { getType, isColorCategoryToken } from '../utils/utils.js'; +import { getType, isColorCategoryToken } from '../../utils.js'; const groupByType = R.groupBy((token: TransformedToken) => getType(token)); diff --git a/packages/cli/src/tokens/build/transformers.ts b/packages/cli/src/tokens/build/transformers.ts index 60a77a3960..fa7d962010 100644 --- a/packages/cli/src/tokens/build/transformers.ts +++ b/packages/cli/src/tokens/build/transformers.ts @@ -2,8 +2,8 @@ import { checkAndEvaluateMath } from '@tokens-studio/sd-transforms'; import * as R from 'ramda'; import type { Transform } from 'style-dictionary/types'; +import { getValue, pathStartsWithOneOf, typeEquals } from '../utils.js'; import { noCase } from './utils/noCase.js'; -import { getValue, pathStartsWithOneOf, typeEquals } from './utils/utils.js'; const isPx = R.test(/\b\d+px\b/g); diff --git a/packages/cli/src/tokens/build/types.ts b/packages/cli/src/tokens/build/types.ts index 16e5e7dd0e..a69d89699a 100644 --- a/packages/cli/src/tokens/build/types.ts +++ b/packages/cli/src/tokens/build/types.ts @@ -27,6 +27,7 @@ export type IsCalculatedToken = (token: TransformedToken, options?: StyleDiction export type GetSdConfigOptions = { outPath: string; tokensDir: string; + dry?: boolean; }; export type BuildConfig = { diff --git a/packages/cli/src/tokens/build/utils/entryfile.ts b/packages/cli/src/tokens/build/utils/entryfile.ts index 13238b71d5..b5a2891dd1 100644 --- a/packages/cli/src/tokens/build/utils/entryfile.ts +++ b/packages/cli/src/tokens/build/utils/entryfile.ts @@ -2,6 +2,7 @@ import chalk from 'chalk'; import glob from 'fast-glob'; import fs from 'fs-extra'; import * as R from 'ramda'; +import { writeFile } from '../../utils'; /** * Defines a sort order for the sections of the entry CSS file. @@ -68,12 +69,13 @@ type EntryFile = (options: { outPath: string; buildPath: string; theme: string; + dry?: boolean; }) => Promise; /** * Creates a CSS entry file that imports base CSS files for a theme */ -export const makeEntryFile: EntryFile = async ({ outPath, buildPath, theme }) => { +export const makeEntryFile: EntryFile = async ({ outPath, buildPath, theme, dry }) => { const writePath = `${outPath}/${theme}.css`; const files = await glob(`**/*`, { cwd: buildPath }); @@ -81,5 +83,5 @@ export const makeEntryFile: EntryFile = async ({ outPath, buildPath, theme }) => const sortedFileNames = R.pipe(sortAlphabetically, sortByDefinedOrder)(files); const content = header + concat(sortedFileNames.map((file) => `${buildPath}/${file}`)); - await fs.writeFile(writePath, content); + await writeFile(writePath, content, dry); }; diff --git a/packages/cli/src/tokens/build/utils/utils.ts b/packages/cli/src/tokens/utils.ts similarity index 68% rename from packages/cli/src/tokens/build/utils/utils.ts rename to packages/cli/src/tokens/utils.ts index c71e58e0b5..c09ebdb241 100644 --- a/packages/cli/src/tokens/build/utils/utils.ts +++ b/packages/cli/src/tokens/utils.ts @@ -1,3 +1,5 @@ +import fs from 'node:fs/promises'; +import chalk from 'chalk'; import * as R from 'ramda'; import type { DesignToken, TransformedToken } from 'style-dictionary/types'; @@ -61,3 +63,39 @@ export function isColorCategoryToken(token: TransformedToken, category?: 'main' } return R.startsWith(['color', category], token.path); } + +export const mkdir = async (dir: string, dry?: boolean) => { + if (dry) { + console.log(`${chalk.blue('mkdir')} ${dir}`); + return Promise.resolve(); + } + + return await fs.mkdir(dir, { recursive: true }); +}; + +export const writeFile = async (path: string, data: string, dry?: boolean) => { + if (dry) { + console.log(`${chalk.blue('writeFile')} ${path}`); + return Promise.resolve(); + } + + return await fs.writeFile(path, data, { encoding: 'utf-8' }); +}; + +export const cp = async (src: string, dest: string, dry?: boolean) => { + if (dry) { + console.log(`${chalk.blue('cp')} ${src} ${dest}`); + return Promise.resolve(); + } + + return await fs.cp(src, dest, { recursive: true }); +}; + +export const copyFile = async (src: string, dest: string, dry?: boolean) => { + if (dry) { + console.log(`${chalk.blue('copyFile')} ${src} to ${dest}`); + return Promise.resolve(); + } + + return await fs.copyFile(src, dest); +}; diff --git a/packages/cli/src/tokens/write.ts b/packages/cli/src/tokens/write.ts index b2407cfb02..97a9c982b7 100644 --- a/packages/cli/src/tokens/write.ts +++ b/packages/cli/src/tokens/write.ts @@ -14,6 +14,7 @@ import semanticColorTemplate from './design-tokens/template/semantic/semantic-co import themeBaseFile from './design-tokens/template/themes/theme-base-file.json' with { type: 'json' }; import themeColorTemplate from './design-tokens/template/themes/theme-color-template.json' with { type: 'json' }; import type { Collection, Colors, File, Tokens, TokensSet, TypographyModes } from './types.js'; +import { cp, mkdir, writeFile } from './utils.js'; import { generateMetadataJson } from './write/generate$metadata.js'; import { generateThemesJson } from './write/generate$themes.js'; @@ -47,20 +48,21 @@ const generateTypographyFile = ( }; type WriteTokensOptions = { - writeDir: string; + outDir: string; tokens: Tokens; themeName: string; colors: Colors; + dry?: boolean; }; export const writeTokens = async (options: WriteTokensOptions) => { - const { writeDir, tokens, themeName, colors } = options; - const targetDir = path.resolve(process.cwd(), String(writeDir)); + const { outDir, tokens, themeName, colors, dry } = options; + const targetDir = path.resolve(process.cwd(), String(outDir)); const $themesPath = path.join(targetDir, '$themes.json'); const $metadataPath = path.join(targetDir, '$metadata.json'); let themes = [themeName]; - await fs.mkdir(targetDir, { recursive: true }); + await mkdir(targetDir, dry); try { // Update with existing themes @@ -80,13 +82,11 @@ export const writeTokens = async (options: WriteTokensOptions) => { const $theme = generateThemesJson(['light', 'dark'], themes, colors); const $metadata = generateMetadataJson(['light', 'dark'], themes, colors); - await fs.writeFile($themesPath, stringify($theme)); - await fs.writeFile($metadataPath, stringify($metadata)); + await writeFile($themesPath, stringify($theme), dry); + await writeFile($metadataPath, stringify($metadata), dry); // Copy default files - await fs.cp(DEFAULT_FILES_PATH, targetDir, { - recursive: true, - }); + await cp(DEFAULT_FILES_PATH, targetDir, dry); /* * Colors @@ -103,7 +103,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { ['support', supportColorNames], ] as const) { const colorCategoryPath = path.join(targetDir, 'semantic', 'modes', `${colorCategory}-color`); - await fs.mkdir(colorCategoryPath, { recursive: true }); + await mkdir(colorCategoryPath, dry); for (const colorName of colorNames) { const customColorFile = { @@ -112,7 +112,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { }, }; - await fs.writeFile( + await writeFile( path.join(colorCategoryPath, `${colorName}.json`), JSON.stringify( customColorFile, @@ -124,6 +124,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { }, 2, ), + dry, ); } } @@ -143,7 +144,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { ...semanticColorBaseFile.color, }, }; - await fs.writeFile( + await writeFile( path.join(targetDir, `semantic/color.json`), JSON.stringify( semanticColors, @@ -155,10 +156,11 @@ export const writeTokens = async (options: WriteTokensOptions) => { }, 2, ), + dry, ); // Create themes file - await fs.mkdir(path.join(targetDir, 'themes'), { recursive: true }); + await mkdir(path.join(targetDir, 'themes'), dry); const themeColorTokens = Object.fromEntries( customColors.map( @@ -179,7 +181,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { ...remainingThemeFile, }; - await fs.writeFile( + await writeFile( path.join(targetDir, `themes/${themeName}.json`), JSON.stringify( themeFile, @@ -191,6 +193,7 @@ export const writeTokens = async (options: WriteTokensOptions) => { }, 2, ), + dry, ); // Create color scheme and typography modes @@ -208,11 +211,11 @@ export const writeTokens = async (options: WriteTokensOptions) => { for (const file of files) { const dirPath = path.resolve(file.path); const filePath = path.resolve(file.filePath); - await fs.mkdir(dirPath, { recursive: true }); - await fs.writeFile(filePath, file.data, { encoding: 'utf-8' }); + await mkdir(dirPath, dry); + await writeFile(filePath, file.data, dry); } console.log( - `Finished creating Designsystem design tokens in ${chalk.green(writeDir)} for theme ${chalk.blue(themeName)}`, + `Finished creating Designsystem design tokens in ${chalk.green(outDir)} for theme ${chalk.blue(themeName)}`, ); };