diff --git a/README.md b/README.md index efb2ed9..856e4d5 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ Rule | Meaning `components/*/utils` | ✅  The directory `components` is accepted.
✅  Any *first level* nested directory is accepted.
✅  The *second level* nested directory `utils` is accepted.
❌  Any other *second level* nested directory is not accepted. `legacy/**` | ✅  The directory `legacy` is accepted.
✅  Any nested directory on *any level* is accepted. `components/*/legacy/**` | ✅  The directory `components` is accepted.
✅  Any *first level* nested directory is accepted.
✅  The *second level* nested directory `legacy` is accepted.
❌  Any other *second level* nested directory is not accepted.
✅  Any nested directory on *any level* inside of *legacy* directory is accepted. +`!pages/*` | ❌  Any nested directory inside `pages` is not accepted. ⚠️ A rule like `components/*/utils` automatically make the `components` and `components/*` rules work. So, no need to specify a rule for every level directory. You need to specify the deepest path. diff --git a/__tests__/runLinter.js b/__tests__/runLinter.js index 9f7d448..fa4f055 100644 --- a/__tests__/runLinter.js +++ b/__tests__/runLinter.js @@ -196,3 +196,20 @@ test('should not accept files with * and ** in the same rule', () => { 'folderslint: 2 error(s) found' ) }) + +test('should not accept files with ! (negation) in the beginning of the rule ', () => { + parseConfig.mockReturnValue({ + root: 'src', + rules: ['!pages/*'], + }) + + runLinter(['cwd/src/pages/components']) + + expect(process.exit).toHaveBeenLastCalledWith(1) + + expect(console.log).toHaveBeenNthCalledWith( + 1, + chalk.underline('cwd/src/pages/components') + ) + expect(console.log).toHaveBeenNthCalledWith(2, ERROR_MESSAGE) +}) diff --git a/src/parseConfig.js b/src/parseConfig.js index 660bbc3..7a5790e 100644 --- a/src/parseConfig.js +++ b/src/parseConfig.js @@ -19,6 +19,16 @@ const validateParsedConfig = (config) => { console.error('A rule can have ** only at the end') process.exit(1) } + + if ( + rule.includes('!') && + rule.startsWith('!') && + rule.split('!').length > 2 + ) { + console.error(`Invalid rule: ${rule}`) + console.error('A rule can have at most one ! at the beginning') + process.exit(1) + } }) return config } diff --git a/src/rules.js b/src/rules.js index 06ce788..0975264 100644 --- a/src/rules.js +++ b/src/rules.js @@ -29,7 +29,9 @@ const getExtendedRules = (root = '', rules) => { const isPathMatchRule = (path, rule) => { const splittedPath = path.split('/') - const splittedRule = rule.split('/') + + const isNegation = rule.startsWith('!') + const splittedRule = (isNegation ? rule.substring(1) : rule).split('/') const isValid = splittedPath.reduce((acc, pathPart, i) => { const rulePart = splittedRule[i] @@ -41,14 +43,14 @@ const isPathMatchRule = (path, rule) => { }, true) if (!isValid) { - return false + return isNegation } if (!rule.includes('**') && splittedPath.length > splittedRule.length) { - return false + return isNegation } - return true + return !isNegation } const checkPath = (path, rules) => {