UNPKG

stylelint

Version:

A mighty CSS linter that helps you avoid errors and enforce conventions.

91 lines (73 loc) 2.08 kB
import { resolveNestedSelector } from '@csstools/selector-resolve-nested'; import { isAtRule, isRule } from './typeGuards.mjs'; import getRuleSelector from './getRuleSelector.mjs'; import isStandardSyntaxRule from './isStandardSyntaxRule.mjs'; import parseSelector from './parseSelector.mjs'; import selectorParser from 'postcss-selector-parser'; /** @import { Selector, Root as SelectorRoot } from 'postcss-selector-parser' */ /** @import { Rule, Node } from 'postcss' */ /** @import { PostcssResult } from 'stylelint' */ /** * Resolve nested selectors following the CSS nesting specification * * @typedef {{selector: Selector, resolvedSelectors: SelectorRoot, nested: boolean}} ResolvedSelector * * @param {Rule} rule * @param {PostcssResult} result * @returns {Array<ResolvedSelector>} */ export default function resolveNestedSelectorsForRule(rule, result) { const ownAST = parseSelector(getRuleSelector(rule), result, rule); if (!ownAST) return []; /** @type {SelectorRoot | undefined} */ let ast = undefined; /** @type {Array<Node>} */ const ancestors = []; { /** @type {Node['parent']} */ let parent = rule.parent; while (parent) { ancestors.push(parent); parent = parent.parent; } } ancestors.reverse(); for (const child of ancestors) { if (isAtRule(child) && child.name === 'scope') { ast = parseSelector(':where(:scope)', result, child); continue; } if (!isRule(child)) continue; if (!isStandardSyntaxRule(child)) return []; const childAST = parseSelector(getRuleSelector(child), result, child); if (!childAST) return []; if (ast) { ast = resolveNestedSelector(childAST, ast); } else { ast = childAST; } } return ownAST.map((selector) => { if (!ast) { return { selector, resolvedSelectors: selectorParser.root({ value: '', nodes: [selector], }), nested: false, }; } return { selector, resolvedSelectors: resolveNestedSelector( selectorParser.root({ nodes: [selector], value: '', }), ast, ), nested: true, }; }); }