el-beeswarm
Version:
<div style="display: flex; padding: 1rem; flex-direction: column; align-items: center; justify-content: center; height: 100vh; text-align: center; display: flex;
114 lines (91 loc) • 3.57 kB
JavaScript
;
const _ = require('lodash');
const putIfAbsent = require('./utils/putIfAbsent');
/** @typedef {import('postcss/lib/comment')} PostcssComment */
/** @typedef {import('stylelint').DisabledRange} DisabledRange */
/** @typedef {import('stylelint').RangeType} RangeType */
/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */
/**
* @param {import('stylelint').StylelintResult[]} results
*/
module.exports = function (results) {
results.forEach((result) => {
// File with `CssSyntaxError` have not `_postcssResult`
if (!result._postcssResult) {
return;
}
const stylelintResult = result._postcssResult.stylelint;
if (!stylelintResult.config) return; // Linting error
if (!stylelintResult.config.reportNeedlessDisables) return;
/** @type {{[ruleName: string]: Array<DisabledRange>}} */
const rangeData = _.cloneDeep(stylelintResult.disabledRanges);
if (!rangeData) {
return;
}
const disabledWarnings = stylelintResult.disabledWarnings || [];
// A map from `stylelint-disable` comments to the set of rules that
// are usefully disabled by each comment. We track this
// comment-by-comment rather than range-by-range because ranges that
// disable *all* rules are duplicated for each rule they apply to in
// practice.
/** @type {Map<PostcssComment, Set<string>>}} */
const usefulDisables = new Map();
for (const warning of disabledWarnings) {
const rule = warning.rule;
const ruleRanges = rangeData[rule];
if (ruleRanges) {
for (const range of ruleRanges) {
if (isWarningInRange(warning, range)) {
putIfAbsent(usefulDisables, range.comment, () => new Set()).add(rule);
}
}
}
for (const range of rangeData.all) {
if (isWarningInRange(warning, range)) {
putIfAbsent(usefulDisables, range.comment, () => new Set()).add(rule);
}
}
}
const rangeEntries = Object.entries(rangeData);
// Get rid of the duplicated ranges for each `all` rule. We only care
// if the entire `all` rule is useful as a whole or not.
for (const range of rangeData.all) {
for (const [rule, ranges] of rangeEntries) {
if (rule === 'all') continue;
_.remove(ranges, (otherRange) => range.comment === otherRange.comment);
}
}
for (const [rule, ranges] of rangeEntries) {
for (const range of ranges) {
const useful = usefulDisables.get(range.comment) || new Set();
// Only emit a warning if this range's comment isn't useful for this rule.
// For the special rule "all", only emit a warning if it's not useful for
// *any* rules, because it covers all of them.
if (rule === 'all' ? useful.size !== 0 : useful.has(rule)) continue;
// If the comment doesn't have a location, we can't report a useful error.
// In practice we expect all comments to have locations, though.
if (!range.comment.source || !range.comment.source.start) continue;
result.warnings.push({
text: `Needless disable for "${rule}"`,
rule: '--report-needless-disables',
line: range.comment.source.start.line,
column: range.comment.source.start.column,
severity: 'error',
});
}
}
});
};
/**
* @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)
);
}