search
LoginSignup
8
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

一人PostCSS Advent Calendar 2016 Day 3

posted at

PostCSSのASTを操作する

PostCSSには2日目で説明した、ASTを簡単に操作するためのAPIが用意されています。ASTはJavaScriptのオブジェクトなので、JavaScriptの構文で直接変換させることもできますが、より便利に、そして効率の良い処理をするためにも提供されているAPIを使います。

また、PostCSSの全てのAPIはAPIドキュメントで確認することができます。

ノードの種類

まずはASTのノードの種類です。PostCSSのASTのノードは以下の5つです。

  • Rootノード: ASTの1番上のノード(Rootノードは親ノードがない)
  • Ruleノード: 1つのルールセット
  • AtRuleノード: 1つの@ルール
  • Declarationノード: 1プロパティ宣言
  • Comment: 1つのコメント

これらは実装的には PostCSSの Node クラスを継承したもので、Node.type を参照することで、それが何のノードかを知ることができます。

ノードの探索

次にノードを探索するAPIを見てみましょう。以下の input.css を入力としたときの例を挙げます。

.foo {
  font-size: 1.2rem;
}

.bar {
  color: pink;
}

@media (max-width: 415px) {
  .foo {
    font-size: 1rem;
  }
}

Ruleノードの探索

Ruleノードは container.walkRules([selector], callback) というAPIを使って探索することができます。 container というのは「子ノードを持つことができる(親ノードになることができる)ノード」である Container クラスのインスタンスです。Root ノード、Rule ノード、AtRuleノードがそれに当たります。

var css = fs.readFileSync('./input.css');
var root = postcss.parse(css); // `input.css`をパースしてASTを返す

root.walkRule(function (rule) {
  // 全てのルールセットを探索
});

walkRules() は第一引数にセレクタ名を文字列(または正規表現)で指定することもできます。

root.walkRules('.foo', function (rule) {
  // 全て`.foo`セレクタのルールセットを探索
});

AtRuleノードの探索

AtRuleノードは container.walkAtRules([name], callback) というAPIを使って探索することができます。第一引数に@ルール名を指定することもできます。

root.walkAtRules('media', function (atrule) {
  // `@media` の@ルールを探索
});

Declarationノードの探索

AtRuleノードは container.walkAtRules([prop], callback) というAPIを使って探索することができます。第一引数にプロパティ名を指定することもできます。

root.walkDecls('font-size', function (decl) {
  // `font-size`プロパティのプロパティ宣言を探索
});

Commentノードの探索

AtRuleノードは container.walkAtRules([prop], callback) というAPIを使って探索することができます。

root.walkComments(function (comment) {
  // 全てのコメントを探索
});

ノードの挿入・移動・削除

container.insertBefore(exist, add), container.insertAfter(exist, add) はそれぞれ、ノードの指定した子ノードの直前と直後に新しくノード(add)を追加するためのAPIです。

rule.insertBefore(decl, { prop: 'color', value: 'pink' }));

node.moveTo(newParent) は、そのノードを削除し、指定したノードの子要素に追加するものです。

atrule.moveTo(atrule.root());

node.remove() はノードを削除するためのAPIです。

if ( decl.prop.match(/^-webkit-/) ) {
  decl.remove();
}

今日はPostCSSのASTを操作するためのAPIをいくつか紹介しました。これらのAPIを使って、ASTを変換するプラグラムがPostCSSのプラグインです。簡単なプラグインの実装を読んでみると、さらに理解が深まると思います。

明日は、これらのAPIを使って実際にPostCSSのプラグインの書き方を説明します。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8
Help us understand the problem. What are the problem?