2017-05-18 111 views
0

Interactive Fiddle

这里是行为的短重复的例子,我想实现:嵌套postcss在规则不被删除

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

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; 
} 

鉴于在规则列表遍历:

  1. @keepme
  2. @removeme

规则行者保留当前检查规则的索引。在索引1找到keepmekeepme.replaceWith(removeme)将插入removemekeepme,然后继续走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