From aa9feb2b1c7de22c0420e8184403ba5570b8576f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Mon, 1 Nov 2021 10:06:43 +0100 Subject: [PATCH] feat(cli): allow all CLI options in config (#615) Also run Prettier on index.js file. Closes #570 --- __fixtures__/custom-index-template.js | 2 +- .../cli/src/__snapshots__/index.test.ts.snap | 13 +++-- packages/cli/src/dirCommand.ts | 50 ++++++++++++------- packages/cli/src/fileCommand.ts | 5 +- packages/cli/src/index.test.ts | 38 +++++++------- packages/cli/src/index.ts | 34 +++---------- 6 files changed, 72 insertions(+), 70 deletions(-) diff --git a/__fixtures__/custom-index-template.js b/__fixtures__/custom-index-template.js index ae83c6f9..5fc35dbc 100644 --- a/__fixtures__/custom-index-template.js +++ b/__fixtures__/custom-index-template.js @@ -3,7 +3,7 @@ const path = require('path') function indexTemplate(files) { const exportEntries = files.map(file => { const basename = path.basename(file, path.extname(file)) - return `export { ${basename} } from './${basename}'` + return `export { ${basename} } from './${basename}';` }) return exportEntries.join('\n') } diff --git a/packages/cli/src/__snapshots__/index.test.ts.snap b/packages/cli/src/__snapshots__/index.test.ts.snap index a11c02f9..378c60a5 100644 --- a/packages/cli/src/__snapshots__/index.test.ts.snap +++ b/packages/cli/src/__snapshots__/index.test.ts.snap @@ -2,7 +2,8 @@ exports[`cli should add Svg prefix to index.js exports staring with number 1`] = ` "export { default as Svg2File } from './2File' -export { default as File } from './File'" +export { default as File } from './File' +" `; exports[`cli should not override config with cli defaults 1`] = ` @@ -19,7 +20,10 @@ export default SvgFile " `; -exports[`cli should support --index-template in cli 1`] = `"export { File } from './File'"`; +exports[`cli should support --index-template in cli 1`] = ` +"export { File } from './File' +" +`; exports[`cli should support --no-index 1`] = ` Array [ @@ -92,7 +96,10 @@ Array [ ] `; -exports[`cli should support custom index.js with directory output 1`] = `"export { default as File } from './File'"`; +exports[`cli should support custom index.js with directory output 1`] = ` +"export { File } from './File' +" +`; exports[`cli should support different filename cases with directory output 1`] = ` Array [ diff --git a/packages/cli/src/dirCommand.ts b/packages/cli/src/dirCommand.ts index 38fcb5d8..74f1e82b 100644 --- a/packages/cli/src/dirCommand.ts +++ b/packages/cli/src/dirCommand.ts @@ -3,13 +3,14 @@ import { promises as fs } from 'fs' import * as path from 'path' import { grey, white } from 'chalk' import { loadConfig, Config } from '@svgr/core' +import { format, resolveConfig } from 'prettier' import { convertFile, transformFilename, politeWrite, formatExportName, } from './util' -import type { SvgrCommand } from './index' +import type { Options, SvgrCommand } from './index' const exists = async (filepath: string) => { try { @@ -50,20 +51,20 @@ const resolveExtension = (config: Config, ext?: string) => ext || (config.typescript ? 'tsx' : 'js') export const dirCommand: SvgrCommand = async ( - { + opts, + _, + filenames, +): Promise => { + const { ext: extOpt, filenameCase = 'pascal', ignoreExisting, silent, - indexTemplate: indexTemplateOpt, configFile, outDir, - }, - _, - filenames, - config, -): Promise => { - const ext = resolveExtension(config, extOpt) + } = opts + + const ext = resolveExtension(opts, extOpt) const write = async (src: string, dest: string) => { if (!isCompilable(src)) { @@ -71,7 +72,7 @@ export const dirCommand: SvgrCommand = async ( } dest = rename(dest, ext, filenameCase) - const code = await convertFile(src, config) + const code = await convertFile(src, opts) const cwdRelative = path.relative(process.cwd(), dest) const logOutput = `${src} -> ${cwdRelative}\n` @@ -86,10 +87,25 @@ export const dirCommand: SvgrCommand = async ( return { transformed: true, dest } } - const generateIndex = async (dest: string, files: string[]) => { - const indexFile = path.join(dest, `index.${ext}`) - const indexTemplate = indexTemplateOpt || defaultIndexTemplate - await fs.writeFile(indexFile, indexTemplate(files)) + const generateIndex = async ( + dest: string, + files: string[], + opts: Options, + ) => { + const filepath = path.join(dest, `index.${ext}`) + const indexTemplate = opts.indexTemplate || defaultIndexTemplate + const fileContent = indexTemplate(files) + const prettyContent = await (async () => { + if (!opts.prettier) return fileContent + const prettierRcConfig = opts.runtimeConfig + ? await resolveConfig(filepath, { editorconfig: true }) + : {} + return format(fileContent, { + ...prettierRcConfig, + ...opts.prettierConfig, + }) + })() + await fs.writeFile(filepath, prettyContent) } async function handle(filename: string, root: string) { @@ -114,11 +130,11 @@ export const dirCommand: SvgrCommand = async ( path.relative(root, dirname), ) const resolvedConfig = loadConfig.sync( - { configFile, ...config }, + { configFile, ...opts }, { filePath: dest }, - ) + ) as Options if (resolvedConfig.index) { - await generateIndex(dest, destFiles) + await generateIndex(dest, destFiles, opts) } } return { transformed: false, dest: null } diff --git a/packages/cli/src/fileCommand.ts b/packages/cli/src/fileCommand.ts index ae591e68..47de0e2d 100644 --- a/packages/cli/src/fileCommand.ts +++ b/packages/cli/src/fileCommand.ts @@ -21,11 +21,10 @@ export const fileCommand: SvgrCommand = async ( opts, program, filenames, - config, ): Promise => { if (opts.stdin || (filenames.length === 0 && !process.stdin.isTTY)) { const input = await readStdin() - const output = convert(input, config, { filePath: opts.stdinFilepath }) + const output = convert(input, opts, { filePath: opts.stdinFilepath }) process.stdout.write(`${output}\n`) return } @@ -46,6 +45,6 @@ export const fileCommand: SvgrCommand = async ( exitError('Directory are not supported without `--out-dir` option instead.') } - const output = await convertFile(filename, config) + const output = await convertFile(filename, opts) process.stdout.write(`${output}\n`) } diff --git a/packages/cli/src/index.test.ts b/packages/cli/src/index.test.ts index 4017bf3e..45f8d52a 100644 --- a/packages/cli/src/index.test.ts +++ b/packages/cli/src/index.test.ts @@ -18,7 +18,7 @@ describe('cli', () => { it('should work with a simple file', async () => { const result = await cli('__fixtures__/simple/file.svg') expect(result).toMatchSnapshot() - }, 10000) + }) it('should not work with a directory without --out-dir option', async () => { expect.assertions(1) @@ -29,7 +29,7 @@ describe('cli', () => { 'Directory are not supported without `--out-dir` option instead', ) } - }, 10000) + }) it('should not work with several files without destination', async () => { expect.assertions(1) @@ -40,19 +40,19 @@ describe('cli', () => { 'Please specify only one filename or use `--out-dir` option', ) } - }, 10000) + }) it('should work with stdin', async () => { const result = await cli('< __fixtures__/simple/file.svg') expect(result).toMatchSnapshot() - }, 10000) + }) it('should support stdin filepath', async () => { const result = await cli( '--stdin-filepath __fixtures__/simple/file.svg < __fixtures__/simple/file.svg', ) expect(result).toMatchSnapshot() - }, 10000) + }) it('should transform a whole directory and output relative destination paths', async () => { const result = await cli('--out-dir __fixtures_build__/whole __fixtures__') @@ -62,7 +62,7 @@ describe('cli', () => { .map((x) => x.toLowerCase()) .join('\n') expect(sorted).toMatchSnapshot() - }, 10000) + }) it('should transform a whole directory with --typescript', async () => { const result = await cli( @@ -74,7 +74,7 @@ describe('cli', () => { .map((x) => x.toLowerCase()) .join('\n') expect(sorted).toMatchSnapshot() - }, 10000) + }) it('should suppress output when transforming a directory with a --silent option', async () => { const result = await cli( @@ -82,35 +82,35 @@ describe('cli', () => { ) const sorted = result.split(/\n/).sort().join('\n') expect(sorted).toMatchSnapshot() - }, 10000) + }) it('should support --prettier-config as json', async () => { const result = await cli( `--prettier-config '{"tabWidth": 5}' __fixtures__/simple/file.svg`, ) expect(result).toMatchSnapshot() - }, 10000) + }) it('should support --prettier-config as file', async () => { const result = await cli( `--prettier-config __fixtures__/withPrettierRc/.prettierrc __fixtures__/simple/file.svg`, ) expect(result).toMatchSnapshot() - }, 10000) + }) it('should support --svgo-config as json', async () => { const result = await cli( `--svgo-config '{"plugins":[{"name":"preset-default","params":{"overrides":{"removeTitle":false}}}]}' __fixtures__/simple/file.svg`, ) expect(result).toMatchSnapshot() - }, 10000) + }) it('should support --svgo-config as file', async () => { const result = await cli( `--svgo-config __fixtures__/withSvgoConfig/svgo.config.js __fixtures__/simple/file.svg`, ) expect(result).toMatchSnapshot() - }, 10000) + }) it.each([ ['--no-dimensions'], @@ -164,7 +164,7 @@ describe('cli', () => { await del(outDir) await cli(`--ext=ts ${inDir} --out-dir=${outDir}`) expect(await fs.readdir(outDir)).toMatchSnapshot() - }, 10000) + }) it('should support "--ignore-existing"', async () => { const inDir = '__fixtures__/simple' @@ -172,14 +172,14 @@ describe('cli', () => { await cli(`${inDir} --out-dir=${outDir} --ignore-existing`) const content = await fs.readFile(path.join(outDir, 'File.js'), 'utf-8') expect(content).toBe('// nothing') - }, 10000) + }) it('should not override config with cli defaults', async () => { const result = await cli( '__fixtures__/simple/file.svg --config-file=__fixtures__/overrides.config.js', ) expect(result).toMatchSnapshot() - }, 10000) + }) it('should add Svg prefix to index.js exports staring with number', async () => { const inDir = '__fixtures__/numeric' @@ -188,7 +188,7 @@ describe('cli', () => { await cli(`${inDir} --out-dir=${outDir}`) const content = await fs.readFile(path.join(outDir, 'index.js'), 'utf-8') expect(content).toMatchSnapshot() - }, 10000) + }) it('should support custom index.js with directory output', async () => { const inDir = '__fixtures__/simple' @@ -199,7 +199,7 @@ describe('cli', () => { ) const content = await fs.readFile(path.join(outDir, 'index.js'), 'utf-8') expect(content).toMatchSnapshot() - }, 10000) + }) it('should support --index-template in cli', async () => { const inDir = '__fixtures__/simple' @@ -210,7 +210,7 @@ describe('cli', () => { ) const content = await fs.readFile(path.join(outDir, 'index.js'), 'utf-8') expect(content).toMatchSnapshot() - }, 10000) + }) it('should support --no-index', async () => { const inDir = '__fixtures__/simple' @@ -218,5 +218,5 @@ describe('cli', () => { await del(outDir) await cli(`--no-index ${inDir} --out-dir=${outDir}`) expect(await fs.readdir(outDir)).toMatchSnapshot() - }, 10000) + }) }) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index ff78db6a..8c8aec1a 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -68,7 +68,7 @@ const parseTemplate = (name: string) => (arg: string) => { } } -interface ProgramOpts extends Config { +export interface Options extends Config { configFile?: string runtimeConfig?: boolean outDir?: string @@ -82,12 +82,7 @@ interface ProgramOpts extends Config { } export interface SvgrCommand { - ( - opts: ProgramOpts, - program: Command, - filenames: string[], - config: Config, - ): Promise + (opts: Options, program: Command, filenames: string[]): Promise } program @@ -193,28 +188,13 @@ async function run() { process.exit(2) } - const opts = noUndefinedKeys(program.opts()) - - const config = await loadConfig(opts, { filePath: process.cwd() }) - - if (opts.dimensions === true) { - delete config.dimensions - } - - if (opts.svgo === true) { - delete config.svgo - } - - if (opts.prettier === true) { - delete config.prettier - } - - if (opts.index === false) { - delete config.index - } + const programOpts = noUndefinedKeys(program.opts()) + const opts = (await loadConfig(programOpts, { + filePath: process.cwd(), + })) as Options const command = opts.outDir ? dirCommand : fileCommand - await command(opts, program, filenames, config) + await command(opts, program, filenames) } run().catch((error) => {