こんにちは、私は 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;
}
})
}