Help us understand the problem. What is going on with this article?

PostCSSのASTを操作する

More than 3 years have passed since last update.

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

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

http://api.postcss.org/

ノードの種類

まずは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のプラグインの書き方を説明します。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away