knowledge base

マークアップ/フロントエンドエンジニアのWEB制作における備忘録です。平日はWEB屋、休日は社会人劇団の主宰・劇作家をしています。

gulpでSassをコンパイルするとcharset指定が削除される

ファイル中にマルチバイト文字があるか確認

gulp-sassモジュールを利用してsassをコンパイルしていると、以下のようにscssファイル中に文字コードを指定していても削除されてしまうことがあります。

@charset "UTF-8";

scssファイル中にマルチバイト文字があるかどうか確認してください。

どうやらgulp-sassはマルチバイト文字が存在するファイルにのみ文字コード指定を出力するようです。

ですので、コメントに日本語を記入してしまえばこのようなことにはならないのですが、このような理由で運用上ルールを追加するのはナンセンスです。

そこで、gulpの他モジュールの力を借りてこれを解決します。

使用するのはまず、gulp-headerモジュールです。

このモジュールは対象となるファイルの先頭に任意の文字列を挿入する機能を持っています。

こちらを用いて、以下のようなタスクファイルを作成します。

var gulp  = require('gulp');
var sass = require('gulp-sass');
var header = require('gulp-header');

gulp.task('sass', function(){
  gulp.src('path/to/scss/*.scss')
    .pipe(sass())
    .pipe(header('@charset "UTF-8";\n\n'))
    .pipe(gulp.dest('dest/to/css'));
});

コンパイルしたcssの先頭に「@charset "UTF-8";」の文字列を追加していいます。

しかしこれだけでは不十分です。

なぜならこのままだと実際にコメント中に日本語が入っていたり、またCSSのプロパティにおいてマルチバイト文字が使われている場合、すでに文字コード指定が出力された上にさらにgulp-headerにより文字コード指定が重複して出力されてしまいます。

具体的には次のような記述があるケースです。

■コメント中の日本後

// これは日本語によるコメントです

■font-familyの指定

body{
  font-family: "游ゴシック体", YuGothic, sans-serif;
}

■アイコンフォント等における擬似要素での指定

.icon:before{
  content: "\e006";
}

そこで、どのような場合でも文字コード指定が重複して出力されないようにしなければなりません。

マルチバイト文字の存在を判別することは現状Node.jsではできないため、ファイル中の文字列置換を行うgulp-replaceモジュールを併用します。

var gulp  = require('gulp');
var sass = require('gulp-sass');
var header = require('gulp-header');
var replace = require('gulp-replace');

gulp.task('sass', function(){
  gulp.src('path/to/scss/*.scss')
    .pipe(sass())
    .pipe(replace(/@charset "UTF-8";/g, ''))
    .pipe(header('@charset "UTF-8";\n\n'))
    .pipe(gulp.dest('dest/to/css'));
});

コンパイル結果から一度文字コード指定を取り除いた上で、改めて文字コードを追加しています。

若干冗長ではありますが、gulpではこれが精一杯の対応となります。