Horic Design

a-blog cmsやJavaScriptなどの情報を発信しています。

4ページ目 | js

gulpを使ってlessをscssに変換してみた

今回はgulpというストリーミングビルドシステムを使ってlessをscssに変換してみました。どうせそういったプラグインがあるんだろうなと思って、ググっても見つからなかったので、下のページを参考にして自分で変換するコードを書いてみました。


そのためにgulp-replaceというプラグインを使って、正規表現を駆使してlessからscssに変換しています。
正規表現を知らない方でも、lessとscssの勉強になると思うので是非おつきあいください。

ソースコード

まず、下が肝心のソースコードです。このソースコードで、lessファイルをscssファイルに変換することができました。
どのようなプロセスで下のようなソースコードに行き着いたのかを大まかに綴っていきたいと思います。

gulp.task('lessToScss',function(){
    gulp.src('themes/system/less/*.less')
		.pipe(replace(/\/less\//g, '/scss/'))
		.pipe(replace(/\.less/g, '.scss'))
		.pipe(replace(/@/g, '$'))
		.pipe(replace(/ e\(/g, ' unquote('))
		.pipe(replace(/\.([\w\-]*)\s*\((.*)\)\s*\{/g, '@mixin $1($2){'))
		.pipe(replace(/@mixin ([\w\-]*)\s*\((.*)\)\s*\{\s*\}/g, '// @mixin $1($2){}'))
		.pipe(replace(/@mixin ([\w\-]*)\s*\((.*);(.*)\)/g,function(all){
			all = all.replace(/;/g,',');
			return all;
		}))
		.pipe(replace(/\.(hook[a-zA-Z\-\d]+);/g, '@include $1();'))
		.pipe(replace(/\.([\w\-]*)\((.*)\);*/g,'@include $1($2);'))
		.pipe(replace(/\.([^\d\s\"]+);/g,'@include $1;'))
		.pipe(replace(/\$(import|charset|media|font-face|page|-ms-viewport|keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes|-moz-document)/g, '@$1'))
		.pipe(replace(/\$\{/g, '#{$'))
		.pipe(replace(/~("[^"]+")/g, 'unquote($1)'))
		.pipe(replace(/spin/g,'adjust-hue'))
		.pipe(rename({
			extname: '.scss'
		}))
		.pipe(gulp.dest('themes/system/scss'));
});

使用したgulpプラグイン

今回はgulp-replaceというプラグインを使ってファイルの文字列を置換しました。node.jsのパッケージで、npm install gulp-replaceでダウンロードできます。
基本的な使い方はJavaScriptの文字列を置換する時に利用するreplaceメソッドと同じで、引き数に変換したい文字列パターン、変換後の文字列を渡してあげます。

replaceメソッドの使用例

var string = "hori:godai".replace(/(.*):(.*)/,"$1 $2");
console.log(string);//hori godai

プロセス

1. パスをlessからscssに変換

文字列/less/を文字列/scss/に変換します

2.拡張子をlessからscssに変換

文字列.lessを文字列.scssに変換します

3. @マークを$マークに変換

lessは変数を@マークで宣言しますが、scssは$マークで宣言します。
そのため、replace(/@/g, '$')で@マークを$マークに変換しています。ただし、@keyframeや@charsetなどの文字には@マークが必要なので、後で個別に$マークに変換しなおしてあげる必要があります。

.pipe(replace(/\$(import|charset|media|font-face|page|-ms-viewport|keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes|-moz-document)/g, '@$1'))

4. mixinの変換

lessのmixinの定義例

.clearfix() {
	&:before,
	&:after {
		content: " ";
		display: table;
	}
	&:after {
		clear: both;
	}
}

scssのmixinの定義例

@mixin clearfix(){
	&:before,
	&:after {
		content: " ";
		display: table;
	}
	&:after {
		clear: both;
	}
}

このようにlessは.mixin名{}でmixinを定義しますが、scssでは@mixin mixin名{}でmixinを定義します。そのため、ドットマークを@mixinに変換する作業が必要です。

.pipe(replace(/\.([\w\-]*)\s*\((.*)\)\s*\{/g, '@mixin $1($2){'))

さらにlessのmixinでは引き数の区切りに;を付けますが、scssでは,です。そのため下のソースでmixinの括弧の中の;,に変換します。

.pipe(replace(/@mixin ([\w\-]*)\s*\((.*);(.*)\)/g,function(all){
	all = all.replace(/;/g,',');
 	return all;
}))

5. mixinの呼び出し方の変更

lessでは定義したmixinを利用する場合.clearfix()としますが、scssの場合は@include clearfix()です。よって下のように呼び出し方を変更します。

.pipe(replace(/\.([\w\-]*)\((.*)\);*/g,'@include $1($2);'))

6. spinをadjust-hueに変更する

lessで、spinという色調を調整するmixinがあるのですが、scssではadjust-hueです。
置換する必要があります。
.pipe(replace(/spin/g,'adjust-hue'))

最後に

以上が大まかな流れになります。これらの処理でlessをscssに変換することが出来ました。lessファイルによってはもう少し処理を書く必要があるかもしれません。
なお、正規表現に不慣れな人は下記のサイトに正規表現を貼付けるとビジュアライズ化してくれるので勉強になりますよ。



JavaScriptのガイドを簡単に生成するJSDuck

職場でCSSのガイドだけじゃなくて、JavaScriptのガイドも欲しいねという話になりました。そういったツールはないだろうかと探した所、JSDuckというツールを見つけました。


これを使うと下のようなJavaScriptのドキュメントが簡単に作成できます。ソースコードにコメントアウトでこれはコンストラクタだよとか、これはメソッドだよと明示してあげる必要はありますが。


導入方法

ターミナルより、sudo gem install jsduckと入力します。するとjsduckがインストールされるはずです。

実行方法

ドキュメント化したいJSファイルがあるディレクトリに移動し、jsduck ファイル名 --output docs --title "ドキュメントのタイトル"このように入力してください。私の場合はAtlas.jsという自分の作っているゲームライブラリをドキュメント化したかったので下のように入力しました。
jsduck Atlas.js --output docs --title "Atlas.js"

コメント文の書き方

クラスを明示する

直前に@class クラス名でコメント文を挿入します。

    /**
     * @class Atlas.Util
     **/
    Atlas.Util = Atlas.createClass({
	....
    });

メソッドを明示する

@method メソッド名でメソッド名を明示し、@param 引数名 型で引数名とその型を指定することができます。

/**
 * @method moveTo
 * オフジェクトを(x,y)の座標にframeフレームで移動させる
 * @param x {Number}
 * @param y {Number}
 * @param frame {Number}
 **/
moveTo : function(x,y,frame){
    ...
},

サンプル

試しに私が開発したAtlas.jsというライブラリも一部だけドキュメント化してみました。下のリンクからサンプルが確認できます。


感想

ドキュメント化されることを念頭に普段からコメント文をしっかり書いておくことで、第三者の人がソースを読んでも読みやすくなるんじゃないかなと思いました。そういった意味でJSDuckのコメント記法を勉強するのはありですね。
また自分がgithubで公開しているライブラリもドキュメント化したいなと思っています。


uikitで自分の欲しいCSS,JSのみをgulpで書き出す方法

CSSフレームワークはとても柔軟な作りになっています。例えばそのフレームワークから自分の欲しいパーツのみを切り出して使うなんてことも可能です。
今回はUIkitを使って、オフキャンバスのCSS,JSのみを書き出しを紹介したいと思います。

UIkitをダウンロード

https://github.com/uikit/uikitから下の図のようにzipファイルをダウンロードしましょう。


lessファイルの編集

中身を展開したら、/src/lessの中にあるuikit.lessを編集します。variable.less及びoffcanvas.less以外のインポートをコメントアウトしましょう

// LESS related
@import "core/variables.less";

// Defaults
//@import "core/base.less";

// Layout
//@import "core/grid.less";
//@import "core/panel.less";
//@import "core/article.less";
//@import "core/comment.less";

// Navs
//@import "core/nav.less";
//@import "core/navbar.less";
//@import "core/subnav.less";
//@import "core/breadcrumb.less";
//@import "core/pagination.less";
//@import "core/tab.less";

// Elements
//@import "core/list.less";
//@import "core/description-list.less";
//@import "core/table.less";
//@import "core/form.less";

// Common
//@import "core/button.less";
//@import "core/icon.less";
//@import "core/close.less";
//@import "core/badge.less";
//@import "core/alert.less";
//@import "core/thumbnail.less";
//@import "core/overlay.less";
//@import "core/progress.less";
//@import "core/animation.less";

// JavaScript
//@import "core/dropdown.less";
//@import "core/modal.less";
@import "core/offcanvas.less";
//@import "core/switcher.less";
//@import "core/tooltip.less";

// Need to be loaded last
//@import "core/text.less";
//@import "core/utility.less";
//@import "core/print.less";

gulp.jsの編集

次にgulpfile.jsの編集です。59行目に読み込むjsを定義した配列がありますので、core.jsoffcanvas.js以外をコメントアウトしましょう。

    corejs = [
        './src/js/core/core.js',
        // './src/js/core/touch.js',
        // './src/js/core/utility.js',
        // './src/js/core/smooth-scroll.js',
        // './src/js/core/scrollspy.js',
        // './src/js/core/toggle.js',
        // './src/js/core/alert.js',
        // './src/js/core/button.js',
        // './src/js/core/dropdown.js',
        // './src/js/core/grid.js',
        // './src/js/core/modal.js',
        // './src/js/core/nav.js',
        './src/js/core/offcanvas.js',
        // './src/js/core/switcher.js',
        // './src/js/core/tab.js',
        // './src/js/core/tooltip.js'
    ];

コマンド操作

あとはコマンド操作でcssとjsを書き出すだけです。npm installで依存ファイルをダウンロードした後、gulp dist defaultと入力し、コンパイルしましょう。distディレクトリの中のcssディレクトリ及びjsディレクトリにminifyされたファイルが出力されていると思います。それぞれuikit.min.js及びuikit.min.cssです。

DEMO

実際に書き出したファイルでDEMOページを作りました。とても簡素ですが、ちゃんとオフキャンバスが動作していることが確認できます。

DEMOページへ

読み込んでいるCSS内に指定したルールが記述されているかを確かめるメソッドを書いてみた

このページでこのクラスを読み込んでたっけ?とCSSファイルを探さないとすぐには分からない場合があるとおもいます。そこで今回は、$.isRuleExist()というメソッドを作成してみました。以下がそのソースになります。

ソース

(function($){
     $.extend({
       isRuleExist:function(className){
              var classes = [];
              var sheets = document.styleSheets;
              var push = Array.prototype.push;
              for(var i = 0,n = sheets.length; i < n; i++){
                push.apply(classes, sheets[i].rules || sheets[i].cssRules);
              }
              for(var i = 0,n = classes.length; i < n; i++){
                 if(classes[i].selectorText == className){
                         return true;
                 }
             }
             return false;
          }
     });
})(jQuery);

使い方

$.isRuleExist(".entryList li");

もしCSSファイルにこのルールが存在すればtrueなければfalseを返します


うーん、でも普通にChrome Dev Toolでリソースを調べた方が速いかも。


gruntでjsファイルどうしを結合

1つのjsが変更されたら、すべてのjsファイルを結合して1つのjsにまとめるための処理をgruntで書いてみました。今回はそのメモになります。
結合することのメリットとすれば、例えば下の図のようにオフキャンバス用のjsやモーダルウィンドウ用のjs、カルーセル用のjsを1つのファイルとしてまとめられることではないでしょうか?


操作の手順としては以下のようになります。

  1. package.jsonの定義
  2. Gruntfile.coffeeの記述
  3. grunt watchで監視

1.package.jsonの定義

依存するファイルを記述しておきます

  "dependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-concat": "~0.4.0",
    "grunt-contrib-clean": "~0.6.0",
    "grunt-contrib-watch": "~0.6.1",
    "load-grunt-tasks": "~0.6.0",
    "nib": "~1.0.3"
  },

dependenciesを記述したら依存ファイルをnpm installで一気にダウンロードしちゃいましょう

2.Gruntfile.coffeeの記述

module.exports = (grunt) ->
  grunt.initConfig
    pkg: grunt.file.readJSON 'package.json'
    watch:
      js:
        files: 'js/**/*.js'
        tasks: 'js'
    concat:
      dist:
        src: ['js/**/*.js']
        dest: 'dist/js/callisto.js'
  require('load-grunt-tasks')(grunt)
  grunt.registerTask 'js', ['concat:dist']

gruntでは、CofeeScriptが使えるので記述がすごくシンプルになります。

3.grunt watchで監視

あとは、grunt watchでjsを監視するだけです。jsファイルのうち1つでも変更があればすぐに、結合ファイルが作成されます。


堀 悟大

有限会社アップルップル マークアップエンジニア。2014年高知大学理学部卒業。学生時代にHTML5のCanvas要素を使ってゲームを作っていたことでWeb全般に興味をもつ。アップルップル入社後はa-blog cmsを便利に使うための機能の実装や、HTML5の技術を使ったデジタルサイネージの実装を行う。趣味は英語。読むことも話すことも好き。

エントリーリスト

カテゴリーリスト

タグクラウド