UNPKG

style-dictionary

Version:

Style once, use everywhere. A build system for creating cross-platform styles.

181 lines (160 loc) 5.12 kB
#!/usr/bin/env node 'use strict'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import node_fs from 'node:fs'; import JSON5 from 'json5'; import { Command } from 'commander'; // usually also node:fs in this context, but can be customized by user import { fs } from 'style-dictionary/fs'; import StyleDictionary from 'style-dictionary'; import { logWarningLevels, logVerbosityLevels } from '../lib/enums/index.js'; /** * @typedef {{ * config?: string; * platform?: string[]; * verbose?: boolean; * warn?: boolean; * silent?: boolean; * }} BuildOptions */ const program = new Command(); const __dirname = path.dirname(fileURLToPath(import.meta.url)); const { silent, verbose } = logVerbosityLevels; const pkg = JSON5.parse(node_fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); /** * @param {string} val * @param {string[]} arr */ function collect(val, arr) { arr.push(val); return arr; } /** * @param {BuildOptions} options */ function getConfigPath(options) { let configPath = options.config; if (!configPath) { if (fs.existsSync('./config.json')) { configPath = './config.json'; } else if (fs.existsSync('./config.js')) { configPath = './config.js'; } else { console.error('Build failed; unable to find config file.'); process.exit(1); } } return configPath; } program.version(pkg.version).description(pkg.description).usage('[command] [options]'); program .command('build') .description('Builds a style dictionary package from the current directory.') .option('-c, --config <path>', 'set config path. defaults to ./config.json') .option( '-v, --verbose', 'enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences', ) .option('-n, --no-warn', 'disable all warnings, only success logs and fatal errors shown') .option('-s, --silent', 'silence all logging, except for fatal errors') .option( '-p, --platform [platform]', 'only build specific platforms. Must be defined in the config', collect, [], ) .action(styleDictionaryBuild); program .command('clean') .description( 'Removes files specified in the config of the style dictionary package of the current directory.', ) .option('-c, --config <path>', 'set config path. defaults to ./config.json') .option( '-v, --verbose', 'enable verbose logging for reference errors, token collisions and filtered tokens with outputReferences', ) .option('-n, --no-warn', 'disable all warnings, only success logs and fatal errors shown') .option('-s, --silent', 'silence all logging, except for fatal errors') .option( '-p, --platform [platform]', 'only clean specific platform(s). Must be defined in the config', collect, [], ) .action(styleDictionaryClean); program .command('init <type>') .description('Generates a starter style dictionary') .action(function (type) { const types = ['basic', 'complete']; if (types.indexOf(type) < 0) { console.error('Please supply 1 type of project from: ' + types.join(', ')); process.exit(1); } /* eslint-disable no-console */ console.log('Copying starter files...\n'); node_fs.cpSync(path.join(__dirname, '..', 'examples', type), process.cwd(), { recursive: true, }); console.log('Source style dictionary starter files created!\n'); console.log( 'Running `style-dictionary build` for the first time to generate build artifacts.\n', ); styleDictionaryBuild(); }); // error on unknown commands program.on('command:*', function () { console.error( 'Invalid command: %s\nSee --help for a list of available commands.', process.argv.slice(2).join(' '), ); process.exit(1); }); /** * @param {string} configPath * @param {BuildOptions} options */ function getSD(configPath, options) { let verbosity; let warnings; if (options.verbose || options.silent) { verbosity = options.verbose ? verbose : silent; } if (options.warn === false) { warnings = logWarningLevels.disabled; } return new StyleDictionary(configPath, { verbosity, warnings }); } /** * @param {BuildOptions} [options] */ async function styleDictionaryBuild(options) { options = options || {}; const configPath = getConfigPath(options); const sd = getSD(configPath, options); if (options.platform && options.platform.length > 0) { await Promise.all(options.platform.map((platform) => sd.buildPlatform(platform))); } else { await sd.buildAllPlatforms(); } } /** * @param {BuildOptions} [options] */ async function styleDictionaryClean(options) { options = options || {}; const configPath = getConfigPath(options); const sd = getSD(configPath, options); if (options.platform && options.platform.length > 0) { await Promise.all(options.platform.map((platform) => sd.cleanPlatform(platform))); } else { await sd.cleanAllPlatforms(); } } program.parse(process.argv); // show help on no command if (!process.argv.slice(2).length) { program.outputHelp(); }