0

こんにちは、私は PostCSS を試していて、特定の CSS プロパティを見つけたときに新しいルールを追加するプラグインの作成に少し苦労しています。

私が達成しようとしていること…</p>

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-*…</p>

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 +' }');
        });
    });
}

しかし、出力は理想的ではありません…</p>

.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 関数内で条件を許可していないようです。 .

上記のコードのデモにリンクしました。前に言ったように、より良いアーキテクチャの提案は大歓迎です。私はこれにかなり慣れていません。ありがとう!

デモ

編集:解決しました。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;
        }
    })

}

ソリューションのデモ

4

1 に答える 1

1

walkDeclsinsideは必要ありません。次の操作を行うwalkRulesだけ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);
    }
})
于 2016-07-12T23:02:17.650 に答える