UNPKG

2.82 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4
5/** @typedef {import('stylelint').RangeType} RangeType */
6/** @typedef {import('stylelint').UnusedRange} UnusedRange */
7/** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */
8
9/**
10 * @param {import('stylelint').StylelintResult[]} results
11 * @returns {StylelintDisableOptionsReport}
12 */
13module.exports = function(results) {
14 /** @type {StylelintDisableOptionsReport} */
15 const report = [];
16
17 results.forEach((result) => {
18 // File with `CssSyntaxError` have not `_postcssResult`
19 if (!result._postcssResult) {
20 return;
21 }
22
23 /** @type {{ranges: UnusedRange[], source: string}} */
24 const unused = { source: result.source || '', ranges: [] };
25
26 /** @type {{[ruleName: string]: Array<RangeType>}} */
27 const rangeData = _.cloneDeep(result._postcssResult.stylelint.disabledRanges);
28
29 if (!rangeData) {
30 return;
31 }
32
33 result.warnings.forEach((warning) => {
34 const rule = warning.rule;
35
36 const ruleRanges = rangeData[rule];
37
38 if (ruleRanges) {
39 // Back to front so we get the *last* range that applies to the warning
40 for (const range of ruleRanges.reverse()) {
41 if (isWarningInRange(warning, range)) {
42 range.used = true;
43
44 return;
45 }
46 }
47 }
48
49 for (const range of rangeData.all.reverse()) {
50 if (isWarningInRange(warning, range)) {
51 range.used = true;
52
53 return;
54 }
55 }
56 });
57
58 Object.keys(rangeData).forEach((rule) => {
59 rangeData[rule].forEach((range) => {
60 // Is an equivalent range already marked as unused?
61 const alreadyMarkedUnused = unused.ranges.find((unusedRange) => {
62 return unusedRange.start === range.start && unusedRange.end === range.end;
63 });
64
65 // If this range is unused and no equivalent is marked,
66 // mark this range as unused
67 if (!range.used && !alreadyMarkedUnused) {
68 unused.ranges.push({
69 start: range.start,
70 end: range.end,
71 unusedRule: rule,
72 });
73 }
74
75 // If this range is used but an equivalent has been marked as unused,
76 // remove that equivalent. This can happen because of the duplication
77 // of ranges in rule-specific range sets and the "all" range set
78 if (range.used && alreadyMarkedUnused) {
79 _.remove(unused.ranges, alreadyMarkedUnused);
80 }
81 });
82 });
83
84 unused.ranges = _.sortBy(unused.ranges, ['start', 'end']);
85
86 report.push(unused);
87 });
88
89 return report;
90};
91
92/**
93 * @param {import('stylelint').StylelintWarning} warning
94 * @param {RangeType} range
95 * @return {boolean}
96 */
97function isWarningInRange(warning, range) {
98 const line = warning.line;
99
100 // Need to check if range.end exist, because line number type cannot be compared to undefined
101 return (
102 range.start <= line &&
103 ((range.end !== undefined && range.end >= line) || range.end === undefined)
104 );
105}