UNPKG

2.94 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4
5/** @typedef {import('stylelint').RangeType} RangeType */
6/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */
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: DisableReportRange[], 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 const disabledWarnings = result._postcssResult.stylelint.disabledWarnings || [];
34
35 disabledWarnings.forEach((warning) => {
36 const rule = warning.rule;
37
38 const ruleRanges = rangeData[rule];
39
40 if (ruleRanges) {
41 // Back to front so we get the *last* range that applies to the warning
42 for (const range of ruleRanges.reverse()) {
43 if (isWarningInRange(warning, range)) {
44 range.used = true;
45
46 return;
47 }
48 }
49 }
50
51 for (const range of rangeData.all.reverse()) {
52 if (isWarningInRange(warning, range)) {
53 range.used = true;
54
55 return;
56 }
57 }
58 });
59
60 Object.keys(rangeData).forEach((rule) => {
61 rangeData[rule].forEach((range) => {
62 // Is an equivalent range already marked as unused?
63 const alreadyMarkedUnused = unused.ranges.find((unusedRange) => {
64 return unusedRange.start === range.start && unusedRange.end === range.end;
65 });
66
67 // If this range is unused and no equivalent is marked,
68 // mark this range as unused
69 if (!range.used && !alreadyMarkedUnused) {
70 unused.ranges.push({
71 rule,
72 start: range.start,
73 end: range.end,
74 unusedRule: rule,
75 });
76 }
77
78 // If this range is used but an equivalent has been marked as unused,
79 // remove that equivalent. This can happen because of the duplication
80 // of ranges in rule-specific range sets and the "all" range set
81 if (range.used && alreadyMarkedUnused) {
82 _.remove(unused.ranges, alreadyMarkedUnused);
83 }
84 });
85 });
86
87 unused.ranges = _.sortBy(unused.ranges, ['start', 'end']);
88
89 report.push(unused);
90 });
91
92 return report;
93};
94
95/**
96 * @param {import('stylelint').DisabledWarning} warning
97 * @param {RangeType} range
98 * @return {boolean}
99 */
100function isWarningInRange(warning, range) {
101 const line = warning.line;
102
103 // Need to check if range.end exist, because line number type cannot be compared to undefined
104 return (
105 range.start <= line &&
106 ((range.end !== undefined && range.end >= line) || range.end === undefined)
107 );
108}