diff --git a/src/getStylelint.js b/src/getStylelint.js index f8f1b66..e60be72 100644 --- a/src/getStylelint.js +++ b/src/getStylelint.js @@ -15,7 +15,7 @@ const cache = {}; /** @typedef {import('./options').Options} Options */ /** @typedef {() => Promise} AsyncTask */ /** @typedef {(files: string|string[]) => Promise} LintTask */ -/** @typedef {{stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number, }} Linter */ +/** @typedef {{api: import('stylelint').InternalApi, stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number, }} Linter */ /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */ /** @@ -23,10 +23,12 @@ const cache = {}; * @returns {Linter} */ function loadStylelint(options) { - const stylelint = setup(options, getStylelintOptions(options)); + const stylelintOptions = getStylelintOptions(options); + const stylelint = setup(options, stylelintOptions); return { stylelint, + api: stylelint.createLinter(stylelintOptions), lintFiles, cleanup: async () => {}, threads: 1, diff --git a/src/index.js b/src/index.js index 68b3137..cb9e429 100644 --- a/src/index.js +++ b/src/index.js @@ -95,20 +95,43 @@ class StylelintWebpackPlugin { compiler.hooks.thisCompilation.tap(this.key, (compilation) => { /** @type {import('./linter').Linter} */ let lint; + + /** @type {import('stylelint').InternalApi} */ + let api; + /** @type {import('./linter').Reporter} */ let report; + /** @type number */ let threads; try { - ({ lint, report, threads } = linter(this.key, options, compilation)); + ({ lint, api, report, threads } = linter( + this.key, + options, + compilation + )); } catch (e) { compilation.errors.push(e); return; } - compilation.hooks.finishModules.tap(this.key, () => { - const files = this.getFiles(compiler, wanted, exclude); + compilation.hooks.finishModules.tapPromise(this.key, async () => { + /** @type {string[]} */ + // @ts-ignore + const files = ( + await Promise.all( + this.getFiles(compiler, wanted, exclude).map( + async (/** @type {string | undefined} */ file) => { + try { + return (await api.isPathIgnored(file)) ? false : file; + } catch (e) { + return file; + } + } + ) + ) + ).filter((file) => file !== false); if (threads > 1) { for (const file of files) { diff --git a/src/linter.js b/src/linter.js index 4a611f6..9350694 100644 --- a/src/linter.js +++ b/src/linter.js @@ -7,6 +7,7 @@ const getStylelint = require('./getStylelint'); /** @typedef {import('stylelint')} Stylelint */ /** @typedef {import('stylelint').LintResult} LintResult */ +/** @typedef {import('stylelint').InternalApi} InternalApi */ /** @typedef {import('webpack').Compiler} Compiler */ /** @typedef {import('webpack').Compilation} Compilation */ /** @typedef {import('./options').Options} Options */ @@ -25,12 +26,15 @@ const resultStorage = new WeakMap(); * @param {string|undefined} key * @param {Options} options * @param {Compilation} compilation - * @returns {{lint: Linter, report: Reporter, threads: number}} + * @returns {{api: InternalApi, lint: Linter, report: Reporter, threads: number}} */ function linter(key, options, compilation) { /** @type {Stylelint} */ let stylelint; + /** @type {InternalApi} */ + let api; + /** @type {(files: string|string[]) => Promise} */ let lintFiles; @@ -46,13 +50,17 @@ function linter(key, options, compilation) { const crossRunResultStorage = getResultStorage(compilation); try { - ({ stylelint, lintFiles, cleanup, threads } = getStylelint(key, options)); + ({ stylelint, api, lintFiles, cleanup, threads } = getStylelint( + key, + options + )); } catch (e) { throw new StylelintError(e.message); } return { lint, + api, report, threads, }; diff --git a/test/fixtures/stylelintignore/.stylelintignore b/test/fixtures/stylelintignore/.stylelintignore new file mode 100644 index 0000000..9807424 --- /dev/null +++ b/test/fixtures/stylelintignore/.stylelintignore @@ -0,0 +1,7 @@ +ignore.scss + +# comment + +noop.scss + +ignore.scss diff --git a/test/fixtures/stylelintignore/ignore.scss b/test/fixtures/stylelintignore/ignore.scss new file mode 100644 index 0000000..f9da5f6 --- /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/mock/stylelint/index.js b/test/mock/stylelint/index.js index f5b72dc..e03e268 100644 --- a/test/mock/stylelint/index.js +++ b/test/mock/stylelint/index.js @@ -24,4 +24,12 @@ module.exports = { ], }; }, + + createLinter() { + return { + isPathIgnored() { + return false; + }, + }; + }, }; diff --git a/test/stylelint-ignore.test.js b/test/stylelint-ignore.test.js new file mode 100644 index 0000000..51e67f6 --- /dev/null +++ b/test/stylelint-ignore.test.js @@ -0,0 +1,13 @@ +import pack from './utils/pack'; + +describe('stylelint ignore', () => { + it('should ignore file', (done) => { + const compiler = pack('stylelintignore'); + + compiler.run((err, stats) => { + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(false); + done(); + }); + }); +}); diff --git a/test/stylelint-lint.test.js b/test/stylelint-lint.test.js index a7caf60..3283eb8 100644 --- a/test/stylelint-lint.test.js +++ b/test/stylelint-lint.test.js @@ -9,6 +9,11 @@ describe('stylelint lint', () => { jest.mock('stylelint', () => { return { lint: mockLintFiles, + createLinter: () => { + return { + isPathIgnored: () => false, + }; + }, }; }); }); diff --git a/types/getStylelint.d.ts b/types/getStylelint.d.ts index 201e61b..8b69074 100644 --- a/types/getStylelint.d.ts +++ b/types/getStylelint.d.ts @@ -22,6 +22,7 @@ declare namespace getStylelint { } type Options = import('./options').Options; type Linter = { + api: import('stylelint').InternalApi; stylelint: Stylelint; lintFiles: LintTask; cleanup: AsyncTask; diff --git a/types/linter.d.ts b/types/linter.d.ts index 411a9c0..7e1d272 100644 --- a/types/linter.d.ts +++ b/types/linter.d.ts @@ -4,13 +4,14 @@ export = linter; * @param {string|undefined} key * @param {Options} options * @param {Compilation} compilation - * @returns {{lint: Linter, report: Reporter, threads: number}} + * @returns {{api: InternalApi, lint: Linter, report: Reporter, threads: number}} */ declare function linter( key: string | undefined, options: Options, compilation: Compilation ): { + api: InternalApi; lint: Linter; report: Reporter; threads: number; @@ -19,6 +20,7 @@ declare namespace linter { export { Stylelint, LintResult, + InternalApi, Compiler, Compilation, Options, @@ -33,6 +35,7 @@ declare namespace linter { } type Options = import('./options').Options; type Compilation = import('webpack').Compilation; +type InternalApi = import('stylelint').InternalApi; type Linter = (files: string | string[]) => void; type Reporter = () => Promise; type Stylelint = import('postcss').PluginCreator<