From c62ff9c705770415d052c785743ccc3f8c25f727 Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Fri, 19 Jan 2024 16:45:04 +0800 Subject: [PATCH 1/3] feat: new ignore arguments --- bin/index.js | 14 ++++-- package.json | 1 + pnpm-lock.yaml | 12 +++--- src/options.ts | 4 +- src/rc/index.ts | 111 +++++++++++++++++++++++++++++++++++++----------- 5 files changed, 107 insertions(+), 35 deletions(-) diff --git a/bin/index.js b/bin/index.js index f6346b4..f493ac8 100755 --- a/bin/index.js +++ b/bin/index.js @@ -3,6 +3,7 @@ const fs = require('fs') const minimist = require('minimist') const glob = require('glob') +const gitignore = require('./ignore') const { readRc, runWithConfig, report } = require('../') const helpMessage = ` @@ -24,7 +25,11 @@ Config arguments: .zhlintrc by default --ignore + --file-ignore .zhlintignore by default + + --case-ignore + .zhlintcaseignore by default --dir current directory by default @@ -69,11 +74,14 @@ const main = () => { const [filePattern] = [...argv._] const configDir = argv.dir const configPath = argv.config - const ignorePath = argv.ignore - const config = readRc(configDir, configPath, ignorePath) + const fileIgnorePath = argv.ignore || argv['file-ignore'] + const caseIgnorePath = argv['case-ignore'] + const config = readRc(configDir, configPath, fileIgnorePath, caseIgnorePath) + const fileIgnore = gitignore().add(config.fileIgnores) + const fileIgnoreFilter = fileIgnore.createFilter() try { const files = glob.sync(filePattern) - const resultList = files.map((file) => { + const resultList = files.filter(fileIgnoreFilter).map((file) => { console.log(`[start] ${file}`) const origin = fs.readFileSync(file, { encoding: 'utf8' }) const { result, validations } = runWithConfig(origin, config) diff --git a/package.json b/package.json index c9a2b8b..7917f48 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "dependencies": { "chalk": "^4.0.0", "glob": "^7.1.6", + "ignore": "^5.3.0", "minimist": "^1.2.0", "node-stdlib-browser": "^1.2.0", "remark-frontmatter": "^1.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b63837..cfba9a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: glob: specifier: ^7.1.6 version: 7.2.0 + ignore: + specifier: ^5.3.0 + version: 5.3.0 minimist: specifier: ^1.2.0 version: 1.2.6 @@ -555,7 +558,7 @@ packages: debug: 4.3.3 eslint: 8.6.0 functional-red-black-tree: 1.0.1 - ignore: 5.2.0 + ignore: 5.3.0 regexpp: 3.2.0 semver: 7.3.5 tsutils: 3.21.0(typescript@4.5.4) @@ -1770,7 +1773,7 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.2.10 - ignore: 5.2.0 + ignore: 5.3.0 merge2: 1.4.1 slash: 3.0.0 dev: true @@ -1844,10 +1847,9 @@ packages: engines: {node: '>= 4'} dev: true - /ignore@5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} engines: {node: '>= 4'} - dev: true /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} diff --git a/src/options.ts b/src/options.ts index 7cc30ee..f1b6ca8 100644 --- a/src/options.ts +++ b/src/options.ts @@ -157,8 +157,8 @@ export const normalizeConfig = ( }) // ignored cases - if (config.ignores) { - config.ignores.forEach((x) => { + if (config.caseIgnores) { + config.caseIgnores.forEach((x) => { const ignoredCase = parseIngoredCase(x) if (ignoredCase) { options.ignoredCases.push(ignoredCase) diff --git a/src/rc/index.ts b/src/rc/index.ts index f7f5b17..9b58c37 100644 --- a/src/rc/index.ts +++ b/src/rc/index.ts @@ -7,25 +7,34 @@ import { env } from '../report' type PathResult = { config: string | undefined - ignore: string | undefined + fileIgnore: string | undefined + caseIgnore: string | undefined } +const DEFAULT_CONFIG_PATH = '.zhlintrc' +const DEFAULT_FILE_IGNORE_PATH = '.zhlintignore' +const DEFAULT_CASE_IGNORE_PATH = '.zhlintignore' + const resolvePath = ( dir: string, config: string, - ignore: string, + fileIgnore: string, + caseIgnore: string, logger: Console = env.defaultLogger ): PathResult => { const result: PathResult = { config: undefined, - ignore: undefined + fileIgnore: undefined, + caseIgnore: undefined, } + dir = resolve(dir ?? '.') if (!existsSync(dir)) { logger.log(`"${dir}" does not exist.`) return result } - config = resolve(dir, config ?? '.zhlintrc') + + config = resolve(dir, config ?? DEFAULT_CONFIG_PATH) if (existsSync(config)) { result.config = config } else { @@ -33,14 +42,25 @@ const resolvePath = ( `Config file "${config}" does not exist. Will proceed as default.` ) } - ignore = resolve(dir, ignore ?? '.zhlintignore') - if (existsSync(ignore)) { - result.ignore = ignore + + fileIgnore = resolve(dir, fileIgnore ?? DEFAULT_FILE_IGNORE_PATH) + if (existsSync(fileIgnore)) { + result.fileIgnore = fileIgnore } else { logger.log( - `Global ignored cases file "${ignore}" does not exist. Will proceed as none.` + `Global ignored cases file "${fileIgnore}" does not exist. Will proceed as none.` ) } + + caseIgnore = resolve(dir, caseIgnore ?? DEFAULT_CASE_IGNORE_PATH) + if (existsSync(caseIgnore)) { + result.caseIgnore = caseIgnore + } else { + logger.log( + `Global ignored cases file "${caseIgnore}" does not exist. Will proceed as none.` + ) + } + return result } @@ -48,7 +68,8 @@ export type Config = { preset?: string rules?: Options['rules'] hyperParsers?: string[] - ignores?: string[] + fileIgnores?: string[] + caseIgnores?: string[] } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -59,15 +80,17 @@ const readJSONSync = (filepath: string): any => { const resolveConfig = ( normalizedConfigPath: string | undefined, - normalizedIgnorePath: string | undefined, + normalizedFileIgnorePath: string | undefined, + normalizedCaseIgnorePath: string | undefined, logger: Console = env.defaultLogger ): Config => { const result: Config = { preset: 'default' } + if (normalizedConfigPath) { try { - const config: Config = readJSONSync(normalizedConfigPath) + const config = readJSONSync(normalizedConfigPath) as Config if (typeof config.preset === 'string') { result.preset = config.preset } @@ -77,8 +100,11 @@ const resolveConfig = ( if (Array.isArray(config.hyperParsers)) { result.hyperParsers = config.hyperParsers } - if (Array.isArray(config.ignores)) { - result.ignores = config.ignores + if (Array.isArray(config.fileIgnores)) { + result.fileIgnores = config.fileIgnores + } + if (Array.isArray(config.caseIgnores)) { + result.caseIgnores = config.caseIgnores } } catch (error) { logger.log( @@ -86,39 +112,74 @@ const resolveConfig = ( ) } } - if (normalizedIgnorePath) { + + if (normalizedFileIgnorePath) { + try { + const fileIgnores = readFileSync(normalizedFileIgnorePath, { encoding: 'utf8' }) + fileIgnores + .split(/\n/) + .map((x) => x.trim()) + .forEach((x) => { + if (!x) { + return + } + if (!result.fileIgnores) { + result.fileIgnores = [] + } + if (result.fileIgnores.indexOf(x) === -1) { + result.fileIgnores.push(x) + } + }) + } catch (error) { + logger.log( + `Failed to read "${normalizedFileIgnorePath}": ${(error as Error).message}` + ) + } + } + + if (normalizedCaseIgnorePath) { try { - const ignores = readFileSync(normalizedIgnorePath, { encoding: 'utf8' }) - ignores + const caseIgnores = readFileSync(normalizedCaseIgnorePath, { encoding: 'utf8' }) + caseIgnores .split(/\n/) .map((x) => x.trim()) .forEach((x) => { if (!x) { return } - if (!result.ignores) { - result.ignores = [] + if (!result.caseIgnores) { + result.caseIgnores = [] } - if (result.ignores.indexOf(x) === -1) { - result.ignores.push(x) + if (result.caseIgnores.indexOf(x) === -1) { + result.caseIgnores.push(x) } }) } catch (error) { logger.log( - `Failed to read "${normalizedIgnorePath}": ${(error as Error).message}` + `Failed to read "${normalizedCaseIgnorePath}": ${(error as Error).message}` ) } } + return result } export const readRc = ( dir: string, config: string, - ignore: string, + fileIgnore: string, + caseIgnore: string, logger: Console = env.defaultLogger ): Config => { - const { config: normalizedConfigPath, ignore: normalizedIgnorePath } = - resolvePath(dir, config, ignore, logger) - return resolveConfig(normalizedConfigPath, normalizedIgnorePath, logger) + const { + config: normalizedConfigPath, + fileIgnore: normalizedFileIgnorePath, + caseIgnore: normalizedCaseIgnorePath + } = resolvePath(dir, config, fileIgnore, caseIgnore, logger) + return resolveConfig( + normalizedConfigPath, + normalizedFileIgnorePath, + normalizedCaseIgnorePath, + logger + ) } From 6ba7bca9ca95070454bd101d3c72123d40fb49e0 Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Fri, 19 Jan 2024 16:54:26 +0800 Subject: [PATCH 2/3] docs: update ignore rc --- README.md | 15 +++++++++++---- docs/index.md | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f9954ec..2d23819 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ zhlint --config # .zhlintignore by default zhlint --ignore +zhlint --file-ignore + +# .zhlintcaseignore by default +zhlint --case-ignore # current directory by default zhlint --dir @@ -68,7 +72,9 @@ In the config file, you can write a JSON like: For more details, see [supported rules](#supported-rules). -In the ignore file, you can write some lines of ignored cases like: +In the file-ignore file, you can write some lines to ignore files in [.gitignore syntax](https://git-scm.com/docs/gitignore#_pattern_format): + +In the case-ignore file, you can write some lines of ignored cases like: ```txt ( , ) @@ -121,9 +127,10 @@ const value = '自动在中文和English之间加入空格' const dir = '...' // the target directory path const configPath = '...' // the config file path -const ignorePath = '...' // the ignore file path +const fileIgnorePath = '...' // the file-ignore file path +const caseIgnorePath = '...' // the case-ignore file path -const config = readRc(dir, configPath, ignorePath) +const config = readRc(dir, configPath, fileIgnorePath, caseIgnorePath) const output = runWithConfig(value, config) // ... further actions @@ -175,7 +182,7 @@ type Options = { - `preset`: `string` (optional) - `rules`: `RuleOptions` without the `preset` field. (optional) - `hyperParsers`: `string[]` (optional) -- `ignores`: `string[]` and the priority is lower than `.zhlintignore`. (optional) +- `caseIgnores`: `string[]` and the priority is lower than `.zhlintcaseignore`. (optional) ### Output diff --git a/docs/index.md b/docs/index.md index 3cf7fe1..4d5a5c0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -56,6 +56,10 @@ zhlint --config # .zhlintignore by default zhlint --ignore +zhlint --file-ignore + +# .zhlintcaseignore by default +zhlint --case-ignore # current directory by default zhlint --dir @@ -74,7 +78,9 @@ In the config file, you can write a JSON like: For more details, see [supported rules](#supported-rules). -In the ignore file, you can write some lines of ignored cases like: +In the file-ignore file, you can write some lines to ignore files in [.gitignore syntax](https://git-scm.com/docs/gitignore#_pattern_format): + +In the case-ignore file, you can write some lines of ignored cases like: ```txt ( , ) @@ -131,9 +137,10 @@ const value = '自动在中文和English之间加入空格' const dir = '...' // the target directory path const configPath = '...' // the config file path -const ignorePath = '...' // the ignore file path +const fileIgnorePath = '...' // the file-ignore file path +const caseIgnorePath = '...' // the case-ignore file path -const config = readRc(dir, configPath, ignorePath) +const config = readRc(dir, configPath, fileIgnorePath, caseIgnorePath) const output = runWithConfig(value, config) // ... further actions @@ -187,7 +194,7 @@ type Options = { - `preset`: `string` (optional) - `rules`: `RuleOptions` without the `preset` field. (optional) - `hyperParsers`: `string[]` (optional) -- `ignores`: `string[]` and the priority is lower than `.zhlintignore`. (optional) +- `caseIgnores`: `string[]` and the priority is lower than `.zhlintcaseignore`. (optional) ### Output From 157ba5e1c1ffe7c4cef4ff4eb25de17868acfa4d Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Sat, 20 Jan 2024 11:12:21 +0800 Subject: [PATCH 3/3] fix: ignore config error --- README.md | 2 +- bin/index.js | 2 +- docs/index.md | 2 +- src/rc/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2d23819..afbb12e 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ type Options = { - `hyperParse`: customize the hyper parser by their names. It could be `undefined` which means just use default [ignored cases parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/ignore.js), [Markdown parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/md.js) and the [Hexo tags parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/hexo.js). - `ignoredCases`: provide exception cases which you would like to skip. - `IgnoredCase`: `{ prefix?, textStart, textEnd?, suffix? }` - - Just follows a certain format inspired from [W3C Scroll To Text Fragment Proposal](https://github.com/WICG/ScrollToTextFragment). + - Just follows a certain format `[prefix-,]textStart[,textEnd][,-suffix]` inspired from [W3C Scroll To Text Fragment Proposal](https://github.com/WICG/ScrollToTextFragment). - `logger`: same to the parameter in `report(...)`. ### RC Config diff --git a/bin/index.js b/bin/index.js index f493ac8..5d96860 100755 --- a/bin/index.js +++ b/bin/index.js @@ -3,7 +3,7 @@ const fs = require('fs') const minimist = require('minimist') const glob = require('glob') -const gitignore = require('./ignore') +const gitignore = require('ignore') const { readRc, runWithConfig, report } = require('../') const helpMessage = ` diff --git a/docs/index.md b/docs/index.md index 4d5a5c0..15340d7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -186,7 +186,7 @@ type Options = { - `hyperParse`: customize the hyper parser by their names. It could be `undefined` which means just use default [ignored cases parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/ignore.js), [Markdown parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/md.js) and the [Hexo tags parser](https://github.com/zhlint-project/zhlint/tree/master/src/hypers/hexo.js). - `ignoredCases`: provide exception cases which you would like to skip. - `IgnoredCase`: `{ prefix?, textStart, textEnd?, suffix? }` - - Just follows a certain format inspired from [W3C Scroll To Text Fragment Proposal](https://github.com/WICG/ScrollToTextFragment). + - Just follows a certain format `[prefix-,]textStart[,textEnd][,-suffix]` inspired from [W3C Scroll To Text Fragment Proposal](https://github.com/WICG/ScrollToTextFragment). - `logger`: same to the parameter in `report(...)`. ### RC Config diff --git a/src/rc/index.ts b/src/rc/index.ts index 9b58c37..6eabfdc 100644 --- a/src/rc/index.ts +++ b/src/rc/index.ts @@ -13,7 +13,7 @@ type PathResult = { const DEFAULT_CONFIG_PATH = '.zhlintrc' const DEFAULT_FILE_IGNORE_PATH = '.zhlintignore' -const DEFAULT_CASE_IGNORE_PATH = '.zhlintignore' +const DEFAULT_CASE_IGNORE_PATH = '.zhlintcaseignore' const resolvePath = ( dir: string,