以前書いた記事
Grunt から gulp へ移行してみた:
https://bunlog.dreamseeker.dev/2014/06/08/gulpjs-setting/
を読み返してみて、そういえば gulp.spritesmith の対象ディレクトリを自動取得できるようにしてたな・・・と思い出したので、記事にしてみます。
gulp.spritesmith のインストール
パッケージがインストールされていることが前提となりますので、下記コマンドを実行します。
$ npm install gulp.spritesmith --save-dev
プラグインを読み込む
gulpfile.js では gulp.spritesmith を $.spritesmith で実行できるよう、gulp-load-plugins を読み込む際に置換しつつ変数にセットしておきます。
// load gulp.js & plugins
var gulp = require('gulp'),
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'gulp.*'],
replaceString: /\bgulp[\-.]/
});
上記の例だと、gulp- もしくは gulp. ではじまるプラグインが対象となります。
ディレクトリ一覧を取得するための関数を定義
よい方法がないかなと探していたところ、Stack Overflow で気になる話題を見かけました。
node.js - Get all directories within directory nodejs - Stack Overflow:
http://stackoverflow.com/questions/18112204/get-all-directories-within-directory-nodejs
こちらを参考に、指定したディレクトリ直下のディレクトリ一覧を取得する関数を定義します。
// load Node.js API
var fs = require('fs'),
path = require('path');
// function.getFolders
var getFolders = function (dir) {
return fs.readdirSync(dir)
.filter(function (file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
File System の readdirSync を利用しているため、戻り値は配列になるようです。
fs.readdirSync(path) - Node.js v0.10.34 Manual & Documentation:
http://nodejs.org/api/fs.html#fs_fs_readdirsync_path
gulp.spritesmith のタスクを調整
名称を変更した際の手間を省くため、あらかじめ取得や出力の対象になるディレクトリ名を変数にセットしておきます。
// directory
var dir = {
source: 'source',
scss: 'scss',
img: 'img',
sprite: 'sprite'
};
タスクの定義では、前述の getFolders 関数を利用しつつ、JavaScript の map 関数でループ処理を行います。
// task.sprites
gulp.task('sprites', function () {
// set target folders
var folders = getFolders(dir.source + '/' + dir.img + '/sprite/');
// generate image & sass files
folders.map(function (folder) {
var spriteData = gulp.src('sprite/' + folder + '/*.png', {cwd: dir.source + '/' + dir.img})
.pipe($.spritesmith({
imgName: 'sprite-' + folder + '.png',
imgPath: '../' + dir.img + '/sprite-' + folder + '.png',
cssName: folder + '.scss',
algorithm: 'binary-tree',
padding: 4,
cssFormat: 'scss'
}));
spriteData.img.pipe(gulp.dest(dir.source + '/' + dir.img));
spriteData.css.pipe(gulp.dest(dir.source + '/' + dir.scss + '/' + dir.sprite));
});
});
タスクの実行
下記コマンドを実行すると、プロジェクト直下の source/img に sprite-[ディレクトリ名].png、source/scss/sprite に [ディレクトリ名].scss が生成されます。
$ gulp sprites
やってみて
以前の定義だと、プロジェクトごとにディレクトリの配列を調整しないといけなかったのですが、やはり自動化できると便利ですよね。
なお、夏の終わり頃に調整した内容をまとめているため、現時点ではもっと効率的な手法があるかもしれません w
おまけ
自分で判りやすいようにコメントなどを附記した、今回の gulpfile.js のサンプルです。
// ---------------------------------
// config
// ---------------------------------
// load gulp.js & plugins
var gulp = require('gulp'),
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'gulp.*'],
replaceString: /\bgulp[\-.]/
});
// load Node.js API
var fs = require('fs'),
path = require('path');
// directory
var dir = {
source: 'source',
scss: 'scss',
img: 'img',
sprite: 'sprite'
};
// ---------------------------------
// Functions
// ---------------------------------
// function.getFolders
var getFolders = function (dir) {
return fs.readdirSync(dir)
.filter(function (file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
// ---------------------------------
// Tasks
// ---------------------------------
// task.sprites
gulp.task('sprites', function () {
// set target folders
var folders = getFolders(dir.source + '/' + dir.img + '/sprite/');
// generate image & sass files
folders.map(function (folder) {
var spriteData = gulp.src('sprite/' + folder + '/*.png', {cwd: dir.source + '/' + dir.img})
.pipe($.spritesmith({
imgName: 'sprite-' + folder + '.png',
imgPath: '../' + dir.img + '/sprite-' + folder + '.png',
cssName: folder + '.scss',
algorithm: 'binary-tree',
padding: 4,
cssFormat: 'scss'
}));
spriteData.img.pipe(gulp.dest(dir.source + '/' + dir.img));
spriteData.css.pipe(gulp.dest(dir.source + '/' + dir.scss + '/' + dir.sprite));
});
});