'use strict'; const _ = require('lodash'); /** @typedef {import('stylelint').RangeType} RangeType */ /** @typedef {import('stylelint').DisableReportRange} DisableReportRange */ /** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */ /** * @param {import('stylelint').StylelintResult[]} results * @returns {StylelintDisableOptionsReport} */ module.exports = function (results) { /** @type {StylelintDisableOptionsReport} */ const report = []; results.forEach((result) => { // File with `CssSyntaxError` have not `_postcssResult` if (!result._postcssResult) { return; } /** @type {{ranges: DisableReportRange[], source: string}} */ const unused = { source: result.source || '', ranges: [] }; /** @type {{[ruleName: string]: Array}} */ const rangeData = _.cloneDeep(result._postcssResult.stylelint.disabledRanges); if (!rangeData) { return; } const disabledWarnings = result._postcssResult.stylelint.disabledWarnings || []; disabledWarnings.forEach((warning) => { const rule = warning.rule; const ruleRanges = rangeData[rule]; if (ruleRanges) { // Back to front so we get the *last* range that applies to the warning for (const range of ruleRanges.reverse()) { if (isWarningInRange(warning, range)) { range.used = true; return; } } } for (const range of rangeData.all.reverse()) { if (isWarningInRange(warning, range)) { range.used = true; return; } } }); Object.keys(rangeData).forEach((rule) => { rangeData[rule].forEach((range) => { // Is an equivalent range already marked as unused? const alreadyMarkedUnused = unused.ranges.find((unusedRange) => { return unusedRange.start === range.start && unusedRange.end === range.end; }); // If this range is unused and no equivalent is marked, // mark this range as unused if (!range.used && !alreadyMarkedUnused) { unused.ranges.push({ rule, start: range.start, end: range.end, unusedRule: rule, }); } // If this range is used but an equivalent has been marked as unused, // remove that equivalent. This can happen because of the duplication // of ranges in rule-specific range sets and the "all" range set if (range.used && alreadyMarkedUnused) { _.remove(unused.ranges, alreadyMarkedUnused); } }); }); unused.ranges = _.sortBy(unused.ranges, ['start', 'end']); report.push(unused); }); return report; }; /** * @param {import('stylelint').DisabledWarning} warning * @param {RangeType} range * @return {boolean} */ function isWarningInRange(warning, range) { const line = warning.line; // Need to check if range.end exist, because line number type cannot be compared to undefined return ( range.start <= line && ((range.end !== undefined && range.end >= line) || range.end === undefined) ); }