gulpでSVGをWebフォント化する

YuG1224/gulp-task-svg-webify

Webフォント化するためにIcoMoonにSVGをアップロードするのが面倒なので、SVG画像をminifyして、Webフォント化するgulpタスクを作りました。

参考にしたのはここ。

構造

全体の構造は以下。

src/svg/以下にSVG画像を置けば、dist以下に生成される仕組みになっています。

.
├── README.md
├── dist
│   ├── css
│   ├── fonts
│   ├── index.html
│   └── svg
├── doc
├── gulpfile.coffee
├── node_modules
├── package.json
└── src
    ├── svg
    ├── template.css
    └── template.html

gulp minify

svgのminifyにはgulp-svgminを使います。

./src/svg/以下に置いたSVGを圧縮して、./dist/svg/以下に出力します。

gulp = require "gulp"
foreach = require "gulp-foreach"
svgmin = require "gulp-svgmin"
concat = require "gulp-concat"

# minify
gulp.task "minify", () ->
  return gulp.src ["src/svg/*.svg"]
    .pipe foreach (stream, file) ->
      filename = file.path.replace file.base, ""
      stream.pipe svgmin()
        .pipe concat filename
    .pipe gulp.dest "dist/svg"

gulp webify

minifyしたSVGを元にgulp-iconfontgulp-consolidateでwebfont化します。

template用のcssとhtmlはcognitom/symbols-for-sketchにあるtemplateを自分が好きなHandlebars形式に改変して使わせて頂きました。

Webフォント化した時にデフォルトではUnicodeの私用領域の最初E001から埋めていくのですが、SoftBankの絵文字と衝突してしまい環境によっては正しく表示されなくなります。

スマホ利用もあると考えて、options.startCodepoint0xF001にしてみました。

gulp = require "gulp"
foreach = require "gulp-foreach"
iconfont = require "gulp-iconfont"
consolidate = require "gulp-consolidate"
concat = require "gulp-concat"
rs = require("run-sequence").use(gulp)

options =
  fontName: "webfont"
  className: "wf"
  startCodepoint: 0xF001

# webify
gulp.task "webify", () ->
  return gulp.src ["dist/svg/*.svg"]
    .pipe iconfont options
    .on "codepoints", (codepoints, options) ->
      for val in codepoints
        val.codepoint = val.codepoint.toString(16).toUpperCase()
      engine = "handlebars"
      consolidateOptions =
        glyphs: codepoints,
        fontName: options.fontName
        fontPath: "../fonts/"
        className: options.className

      gulp.src "src/template.css"
        .pipe consolidate engine, consolidateOptions
        .pipe concat "#{options.fontName}.css"
        .pipe gulp.dest "dist/css/"

      gulp.src "src/template.html"
        .pipe consolidate engine, consolidateOptions
        .pipe concat "index.html"
        .pipe gulp.dest "dist/"

    .pipe gulp.dest "dist/fonts/"

gulp webserver

SVGを編集しながら、生成されたWebフォントをブラウザで確認するために、webserverのタスクも作りました。

src/svg/*.svgの変更を監視してminify,webifyが実行され、distの変更を監視してlivereload機能が動きます。

debug画面

gulp = require "gulp"
del = require "del"
rs = require("run-sequence").use(gulp)
webserver = require "gulp-webserver"

# watch
gulp.task "watch", () ->
  gulp.watch ["src/svg/*.svg"], () ->
    rs "clean", "minify", "webify"

# webserver
gulp.task "webserver", ["compile", "watch"], () ->
  gulp.src "dist"
    .pipe webserver
      livereload: true

# clean
gulp.task "clean", (done) ->
  del ["dist/*/*"], done

# initialize
gulp.task "initialize", (done) ->
  del ["dist"], done

# compile
gulp.task "compile", (done) ->
  rs "initialize", "minify", "webify", done

まとめ

$ gulp compile    // minify, webify を1回のみ実行
$ gulp webserver  // 変更を監視して、minify, webify を実行し、ブラウザ画面を自動更新

途中、gulp-iconfontが最低500x500以上のSVGが対象ということに気づかず、Webフォントが崩れてしまう現象にハマった。

素材が500x500以上というのが気になるけれど、ひとまずこれでIcoMoonにアップしなくてもローカル環境でWebフォント化することが出来るようになった。

Node.jsgulpio.js