stylelint-webpack-plugin 3.3.0 → 4.1.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]
@@ -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
@@ -9,7 +9,5 @@ class StylelintError extends Error {
9
9
  this.name = 'StylelintError';
10
10
  this.stack = '';
11
11
  }
12
-
13
12
  }
14
-
15
13
  module.exports = StylelintError;
@@ -3,94 +3,94 @@
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 {{lint: (options: LinterOptions) => Promise<LinterResult>, formatters: { [k: string]: Formatter }}} Stylelint */
30
26
  /** @typedef {import('stylelint').LintResult} LintResult */
31
-
27
+ /** @typedef {import('stylelint').LinterOptions} LinterOptions */
28
+ /** @typedef {import('stylelint').LinterResult} LinterResult */
29
+ /** @typedef {import('stylelint').Formatter} Formatter */
30
+ /** @typedef {import('stylelint').FormatterType} FormatterType */
32
31
  /** @typedef {import('./options').Options} Options */
33
-
32
+ /** @typedef {(stylelint: Stylelint, filePath: string) => Promise<boolean>} isPathIgnored */
34
33
  /** @typedef {() => Promise<void>} AsyncTask */
35
-
36
34
  /** @typedef {(files: string|string[]) => Promise<LintResult[]>} LintTask */
37
-
38
- /** @typedef {{api: import('stylelint').InternalApi, stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number, }} Linter */
39
-
35
+ /** @typedef {{stylelint: Stylelint, isPathIgnored: isPathIgnored, lintFiles: LintTask, cleanup: AsyncTask, threads: number }} Linter */
40
36
  /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */
41
37
 
42
38
  /**
43
39
  * @param {Options} options
44
40
  * @returns {Linter}
45
41
  */
46
-
47
42
  function loadStylelint(options) {
48
43
  const stylelintOptions = getStylelintOptions(options);
49
44
  const stylelint = setup(options, stylelintOptions);
45
+
46
+ /** @type {isPathIgnored} */
47
+ let isPathIgnored;
48
+ try {
49
+ isPathIgnored = require(`${options.stylelintPath}/lib/isPathIgnored`);
50
+ } catch (e) {
51
+ try {
52
+ // @ts-ignore
53
+ isPathIgnored = require('stylelint/lib/isPathIgnored');
54
+ } catch (_) {
55
+ isPathIgnored = () => Promise.resolve(false);
56
+ }
57
+ }
50
58
  return {
51
59
  stylelint,
52
- api: stylelint.createLinter(stylelintOptions),
60
+ isPathIgnored,
53
61
  lintFiles,
54
62
  cleanup: async () => {},
55
63
  threads: 1
56
64
  };
57
65
  }
66
+
58
67
  /**
59
68
  * @param {string|undefined} key
60
69
  * @param {number} poolSize
61
70
  * @param {Options} options
62
71
  * @returns {Linter}
63
72
  */
64
-
65
-
66
73
  function loadStylelintThreaded(key, poolSize, options) {
67
74
  const cacheKey = getCacheKey(key, options);
68
-
69
75
  const source = require.resolve('./worker');
70
-
71
76
  const workerOptions = {
72
77
  enableWorkerThreads: true,
73
78
  numWorkers: poolSize,
74
79
  setupArgs: [options, getStylelintOptions(options)]
75
80
  };
76
81
  const local = loadStylelint(options);
77
- let worker =
78
- /** @type {Worker?} */
79
- new JestWorker(source, workerOptions);
80
- /** @type {Linter} */
82
+ let worker = /** @type {Worker?} */new JestWorker(source, workerOptions);
81
83
 
82
- const context = { ...local,
84
+ /** @type {Linter} */
85
+ const context = {
86
+ ...local,
83
87
  threads: poolSize,
84
- lintFiles: async files =>
85
- /* istanbul ignore next */
88
+ lintFiles: async files => /* istanbul ignore next */
86
89
  worker ? worker.lintFiles(files) : local.lintFiles(files),
87
90
  cleanup: async () => {
88
91
  cache[cacheKey] = local;
89
-
90
92
  context.lintFiles = files => local.lintFiles(files);
91
93
  /* istanbul ignore next */
92
-
93
-
94
94
  if (worker) {
95
95
  worker.end();
96
96
  worker = null;
@@ -99,13 +99,12 @@ function loadStylelintThreaded(key, poolSize, options) {
99
99
  };
100
100
  return context;
101
101
  }
102
+
102
103
  /**
103
104
  * @param {string|undefined} key
104
105
  * @param {Options} options
105
106
  * @returns {Linter}
106
107
  */
107
-
108
-
109
108
  function getStylelint(key, {
110
109
  threads,
111
110
  ...options
@@ -115,25 +114,21 @@ function getStylelint(key, {
115
114
  threads,
116
115
  ...options
117
116
  });
118
-
119
117
  if (!cache[cacheKey]) {
120
118
  cache[cacheKey] = max > 1 ? loadStylelintThreaded(key, max, options) : loadStylelint(options);
121
119
  }
122
-
123
120
  return cache[cacheKey];
124
121
  }
122
+
125
123
  /**
126
124
  * @param {string|undefined} key
127
125
  * @param {Options} options
128
126
  * @returns {string}
129
127
  */
130
-
131
-
132
128
  function getCacheKey(key, options) {
133
129
  return JSON.stringify({
134
130
  key,
135
131
  options
136
132
  }, jsonStringifyReplacerSortKeys);
137
133
  }
138
-
139
134
  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,78 +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
47
  this.key = compiler.name || `${this.key}_${counter += 1}`;
58
48
  const context = this.getContext(compiler);
59
49
  const excludeDefault = ['**/node_modules/**', String(compiler.options.output.path)];
60
- const options = { ...this.options,
50
+ const options = {
51
+ ...this.options,
61
52
  context,
62
53
  exclude: parseFiles(this.options.exclude || excludeDefault, context),
63
54
  extensions: arrify(this.options.extensions),
64
55
  files: parseFiles(this.options.files || '', context)
65
56
  };
66
57
  const wanted = parseFoldersToGlobs(options.files, options.extensions);
67
- const exclude = parseFoldersToGlobs(options.exclude); // If `lintDirtyModulesOnly` is disabled,
68
- // execute the linter on the build
58
+ const exclude = parseFoldersToGlobs(options.exclude);
69
59
 
60
+ // If `lintDirtyModulesOnly` is disabled,
61
+ // execute the linter on the build
70
62
  if (!this.options.lintDirtyModulesOnly) {
71
63
  compiler.hooks.run.tapPromise(this.key, c => this.run(c, options, wanted, exclude));
72
64
  }
73
-
74
65
  let isFirstRun = this.options.lintDirtyModulesOnly;
75
66
  compiler.hooks.watchRun.tapPromise(this.key, c => {
76
67
  if (isFirstRun) {
77
68
  isFirstRun = false;
78
69
  return Promise.resolve();
79
70
  }
80
-
81
71
  return this.run(c, options, wanted, exclude);
82
72
  });
83
73
  }
74
+
84
75
  /**
85
76
  * @param {Compiler} compiler
86
77
  * @param {Options} options
87
78
  * @param {string[]} wanted
88
79
  * @param {string[]} exclude
89
80
  */
90
-
91
-
92
81
  async run(compiler, options, wanted, exclude) {
93
82
  // Do not re-hook
94
-
95
83
  /* istanbul ignore if */
96
- if ( // @ts-ignore
84
+ if (
85
+ // @ts-ignore
97
86
  compiler.hooks.thisCompilation.taps.find(({
98
87
  name
99
88
  }) => name === this.key)) {
100
89
  return;
101
90
  }
102
-
103
91
  compiler.hooks.thisCompilation.tap(this.key, compilation => {
92
+ /** @type {import('./getStylelint').Stylelint} */
93
+ let stylelint;
94
+
104
95
  /** @type {import('./linter').Linter} */
105
96
  let lint;
106
- /** @type {import('stylelint').InternalApi} */
107
97
 
108
- let api;
109
- /** @type {import('./linter').Reporter} */
98
+ /** @type {import('./linter').isPathIgnored} */
99
+ let isPathIgnored;
110
100
 
101
+ /** @type {import('./linter').Reporter} */
111
102
  let report;
112
- /** @type number */
113
103
 
104
+ /** @type number */
114
105
  let threads;
115
-
116
106
  try {
117
107
  ({
108
+ stylelint,
118
109
  lint,
119
- api,
110
+ isPathIgnored,
120
111
  report,
121
112
  threads
122
113
  } = linter(this.key, options, compilation));
@@ -124,7 +115,6 @@ class StylelintWebpackPlugin {
124
115
  compilation.errors.push(e);
125
116
  return;
126
117
  }
127
-
128
118
  compilation.hooks.finishModules.tapPromise(this.key, async () => {
129
119
  /** @type {string[]} */
130
120
  // @ts-ignore
@@ -137,30 +127,28 @@ class StylelintWebpackPlugin {
137
127
  ignore: exclude
138
128
  })).map(async file => {
139
129
  try {
140
- return (await api.isPathIgnored(file)) ? false : file;
130
+ return (await isPathIgnored(stylelint, file)) ? false : file;
141
131
  } catch (e) {
142
132
  return file;
143
133
  }
144
134
  }))).filter(file => file !== false);
145
-
146
135
  if (threads > 1) {
147
136
  for (const file of files) {
148
- lint(parseFiles(file, options.context || ''));
137
+ lint(parseFiles(file, String(options.context)));
149
138
  }
150
139
  } else if (files.length > 0) {
151
- lint(parseFiles(files, options.context || ''));
140
+ lint(parseFiles(files, String(options.context)));
152
141
  }
153
- }); // await and interpret results
142
+ });
154
143
 
144
+ // await and interpret results
155
145
  compilation.hooks.additionalAssets.tapPromise(this.key, processResults);
156
-
157
146
  async function processResults() {
158
147
  const {
159
148
  errors,
160
149
  warnings,
161
150
  generateReportAsset
162
151
  } = await report();
163
-
164
152
  if (warnings && !options.failOnWarning) {
165
153
  // @ts-ignore
166
154
  compilation.warnings.push(warnings);
@@ -168,7 +156,6 @@ class StylelintWebpackPlugin {
168
156
  // @ts-ignore
169
157
  compilation.errors.push(warnings);
170
158
  }
171
-
172
159
  if (errors && options.failOnError) {
173
160
  // @ts-ignore
174
161
  compilation.errors.push(errors);
@@ -176,32 +163,26 @@ class StylelintWebpackPlugin {
176
163
  // @ts-ignore
177
164
  compilation.warnings.push(errors);
178
165
  }
179
-
180
166
  if (generateReportAsset) {
181
167
  await generateReportAsset(compilation);
182
168
  }
183
169
  }
184
170
  });
185
171
  }
172
+
186
173
  /**
187
174
  *
188
175
  * @param {Compiler} compiler
189
176
  * @returns {string}
190
177
  */
191
-
192
-
193
178
  getContext(compiler) {
194
179
  if (!this.options.context) {
195
180
  return String(compiler.options.context);
196
181
  }
197
-
198
182
  if (!isAbsolute(this.options.context)) {
199
183
  return join(String(compiler.options.context), this.options.context);
200
184
  }
201
-
202
185
  return this.options.context;
203
186
  }
204
-
205
187
  }
206
-
207
188
  module.exports = StylelintWebpackPlugin;