LoginSignup
6
3

More than 1 year has passed since last update.

sassc を直に使う

Last updated at Posted at 2020-05-31

Rails や Sinatra などのフレームワークで CSS を編集する人はたいがい Sass 言語で書いていると思う。
フレームワークが全てをやってくれるのであまり意識することは無いが,多くの場合に sassc という gem のお世話になっているだろう1

この記事は,sassc を直接扱うことについて書く。

なお,Sass 言語の構文には,当初から存在した「Sass 構文」と,のちに追加された「SCSS 構文」の二つがあるが,本記事では Sass 構文で例を示す2。SCSS 構文でも本質的に変わらない。

使ってみる

require

Gemfile に

gem "sassc"

と書いて,スクリプトで

require "bundler"
Bundler.require

すれば使える。

また,sassc がインストールされている環境ではスクリプトで

require "sassc"

すれば使える。
この記事では後者の方法で示す。

変換する

変換元の Sass ソースを与えて SassC::Engine オブジェクトを作り,render メソッドを呼ぶだけ。

以下のように書く。

require "sassc"

source = <<SASS
body
  margin: 0
SASS

p SassC::Engine.new(source, syntax: :sass, style: :compact).render
# => "body { margin: 0; }\n"

オプション

SassC::Engine.new に与える重要なオプションとして,以下のものがある。

:syntax

どっちの構文かをシンボルで与える。

Sass 構文なら syntax: :sass とし,SCSS 構文なら syntax: :scss とする。

:style

出力の形式を :nested:compact:compressed:expanded から選ぶ。

最も小さくなるのが :compressed

CSS の最もふつうの(?)形式が :expanded

非 ASCII 文字の扱い

仕様を確認したわけではないが,非 ASCII 文字を含むかどうかで変換結果の形式に少し違いがあるようだ。

実のところ,記事を書こうと思った動機がコレ。
特筆すべきは compressed スタイルの場合なので,これを expanded と比較する。

まず最初に ASCII 文字だけの例を見よう。

Sass が

Sass
a
  font-family: "hoge"

だとする。
expanded と compressed の出力は以下のとおり。

expandedスタイル
a {
  font-family: "hoge";
}
compressedスタイル
a{font-family:"hoge"}

とくにどうということもない。

次に,Sass に非 ASCII 文字が入った以下のケース。

Sass
a
  font-family: "ほげ"

これを expanded で出力するとこうなる:

expandedスタイル
@charset "UTF-8";
a {
  font-family: "ほげ";
}

ふむ,@charset "UTF-8"; が付いた。なるほどこれは理にかなっている。

では compressed は?

compressedスタイル
a{font-family:"ほげ"}

おや? @charset が無い。いいのこれで?

謎解き

実は,さきほどの実験で,非 ASCII 文字を含む場合に,compressed スタイルで出力した CSS は,a で始まっているように見えるが,そうではない。
先頭に BOM(Byte Order Mark:バイト順マーク)が入っているのだ。

それを確かめるため,

a
  font-family: "ほげ"

compressed で CSS に変換した結果の最初の 5 文字のコードポイントを表示させてみよう:

require "sassc"

source = <<SASS
a
  font-family: "ほげ"
SASS

css_text = SassC::Engine.new(source, syntax: :sass, style: :compressed).render

puts css_text.codepoints.take(5).map{ |c| "U+%04X" % c }.join(" ")
# => U+FEFF U+0061 U+007B U+0066 U+006F

やっぱり最初の文字は U+FEFF,つまり BOM であった。

スタイルを四つ全部試したところ,BOM が付くのは compressed だけであった。
また,ASCII 文字だけの場合は BOM が付かなかった。

よくは調べてないが,上記の動作は sassc というライブラリーの特性とかではなく,Sass 言語の仕様であるらしい。したがって Dart Sass など,他の Sass 処理系でやっても同じ結果になると思う(確かめてない)。

さて,U+FEFF は不可視3なので,入っていることに気づきにくい。これがときに大きな問題を引き起こすのだが,それについては以下の別記事で述べた。

Sass の吐き出す BOM に注意! - Qiita


  1. 以前は sass という gem が使われていたが,処理を C で実装した高速な sassc に置き換えられていっている。 

  2. SCSS 構文が Sass 構文より良い点は「CSS の上位互換」ということしかない気がするが,それでも圧倒的に SCSS が使われているのはなぜだろう? 

  3. ゼロ幅のスペースなので見えなくて当然。ただし,閲覧環境(テキストエディター,コードエディター,ターミナルなど)によっては何らかの表示がされる場合もある。 

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3