// NOTICE: This file is generated by Rollup. To modify it, // please instead edit the ESM counterpart and rebuild with Rollup (npm run build). 'use strict'; const validateTypes = require('./validateTypes.cjs'); const constants = require('../constants.cjs'); /** @import { DisabledRangeObject, Problem, Range, RuleMessage, StylelintPostcssResult, Utils, WarningOptions } from 'stylelint' */ /** * Report a problem. * * This function accounts for `disabledRanges` attached to the result. * That is, if the reported problem is within a disabledRange, * it is ignored. Otherwise, it is attached to the result as a * postcss warning. * * It also accounts for the rule's severity. * * You *must* pass *either* a node or a line number. * * @type {Utils['report']} */ function report(problem) { const { node, index, endIndex, line, start, end, result, ruleName, word, fix, ...rest } = problem; const { disabledRanges, quiet, ruleSeverities, config: { defaultSeverity, ignoreDisables } = {}, customMessages: { [ruleName]: message = rest.message }, customUrls: { [ruleName]: customUrl }, ruleMetadata: { [ruleName]: metadata }, } = result.stylelint; const { messageArgs = [], severity = ruleSeverities[ruleName] } = rest; const ruleSeverity = (validateTypes.isFunction(severity) ? severity(...messageArgs) : severity) ?? defaultSeverity ?? constants.DEFAULT_SEVERITY; // In quiet mode, mere warnings are ignored if (quiet && ruleSeverity === constants.SEVERITY_WARNING) return; if (validateTypes.isFunction(fix) && metadata && !metadata.fixable) { throw new Error( `The "${ruleName}" rule requires "meta.fixable" to be truthy if the "fix" callback is being passed`, ); } const range = node?.rangeBy({ index, endIndex }) ?? {}; // If a line is not passed, use the node.rangeBy method to get the // line number that the complaint pertains to const startLine = line ?? range.start?.line; if (!startLine) { throw new Error( `The "${ruleName}" rule failed to pass either a node or a line number to the \`report()\` function.`, ); } if (isFixApplied({ ...problem, line: startLine })) return; if (isDisabled(ruleName, startLine, disabledRanges)) { // Collect disabled warnings // Used to report `needlessDisables` in subsequent processing. const disabledWarnings = (result.stylelint.disabledWarnings ||= []); disabledWarnings.push({ rule: ruleName, line: startLine, }); if (!ignoreDisables) return; } if (!result.stylelint.stylelintError && ruleSeverity === constants.SEVERITY_ERROR) { result.stylelint.stylelintError = true; } if (!result.stylelint.stylelintWarning && ruleSeverity === constants.SEVERITY_WARNING) { result.stylelint.stylelintWarning = true; } /** @type {WarningOptions} */ const warningProperties = { severity: ruleSeverity, rule: ruleName, }; if (node) { warningProperties.node = node; } if (start) { warningProperties.start = start; } else if (validateTypes.isNumber(index)) { warningProperties.index = index; } if (end) { warningProperties.end = end; } else if (validateTypes.isNumber(endIndex)) { warningProperties.endIndex = endIndex; } if (word) { warningProperties.word = word; } if (customUrl) { warningProperties.url = customUrl; } const warningMessage = buildWarningMessage(message, messageArgs); result.warn(warningMessage, warningProperties); } /** * @param {RuleMessage} message * @param {NonNullable} messageArgs * @returns {string} */ function buildWarningMessage(message, messageArgs) { if (validateTypes.isString(message)) { return printfLike(message, ...messageArgs); } return message(...messageArgs); } /** * @param {string} format * @param {Array} args * @returns {string} */ function printfLike(format, ...args) { return args.reduce((/** @type {string} */ result, arg) => { return result.replace(/%[ds]/, String(arg)); }, format); } /** * @param {string} ruleName * @param {number} startLine * @param {DisabledRangeObject} disabledRanges */ function isDisabled(ruleName, startLine, disabledRanges) { const ranges = disabledRanges[ruleName] ?? disabledRanges[constants.RULE_NAME_ALL] ?? []; for (const range of ranges) { if ( // If the problem is within a disabledRange, // and that disabledRange's rules include this one range.start <= startLine && (range.end === undefined || range.end >= startLine) && (!range.rules || range.rules.includes(ruleName)) ) { return true; } } return false; } /** @param {Problem & { line: number }} problem */ function isFixApplied({ fix, line, result: { stylelint }, ruleName }) { const { disabledRanges, config = {}, fixersData } = stylelint; if (!validateTypes.isFunction(fix)) { addFixData({ fixersData, ruleName, fixed: false }); return false; } const shouldFix = Boolean(config.fix && !config.rules?.[ruleName][1]?.disableFix); const mayFix = shouldFix && (config.ignoreDisables || !isDisabled(ruleName, line, disabledRanges)); addFixData({ fixersData, ruleName, fixed: mayFix }); if (!mayFix) return false; fix(); return true; } /** * @param {object} o * @param {StylelintPostcssResult['fixersData']} o.fixersData * @param {string} o.ruleName * @param {Range} [o.range] * @param {boolean} o.fixed * @todo stylelint/stylelint#7192 */ function addFixData({ fixersData, ruleName, range, fixed }) { const ruleFixers = (fixersData[ruleName] ??= []); ruleFixers.push({ range, fixed }); } module.exports = report;