LoginSignup
6
5

More than 5 years have passed since last update.

stylusのmixinをプラグインとして公開する

Last updated at Posted at 2016-06-12

動機

だいたいの問題は上記が解決してくれるとして、それ以外のよく使う方言をstylusプラグインとして公開したい場合があると思うので、自分が実践した手順を紹介します。

環境

node-v6.2.1 および 下記package.jsonを使用します。

bash
mkdir foo
cd foo
vim package.json
npm install
package.json
{
  "scripts": {
    "build": "stylus index.styl --out index.css",
    "test": "ava",
    "lint": "xo"
  },
  "devDependencies": {
    "ava": "^0.15.2",
    "stylus": "^0.54.5",
    "xo": "^0.15.1"
  },
  "xo": {
    "space": 2
  }
}

stylusに認識させる

stylusは@importを使用したさいに、登録してあるpathsから順にファイルを精査します。

CLIから--includeオプションを使用せずコンパイルした場合、現在のディレクトリを基準にするため、以下は正常に動作します。

bash
tree -L 1
# .
# ├── index.styl
# └── my-plugin.styl

npm run build
# h1 {
#   font-size: 10vw;
# }
./index.styl
@import 'my-plugin'
./my-plugin.styl
h1
  font-size 10vw

JavaScriptから実行した場合も同様です。

build.js
const fs = require('fs');
const stylus = require('stylus');

const entry = fs.readFileSync('index.styl', 'utf8');
stylus(entry)
.render((err, css) => {
  console.log(css);
  // h1 {
  //   font-size: 10vw;
  // }
});

node_modulesとして動作させる

既存のプラグインはnpm installnode_modulesにインストールできますが、使用する前に--use my-pluginなり、.use(myPlugin())などで登録を行います。

いずれにしても、プラグインをrequireし、requireしたディレクトリ直下のindex.jsか、同じくディレクトリ直下のpackage.json>mainに定義されている位置のファイルを読み込み、module.exportsで定義されている関数が実行されるはずです。

./index.js(最低限必要なプラグインの初期化処理)
module.exports = function () {
  return function (stylus) {
    stylus.include(__dirname);
  };
};

nibの実装では、実行した関数が関数を返し、その中で初期化処理を行っています。
注目すべきは最初のstyle.include(__dirname)という箇所で、これはstylusのpathsにそのディレクトリ(node_modules/nib/lib)を登録しています。ですので、この状態で前章のindex.styl@import 'nib'と書くと、node_modules/nib/libnib/index.stylまたはnib.stylが読み込まれます。

仮に、先に登録したpathsに同名のフォルダやファイルが存在していた場合、そちらが優先されるようです。

この動作は、実際にnode_modules内にフォルダを作成してみて、CLIの動作を確認してみるとイメージしやすいです。

mkdir node_modules/my-plugin2
vim node_modules/my-plugin2/index.js
vim node_modules/my-plugin2/my-plugin2.styl
node_modules/my-plugin2/index.js
module.exports = function () {
  return function (stylus) {
    stylus.include(__dirname);
  };
};
node_modules/my-plugin2/my-plugin2.styl
h2
  font-size 5vw

CLIで--use my-plugin2または--include node_modules/my-plugin2/で、my-plugin2pathsに追加すると、コンパイルに成功することを確認できます。

./index.styl
@import 'my-plugin'
@import 'my-plugin2'
bash
npm run build
# failed to locate @import file my-plugin2.styl

npm run build -- --use my-plugin2
npm run build -- --include node_modules/my-plugin2/
# h1 {
#   font-size: 10vw;
# }
# h2 {
#   font-size: 5vw;
# }

テスト環境の整備

描写結果を確認したい場合は karma を使い、ブラウザが計算したスタイルを検証するべきでしょうが、この記事では言及しません。
今回は、コンパイルしたstylが指定のcssに一致するかのテストをava + xoで行います。

xo@0.15babel-eslint@6を含んだlinterです。生eslintに比べて、プロジェクト自体のdevDepsを減らせるので、プロジェクトを小さくしたい場合にお勧めです。

これまでの章で作成したindex.js, my-plugin.styl以外のファイルは以降使用しないので、削除してください。

bash
tree -L 1
# .
# ├── index.js
# ├── my-plugin.styl
# ├── node_modules
# ├── package.json
# └── test.js

./my-plugin.stylmixinに変更します。

./my-plugin.styl
large-font()
  font-size 10vw

npm testで使用するテスト本体を記述します。

./test.js
import test from 'ava';
import stylus from 'stylus';

import myPlugin from './';

const render = (str) => {
  let css;
  stylus(str)
  .use(myPlugin())
  .import('my-plugin')
  .set('compress', true)
  .render((err, data) => {
    if (err) {
      throw err;
    }

    css = data;
  });
  return css;
};

const specs = [
  {
    description: 'h1のfont-sizeを10vwにすべき',
    code: `
    h1
      large-font()
    `,
    expected: 'h1{font-size:10vw}'
  }
];

specs.forEach(spec => {
  test(spec.description, t => {
    const {code, expected} = spec;
    t.true(render(code) === expected);
  });
});

compressオプションを利用することでテストしやすいcssが生成できるので、stylusの初期化処理を含めてヘルパ関数として定義します。test内ではヘルパの実行と、結果の比較のみを行い、テストデータspecsを増やしていくことで、検証内容を自動で増やすことが可能です。

npm testでテストが通ること、テスト内容を変更して失敗することを確認します。

bash
npm test
# 1 passed

vim test.js

npm test
# 1 failed

実施例

59naga/stylus-responsive-breakpoints: a media queries of stylus block mixins

angular-materialのメディアクエリのテンプレートstylプラグインとして移植したものです。他にiphone, ipaddevice-widthで検出するメディアクエリなどを追加しています。

6
5
0

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
  3. You can use dark theme
What you can do with signing up
6
5