SassでコンパイルされるCSSの書式をカスタマイズする

Sass、便利ですよね。
変数、関数、mixin、extend...、Sass 3.2 からはPlaceHolderなんて機能まで追加されました。

機能的には全く問題ないのですが、
ただ1つ不満なのは、デフォルトでコンパイルされるCSSの書式。

例えば、下記のようなコード(SCSS)。

//ネストする場合
html {
	body {
		#container {
			margin:0 auto;
			width:900px;

			#content {
				padding-bottom:120px;

				#main ,
				#sub {
					background:#fff;
				}

				#main {
					float:left;
					width:600px;
				}

				#sub {
					float:right;
					width:200px;
				}
			}
		}
	}
}

//比較の為にネストしない場合
html body #container {
	margin:0 auto;
	width:900px;
}

html body #container #content {
	padding-bottom:120px;
}

html body #container #content #main ,
html body #container #content #sub {
	background:#fff;
}

html body #container #content #main {
	float:left;
	width:600px;
}

html body #container #content #sub {
	float:right;
	width:200px;
}

コンパイルするとこうなります。

html body #container {
  margin: 0 auto;
  width: 900px;
}
html body #container #content {
  padding-bottom: 120px;
}
html body #container #content #main,
html body #container #content #sub {
  background: #fff;
}
html body #container #content #main {
  float: left;
  width: 600px;
}
html body #container #content #sub {
  float: right;
  width: 200px;
}

html body #container {
  margin: 0 auto;
  width: 900px;
}

html body #container #content {
  padding-bottom: 120px;
}

html body #container #content #main,
html body #container #content #sub {
  background: #fff;
}

html body #container #content #main {
  float: left;
  width: 600px;
}

html body #container #content #sub {
  float: right;
  width: 200px;
}

個人的に、とっても気持ち悪い結果に(笑)

理想はこうです。

html body #container {
	margin:0 auto;
	width:900px;
}

html body #container #content {
	padding-bottom:120px;
}

html body #container #content #main ,
html body #container #content #sub {
	background:#fff;
}

html body #container #content #main {
	float:left;
	width:600px;
}

html body #container #content #sub {
	float:right;
	width:200px;
}
  • プロパティ前のインデントが半角スペース2つに置き換わる
  • プロパティのコロンの後に半角スペースが1つ入る
  • 複数要素指定の場合、コンマの前の半角スペースが消える
  • ネストした場合、閉じ括弧の次の行に次の指定がくる

この4点をどうしても回避したい。
という事で、前置きが長くなりましたが、実際にSassがCSSにコンパイル際に実行されるコードを修正しようと思います。

環境によってpathは違うと思いますが、ファイルの在り処です。

/usr/local/lib/ruby/gems/1.9.1/gems/sass-3.2.1/lib/sass/tree/visitors/to_css.rb

全て、既存コードをコメントアウトして、直後に修正したコードを記述しています。
また、バージョンによって記載箇所は異なると思います。

124行目辺り
プロパティ前のインデントをタブに/コロンの後のスペース削除
   def visit_prop(node)
    #tab_str = '  ' * (@tabs + node.tabs)
    tab_str = "\t" * (@tabs + node.tabs)
    if node.style == :compressed
      "#{tab_str}#{node.resolved_name}:#{node.resolved_value}"
    else
      #"#{tab_str}#{node.resolved_name}: #{node.resolved_value};"
      "#{tab_str}#{node.resolved_name}:#{node.resolved_value};"
    end
  end
136行目辺り
複数要素指定時の、コンマの前の半角スペースを追加(mixin include時に、1行に展開されてしまうので、コンマの後に改行も追加)
  def visit_rule(node)
    with_tabs(@tabs + node.tabs) do
      #rule_separator = node.style == :compressed ? ',' : ', '
      rule_separator = node.style == :compressed ? ',' : " ,\n"
      line_separator =
        case node.style
          when :nested, :expanded; "\n"
          when :compressed; ""
          else; " "
        end
      rule_indent = '  ' * @tabs
      per_rule_indent, total_indent = [:nested, :expanded].include?(node.style) ? [rule_indent, ''] : ['', rule_indent]
194行目辺り
閉じ括弧後に空白行追加
      if node.style == :compact
        properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(' ')}
        to_return << "#{total_rule} { #{properties} }#{"\n" if node.group_end}"
      elsif node.style == :compressed
        properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(';')}
        to_return << "#{total_rule}{#{properties}}"
      else
        properties = with_tabs(@tabs + 1) {node.children.map {|a| visit(a)}.join("\n")}
        end_props = (node.style == :expanded ? "\n" + old_spaces : ' ')
        #to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n" if node.group_end}"
        to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n"}"
      end

      to_return

以上で、理想の書式に(あくまでも個人的には)!!

ただこれ、Sassのバージョンを上げると当然コードが上書きされるので再度修正が必要となりますし、
コードの中身がガラっと変わる可能性も考えられるので、根本的な解決にはなっていません。

書式を独自定義したファイル用意してそれを参照させるように出来ないものか・・・。
非rubyerなので今のところはこの方法をとるしかなさそうです。