以下是我想要实现的行为的简短可重现示例:
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; }
}
}
我希望这会返回一个空字符串。
相反,我收到输出
@removeme {
.selector { color: red; }
}
@keepme
规则似乎正确地将其自身替换为其节点(然后不执行?)。
我不知道该如何解决这个问题。有什么建议吗?
答案 0 :(得分:0)
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;
}
给出要遍历的规则列表:
rule-walker保留当前检查规则的索引。在索引1处,它找到keepme
。
keepme.replaceWith(removeme)
会在 removeme
之前插入keepme
,然后继续走向...
由于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