stylelint-webpack-plugin 2.4.0 → 2.5.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/dist/linter.js CHANGED
@@ -5,73 +5,57 @@ const {
5
5
  isAbsolute,
6
6
  join
7
7
  } = require('path');
8
-
9
8
  const arrify = require('arrify');
10
-
11
9
  const StylelintError = require('./StylelintError');
12
-
13
10
  const getStylelint = require('./getStylelint');
14
- /** @typedef {import('stylelint')} Stylelint */
15
-
16
- /** @typedef {import('stylelint').LintResult} LintResult */
17
-
18
- /** @typedef {import('stylelint').InternalApi} InternalApi */
19
11
 
20
12
  /** @typedef {import('webpack').Compiler} Compiler */
21
-
22
13
  /** @typedef {import('webpack').Compilation} Compilation */
23
-
14
+ /** @typedef {import('./getStylelint').Stylelint} Stylelint */
15
+ /** @typedef {import('./getStylelint').LintResult} LintResult */
16
+ /** @typedef {import('./getStylelint').LinterResult} LinterResult */
17
+ /** @typedef {import('./getStylelint').Formatter} Formatter */
18
+ /** @typedef {import('./getStylelint').FormatterType} FormatterType */
19
+ /** @typedef {import('./getStylelint').isPathIgnored} isPathIgnored */
24
20
  /** @typedef {import('./options').Options} Options */
25
-
26
- /** @typedef {import('./options').FormatterType} FormatterType */
27
-
28
- /** @typedef {((results: LintResult[]) => string)} FormatterFunction */
29
-
30
21
  /** @typedef {(compilation: Compilation) => Promise<void>} GenerateReport */
31
-
32
22
  /** @typedef {{errors?: StylelintError, warnings?: StylelintError, generateReportAsset?: GenerateReport}} Report */
33
-
34
23
  /** @typedef {() => Promise<Report>} Reporter */
35
-
36
24
  /** @typedef {(files: string|string[]) => void} Linter */
37
-
38
25
  /** @typedef {{[files: string]: LintResult}} LintResultMap */
39
26
 
40
27
  /** @type {WeakMap<Compiler, LintResultMap>} */
41
-
42
-
43
28
  const resultStorage = new WeakMap();
29
+
44
30
  /**
45
31
  * @param {string|undefined} key
46
32
  * @param {Options} options
47
33
  * @param {Compilation} compilation
48
- * @returns {{api: InternalApi, lint: Linter, report: Reporter, threads: number}}
34
+ * @returns {{stylelint: Stylelint, isPathIgnored: isPathIgnored, lint: Linter, report: Reporter, threads: number}}
49
35
  */
50
-
51
36
  function linter(key, options, compilation) {
52
37
  /** @type {Stylelint} */
53
38
  let stylelint;
54
- /** @type {InternalApi} */
55
39
 
56
- let api;
57
- /** @type {(files: string|string[]) => Promise<LintResult[]>} */
40
+ /** @type {isPathIgnored} */
41
+ let isPathIgnored;
58
42
 
43
+ /** @type {(files: string|string[]) => Promise<LintResult[]>} */
59
44
  let lintFiles;
60
- /** @type {() => Promise<void>} */
61
45
 
46
+ /** @type {() => Promise<void>} */
62
47
  let cleanup;
63
- /** @type number */
64
48
 
49
+ /** @type number */
65
50
  let threads;
66
- /** @type {Promise<LintResult[]>[]} */
67
51
 
52
+ /** @type {Promise<LintResult[]>[]} */
68
53
  const rawResults = [];
69
54
  const crossRunResultStorage = getResultStorage(compilation);
70
-
71
55
  try {
72
56
  ({
73
57
  stylelint,
74
- api,
58
+ isPathIgnored,
75
59
  lintFiles,
76
60
  cleanup,
77
61
  threads
@@ -79,60 +63,68 @@ function linter(key, options, compilation) {
79
63
  } catch (e) {
80
64
  throw new StylelintError(e.message);
81
65
  }
82
-
83
66
  return {
67
+ stylelint,
84
68
  lint,
85
- api,
69
+ isPathIgnored,
86
70
  report,
87
71
  threads
88
72
  };
73
+
89
74
  /**
90
75
  * @param {string | string[]} files
91
76
  */
92
-
93
77
  function lint(files) {
94
78
  for (const file of arrify(files)) {
95
79
  delete crossRunResultStorage[file];
96
80
  }
97
-
98
81
  rawResults.push(lintFiles(files).catch(e => {
99
82
  // @ts-ignore
100
83
  compilation.errors.push(new StylelintError(e.message));
101
84
  return [];
102
85
  }));
103
86
  }
104
-
105
87
  async function report() {
106
88
  // Filter out ignored files.
107
- let results = removeIgnoredWarnings( // Get the current results, resetting the rawResults to empty
89
+ let results = removeIgnoredWarnings(
90
+ // Get the current results, resetting the rawResults to empty
108
91
  await flatten(rawResults.splice(0, rawResults.length)));
109
92
  await cleanup();
110
-
111
93
  for (const result of results) {
112
94
  crossRunResultStorage[String(result.source)] = result;
113
95
  }
96
+ results = Object.values(crossRunResultStorage);
114
97
 
115
- results = Object.values(crossRunResultStorage); // do not analyze if there are no results or stylelint config
116
-
98
+ // do not analyze if there are no results or stylelint config
117
99
  if (!results || results.length < 1) {
118
100
  return {};
119
101
  }
120
-
121
102
  const formatter = loadFormatter(stylelint, options.formatter);
103
+
104
+ /** @type {LinterResult} */
105
+ const returnValue = {
106
+ // @ts-ignore
107
+ cwd: options.cwd,
108
+ errored: false,
109
+ results: [],
110
+ output: '',
111
+ reportedDisables: [],
112
+ ruleMetadata: getRuleMetadata(results)
113
+ };
122
114
  const {
123
115
  errors,
124
116
  warnings
125
- } = formatResults(formatter, parseResults(options, results));
117
+ } = formatResults(formatter, parseResults(options, results), returnValue);
126
118
  return {
127
119
  errors,
128
120
  warnings,
129
121
  generateReportAsset
130
122
  };
123
+
131
124
  /**
132
125
  * @param {Compilation} compilation
133
126
  * @returns {Promise<void>}
134
127
  */
135
-
136
128
  async function generateReportAsset({
137
129
  compiler
138
130
  }) {
@@ -143,16 +135,14 @@ function linter(key, options, compilation) {
143
135
  * @param {string} name
144
136
  * @param {string | Buffer} content
145
137
  */
146
-
147
- const save = (name, content) =>
148
- /** @type {Promise<void>} */
138
+ const save = (name, content) => /** @type {Promise<void>} */
149
139
  new Promise((finish, bail) => {
150
140
  const {
151
141
  mkdir,
152
142
  writeFile
153
- } = compiler.outputFileSystem; // ensure directory exists
143
+ } = compiler.outputFileSystem;
144
+ // ensure directory exists
154
145
  // @ts-ignore - the types for `outputFileSystem` are missing the 3 arg overload
155
-
156
146
  mkdir(dirname(name), {
157
147
  recursive: true
158
148
  }, err => {
@@ -163,43 +153,38 @@ function linter(key, options, compilation) {
163
153
  });
164
154
  });
165
155
  });
166
-
167
156
  if (!outputReport || !outputReport.filePath) {
168
157
  return;
169
158
  }
170
-
171
- const content = outputReport.formatter ? loadFormatter(stylelint, outputReport.formatter)(results) : formatter(results);
159
+ const content = outputReport.formatter;
160
+ loadFormatter(stylelint, outputReport.formatter)(results, returnValue);
161
+ formatter(results, returnValue);
172
162
  let {
173
163
  filePath
174
164
  } = outputReport;
175
-
176
165
  if (!isAbsolute(filePath)) {
177
166
  filePath = join(compiler.outputPath, filePath);
178
167
  }
179
-
180
- await save(filePath, content);
168
+ await save(filePath, String(content));
181
169
  }
182
170
  }
183
171
  }
172
+
184
173
  /**
185
- * @param {FormatterFunction} formatter
174
+ * @param {Formatter} formatter
186
175
  * @param {{ errors: LintResult[]; warnings: LintResult[]; }} results
176
+ * @param {LinterResult} returnValue
187
177
  * @returns {{errors?: StylelintError, warnings?: StylelintError}}
188
178
  */
189
-
190
-
191
- function formatResults(formatter, results) {
179
+ function formatResults(formatter, results, returnValue) {
192
180
  let errors;
193
181
  let warnings;
194
-
195
182
  if (results.warnings.length > 0) {
196
- warnings = new StylelintError(formatter(results.warnings));
183
+ warnings = new StylelintError(formatter(results.warnings, returnValue));
197
184
  }
198
-
199
185
  if (results.errors.length > 0) {
200
- errors = new StylelintError(formatter(results.errors));
186
+ errors = new StylelintError(formatter(results.errors, returnValue));
201
187
  }
202
-
203
188
  return {
204
189
  errors,
205
190
  warnings
@@ -210,27 +195,24 @@ function formatResults(formatter, results) {
210
195
  * @param {LintResult[]} results
211
196
  * @returns {{errors: LintResult[], warnings: LintResult[]}}
212
197
  */
213
-
214
-
215
198
  function parseResults(options, results) {
216
199
  /** @type {LintResult[]} */
217
200
  const errors = [];
218
- /** @type {LintResult[]} */
219
201
 
202
+ /** @type {LintResult[]} */
220
203
  const warnings = [];
221
204
  results.forEach(file => {
222
205
  const fileErrors = file.warnings.filter(message => options.emitError && message.severity === 'error');
223
-
224
206
  if (fileErrors.length > 0) {
225
- errors.push({ ...file,
207
+ errors.push({
208
+ ...file,
226
209
  warnings: fileErrors
227
210
  });
228
211
  }
229
-
230
212
  const fileWarnings = file.warnings.filter(message => options.emitWarning && message.severity === 'warning');
231
-
232
213
  if (fileWarnings.length > 0) {
233
- warnings.push({ ...file,
214
+ warnings.push({
215
+ ...file,
234
216
  warnings: fileWarnings
235
217
  });
236
218
  }
@@ -240,67 +222,75 @@ function parseResults(options, results) {
240
222
  warnings
241
223
  };
242
224
  }
225
+
243
226
  /**
244
227
  * @param {Stylelint} stylelint
245
228
  * @param {FormatterType=} formatter
246
- * @returns {FormatterFunction}
229
+ * @returns {Formatter}
247
230
  */
248
-
249
-
250
231
  function loadFormatter(stylelint, formatter) {
251
232
  if (typeof formatter === 'function') {
252
233
  return formatter;
253
234
  }
254
-
255
235
  if (typeof formatter === 'string') {
256
236
  try {
257
237
  return stylelint.formatters[formatter];
258
- } catch (_) {// Load the default formatter.
238
+ } catch (_) {
239
+ // Load the default formatter.
259
240
  }
260
241
  }
261
-
262
242
  return stylelint.formatters.string;
263
243
  }
244
+
264
245
  /**
265
246
  * @param {LintResult[]} results
266
247
  * @returns {LintResult[]}
267
248
  */
268
-
269
-
270
249
  function removeIgnoredWarnings(results) {
271
250
  return results.filter(result => !result.ignored);
272
251
  }
252
+
273
253
  /**
274
254
  * @param {Promise<LintResult[]>[]} results
275
255
  * @returns {Promise<LintResult[]>}
276
256
  */
277
-
278
-
279
257
  async function flatten(results) {
280
258
  /**
281
259
  * @param {LintResult[]} acc
282
260
  * @param {LintResult[]} list
283
261
  */
284
262
  const flat = (acc, list) => [...acc, ...list];
285
-
286
263
  return (await Promise.all(results)).reduce(flat, []);
287
264
  }
265
+
288
266
  /**
289
267
  * @param {Compilation} compilation
290
268
  * @returns {LintResultMap}
291
269
  */
292
-
293
-
294
270
  function getResultStorage({
295
271
  compiler
296
272
  }) {
297
273
  let storage = resultStorage.get(compiler);
298
-
299
274
  if (!storage) {
300
275
  resultStorage.set(compiler, storage = {});
301
276
  }
302
-
303
277
  return storage;
304
278
  }
305
279
 
280
+ /**
281
+ * @param {LintResult[]} lintResults
282
+ */
283
+ /* istanbul ignore next */
284
+ function getRuleMetadata(lintResults) {
285
+ const [lintResult] = lintResults;
286
+
287
+ // eslint-disable-next-line no-undefined
288
+ if (lintResult === undefined) return {};
289
+
290
+ // eslint-disable-next-line no-underscore-dangle, no-undefined
291
+ if (lintResult._postcssResult === undefined) return {};
292
+
293
+ // eslint-disable-next-line no-underscore-dangle
294
+ return lintResult._postcssResult.stylelint.ruleMetadata;
295
+ }
306
296
  module.exports = linter;
package/dist/options.js CHANGED
@@ -2,15 +2,13 @@
2
2
 
3
3
  const {
4
4
  validate
5
- } = require('schema-utils'); // @ts-ignore
6
-
5
+ } = require('schema-utils');
7
6
 
7
+ // @ts-ignore
8
8
  const schema = require('./options.json');
9
- /** @typedef {import("stylelint")} stylelint */
10
-
11
- /** @typedef {import("stylelint").LinterOptions} StylelintOptions */
12
9
 
13
- /** @typedef {import("stylelint").FormatterType} FormatterType */
10
+ /** @typedef {import('./getStylelint').LinterOptions} StylelintOptions */
11
+ /** @typedef {import('./getStylelint').FormatterType} FormatterType */
14
12
 
15
13
  /**
16
14
  * @typedef {Object} OutputReport
@@ -42,8 +40,6 @@ const schema = require('./options.json');
42
40
  * @param {Options} pluginOptions
43
41
  * @returns {Partial<PluginOptions>}
44
42
  */
45
-
46
-
47
43
  function getOptions(pluginOptions) {
48
44
  const options = {
49
45
  extensions: ['css', 'scss', 'sass'],
@@ -55,39 +51,40 @@ function getOptions(pluginOptions) {
55
51
  emitError: true,
56
52
  emitWarning: false
57
53
  } : {})
58
- }; // @ts-ignore
54
+ };
59
55
 
56
+ // @ts-ignore
60
57
  validate(schema, options, {
61
58
  name: 'Stylelint Webpack Plugin',
62
59
  baseDataPath: 'options'
63
60
  });
64
61
  return options;
65
62
  }
63
+
66
64
  /**
67
65
  * @param {Options} pluginOptions
68
66
  * @returns {Partial<StylelintOptions>}
69
67
  */
70
-
71
-
72
68
  function getStylelintOptions(pluginOptions) {
73
- const stylelintOptions = { ...pluginOptions
74
- }; // Keep the files and formatter option because it is common to both the plugin and Stylelint.
69
+ const stylelintOptions = {
70
+ ...pluginOptions
71
+ };
75
72
 
73
+ // Keep the files and formatter option because it is common to both the plugin and Stylelint.
76
74
  const {
77
75
  files,
78
76
  formatter,
79
77
  ...stylelintOnlyOptions
80
- } = schema.properties; // No need to guard the for-in because schema.properties has hardcoded keys.
81
- // eslint-disable-next-line guard-for-in
78
+ } = schema.properties;
82
79
 
80
+ // No need to guard the for-in because schema.properties has hardcoded keys.
81
+ // eslint-disable-next-line guard-for-in
83
82
  for (const option in stylelintOnlyOptions) {
84
83
  // @ts-ignore
85
84
  delete stylelintOptions[option];
86
85
  }
87
-
88
86
  return stylelintOptions;
89
87
  }
90
-
91
88
  module.exports = {
92
89
  getOptions,
93
90
  getStylelintOptions
package/dist/utils.js CHANGED
@@ -3,61 +3,50 @@
3
3
  const {
4
4
  resolve
5
5
  } = require('path');
6
-
7
6
  const {
8
7
  statSync
9
8
  } = require('fs');
10
-
11
9
  const normalizePath = require('normalize-path');
12
-
13
10
  const arrify = require('arrify');
11
+
14
12
  /**
15
13
  * @param {string|(string|undefined)[]} files
16
14
  * @param {string} context
17
15
  * @returns {string[]}
18
16
  */
19
-
20
-
21
17
  function parseFiles(files, context) {
22
18
  return arrify(files).filter(file => typeof file === 'string').map(file => normalizePath(resolve(context, file || '')));
23
19
  }
20
+
24
21
  /**
25
22
  * @param {string|string[]} patterns
26
23
  * @param {string|string[]} extensions
27
24
  * @returns {string[]}
28
25
  */
29
-
30
-
31
26
  function parseFoldersToGlobs(patterns, extensions = []) {
32
27
  const extensionsList = arrify(extensions);
33
28
  const [prefix, postfix] = extensionsList.length > 1 ? ['{', '}'] : ['', ''];
34
- const extensionsGlob = extensionsList.map((
35
- /** @type {string} */
36
- extension) => extension.replace(/^\./u, '')).join(',');
37
- return arrify(patterns).map((
38
- /** @type {string} */
39
- pattern) => {
29
+ const extensionsGlob = extensionsList.map(( /** @type {string} */extension) => extension.replace(/^\./u, '')).join(',');
30
+ return arrify(patterns).map(( /** @type {string} */pattern) => {
40
31
  try {
41
32
  // The patterns are absolute because they are prepended with the context.
42
33
  const stats = statSync(pattern);
43
34
  /* istanbul ignore else */
44
-
45
35
  if (stats.isDirectory()) {
46
36
  return pattern.replace(/[/\\]*?$/u, `/**${extensionsGlob ? `/*.${prefix + extensionsGlob + postfix}` : ''}`);
47
37
  }
48
- } catch (_) {// Return the pattern as is on error.
38
+ } catch (_) {
39
+ // Return the pattern as is on error.
49
40
  }
50
-
51
41
  return pattern;
52
42
  });
53
43
  }
44
+
54
45
  /**
55
46
  *
56
47
  * @param {string} _ key, but unused
57
48
  * @param {any} value
58
49
  */
59
-
60
-
61
50
  const jsonStringifyReplacerSortKeys = (_, value) => {
62
51
  /**
63
52
  * @param {{ [x: string]: any; }} sorted
@@ -68,10 +57,8 @@ const jsonStringifyReplacerSortKeys = (_, value) => {
68
57
  sorted[key] = value[key];
69
58
  return sorted;
70
59
  };
71
-
72
60
  return value instanceof Object && !(value instanceof Array) ? Object.keys(value).sort().reduce(insert, {}) : value;
73
61
  };
74
-
75
62
  module.exports = {
76
63
  parseFiles,
77
64
  parseFoldersToGlobs,
package/dist/worker.js CHANGED
@@ -1,42 +1,42 @@
1
1
  "use strict";
2
2
 
3
- /** @typedef {import('stylelint')} Stylelint */
4
-
5
- /** @typedef {import("stylelint").LinterOptions} StylelintOptions */
6
-
3
+ /** @typedef {import('./getStylelint').Stylelint} Stylelint */
4
+ /** @typedef {import('./getStylelint').LinterOptions} StylelintOptions */
7
5
  /** @typedef {import('./options').Options} Options */
6
+
8
7
  Object.assign(module.exports, {
9
8
  lintFiles,
10
9
  setup
11
10
  });
12
- /** @type {Stylelint} */
13
11
 
12
+ /** @type {Stylelint} */
14
13
  let stylelint;
15
- /** @type {Partial<StylelintOptions>} */
16
14
 
15
+ /** @type {Partial<StylelintOptions>} */
17
16
  let linterOptions;
17
+
18
18
  /**
19
19
  * @param {Options} options
20
20
  * @param {Partial<StylelintOptions>} stylelintOptions
21
21
  */
22
-
23
22
  function setup(options, stylelintOptions) {
24
23
  stylelint = require(options.stylelintPath || 'stylelint');
25
24
  linterOptions = stylelintOptions;
26
25
  return stylelint;
27
26
  }
27
+
28
28
  /**
29
29
  * @param {string | string[]} files
30
30
  */
31
-
32
-
33
31
  async function lintFiles(files) {
34
32
  const {
35
33
  results
36
- } = await stylelint.lint({ ...linterOptions,
34
+ } = await stylelint.lint({
35
+ ...linterOptions,
37
36
  files
38
- }); // Reset result to work with worker
37
+ });
39
38
 
39
+ // Reset result to work with worker
40
40
  return results.map(result => {
41
41
  return {
42
42
  source: result.source,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stylelint-webpack-plugin",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "A Stylelint plugin for webpack",
5
5
  "license": "MIT",
6
6
  "repository": "webpack-contrib/stylelint-webpack-plugin",
@@ -42,49 +42,49 @@
42
42
  "types"
43
43
  ],
44
44
  "peerDependencies": {
45
- "stylelint": "^13.0.0 || ^14.0.0",
45
+ "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0",
46
46
  "webpack": "^4.0.0 || ^5.0.0"
47
47
  },
48
48
  "dependencies": {
49
49
  "arrify": "^2.0.1",
50
- "globby": "^11.0.4",
51
- "jest-worker": "^28.1.0",
50
+ "globby": "^11.1.0",
51
+ "jest-worker": "^28.1.3",
52
52
  "micromatch": "^4.0.5",
53
53
  "normalize-path": "^3.0.0",
54
54
  "schema-utils": "^3.1.1"
55
55
  },
56
56
  "devDependencies": {
57
- "@babel/cli": "^7.17.10",
58
- "@babel/core": "^7.18.0",
59
- "@babel/preset-env": "^7.18.0",
60
- "@commitlint/cli": "^12.1.4",
61
- "@commitlint/config-conventional": "^12.1.4",
57
+ "@babel/cli": "^7.21.0",
58
+ "@babel/core": "^7.21.0",
59
+ "@babel/preset-env": "^7.20.2",
60
+ "@commitlint/cli": "^16.2.4",
61
+ "@commitlint/config-conventional": "^16.2.4",
62
62
  "@types/fs-extra": "^9.0.13",
63
63
  "@types/micromatch": "^4.0.2",
64
+ "@types/node": "^18.14.6",
64
65
  "@types/normalize-path": "^3.0.0",
65
66
  "@types/webpack": "^5.28.0",
66
67
  "@webpack-contrib/eslint-config-webpack": "^3.0.0",
67
68
  "babel-eslint": "^10.1.0",
68
- "babel-jest": "^28.1.0",
69
- "chokidar": "^3.5.3",
69
+ "babel-jest": "^28.1.3",
70
70
  "cross-env": "^7.0.3",
71
- "del": "^6.1.0",
71
+ "del": "^6.1.1",
72
72
  "del-cli": "^3.0.1",
73
73
  "eslint": "^7.32.0",
74
- "eslint-config-prettier": "^8.5.0",
75
- "eslint-plugin-import": "^2.26.0",
74
+ "eslint-config-prettier": "^8.7.0",
75
+ "eslint-plugin-import": "^2.27.5",
76
76
  "file-loader": "^6.2.0",
77
77
  "fs-extra": "^9.1.0",
78
78
  "husky": "^6.0.0",
79
- "jest": "^28.1.0",
79
+ "jest": "^28.1.3",
80
80
  "lint-staged": "^11.2.6",
81
81
  "npm-run-all": "^4.1.5",
82
82
  "postcss-scss": "^3.0.5",
83
- "prettier": "^2.6.2",
83
+ "prettier": "^2.8.4",
84
84
  "standard-version": "^9.5.0",
85
- "stylelint": "^14.8.2",
86
- "typescript": "^4.6.4",
87
- "webpack": "^5.72.1"
85
+ "stylelint": "^15.2.0",
86
+ "typescript": "^4.9.5",
87
+ "webpack": "^5.76.0"
88
88
  },
89
89
  "keywords": [
90
90
  "stylelint",