diff --git a/package.json b/package.json index 3045259..1e04d5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lint-pilot", - "description": "Lint Pilot: Your co-pilot for maintaining high code quality with seamless ESLint, Stylelint, and MarkdownLint integration.", + "description": "Lint Pilot: Your co-pilot for maintaining high code quality with seamless ESLint, Stylelint, and Markdownlint integration.", "repository": { "type": "git", "url": "git+https://github.com/01taylop/lint-pilot.git" diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 699020a..fc53253 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -33,7 +33,7 @@ Options: -h, --help display help for command Commands: - lint [options] run all linters: ESLint, Stylelint, and MarkdownLint (default) + lint [options] run all linters: ESLint, Stylelint, and Markdownlint (default) help [command] display help for command `) }) diff --git a/src/__tests__/filePatterns.spec.ts b/src/commands/lint/__tests__/file-patterns.spec.ts similarity index 76% rename from src/__tests__/filePatterns.spec.ts rename to src/commands/lint/__tests__/file-patterns.spec.ts index c41639f..8a851ea 100644 --- a/src/__tests__/filePatterns.spec.ts +++ b/src/commands/lint/__tests__/file-patterns.spec.ts @@ -1,14 +1,16 @@ -import colourLog from '@Utils/colourLog' -import { Linter } from '@Types' +import { Linter } from '@Types/lint' +import colourLog from '@Utils/colour-log' -import getFilePatterns from '../filePatterns' +import { getFilePatterns } from '../file-patterns' -describe('filePatterns', () => { +describe('getFilePatterns', () => { - jest.spyOn(colourLog, 'config').mockImplementation(() => {}) - jest.spyOn(console, 'log').mockImplementation(() => {}) + beforeEach(() => { + jest.spyOn(colourLog, 'config').mockImplementation(() => true) + jest.spyOn(console, 'log').mockImplementation(() => true) + }) - it('returns the correct file patterns for eslint', () => { + it('returns the default file patterns for ESLint', () => { const filePatterns = getFilePatterns({}) const expectedPatterns = [ @@ -19,7 +21,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('ESLint Patterns', expectedPatterns) }) - it('returns the correct file patterns for eslint with an additional include pattern', () => { + it('returns the file patterns for ESLint with an additional include pattern', () => { const filePatterns = getFilePatterns({ eslintInclude: 'foo' }) @@ -33,7 +35,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('ESLint Patterns', expectedPatterns) }) - it('returns the correct file patterns for eslint with several additional include patterns', () => { + it('returns the file patterns for ESLint with several additional include patterns', () => { const filePatterns = getFilePatterns({ eslintInclude: ['foo', 'bar'], }) @@ -48,7 +50,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('ESLint Patterns', expectedPatterns) }) - it('returns the correct file patterns for markdownlint', () => { + it('returns the default file patterns for Markdownlint', () => { const filePatterns = getFilePatterns({}) const expectedPatterns = [ @@ -59,7 +61,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Markdownlint Patterns', expectedPatterns) }) - it('returns the correct file patterns for stylelint', () => { + it('returns the default file patterns for Stylelint', () => { const filePatterns = getFilePatterns({}) const expectedPatterns = [ @@ -70,7 +72,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Stylelint Patterns', expectedPatterns) }) - it('returns the correct ignore file patterns', () => { + it('returns the default ignore file patterns', () => { const filePatterns = getFilePatterns({}) const expectedPatterns = [ @@ -82,7 +84,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Ignore', expectedPatterns) }) - it('returns the correct ignore file patterns with an additional directory ignored', () => { + it('returns the ignore file patterns with an additional directory ignored', () => { const filePatterns = getFilePatterns({ ignoreDirs: 'foo' }) @@ -96,7 +98,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Ignore', expectedPatterns) }) - it('returns the correct ignore file patterns with several additional directories ignored', () => { + it('returns the ignore file patterns with several additional directories ignored', () => { const filePatterns = getFilePatterns({ ignoreDirs: ['foo', 'bar'], }) @@ -110,7 +112,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Ignore', expectedPatterns) }) - it('returns the correct ignore file patterns with an additional pattern ignored', () => { + it('returns the ignore file patterns with an additional pattern ignored', () => { const filePatterns = getFilePatterns({ ignorePatterns: 'foo' }) @@ -125,7 +127,7 @@ describe('filePatterns', () => { expect(colourLog.config).toHaveBeenCalledWith('Ignore', expectedPatterns) }) - it('returns the correct ignore file patterns with several additional patterns ignored', () => { + it('returns the ignore file patterns with several additional patterns ignored', () => { const filePatterns = getFilePatterns({ ignorePatterns: ['foo', 'bar'], }) diff --git a/src/filePatterns.ts b/src/commands/lint/file-patterns.ts similarity index 61% rename from src/filePatterns.ts rename to src/commands/lint/file-patterns.ts index 43f3c1b..8df8d64 100644 --- a/src/filePatterns.ts +++ b/src/commands/lint/file-patterns.ts @@ -1,20 +1,13 @@ -import { type FilePatterns, Linter } from '@Types' -import colourLog from '@Utils/colourLog' +import type { LintOptions } from '@Types/commands' +import { type FilePatterns, Linter } from '@Types/lint' +import colourLog from '@Utils/colour-log' -type StringOrArray = string | Array +type GetFilePatterns = Pick -interface GetFilePatterns { - eslintInclude?: StringOrArray - ignoreDirs?: StringOrArray - ignorePatterns?: StringOrArray -} - -const enforceArray = (value: StringOrArray = []): Array => Array.of(value).flat() - -const getFilePatterns = ({ eslintInclude, ignoreDirs, ignorePatterns }: GetFilePatterns): FilePatterns => { +const getFilePatterns = ({ eslintInclude = [], ignoreDirs = [], ignorePatterns = [] }: GetFilePatterns): FilePatterns => { const eslintIncludePatterns = [ '**/*.{cjs,js,jsx,mjs,ts,tsx}', - ...enforceArray(eslintInclude), + ...Array.of(eslintInclude).flat(), ] const ignoreDirectories = [ @@ -24,12 +17,12 @@ const getFilePatterns = ({ eslintInclude, ignoreDirs, ignorePatterns }: GetFileP 'tmp', 'tscOutput', 'vendor', - ...enforceArray(ignoreDirs), + ...Array.of(ignoreDirs).flat(), ].sort() const ignoreGlobs = [ '**/*.+(map|min).*', - ...enforceArray(ignorePatterns), + ...Array.of(ignorePatterns).flat(), ].sort() const filePatterns = { @@ -53,4 +46,6 @@ const getFilePatterns = ({ eslintInclude, ignoreDirs, ignorePatterns }: GetFileP return filePatterns } -export default getFilePatterns +export { + getFilePatterns, +} diff --git a/src/commands/lint/index.ts b/src/commands/lint/index.ts index e0828f6..47851e0 100644 --- a/src/commands/lint/index.ts +++ b/src/commands/lint/index.ts @@ -3,7 +3,9 @@ import { clearCacheDirectory } from '@Utils/cache' import colourLog from '@Utils/colour-log' import { clearTerminal } from '@Utils/terminal' -const lint = ({ clearCache, debug, emoji, title, ...options }: LintOptions) => { +import { getFilePatterns } from './file-patterns' + +const lint = ({ clearCache, debug, emoji, eslintInclude, ignoreDirs, ignorePatterns, title, ...options }: LintOptions) => { global.debug = debug clearTerminal() @@ -13,7 +15,13 @@ const lint = ({ clearCache, debug, emoji, title, ...options }: LintOptions) => { clearCacheDirectory() } - console.log('Run Lint', options) + const filePatterns = getFilePatterns({ + eslintInclude, + ignoreDirs, + ignorePatterns, + }) + + console.log('Run Lint', options, filePatterns) } export default lint diff --git a/src/index.ts b/src/index.ts index bdcbb16..3d2d4d8 100755 --- a/src/index.ts +++ b/src/index.ts @@ -26,7 +26,7 @@ const createProgram = () => { program .command('lint', { isDefault: true }) - .description('run all linters: ESLint, Stylelint, and MarkdownLint (default)') + .description('run all linters: ESLint, Stylelint, and Markdownlint (default)') .option('-e, --emoji ', 'customise the emoji displayed when running lint-pilot', '✈️') .option('-t, --title ', 'customise the title displayed when running lint-pilot', 'Lint Pilot') @@ -37,14 +37,14 @@ const createProgram = () => { .option('--cache', 'cache linting results', false) .option('--clearCache', 'clear the cache', false) - .option('--ignore-dirs ', 'directories to ignore globally') - .option('--ignore-patterns ', 'file patterns to ignore globally') - .option('--eslint-include ', 'file patterns to include for ESLint') + .option('--ignore-dirs ', 'define directories to ignore') + .option('--ignore-patterns ', 'define file patterns to ignore') + .option('--eslint-include ', 'define additional file patterns for ESLint') - .option('--debug', 'output additional debug information including the list of files being linted', false) - .option('--eslint-use-legacy-config', 'set to true to use the legacy ESLint configuration', false) + .option('--debug', 'output additional debug information', false) + .option('--eslint-use-legacy-config', 'use legacy ESLint config', false) - .action(options => lint(options)) + .action(lint) return program } diff --git a/src/types/lint.ts b/src/types/lint.ts new file mode 100644 index 0000000..71ec183 --- /dev/null +++ b/src/types/lint.ts @@ -0,0 +1,20 @@ +enum Linter { + ESLint = 'ESLint', + Markdownlint = 'Markdownlint', + Stylelint = 'Stylelint', +} + +interface FilePatterns { + includePatterns: { + [key in Linter]: Array + } + ignorePatterns: Array +} + +export type { + FilePatterns, +} + +export { + Linter, +} diff --git a/src/utils/__tests__/cache.spec.ts b/src/utils/__tests__/cache.spec.ts index 6f9f442..38de2b6 100644 --- a/src/utils/__tests__/cache.spec.ts +++ b/src/utils/__tests__/cache.spec.ts @@ -20,12 +20,12 @@ describe('clearCacheDirectory', () => { clearCacheDirectory() - expect(fs.existsSync).toHaveBeenCalledWith(expectedCacheDirectory) - expect(fs.rmSync).toHaveBeenCalledWith(expectedCacheDirectory, { + expect(fs.existsSync).toHaveBeenCalledOnceWith(expectedCacheDirectory) + expect(fs.rmSync).toHaveBeenCalledOnceWith(expectedCacheDirectory, { force: true, recursive: true, }) - expect(colourLog.info).toHaveBeenCalledWith('Cache cleared.\n') + expect(colourLog.info).toHaveBeenCalledOnceWith('Cache cleared.\n') }) it('does not attempt to clear the cache if the directory does not exist', () => { @@ -33,9 +33,9 @@ describe('clearCacheDirectory', () => { clearCacheDirectory() - expect(fs.existsSync).toHaveBeenCalledWith(expectedCacheDirectory) + expect(fs.existsSync).toHaveBeenCalledOnceWith(expectedCacheDirectory) expect(fs.rmSync).not.toHaveBeenCalled() - expect(colourLog.info).toHaveBeenCalledWith('No cache to clear.\n') + expect(colourLog.info).toHaveBeenCalledOnceWith('No cache to clear.\n') }) }) @@ -47,7 +47,7 @@ describe('getCacheDirectory', () => { const result = getCacheDirectory('.eslintcache') - expect(path.resolve).toHaveBeenCalledWith(process.cwd(), '.lintpilotcache', '.eslintcache') + expect(path.resolve).toHaveBeenCalledOnceWith(process.cwd(), '.lintpilotcache', '.eslintcache') expect(result).toBe(`${process.cwd()}/.lintpilotcache/.eslintcache`) }) diff --git a/src/utils/__tests__/colour-log.spec.ts b/src/utils/__tests__/colour-log.spec.ts index 9f3f4bc..d321f0b 100644 --- a/src/utils/__tests__/colour-log.spec.ts +++ b/src/utils/__tests__/colour-log.spec.ts @@ -5,12 +5,34 @@ import colourLog from '../colour-log' jest.mock('chalk', () => ({ blue: jest.fn().mockImplementation(text => text), cyan: jest.fn().mockImplementation(text => text), + dim: jest.fn().mockImplementation(text => text), + magenta: jest.fn().mockImplementation(text => text), })) describe('colourLog', () => { const mockedConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => {}) + describe('config', () => { + + it('logs the key in magenta and a single config item in dim', () => { + colourLog.config('setting', ['foo']) + + expect(chalk.magenta).toHaveBeenCalledOnceWith('setting: ') + expect(chalk.dim).toHaveBeenCalledOnceWith('foo') + expect(mockedConsoleLog).toHaveBeenCalledOnceWith('setting: ', 'foo') + }) + + it('logs the key in magenta and a config array in dim', () => { + colourLog.config('setting', ['foo', 'bar', 'baz']) + + expect(chalk.magenta).toHaveBeenCalledOnceWith('setting: ') + expect(chalk.dim).toHaveBeenCalledOnceWith('[foo, bar, baz]') + expect(mockedConsoleLog).toHaveBeenCalledOnceWith('setting: ', '[foo, bar, baz]') + }) + + }) + describe('info', () => { it('logs the text in blue', () => { diff --git a/src/utils/colour-log.ts b/src/utils/colour-log.ts index ac40376..e9eea55 100644 --- a/src/utils/colour-log.ts +++ b/src/utils/colour-log.ts @@ -1,7 +1,16 @@ import chalk from 'chalk' const colourLog = { + config: (key: string, config: Array) => { + const configString = config.length > 1 + ? `[${config.join(', ')}]` + : config[0] + + console.log(chalk.magenta(`${key}: `), chalk.dim(configString)) + }, + info: (text: string) => console.log(chalk.blue(text)), + title: (title: string) => console.log(chalk.cyan(title)), }