javascript - PostCSS:如何根据当前规则中的声明有条件地添加新规则?

标签 javascript css postcss

你好,我一直在尝试使用 PostCSS,并且在编写一个在发现某些 CSS 属性时附加新规则的插件时遇到了一些困难。

我正在努力实现的目标......

启动 CSS:

.selector {
    color: red;
    not-yet-standard-property-a: 10px;
    not-yet-standard-property-b: 20px;
}

在 PostCSS 插件之后:

.selector {
    color: red;
    not-yet-standard-property-a: 10px;
    not-yet-standard-property-b: 20px;
}

.ie .selector {
    standard-property-a: 10px;
    standard-property-b: 20px;
}

每当我看到其中一个 not-yet-standard-property-*...

时,我很容易添加新规则
return function (css) {
    css.walkRules(function (rule) {
        rule.walkDecls('not-yet-standard-property-a', function (decl) {
            css.insertAfter(rule, '.ie ' + rule.selector + '{ standard-property-a: '+ decl.value +' }');
        });
        rule.walkDecls('not-yet-standard-property-b', function (decl) {
            css.insertAfter(rule, '.ie ' + rule.selector + '{ standard-property-b: '+ decl.value +' }');
        });
        rule.walkDecls('not-yet-standard-property-c', function (decl) {
            css.insertAfter(rule, '.ie ' + rule.selector + '{ standard-property-c: '+ decl.value +' }');
        });
    });
}

但是输出并不理想……

.selector {
    color: red;
    not-yet-standard-property-a: 10px;
    not-yet-standard-property-b: 20px;
    not-yet-standard-property-c: 53px;
}
.ie .selector {
    standard-property-c: 53px;
}
.ie .selector {
    standard-property-b: 20px;
}
.ie .selector {
    standard-property-a: 10px;
}

理想情况下,新规则只会在遍历整个规则后添加一次,但 PostCSS 似乎不允许在 walkRules 函数中使用条件,所以我不确定如何阻止它为每个规则创建新规则规则它看到。

我已经链接到上述代码的演示。任何关于更好架构的建议将不胜感激,就像我之前说过的,我对此很陌生。谢谢!

Demo

编辑:已解决。非常感谢 Andrey Sitnik!我已将他的回答标记为正确,因为其中的概念正是我所需要的。对于那些正在寻找完整解决方案的人,请参阅以下代码(和演示!):

function isNotYetStandardProp (propName) {
    if (propName.indexOf('not-yet-standard-property-') > -1) {
      return true;
    }
    else {
      return false;
    }
}

function transformPropName (propName) {
    return propName.replace("not-yet-", "");
}

var skipNext = false;
var convertedProps = [];
var newRule;
var newNode;

return function (css) {

    css.walkRules(function(rule) {
        // The skipNext flag is used to prevent walkRules from walking onto any
        // newly created rules and recursively creating new rules based on the
        // newly added rule.
        if (!skipNext) {
            // Reset to remove values from last loop
            convertedProps = [];
            newRule = null;
            newNode = null;

            // Search through nodes of current rule and build up array
            // containing each property that needs to change.
            rule.nodes.filter(function (node) {
                if ((node.type === 'decl') && isNotYetStandardProp(node.prop)) {
                    newNode = node.clone();
                    newNode.prop = transformPropName(node.prop); 
                    convertedProps.push(newNode);
                }
            });

            // If there were properties to convert in this rule create a new
            // rule to put them in.
            if (convertedProps.length > 0) {
                newRule = rule.cloneAfter({ selector: '.ie ' + rule.selector });
                newRule.removeAll().append(convertedProps);
                skipNext = true;
            }
        }
        else {
            // We only want to skipNext once.
            skipNext = false;
        }
    })

}

Demo of solution

最佳答案

walkRules 中不需要walkDecls,只需使用rule.nodes:

css.walkRules(rule => {
    const nonStandard = rule.nodes.filter(node => {
        return if node.type === 'decl' && checkPropName(node.prop);
    });
    if ( nonStandard.length > 0 ) {
        const clone = rule.cloneAfter({ selector: '.ie ' + rule.selector });
        clone.append(nonStandard);
    }
})

关于javascript - PostCSS:如何根据当前规则中的声明有条件地添加新规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38339509/

相关文章:

javascript - 如何将鼠标悬停在导航项上并打开下拉列表?

javascript - Grunt grunt-postcss Autoprefixer 不工作

javascript - Ajax html 文档 I18n

javascript - AngularJS - 将焦点设置到第一个文本框之后的下一个文本框

html - 制作一个高度为 100% 的正方形

css - 如何获得有关无效 css 值的警告

reactjs - Webpack:postcss-loader 忽略配置文件

javascript - Angular UI 路由器 : child state loaded twice when parent and child take parameter of same name in url

javascript - IE6特定的javascript代码

html - 使用float : left cause a change of length强制html元素并排定位