嵌套的 postcss at 规则未被删除

Nested postcss at-rules are not removed

Interactive Fiddle

这是我想要实现的行为的一个简短的可重现示例:

var postcss = require('postcss');
var plugin = postcss.plugin('keepme', () => (root) => {
  root.walkAtRules(/keepme|removeme/, (atRule) => {
    if (atRule.name === 'keepme') {
      atRule.replaceWith(atRule.nodes);
    } else {
      atRule.remove();
    }
  });
});
postcss([plugin]).process(`
  @keepme {
    @removeme {
      .selector { color: red; }
    }
  }
`).then(result => console.log(result.css));

给定输入

  @keepme {
    @removeme {
      .selector { color: red; }
    }
  }

我想 return 一个空字符串。

相反,我收到了输出

@removeme {
  .selector { color: red; }
}

@keepme 规则似乎正确地用它的节点替换了自己(然后没有执行?)。

我不知道该怎么做。有什么建议吗?

replaceWith是这样实现的:

/**
 * Inserts node(s) before the current node and removes the current node.
 *
 * @param {...Node} nodes - node(s) to replace current one
 *
 * @example
 * if ( atrule.name == 'mixin' ) {
 *   atrule.replaceWith(mixinRules[atrule.params]);
 * }
 *
 * @return {Node} current node to methods chain
 */
replaceWith(...nodes) {
    if (this.parent) {
        for (let node of nodes) {
            this.parent.insertBefore(this, node);
        }
        this.remove();
    }
    return this;
}

给定要遍历的 at 规则列表:

  1. @keepme
  2. @removeme

rule-walker 保留当前检查的规则的索引。在索引 1 处,它找到 keepmekeepme.replaceWith(removeme)会在keepme之前插入removeme,然后继续走ast...

由于 removeme 向前移动,助行器已经移动过去,不会执行该规则。

解决方法是修改 replaceWith,以便在 检查规则后移动子节点

  root.walkAtRules(/keepme|removeme/, (atRule) => {
    if (atRule.name === 'keepme') {
      if (atRule.parent) {
        for (let node of atRule.nodes.reverse()) {
          atRule.parent.insertAfter(atRule, node);
        }
      }
    }
    atRule.remove();
  });

这按预期工作:Interactive fiddle