haml2slim を改善して haml から slim への移行をしやすくしました
動機
haml から slim へ移行しようとして haml2slim を使おうとしたものの、
上手く変換されず自力で直さないといけないところが多い状態でした。
最初は「リファクタリングする箇所も多いから、一行ずつ注視して自力で変更していけばいいか」と思っていたんですが、
同じところを何度も直していると、ミスも起こるし時間もかかるしで、
haml2slim 自体を直すのが効率良いなと気付きまして、以下のリポジトリを作りました。
気が向いたら本家にプルリクエストを送る可能性もありますが、
2014年のプルリクエストが2022年の今なお放置されている状態で、
希望が薄いので作成する可能性は低いです……。
フォーク元のベースとして、そのプルリクエストである https://github.com/a2ikm/haml2slim/tree/ruby19-hash を使わせていただきました。
ありがとうございます。
本家の haml2slim から変更したこと
https://github.com/nekonenene/haml2slim/compare/9d79c40...4ce0c64
1. .gitignore
を調整
Gemfile.lock
や .bundle
が gitignore の対象になっていたので削除しました。
逆に vendor/bundle
が gitignore の対象になっていなかったので追加しています。
関連する差分: https://github.com/nekonenene/haml2slim/compare/6490994...bef06a9
2. minitest を Gemfile に追加
minitest
をテストで使っているのに Gemfile
に指定がされていなかったので追加しています。
また、 minitest の現在のバージョンでは deprecated になっている記法を修正しました。
関連する差分: https://github.com/nekonenene/haml2slim/commit/dfc0d919433ee93af21853e8623409a14e11d755
3. Ruby 1.9 以降での Hash Syntax に対応
私がベースに使ったリポジトリの作者さんのプルリクエスト ( https://github.com/slim-template/haml2slim/pull/23 ) で
Ruby 1.9 以降での Hash Syntax に対応しているのですが、使ってみて、
これにはまだ不足があることに気付きました。
%button{data: { confirm: "OK?" }}
のような data 属性の変換に対応していないことです。
また、Hash Syntax に関わらず、
キーや値が single quotations ( '
)で囲まれている場合や、
値が Symbol である場合や、値にスペースが含まれる場合に、
正常に変換されていなかったので修正しました。
関連する差分:
- https://github.com/nekonenene/haml2slim/compare/dfc0d91...74a4c9e
- https://github.com/nekonenene/haml2slim/commit/a0d16cdcb21a773ab4f74346d96e622781953e90
- https://github.com/nekonenene/haml2slim/commit/26dfcb01c4498d67c7db550f0a3ab9463bd6caa5
4. 文字列内の変数展開の修正
%span #{1 + 1}
が
span #{1 + 1}
と変換されるようになっていましたが、これでは2行目でエラーを吐いてしまうので、
span | #{1 + 1}
と変換されるように修正しました。
また、
%span 次は#{1 + 2}回目です
がパースの関係で
span 次は# 1 + 2 回目です
のように変換されてしまう問題も修正しました。
関連する差分: https://github.com/nekonenene/haml2slim/compare/77a5072...17acd8d
5. (
, [
, {
は HTML エスケープするように
%span (#{aaa})
は haml では問題なく、文字列としてカッコがレンダリングされるのですが、
span (#{aaa})
と slim でなっている場合、カッコは Attributes Wrapper と思われてしまい
パースしようとするのですが、上手くいかずにパースエラーが起こってしまいます。
思わぬエラーの要因になるので、
HTMLタグのすぐ後ろに (
, [
, {
がある場合には HTML エスケープをおこなうようにしました。
不格好ではありますが、エラーが起こるよりは断然マシです。
関連する差分: https://github.com/nekonenene/haml2slim/commit/4ce0c640b2d0e580e9c3a5274d5be535ce8117d0
6. Vue の変数展開に対応
Rails と Vue.js を組み合わせて使っている場合のみに関係する話ですが、
%span {{ 1 + 1 }}
のように Vue の変数展開を書いているものを、
span {{ 1 + 1 }}
のように slim 向けに直しても上手くいってくれません。
(参考: https://qiita.com/Take-st/items/4bb3ebd25f361276c4c4#comment-ae32b23dae3266a24e54 )
span | {{ 1 + 1 }}
と変換されるようにしてみました。
関連する差分: https://github.com/nekonenene/haml2slim/commit/f23bdc1ee282919a57ad5f65cb4f448ea53c35c4
7. HTMLタグの後ろにスペースを付ける
haml では
%span= Time.now
のように、HTMLタグのすぐ後ろに =
を付けるのが一般的ですが、
slim では
span = Time.now
のようにHTMLタグの後ろにスペースを付けるのが一般的です。
( http://slim-lang.com )
そのように変換されるように調整しました。
関連する差分: https://github.com/nekonenene/haml2slim/compare/17acd8d...18b334e
解決していない問題
これで多くの問題が片付きましたが、これでもまだ全てではありません。
私の気付いているものですと、
= render partial: "dummy", collection: @some_variable, as: :some_variable
のように複数行に渡るものが
= render partial: "dummy", | collection: @some_variable, | as: :some_variable
と変換されてしまい、パースエラーになってしまう問題を残しています。
あまりあるケースではないのと、対応が面倒そうに感じるので放置しています。
おわりに
これで haml から slim への移行作業が大幅に効率化されました。
やはり、自力で繰り返しおこなう作業は、コンピューターに任せるのがなによりですね。