メモを揉め

お勉強の覚書。

Stylusのあまり知られていない機能

というより、自分が最近知った機能。

ハッシュをCSSのプロパティ名と値に展開できる

Stylusではハッシュが使えます。
シンタックスはJSのオブジェクトリテラルとほぼ同じですが、Stylusのnodeをそのまま値に使用できる点が違います。
以下のように、値に10pxと書いてもvalidです。

foo = {
  width: 10px
}

// JSと同じようにアクセスできる
bar = foo.width
bar = foo['width']

// 代入もできる
foo.height = 20px
foo['height'] = 20px

ハッシュを{foo}のようにブレースで囲むと、ハッシュのキーバリューがそのままStylusとして解釈され、CSSのプロパティと値に展開されます。

ハッシュがネストになっている部分は、Stylusのネスト(インデント)として解釈されるので、以下のように&は親セレクタとして展開されます。

foo = {
  width: 10px,
  height: 20px,
  '&:hover': {
    color: crimson
  }
}

.bar
  {foo}

// こう解釈される
// .bar
//   width 10px
//   height 20px
//   &:hover
//     color crimson

// => .bar {
//      width: 10px;
//      height: 20px;
//    }
//    .bar:hover {
//      color crimson
//    }

注意点としてネストされたハッシュや、関数が返すハッシュをそのまま展開しようとするとエラーになります。
いったん変数に代入するとうまくいきます。

foo = {
  bar: {
    opacity: 1
  }
}

.baz
  {foo.bar} // エラー

.baz
  {foo['bar']} // エラー

qux = foo.bar

.baz
  {qux}

// => .baz {
//      opacity: 1;
//    }

JSONを読み込んで色々できる

jsonというビルトイン関数を使用して、JSONを読み込むことができます。

キーバリューがそのまま変数名と値として展開され、変数が定義されます。
ネストされている場合は、各階層のキーが-で連結された物が変数名になります。

{
  "foo": "10px",
  "bar": {
    "baz": "20px",
    "qux": "'Helvetica Neue'"
  }
}

上のJSONを読み込むと以下のように変数定義が行われます。
注意点として、ダブルクォートはトリムされるので文字列を値にしたい場合は内側でさらにシングルクォートで囲うなどする必要があります。

json('./vars.json')

// foo = 10px
// bar-baz = 20px
// bar-qux = 'Helvetica Neue'

.title
  font-family bar-qux

// => .title {
//      font-family: 'Helvetica Neue';
//    }

json関数には以下のオプションが用意されています。

  • hash
  • leave-strings
  • optional

hash

JSONをそのままハッシュとして読み込みます。

vars = json('./vars.json', { hash: true })

p(vars.foo) // => inspect: 10px
p(vars.bar.qux) // => inspect: 'Helvetica Neue'

leave-strings

ダブルクォートをトリムしないようにする、読み込まれる値が全て文字列になります。
leave-stringsは実際にはhashオプション前提のようで、hashをつけなくてもハッシュとして読み込まれます。

vars = json('./vars.json', { hash: true, leave-strings: true })

p(vars.foo) // => inspect: '10px'
p(vars.bar.qux) // => inspect: ''Helvetica Neue''

optional

jsonファイルが存在しなくてもエラーにならない。
こちらもhashオプション前提で、hashをつけなくてもハッシュとして読み込まれます。

vars = json('./nothing.json', { hash: true, optional: true })

p(vars) // => inspect: null

JavaScriptの関数を呼べる

こうしてStylusの中でハッシュも配列も関数もあって、文字列操作もそれなりに用意されていると、だんだん複雑な関数を作り始めたりします。
とはいえ、JSで書けたら楽なのになーという場面も結構あります。

そんな時にもStylusにはJavaScriptを呼び出すためのAPIが用意されています。

JavaScript側では以下のようにプラグインを作っておき、Stylus側ではuse関数を使って読み込みます。

// add.js
module.exports = () => stylus => {
  stylus.define('add', (a, b) => a.operate('+', b));
};

use('path/to/add.js')

res = add(10px, 20px)

// => 30px

CLIの場合でも-uオプションで同じように使用できます。

$ stylus -u ./path/to/add.js src/index.styl -o dist

Stylusのノードを作って返すようなこともできるみたいです。
この辺ドキュメントがあまり詳しく書かれてないのでよく分かってないです、またいずれ調べてみます。

nibはおそらくこんな感じでJavaScriptAPIからnode-canvasを呼び出してgradientをpng画像に変換したりしてるんだと思います。

他にも公式ページを見ていると色々知らない機能が出てくるので面白いです。

stylus-lang.com