CSSプリプロセッサのfunctionを拡張してみた (CSS Preprocessor Advent Calendar 8th day)

CSSプリプロセッサのfunction

CSS Preprocessor Advent Calendar 2012の8日目でございます。飛び道具的な好奇心に基づき、functionの拡張について調べてみた次第。

今回は、下記の2つの関数をサンプルとして扱います。どちらも実用的なものではありませんが、あくまでサンプルということで、、、。

  • reverse - 与えられた文字列を逆順に並べ直して返す
  • randomColor - ランダムなカラーの16進数を返す

Sass編

Module: Sass::Script::FunctionsにあるAdding Custom Functionsを参考にします。じつは、LESSとStylusは使ってたんですが、Sassって使ったことないんですよね...。

sass_add_func.rb

Sass::Script::Functionsにメソッドをつくって、declareすればOK。単純に引数として受け取り、加工して返せば出力されます。

# @see http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#adding_custom_functions
require 'sass'
module Sass::Script::Functions
  def reverse(string)
    assert_type string, :String
    Sass::Script::String.new("'#{string.value.reverse}'")
  end

  def randomColor()
    Sass::Script::String.new('#'+'%06x' % (rand * 0xffffff))
  end
  declare :reverse, :args => [:string]
  declare :randomColor, :args => []
end

ほとんど参考URLのまま写しています。

span::before {
  content: reverse(ABCDEFGHIJKL);
  background-color: randomColor();
}

.scssなファイルはこちら。続くstylusとの代わり映えのため、SCSSとしました。

Use

作成したRubyファイルをrオプションで読み込ませて利用します。compassとあわせるときはconfig.rbに仕込んだりすれば良いようです。

% sass sample.scss  -r ./sass_add_func.rb
span::before {
  content: 'LKJIHGFEDCBA';
  background-color: #33f620; }

順当に出力されます。良いかんじです。

Stylus編

お次はStylusです。Stylus - JavaScript APIを参考にします。ここに書いてある内容は、わりと必要最小限なので、リポジトリlib/nodes/*lib/utils.jsも読んだ方がよさそうです。

stylus_add_func.js

.use(fn)に渡すfunctionをexportsするJavaScriptファイルを用意します。渡ってきたstylus本体に、defineで関数を定義していけばOK。

// @see https://github.com/LearnBoost/stylus/blob/master/docs/js.md
module.exports = function() {
  return function(styl) {
    var nodes = require('stylus/lib/nodes');

    styl.define('reverse', function(arg){
        return arg.string.split('').reverse().join('');
    });

    styl.define('randomColor', function() {
      return new nodes.Literal('#'+Math.floor(Math.random()*16777215).toString(16));
    });
  }
};

randomColorについては、ただのStringで返すと'#12b3b2'のようにシングルクオートがついてくるので、nodes.Literalとして返します。nodesの中は色々あります。

span::before
  content reverse(ABCDEFGHIJKL)
  background-color randomColor()

.stylなファイルはこんな感じ。記号レスとして存分に削ってみました。

Use

uオプションで拡張functionを記述したJavaScriptファイルを読み込ませて、コンパイルを実行します。

% stylus -u ./stylus_add_func.js sample.styl
  compiled sample.css
% cat sample.css
span::before {
  content: 'LKJIHGFEDCBA';
  background-color: #12b3b2;
}

StylusはそのままCSSを生成するので、別途catして確認します。OKOK。

LESS編

えー、node実装ならStylusでいいじゃん、とか乱暴な持論を振り回した上で

・・・時間切れ!時間切れでござるよ!!

lessc -hしてみて、それっぽいのが無かったので時間の都合上、手早くあきらめました。すみません(´・ω・`)

まとめ

そんなわけで、変に限られたコンテキストから頑張って凝ったmixinを定義するより、ちゃっちゃとfunctionとして自由なコンテキストで処理するほうがラクだったりするケースもあるんじゃないでしょーか。

ぜひお試しくださいまし。ではでは。