
先日 foovar という Stylus のライブラリを公開しました。
Stylus の変数を JS ファイルにエクスポートするためのライブラリです。
その時に調べた Stylus JavaScript API の詳細や、プラグイン作成の方法です。
仕様の変更などにより記事の内容が古くなったらすぐ分かるように、記事のテストを書いてみました。
Stylus プラグインの仕組み
プラグインの実体は関数を返す関数(高階関数)です。
これを module.exports するだけでプラグインの体を成します(役に立たないということを除けば)。
npm で公開すればすぐにプラグインとして利用可能です。
module.exports = function() {
return function() {};
};
外側の関数は use (後述)した際に呼ばれ、オプションを引数に受取ります。
内側の関数は Renderer のインスタンスを引数に受け取ります(コード中stylus)。
module.exports = function(...options) {
return function(stylus) {};
};
内側の関数内の this はこの Renderer インスタンスに束縛されて呼び出されます。
require('stylus')() で得られるインスタンスも同じく Renderer のインスタンスです。
module.exports = function(...options) {
return function(stylus) {
this.condtructor.name // 'Renderer'
this === stylus; // true
this.constructor === require('stylus')().constructor; // true
};
};
基本的にはこの Renderer インスタンスを介して Stylus の世界とやり取りをすることになります。
Stylus から呼び出せる関数を JS で定義したり、あらかじめ用意した .styl ファイルへのパスを通したりといった感じです。
この Renderer インスタンスの API については公式のドキュメントに詳しい情報があります。
プラグインの読み込みとオプションの渡し方
プラグインを読み込む方法は3つあります。
- ビルトイン関数
use(path)を使う - JavaScript API の
.use(fn)を使う - CLI の
--use nameオプションを使う
いずれも use という言葉が使われており、このキーワードがプラグイン読み込みを指すと思われる。
ビルトイン関数 use(path)
JS ファイルのパスを指定して呼び出す。
プラグイン名での呼び出しは出来ない。
第2引数にはハッシュをオプションとして渡せる。
渡せるのはハッシュのみで、それ以外はエラーになる。
また第3引数以降は無視される。
use('./my-plugin.js')
use('../../node_modules/plugin/index.js') // 名前での呼び出しは出来ない。 node_modules 配下のエントリポイントを直接指定することは出来る
use('../../node_modules/plugin/index.js', { foo: 20px }) // オプションに渡せるのはハッシュのみ
JavaScript API の .use(fn)
前述の高階関数の内側の関数のみを渡す。
require で読み込んだモジュールを実行して内側の関数を取り出し use に渡すという使い方になる。
const stylus = require('stylus');
stylus(source)
.use(require('plugin-name')())
.render(/*...*/);
外側の関数にはオプションを渡すことが出来る。
require で読み込んで関数を直接呼び出すだけなので、好きな数の引数を好きな型で渡すことができる。
use(path) 、 CLI の --use オプションとAPIを揃えるために、オプションはオブジェクト1個に限定したほうがいいかもしれない。
stylus(source)
.use(require('plugin-name')({foo, 'bar'}))
.render(/*...*/);
CLI の --use name オプション
--use に続けてプラグイン名を渡すと読み込んでくれる。
短縮形は -u 。
$ stylus --use plugin-name path/to/source.styl # あるいは $ stylus -u plugin-name path/to/source.styl
--with に続けて文字列を渡すと、 JS としてパースされ外側の関数にオプションとして渡される。
なぜかドキュメントに載ってないし、 --help にも出てこない。
この場合複数の引数は指定できないので、複数のオプションを扱いたい場合はオブジェクトや配列で渡す必要がある。
$ stylus -u plugin-name --with '{ foo: true }' path/to/source.styl
Stylus のトークンを表現するクラス
ここで記載する API はごく一部です。
より詳しいクラスの詳細はここらへんを見ると良さそう。
これらのコンストラクタを new して Stylus のトークンを自前で生成することもできます。
トークンクラスへのアクセス
evaluator.renderer.nodes.* で Stylus のトークンクラスにアクセスできる。
evaluator は JavaScript API の define(name, fn) で定義した関数内から this で参照することができる。
const fn = function() {
return new this.renderer.nodes.String('hello world');
};
module.exports = function() {
return function(renderer) {
renderer
.define('hello-world', fn);
};
};
以下、各クラスのコンストラクタの使い方、プロパティの型、コンソールに出力した結果です。
Expression
式を表すクラス。
nodes 内の要素が複数であれば tuple もしくは list となる。(要素が一つの場合を長さが1の tuple と言うこともできる)
tuple 、list の違いは isList で判定できる。
constructor
Expression(isList)isList: boolean
instanceMethod
push(node):nodeをthis.nodesに追加するnode: node
instanceProperty
nodes: arrayisList: boolean
{
lineno: 1,
column: 14,
filename: 'index.css',
nodes: [
{
lineno: 1,
column: 14,
filename: 'index.css',
val: 'some string',
string: 'some string',
prefixed: false,
quote: '\''
}
],
isList: undefined
}
Object
Stylus のハッシュを表すクラス。
vals には JS のオブジェクトが入っており、各キーにはさらに Stylus のトークンが入る。
constructor
Object()
instanceMethod
set(key, value):valueの値をkeyにセットするkey: stringvalue: node
instanceProperty
vals: object
{
lineno: 1,
column: 10,
filename: 'index.css',
vals: {
foo: {
lineno: 1,
column: 19,
filename: 'index.css',
nodes: [Object],
isList: undefined
}
}
}
String
Stylus の文字列を表すクラス。
constructor
String(val, quote)val: string
instanceProperty
string: stringval: string
{
lineno: 1,
column: 14,
filename: 'index.css',
val: 'some string',
string: 'some string',
prefixed: false,
quote: '\''
}
Unit
単位付き(あるいは無し)の数値を表すクラス。
10px、1.7em、200ms、0 などは全て Unit のインスタンスとなる。
constructor
Unit(val, type)val: numbertype: string
instanceProperty
val: numbertype: stringraw: string
{
lineno: 1,
column: 10,
filename: 'index.css',
val: 20,
type: 'px',
raw: '20px'
}
RGBA
RGBA形式の色を表現するクラス。
#112233 , #11223344 , rgb(11,22,33) , rgba(11,22,33,44) などは全て RGBA のインスタンスとなる。
16進数表記の時のみ raw プロパティが存在し、16進数表記の文字列が取得できる。
constructor
RGBA(r, g, b, a)r: numberg: numberb: numbera: number
instanceProperty
r: numberg: numberb: numbera: numberraw: string
{
lineno: 2,
column: 16,
filename: 'index.css',
r: 17,
g: 34,
b: 51,
a: 0.26666666666666666,
name: '',
rgba: [Circular],
raw: '#11223344'
}
HSLA
HSLA形式の色を表現するクラス。
hsl(11,22,33) , hsla(11,22,33,44) などは全て HSLA のインスタンスとなる。
constructor
HSLA(h, s, l, a)h: numbers: numberl: numbera: number
instanceProperty
h: numbers: numberl: numbera: number
{
lineno: 3,
column: 12,
filename: 'index.css',
h: 11,
s: 22,
l: 33,
a: 0.4,
hsla: [Circular]
}
Ident
auto 、inherit 、none 等のトークンを表現するクラス。
constructor
Ident(name, val, mixin)name: string
instanceProperty
name: stringstring: string
{
lineno: 1,
column: 13,
filename: 'index.css',
name: 'auto',
string: 'auto',
val: null,
mixin: false
}
Call
cubic-bezier() 等の関数呼び出しを表現するクラス。
constructor
Call(name, args)name: stringargs: expression
instanceProperty
name: stringargs: expression
{
lineno: 1,
column: 40,
filename: 'index.css',
name: 'cubic-bezier',
args: {
lineno: 1,
column: 20,
filename: 'index.css',
nodes: [ [Object], [Object], [Object], [Object] ],
isList: undefined,
map: {}
}
}
テスト
記事の公開時点では Stylus v0.54.5 を対象にテストしています。
all-user/inspect-stylus