アイコンリサイズ用のnpmパッケージを作ってみた その2
前回の記事ではiconcというパッケージの基本機能を実装しましたが、今回の記事はそれをコマンドツールにしてみます。
前回と同じようにテストを書いてみます:
// test/index.test.js
// spawnを使ってコマンドを発行する
const spawn = require('child_process').spawn;
...
it('iconc command', (done) => {
// サンドボックスパス ./test/sandbox
const sandbox = path.join(__dirname, './sandbox');
// サンドボックスは毎回リセット
fs.removeSync(sandbox);
fs.ensureDirSync(sandbox);
// ../bin/iconc -f ../file/_icon_.png -d ./gen -s icon1:w100, icon2:w120, icon:p150というコマンドになります。
// -f 対象ファイル
// -d 生成したファイルの保存先
// -s リサイズ設定
// 前回の実装だと、-s引数ファイルのパス、JSON内容、yaml内容やJSコードのいずれかに対応していますが、さすがにコマンドラインでJSONとyaml書くのが大変なので、
// <ファイル名>:<リサイズタイプ(pかw)><サイズ>, ...というフォーマットにします
const child = spawn(path.join(__dirname, '../bin/iconc'), ['-f', '../file/_icon_.png', '-d', './gen', '-s', 'icon1:w100, icon2:w120, icon:p150'], {
cwd: sandbox,
stdio: 'inherit'
});
// 終了時に実行結果を検証。
child.on('close', () => {
Object.keys({
icon1: { w: 100 },
icon2: { w: 120 },
icon: { p: 150 }
}).forEach(name => {
fs.existsSync(path.join(sandbox, `gen/${name}.png`)).should.be.true();
});
done();
});
});
...
そして、./bin/iconc
を実装します:
引数を取得するyargsを使用しています:
npm install yargs --save
で追加します
#!/usr/bin/env node
const path = require('path');
const argv = require('yargs').argv;
const Iconc = require('../');
const async = require('async');
const fs = require('fs');
const colors = require('colors');
const assert = require('assert');
const SPACE = 8;
const NODE_ENV = process.env.NODE_ENV;
if (NODE_ENV == 'testing') {
console.log = function() {};
}
async.waterfall([
(done) => {
var opt = opt || {};
// コマンドラインから渡された引数をアサインする
opt.file = argv.f || argv.file || opt.file;
opt.dest = argv.d || argv.dest || opt.dest;
opt.schema = argv.s || argv.schema || opt.schema;
// メッセージ表示
console.log(`${'-'.repeat(SPACE-2)}> Source:`.blue, path.join(process.cwd(), opt.file));
console.log(`${'-'.repeat(SPACE-2)}> Target:`.green, path.join(process.cwd(), opt.dest));
console.log('');
try {
const iconc = new Iconc(opt);
iconc.run(done);
} catch (e) {
return done(e);
}
}
], err => {
if (err) return console.error(err.message.red);
});
npm test
コマンドを叩くと:
もし実行権限のエラーが表示されたら、
chmod +x ./bin/iconc
で実行権限を与えてください。
やはりエラーになります。schema
はコマンドライン専用のフォーマットにまだ対応していないので、実装します:
// ./index.js
...
// schemaがstringタイプの場合はファイルパスと認識し、読み込みの試しをする
if (typeof(self.schema) == 'string') {
// コマンドライン専用フォーマットを優先
if (/([^\:]+)\:(w|p)\d+\,?\s?/g.test(self.schema)){
const found = self.schema.split(',').map(i => i.trim());
// schemaを既存フォーマットに変換
self.schema = found.reduce((a, b) => {
const f = b.match(/([^\:]+)\:(w|p)(\d+)/);
a[f[1]] = {};
a[f[1]][f[2]] = parseInt(f[3]);
return a;
}, {});
return done();
}
return fs.exists(self.schema, exists => {
if (!exists) {
return done(new Error(`schema: ${self.schema} not found`));
}
...
もう一度npm test
すると:
通りました!次は、今のコマンドをnpmのグローバルbinに入れてみます。package.json
を開いて、キーを追加:
...,
"bin": "bin/iconc",
...
で、cd
でプロジェクトのルートに移動し、npm install . -g
を実行すると、iconc
というツールはグロバールにインストールされ、iconc
だけで呼び出せるようになりました。
例えば:
iconc -f ./src_icon.png -d . -s some_img:w100
実行結果は:
あれ?何のメッセージも表示されていません。実際ファイルは作成されています。確かに、ファイル処理の進捗の情報はどこにも出してないので、ちょっと怖いんですね。
今度はEventEmitter
というクラスを継承してメッセージを出してみます。いよいよツールとして成立する形になりつつあるので、次回頑張ります〜
次の記事:http://befool.co.jp/blog/chainzhang/creating-npm-package-3/