function increaseSpecifityOfRule()

in packages/build-tools/postcss-wrapper/src/postcssWrap.ts [25:72]


function increaseSpecifityOfRule(rule: postcss.Rule, opts: IOptions, cachedIconName: Record<string, boolean>) {
  rule.selectors = rule.selectors.map((selector: string) => {
    // Apply it to the selector itself if the selector is a `root` level component
    // `html:not(#\\9):not(#\\9):not(#\\9)`
    if (['from', 'to'].indexOf(selector) !== -1) {
      return selector;
    }

    const [firstNode, ...restNodes] = selector.split(/\s+/);

    // 替换部分 css selector 避免污染宿主
    if (firstNode && ['html', ':root', ':host', opts.stackableRoot].includes(firstNode)) {
      return [opts.stackableRoot.repeat(opts.repeat), ...restNodes].join(' ');
    }

    // Otherwise just make it a descendant (this is what will happen most of the time)
    // `:not(#\\9):not(#\\9):not(#\\9) .foo`
    return `${opts.stackableRoot.repeat(opts.repeat) } ${ selector}`;
  });

  if (Object.keys(cachedIconName).length) {
    rule.walkDecls('font-family', (decl) => {
      const fontName = normalizeFontName(decl.value);
      if (cachedIconName[fontName]) {
        decl.value = `${normalizeId(opts.stackableRoot)}${fontName}`;
      }
    });

    rule.walkDecls('font', (decl) => {
      decl.value = decl.value.replace(new RegExp(`^([\\w\\d\\s\\/]*\\s|\\s*)(${Object.keys(cachedIconName).join('|')})$`), (match, $1, $2) => {
        return `${$1}${normalizeId(opts.stackableRoot)}${$2}`;
      });
    });
  }

  if (opts.overrideIds) {
    if (
      // If an id is in there somewhere
      (new RegExp(`#(?!${ escapeStringRegexp(CSS_ESCAPED_TAB) })`)).test(rule.selector) ||
      // Or it is an attribute selector with an id
      (/\[id/).test(rule.selector)
    ) {
      rule.walkDecls((decl) => {
        decl.important = true;
      });
    }
  }
}