Skip to content

Commit

Permalink
Add support for multiple --ignore-path flags (#6345)
Browse files Browse the repository at this point in the history
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
  • Loading branch information
kimulaco and ybiquitous committed Sep 14, 2022
1 parent bb10282 commit b598c18
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/real-items-wait.md
@@ -0,0 +1,5 @@
---
"stylelint": minor
---

Added: support for multiple `--ignore-path` flags
2 changes: 1 addition & 1 deletion docs/user-guide/usage/cli.md
Expand Up @@ -58,7 +58,7 @@ Ignore `stylelint-disable` (e.g. `/* stylelint-disable block-no-empty */`) comme

### `--ignore-path, -i`

A path to a file containing patterns describing files to ignore. The path can be absolute or relative to `process.cwd()`. By default, Stylelint looks for `.stylelintignore` in `process.cwd()`. [More info](options.md#ignorePath).
Path to a file containing patterns that describe files to ignore. The path can be absolute or relative to `process.cwd()`. You can repeat the option to provide multiple paths. By default, Stylelint looks for `.stylelintignore` in `process.cwd()`. [More info](options.md#ignorePath).

### `--ignore-pattern, --ip`

Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/usage/options.md
Expand Up @@ -133,7 +133,7 @@ Disable the default ignores. Stylelint will not automatically ignore the content

CLI flags: `--ignore-path, -i`

A path to a file containing patterns describing files to ignore. The path can be absolute or relative to `process.cwd()`. By default, Stylelint looks for `.stylelintignore` in `process.cwd()`.
Path to a file containing patterns that describe files to ignore. The path can be absolute or relative to `process.cwd()`. You can repeat the option to provide multiple paths. By default, Stylelint looks for `.stylelintignore` in `process.cwd()`.

## `ignoreDisables`

Expand Down
5 changes: 3 additions & 2 deletions lib/__tests__/__snapshots__/cli.test.js.snap
Expand Up @@ -40,8 +40,9 @@ exports[`CLI --help 1`] = `
--ignore-path, -i
Path to a file containing patterns that describe files to ignore. The
path can be absolute or relative to process.cwd(). By default, stylelint
looks for .stylelintignore in process.cwd().
path can be absolute or relative to process.cwd(). You can repeat the
option to provide multiple paths. By default, Stylelint looks for
.stylelintignore in process.cwd().
--ignore-pattern, --ip
Expand Down
12 changes: 10 additions & 2 deletions lib/__tests__/cli.test.js
Expand Up @@ -25,6 +25,7 @@ describe('buildCLI', () => {
formatter: 'string',
help: false,
ignoreDisables: false,
ignorePath: [],
ignorePattern: [],
printConfig: false,
quiet: false,
Expand Down Expand Up @@ -95,8 +96,15 @@ describe('buildCLI', () => {
});

it('flags.ignorePath', () => {
expect(buildCLI(['--ignore-path=/path/to/file']).flags.ignorePath).toBe('/path/to/file');
expect(buildCLI(['-i', '/path/to/file']).flags.ignorePath).toBe('/path/to/file');
expect(buildCLI(['--ignore-path=/path/to/file']).flags.ignorePath).toEqual(['/path/to/file']);
expect(buildCLI(['-i', '/path/to/file']).flags.ignorePath).toEqual(['/path/to/file']);
expect(
buildCLI(['--ignore-path=/path/to/file1', '--ignore-path=/path/to/file2']).flags.ignorePath,
).toEqual(['/path/to/file1', '/path/to/file2']);
expect(buildCLI(['-i', '/path/to/file1', '-i', '/path/to/file2']).flags.ignorePath).toEqual([
'/path/to/file1',
'/path/to/file2',
]);
});

it('flags.ignorePattern', () => {
Expand Down
3 changes: 3 additions & 0 deletions lib/__tests__/fixtures/ignore-2.txt
@@ -0,0 +1,3 @@
# Ignore file patterns are always relative to process.cwd()

fixtures/empty-block-with-disables.css
27 changes: 24 additions & 3 deletions lib/__tests__/ignore.test.js
Expand Up @@ -175,7 +175,28 @@ test('specified `ignorePath` file ignoring one file', async () => {
'block-no-empty': true,
},
},
ignorePath: fixtures('ignore.txt'),
ignorePath: [fixtures('ignore.txt')],
}),
).rejects.toThrow(AllFilesIgnoredError); // all files ignore

process.chdir(actualCwd);
});

test('specified multiple `ignorePath` to ignore files', async () => {
const files = [fixtures('empty-block.css'), fixtures('empty-block-with-disables.css')];
const actualCwd = process.cwd();

process.chdir(__dirname);

await expect(
standalone({
files,
config: {
rules: {
'block-no-empty': true,
},
},
ignorePath: [fixtures('ignore.txt'), fixtures('ignore-2.txt')],
}),
).rejects.toThrow(AllFilesIgnoredError); // all files ignore

Expand All @@ -196,7 +217,7 @@ test('specified `ignorePath` file ignoring one file using options.cwd', async ()
'block-no-empty': true,
},
},
ignorePath: fixtures('ignore.txt'),
ignorePath: [fixtures('ignore.txt')],
cwd: __dirname,
}),
).rejects.toThrow(allFilesIgnoredErrorMessage); // all files ignore
Expand All @@ -209,7 +230,7 @@ test('specified `ignorePath` directory, not a file', async () => {
standalone({
files: [],
config: {},
ignorePath: '__snapshots__',
ignorePath: ['__snapshots__'],
cwd: __dirname,
}),
).rejects.toThrow(/EISDIR/);
Expand Down
2 changes: 1 addition & 1 deletion lib/__tests__/invalidScopeDisables.test.js
Expand Up @@ -157,7 +157,7 @@ it('invalidScopeDisables ignored case', async () => {
config,
files: [fixture('disabled-ranges-1.css'), fixture('ignored-file.css')],
ignoreDisables: true,
ignorePath: fixture('.stylelintignore'),
ignorePath: [fixture('.stylelintignore')],
reportInvalidScopeDisables: true,
});

Expand Down
2 changes: 1 addition & 1 deletion lib/__tests__/needlessDisables.test.js
Expand Up @@ -223,7 +223,7 @@ it('needlessDisables ignored case', async () => {
config,
files: [fixture('disabled-ranges-1.css'), fixture('ignored-file.css')],
reportNeedlessDisables: true,
ignorePath: fixture('.stylelintignore'),
ignorePath: [fixture('.stylelintignore')],
});

expect(results).toHaveLength(1);
Expand Down
31 changes: 31 additions & 0 deletions lib/__tests__/postcssPlugin.test.js
Expand Up @@ -134,6 +134,21 @@ describe('stylelintignore', () => {
postcss([postcssPlugin(options)]).process('a {}', { from: 'foo.css' }),
).resolves.toHaveProperty('stylelint.ignored', true);
});

it('postcssPlugin with ignorePath array and file is ignored', () => {
const options = {
config: {
rules: {
'block-no-empty': true,
},
},
ignorePath: [path.join(__dirname, './stylelintignore-test/.postcssPluginignore')],
};

return expect(
postcss([postcssPlugin(options)]).process('a {}', { from: 'foo.css' }),
).resolves.toHaveProperty('stylelint.ignored', true);
});
});

describe('stylelintignore with options.cwd', () => {
Expand Down Expand Up @@ -169,4 +184,20 @@ describe('stylelintignore with options.cwd', () => {
postcss([postcssPlugin(options)]).process('a {}', { from: path.join(__dirname, 'foo.css') }),
).resolves.toHaveProperty('stylelint.ignored', true);
});

it('postcssPlugin with ignorePath array and file is ignored', () => {
const options = {
config: {
rules: {
'block-no-empty': true,
},
},
cwd: __dirname,
ignorePath: [path.join(__dirname, './stylelintignore-test/.postcssPluginignore')],
};

return expect(
postcss([postcssPlugin(options)]).process('a {}', { from: path.join(__dirname, 'foo.css') }),
).resolves.toHaveProperty('stylelint.ignored', true);
});
});
16 changes: 8 additions & 8 deletions lib/__tests__/stylelintignore-test/stylelintignore.test.js
Expand Up @@ -58,7 +58,7 @@ describe('stylelintignore', () => {
const data = await standalone({
code: '.bar {}',
codeFilename: `${fixturesPath}/empty-block.css`,
ignorePath: path.join(__dirname, '.stylelintignore'),
ignorePath: [path.join(__dirname, '.stylelintignore')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -78,7 +78,7 @@ describe('stylelintignore', () => {
const data = await standalone({
code: '.bar {}',
codeFilename: `${fixturesPath}/empty-block.css`,
ignorePath: path.join(__dirname, '.stylelintignore-empty'),
ignorePath: [path.join(__dirname, '.stylelintignore-empty')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -95,7 +95,7 @@ describe('stylelintignore', () => {
const data = await standalone({
code: 'var a = {',
codeFilename: `test.js`,
ignorePath: path.join(__dirname, '.stylelintignore2'),
ignorePath: [path.join(__dirname, '.stylelintignore2')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -115,7 +115,7 @@ describe('stylelintignore', () => {
const data = await standalone({
code: 'var a = {',
codeFilename: `test.js`,
ignorePath: path.join(__dirname, '.stylelintignore2'),
ignorePath: [path.join(__dirname, '.stylelintignore2')],
});

expect(data).toEqual({
Expand Down Expand Up @@ -175,7 +175,7 @@ describe('stylelintignore with options.cwd', () => {
const data = await standalone({
code: '.bar {}',
codeFilename: `${fixturesPath}/empty-block.css`,
ignorePath: path.join(__dirname, '.stylelintignore'),
ignorePath: [path.join(__dirname, '.stylelintignore')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -196,7 +196,7 @@ describe('stylelintignore with options.cwd', () => {
const data = await standalone({
code: '.bar {}',
codeFilename: `${fixturesPath}/empty-block.css`,
ignorePath: path.join(__dirname, '.stylelintignore-empty'),
ignorePath: [path.join(__dirname, '.stylelintignore-empty')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -214,7 +214,7 @@ describe('stylelintignore with options.cwd', () => {
const data = await standalone({
code: 'var a = {',
codeFilename: `test.js`,
ignorePath: path.join(__dirname, '.stylelintignore2'),
ignorePath: [path.join(__dirname, '.stylelintignore2')],
config: {
extends: `${fixturesPath}/config-block-no-empty`,
},
Expand All @@ -235,7 +235,7 @@ describe('stylelintignore with options.cwd', () => {
const data = await standalone({
code: 'var a = {',
codeFilename: `test.js`,
ignorePath: path.join(__dirname, '.stylelintignore2'),
ignorePath: [path.join(__dirname, '.stylelintignore2')],
cwd: __dirname,
});

Expand Down
8 changes: 5 additions & 3 deletions lib/cli.js
Expand Up @@ -32,7 +32,7 @@ const EXIT_CODE_ERROR = 2;
* @property {string} [formatter="string"]
* @property {string} [help]
* @property {boolean} [ignoreDisables]
* @property {string} [ignorePath]
* @property {string[]} [ignorePath]
* @property {string[]} [ignorePattern]
* @property {string} [noColor]
* @property {string} [outputFile]
Expand Down Expand Up @@ -125,8 +125,9 @@ const meowOptions = {
--ignore-path, -i
Path to a file containing patterns that describe files to ignore. The
path can be absolute or relative to process.cwd(). By default, stylelint
looks for .stylelintignore in process.cwd().
path can be absolute or relative to process.cwd(). You can repeat the
option to provide multiple paths. By default, Stylelint looks for
.stylelintignore in process.cwd().
--ignore-pattern, --ip
Expand Down Expand Up @@ -273,6 +274,7 @@ const meowOptions = {
ignorePath: {
alias: 'i',
type: 'string',
isMultiple: true,
},
ignorePattern: {
alias: 'ip',
Expand Down
39 changes: 24 additions & 15 deletions lib/utils/getFileIgnorer.js
Expand Up @@ -10,25 +10,34 @@ const isPathNotFoundError = require('./isPathNotFoundError');
const DEFAULT_IGNORE_FILENAME = '.stylelintignore';

/**
* @param {{ cwd: string, ignorePath?: string, ignorePattern?: string[] }} options
* @param {{ cwd: string, ignorePath?: string | string[], ignorePattern?: string[] }} options
* @return {import('ignore').Ignore}
*/
module.exports = function getFileIgnorer(options) {
const ignoreFilePath = options.ignorePath || DEFAULT_IGNORE_FILENAME;
const absoluteIgnoreFilePath = path.isAbsolute(ignoreFilePath)
? ignoreFilePath
: path.resolve(options.cwd, ignoreFilePath);
let ignoreText = '';

try {
ignoreText = fs.readFileSync(absoluteIgnoreFilePath, 'utf8');
} catch (readError) {
if (!isPathNotFoundError(readError)) {
throw readError;
const ignorer = ignore();
const ignorePaths = [options.ignorePath || []].flat();

if (ignorePaths.length === 0) {
ignorePaths.push(DEFAULT_IGNORE_FILENAME);
}

for (const ignoreFilePath of ignorePaths) {
const absoluteIgnoreFilePath = path.isAbsolute(ignoreFilePath)
? ignoreFilePath
: path.resolve(options.cwd, ignoreFilePath);

try {
const ignoreText = fs.readFileSync(absoluteIgnoreFilePath, 'utf8');

ignorer.add(ignoreText);
} catch (readError) {
if (!isPathNotFoundError(readError)) {
throw readError;
}
}
}

return ignore()
.add(ignoreText)
.add(options.ignorePattern || []);
ignorer.add(options.ignorePattern || []);

return ignorer;
};
2 changes: 1 addition & 1 deletion types/stylelint/index.d.ts
Expand Up @@ -223,7 +223,7 @@ declare module 'stylelint' {
*/
cwd?: string;
ignoreDisables?: boolean;
ignorePath?: string;
ignorePath?: string | string[];
ignorePattern?: string[];
reportDescriptionlessDisables?: boolean;
reportNeedlessDisables?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion types/stylelint/type-test.ts
Expand Up @@ -32,7 +32,7 @@ const options: Partial<LinterOptions> = {
reportDescriptionlessDisables: true,
reportInvalidScopeDisables: true,
reportNeedlessDisables: true,
ignorePath: 'foo',
ignorePath: ['foo'],
customSyntax: 'postcss-scss',
syntax: 'scss', // Removed but still accepted in type definition
config: {
Expand Down

0 comments on commit b598c18

Please sign in to comment.