diff --git a/README.md b/README.md index 705232a..e6c53bc 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ A string indicating the root of your files. ### `exclude` - Type: `String|Array[String]` -- Default: `['node_modules', compiler.options.output.path]` +- Default: `['node_modules', compiler.options.output.path, '<.stylelintignore content>']` Specify the files and/or directories to exclude. Must be relative to `options.context`. diff --git a/src/index.js b/src/index.js index 8a51230..241e5b1 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,12 @@ import { isMatch } from 'micromatch'; import { getOptions } from './options'; import linter from './linter'; -import { arrify, parseFiles, parseFoldersToGlobs } from './utils'; +import { + arrify, + parseFiles, + parseFoldersToGlobs, + parseStyleLintIgnoreFile, +} from './utils'; /** @typedef {import('webpack').Compiler} Compiler */ /** @typedef {import('webpack').Module} Module */ @@ -70,10 +75,13 @@ class StylelintWebpackPlugin { } const context = this.getContext(compiler); - const excludeDefault = [ - '**/node_modules/**', - String(compiler.options.output.path), - ]; + const excludeDefault = Array.from( + new Set([ + '**/node_modules/**', + String(compiler.options.output.path), + ...parseStyleLintIgnoreFile(context), + ]) + ); const options = { ...this.options, diff --git a/src/utils.js b/src/utils.js index c8de890..43ebafd 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,5 @@ import { resolve } from 'path'; -import { statSync } from 'fs'; +import { statSync, existsSync, readFileSync } from 'fs'; // @ts-ignore import normalizePath from 'normalize-path'; @@ -110,3 +110,24 @@ export const jsonStringifyReplacerSortKeys = (_, value) => { ? Object.keys(value).sort().reduce(insert, {}) : value; }; + +/** + * @param {string} context + * @returns {string[]} + */ +export const parseStyleLintIgnoreFile = (context) => { + const ignoreFilePath = resolve(context, '.stylelintignore'); + + if (!existsSync(ignoreFilePath)) { + return []; + } + + const ignoreContent = readFileSync(ignoreFilePath, 'utf8').split('\n'); + + return ignoreContent.filter((lineRaw) => { + const line = lineRaw.trim(); + + // remove empty and comment line + return line !== '' && !line.startsWith('#'); + }); +}; diff --git a/test/fixtures/stylelintignore/.stylelintignore b/test/fixtures/stylelintignore/.stylelintignore new file mode 100644 index 0000000..dab8497 --- /dev/null +++ b/test/fixtures/stylelintignore/.stylelintignore @@ -0,0 +1,7 @@ +ignore.scss + +# comment + +noop.scss + +ignore.scss \ No newline at end of file diff --git a/test/fixtures/stylelintignore/ignore.scss b/test/fixtures/stylelintignore/ignore.scss new file mode 100644 index 0000000..77cec50 --- /dev/null +++ b/test/fixtures/stylelintignore/ignore.scss @@ -0,0 +1,3 @@ +#stuff { + display: 'block'; // error +} diff --git a/test/fixtures/stylelintignore/index.js b/test/fixtures/stylelintignore/index.js new file mode 100644 index 0000000..8792764 --- /dev/null +++ b/test/fixtures/stylelintignore/index.js @@ -0,0 +1,2 @@ +require('file-loader!./test.scss'); +require('file-loader!./ignore.scss'); diff --git a/test/fixtures/stylelintignore/test.scss b/test/fixtures/stylelintignore/test.scss new file mode 100644 index 0000000..b66215f --- /dev/null +++ b/test/fixtures/stylelintignore/test.scss @@ -0,0 +1,3 @@ +body { + display: block; +} diff --git a/test/stylelint-ignore.test.js b/test/stylelint-ignore.test.js new file mode 100644 index 0000000..d6c2465 --- /dev/null +++ b/test/stylelint-ignore.test.js @@ -0,0 +1,41 @@ +import { join } from 'path'; + +import webpack from 'webpack'; + +import StylelintWebpackPlugin from '../src'; + +describe('stylelintignore', () => { + it('discern stylelintignore', (done) => { + const compiler = webpack({ + context: join(__dirname, 'fixtures', 'stylelintignore'), + mode: 'development', + entry: './index', + plugins: [new StylelintWebpackPlugin()], + }); + + compiler.run((err, stats) => { + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(false); + done(); + }); + }); + + it('not use .stylelintignore file', (done) => { + const compiler = webpack({ + context: join(__dirname, 'fixtures', 'stylelintignore'), + mode: 'development', + entry: './index', + plugins: [ + new StylelintWebpackPlugin({ + exclude: [], + }), + ], + }); + + compiler.run((err, stats) => { + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(true); + done(); + }); + }); +});