Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import stylelint from "stylelint";
import { namespace } from "../helpers.mjs";
const {
utils: { report, ruleMessages, validateOptions },
} = stylelint;
const ruleName = namespace("no-has-selector");
const messages = ruleMessages(ruleName, {
rejected:
'Unexpected ":has()" selector. It scales with the size of the DOM subtree ' +
"and needs more complex invalidation and matching than regular selectors. " +
"Prefer setting an attribute or class from JS, or disable this rule with a " +
"comment explaining why :has() is needed.",
});
const meta = {
fixable: false,
};
const HAS_PSEUDO_CLASS = /:has\(/i;
const ruleFunction = primaryOption => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: primaryOption,
possible: [true],
});
if (!validOptions) {
return;
}
root.walkRules(rule => {
// Report at the start of the rule rather than at each :has(), so that a
// single stylelint-disable-next-line comment before the rule covers it.
// A comment in the middle of a multi-line selector list wouldn't be a
// standalone comment node, and thus wouldn't disable anything.
if (HAS_PSEUDO_CLASS.test(rule.raws.selector?.raw ?? rule.selector)) {
report({
message: messages.rejected,
node: rule,
result,
ruleName,
});
}
});
};
};
ruleFunction.ruleName = ruleName;
ruleFunction.messages = messages;
ruleFunction.meta = meta;
export default ruleFunction;