stylelint-webpack-plugin 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,6 @@
5
5
 
6
6
  [![npm][npm]][npm-url]
7
7
  [![node][node]][node-url]
8
- [![deps][deps]][deps-url]
9
8
  [![tests][tests]][tests-url]
10
9
  [![coverage][cover]][cover-url]
11
10
  [![chat][chat]][chat-url]
@@ -28,7 +27,7 @@ npm install stylelint-webpack-plugin --save-dev
28
27
  or
29
28
 
30
29
  ```console
31
- yarn add -D install stylelint-webpack-plugin
30
+ yarn add -D stylelint-webpack-plugin
32
31
  ```
33
32
 
34
33
  or
@@ -37,7 +36,9 @@ or
37
36
  pnpm add -D stylelint-webpack-plugin
38
37
  ```
39
38
 
40
- **Note**: You also need to install `stylelint >= 13` from npm, if you haven't already:
39
+ > **Note**:
40
+ >
41
+ > You also need to install `stylelint >= 13` from npm, if you haven't already:
41
42
 
42
43
  ```console
43
44
  npm install stylelint --save-dev
@@ -55,7 +56,9 @@ or
55
56
  pnpm add -D stylelint
56
57
  ```
57
58
 
58
- **Note**: If you are using Stylelint 13 rather than 14+, you might also need to install `@types/stylelint` as a dev dependency if getting stylelint related type errors.
59
+ > **Note**:
60
+ >
61
+ > If you are using Stylelint 13 rather than 14+, you might also need to install `@types/stylelint` as a dev dependency if getting stylelint related type errors.
59
62
 
60
63
  Then add the plugin to your webpack config. For example:
61
64
 
@@ -85,7 +88,9 @@ type context = string;
85
88
 
86
89
  Specify the config file location to be used by `stylelint`.
87
90
 
88
- **Note:** By default this is [handled by `stylelint`](https://stylelint.io/user-guide/configure).
91
+ > **Note:**
92
+ >
93
+ > By default this is [handled by `stylelint`](https://stylelint.io/user-guide/configure).
89
94
 
90
95
  ### `context`
91
96
 
@@ -305,8 +310,6 @@ You can pass in a different formatter for the output file, if none is passed in
305
310
  [npm-url]: https://npmjs.com/package/stylelint-webpack-plugin
306
311
  [node]: https://img.shields.io/node/v/stylelint-webpack-plugin.svg
307
312
  [node-url]: https://nodejs.org
308
- [deps]: https://david-dm.org/webpack-contrib/stylelint-webpack-plugin.svg
309
- [deps-url]: https://david-dm.org/webpack-contrib/stylelint-webpack-plugin
310
313
  [tests]: https://github.com/webpack-contrib/stylelint-webpack-plugin/workflows/stylelint-webpack-plugin/badge.svg
311
314
  [tests-url]: https://github.com/webpack-contrib/stylelint-webpack-plugin/actions
312
315
  [cover]: https://codecov.io/gh/webpack-contrib/stylelint-webpack-plugin/branch/master/graph/badge.svg
@@ -5,11 +5,9 @@ class StylelintError extends Error {
5
5
  * @param {string=} messages
6
6
  */
7
7
  constructor(messages) {
8
- super(messages);
8
+ super(`[stylelint] ${messages}`);
9
9
  this.name = 'StylelintError';
10
10
  this.stack = '';
11
11
  }
12
-
13
12
  }
14
-
15
13
  module.exports = StylelintError;
@@ -3,94 +3,90 @@
3
3
  const {
4
4
  cpus
5
5
  } = require('os');
6
-
7
6
  const {
8
7
  Worker: JestWorker
9
- } = require('jest-worker'); // @ts-ignore
10
-
8
+ } = require('jest-worker');
11
9
 
10
+ // @ts-ignore
12
11
  const {
13
12
  setup,
14
13
  lintFiles
15
14
  } = require('./worker');
16
-
17
15
  const {
18
16
  jsonStringifyReplacerSortKeys
19
17
  } = require('./utils');
20
-
21
18
  const {
22
19
  getStylelintOptions
23
20
  } = require('./options');
24
- /** @type {{[key: string]: any}} */
25
-
26
21
 
22
+ /** @type {{[key: string]: any}} */
27
23
  const cache = {};
28
- /** @typedef {import('stylelint')} Stylelint */
29
24
 
25
+ /** @typedef {import('stylelint')} Stylelint */
30
26
  /** @typedef {import('stylelint').LintResult} LintResult */
31
-
32
27
  /** @typedef {import('./options').Options} Options */
33
-
28
+ /** @typedef {(stylelint: Stylelint, filePath: string) => Promise<boolean>} isPathIgnored */
34
29
  /** @typedef {() => Promise<void>} AsyncTask */
35
-
36
30
  /** @typedef {(files: string|string[]) => Promise<LintResult[]>} LintTask */
37
-
38
- /** @typedef {{api: import('stylelint').InternalApi, stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number, }} Linter */
39
-
40
- /** @typedef {import('jest-worker').Worker & {lintFiles: LintTask}} Worker */
31
+ /** @typedef {{stylelint: Stylelint, isPathIgnored: isPathIgnored, lintFiles: LintTask, cleanup: AsyncTask, threads: number }} Linter */
32
+ /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */
41
33
 
42
34
  /**
43
35
  * @param {Options} options
44
36
  * @returns {Linter}
45
37
  */
46
-
47
38
  function loadStylelint(options) {
48
39
  const stylelintOptions = getStylelintOptions(options);
49
40
  const stylelint = setup(options, stylelintOptions);
41
+
42
+ /** @type {isPathIgnored} */
43
+ let isPathIgnored;
44
+ try {
45
+ isPathIgnored = require(`${options.stylelintPath}/lib/isPathIgnored`);
46
+ } catch (e) {
47
+ try {
48
+ // @ts-ignore
49
+ isPathIgnored = require('stylelint/lib/isPathIgnored');
50
+ } catch (_) {
51
+ isPathIgnored = () => Promise.resolve(false);
52
+ }
53
+ }
50
54
  return {
51
55
  stylelint,
52
- api: stylelint.createLinter(stylelintOptions),
56
+ isPathIgnored,
53
57
  lintFiles,
54
58
  cleanup: async () => {},
55
59
  threads: 1
56
60
  };
57
61
  }
62
+
58
63
  /**
59
64
  * @param {string|undefined} key
60
65
  * @param {number} poolSize
61
66
  * @param {Options} options
62
67
  * @returns {Linter}
63
68
  */
64
-
65
-
66
69
  function loadStylelintThreaded(key, poolSize, options) {
67
70
  const cacheKey = getCacheKey(key, options);
68
-
69
71
  const source = require.resolve('./worker');
70
-
71
72
  const workerOptions = {
72
73
  enableWorkerThreads: true,
73
74
  numWorkers: poolSize,
74
75
  setupArgs: [options, getStylelintOptions(options)]
75
76
  };
76
77
  const local = loadStylelint(options);
77
- let worker =
78
- /** @type {Worker?} */
79
- new JestWorker(source, workerOptions);
80
- /** @type {Linter} */
78
+ let worker = /** @type {Worker?} */new JestWorker(source, workerOptions);
81
79
 
82
- const context = { ...local,
80
+ /** @type {Linter} */
81
+ const context = {
82
+ ...local,
83
83
  threads: poolSize,
84
- lintFiles: async files =>
85
- /* istanbul ignore next */
84
+ lintFiles: async files => /* istanbul ignore next */
86
85
  worker ? worker.lintFiles(files) : local.lintFiles(files),
87
86
  cleanup: async () => {
88
87
  cache[cacheKey] = local;
89
-
90
88
  context.lintFiles = files => local.lintFiles(files);
91
89
  /* istanbul ignore next */
92
-
93
-
94
90
  if (worker) {
95
91
  worker.end();
96
92
  worker = null;
@@ -99,13 +95,12 @@ function loadStylelintThreaded(key, poolSize, options) {
99
95
  };
100
96
  return context;
101
97
  }
98
+
102
99
  /**
103
100
  * @param {string|undefined} key
104
101
  * @param {Options} options
105
102
  * @returns {Linter}
106
103
  */
107
-
108
-
109
104
  function getStylelint(key, {
110
105
  threads,
111
106
  ...options
@@ -115,25 +110,21 @@ function getStylelint(key, {
115
110
  threads,
116
111
  ...options
117
112
  });
118
-
119
113
  if (!cache[cacheKey]) {
120
114
  cache[cacheKey] = max > 1 ? loadStylelintThreaded(key, max, options) : loadStylelint(options);
121
115
  }
122
-
123
116
  return cache[cacheKey];
124
117
  }
118
+
125
119
  /**
126
120
  * @param {string|undefined} key
127
121
  * @param {Options} options
128
122
  * @returns {string}
129
123
  */
130
-
131
-
132
124
  function getCacheKey(key, options) {
133
125
  return JSON.stringify({
134
126
  key,
135
127
  options
136
128
  }, jsonStringifyReplacerSortKeys);
137
129
  }
138
-
139
130
  module.exports = getStylelint;
package/dist/index.js CHANGED
@@ -4,36 +4,27 @@ const {
4
4
  isAbsolute,
5
5
  join
6
6
  } = require('path');
7
-
8
7
  const globby = require('globby');
9
-
10
8
  const {
11
9
  isMatch
12
10
  } = require('micromatch');
13
-
14
11
  const {
15
12
  getOptions
16
13
  } = require('./options');
17
-
18
14
  const linter = require('./linter');
19
-
20
15
  const {
21
16
  arrify,
22
17
  parseFiles,
23
18
  parseFoldersToGlobs
24
19
  } = require('./utils');
25
- /** @typedef {import('webpack').Compiler} Compiler */
26
20
 
21
+ /** @typedef {import('webpack').Compiler} Compiler */
27
22
  /** @typedef {import('webpack').Module} Module */
28
-
29
23
  /** @typedef {import('./options').Options} Options */
30
-
31
24
  /** @typedef {Partial<{timestamp:number} | number>} FileSystemInfoEntry */
32
25
 
33
-
34
26
  const STYLELINT_PLUGIN = 'StylelintWebpackPlugin';
35
27
  let counter = 0;
36
-
37
28
  class StylelintWebpackPlugin {
38
29
  /**
39
30
  * @param {Options} options
@@ -45,74 +36,78 @@ class StylelintWebpackPlugin {
45
36
  this.startTime = Date.now();
46
37
  this.prevTimestamps = new Map();
47
38
  }
39
+
48
40
  /**
49
41
  * @param {Compiler} compiler
50
42
  * @returns {void}
51
43
  */
52
-
53
-
54
44
  apply(compiler) {
55
45
  // Generate key for each compilation,
56
46
  // this differentiates one from the other when being cached.
57
- this.key = compiler.name || `${this.key}_${counter += 1}`; // If `lintDirtyModulesOnly` is disabled,
58
- // execute the linter on the build
47
+ this.key = compiler.name || `${this.key}_${counter += 1}`;
48
+ const context = this.getContext(compiler);
49
+ const excludeDefault = ['**/node_modules/**', String(compiler.options.output.path)];
50
+ const options = {
51
+ ...this.options,
52
+ context,
53
+ exclude: parseFiles(this.options.exclude || excludeDefault, context),
54
+ extensions: arrify(this.options.extensions),
55
+ files: parseFiles(this.options.files || '', context)
56
+ };
57
+ const wanted = parseFoldersToGlobs(options.files, options.extensions);
58
+ const exclude = parseFoldersToGlobs(options.exclude);
59
59
 
60
+ // If `lintDirtyModulesOnly` is disabled,
61
+ // execute the linter on the build
60
62
  if (!this.options.lintDirtyModulesOnly) {
61
- compiler.hooks.run.tapPromise(this.key, this.run);
63
+ compiler.hooks.run.tapPromise(this.key, c => this.run(c, options, wanted, exclude));
62
64
  }
63
-
64
65
  let isFirstRun = this.options.lintDirtyModulesOnly;
65
66
  compiler.hooks.watchRun.tapPromise(this.key, c => {
66
67
  if (isFirstRun) {
67
68
  isFirstRun = false;
68
69
  return Promise.resolve();
69
70
  }
70
-
71
- return this.run(c);
71
+ return this.run(c, options, wanted, exclude);
72
72
  });
73
73
  }
74
+
74
75
  /**
75
76
  * @param {Compiler} compiler
77
+ * @param {Options} options
78
+ * @param {string[]} wanted
79
+ * @param {string[]} exclude
76
80
  */
77
-
78
-
79
- async run(compiler) {
81
+ async run(compiler, options, wanted, exclude) {
80
82
  // Do not re-hook
81
-
82
83
  /* istanbul ignore if */
83
- if ( // @ts-ignore
84
+ if (
85
+ // @ts-ignore
84
86
  compiler.hooks.thisCompilation.taps.find(({
85
87
  name
86
88
  }) => name === this.key)) {
87
89
  return;
88
90
  }
89
-
90
- const context = this.getContext(compiler);
91
- const excludeDefault = ['**/node_modules/**', String(compiler.options.output.path)];
92
- const options = { ...this.options,
93
- exclude: parseFiles(this.options.exclude || excludeDefault, context),
94
- extensions: arrify(this.options.extensions),
95
- files: parseFiles(this.options.files || '', context)
96
- };
97
- const wanted = parseFoldersToGlobs(options.files, options.extensions);
98
- const exclude = parseFoldersToGlobs(options.exclude);
99
91
  compiler.hooks.thisCompilation.tap(this.key, compilation => {
92
+ /** @type {import('stylelint')} */
93
+ let stylelint;
94
+
100
95
  /** @type {import('./linter').Linter} */
101
96
  let lint;
102
- /** @type {import('stylelint').InternalApi} */
103
97
 
104
- let api;
105
- /** @type {import('./linter').Reporter} */
98
+ /** @type {import('./linter').isPathIgnored} */
99
+ let isPathIgnored;
106
100
 
101
+ /** @type {import('./linter').Reporter} */
107
102
  let report;
108
- /** @type number */
109
103
 
104
+ /** @type number */
110
105
  let threads;
111
-
112
106
  try {
113
107
  ({
108
+ stylelint,
114
109
  lint,
115
- api,
110
+ isPathIgnored,
116
111
  report,
117
112
  threads
118
113
  } = linter(this.key, options, compilation));
@@ -120,7 +115,6 @@ class StylelintWebpackPlugin {
120
115
  compilation.errors.push(e);
121
116
  return;
122
117
  }
123
-
124
118
  compilation.hooks.finishModules.tapPromise(this.key, async () => {
125
119
  /** @type {string[]} */
126
120
  // @ts-ignore
@@ -133,30 +127,28 @@ class StylelintWebpackPlugin {
133
127
  ignore: exclude
134
128
  })).map(async file => {
135
129
  try {
136
- return (await api.isPathIgnored(file)) ? false : file;
130
+ return (await isPathIgnored(stylelint, file)) ? false : file;
137
131
  } catch (e) {
138
132
  return file;
139
133
  }
140
134
  }))).filter(file => file !== false);
141
-
142
135
  if (threads > 1) {
143
136
  for (const file of files) {
144
- lint(parseFiles(file, context));
137
+ lint(parseFiles(file, String(options.context)));
145
138
  }
146
139
  } else if (files.length > 0) {
147
- lint(parseFiles(files, context));
140
+ lint(parseFiles(files, String(options.context)));
148
141
  }
149
- }); // await and interpret results
142
+ });
150
143
 
144
+ // await and interpret results
151
145
  compilation.hooks.additionalAssets.tapPromise(this.key, processResults);
152
-
153
146
  async function processResults() {
154
147
  const {
155
148
  errors,
156
149
  warnings,
157
150
  generateReportAsset
158
151
  } = await report();
159
-
160
152
  if (warnings && !options.failOnWarning) {
161
153
  // @ts-ignore
162
154
  compilation.warnings.push(warnings);
@@ -164,7 +156,6 @@ class StylelintWebpackPlugin {
164
156
  // @ts-ignore
165
157
  compilation.errors.push(warnings);
166
158
  }
167
-
168
159
  if (errors && options.failOnError) {
169
160
  // @ts-ignore
170
161
  compilation.errors.push(errors);
@@ -172,32 +163,26 @@ class StylelintWebpackPlugin {
172
163
  // @ts-ignore
173
164
  compilation.warnings.push(errors);
174
165
  }
175
-
176
166
  if (generateReportAsset) {
177
167
  await generateReportAsset(compilation);
178
168
  }
179
169
  }
180
170
  });
181
171
  }
172
+
182
173
  /**
183
174
  *
184
175
  * @param {Compiler} compiler
185
176
  * @returns {string}
186
177
  */
187
-
188
-
189
178
  getContext(compiler) {
190
179
  if (!this.options.context) {
191
180
  return String(compiler.options.context);
192
181
  }
193
-
194
182
  if (!isAbsolute(this.options.context)) {
195
183
  return join(String(compiler.options.context), this.options.context);
196
184
  }
197
-
198
185
  return this.options.context;
199
186
  }
200
-
201
187
  }
202
-
203
188
  module.exports = StylelintWebpackPlugin;