はてなブログのシンタックスハイライトにCodeMirrorを使う
はてなブログのコードの表示に個人的になんとなく違和感があって、特にモバイル環境で見た時の折り返しが見難い。
どうにもこういうものは見た目をカスタマイズしたい願望があって、はてなブログはモバイルのデザインをカスタマイズできない*1のがどうにもつらい気持ちがあった。*2
ブログを始めた当初は自分でシンタックスハイライトを作ったりもしたんだけど、最近見たらおもくそバグってたのと、自動化できてないので投稿前に手動でマークアップ済みのHTMLを貼り付けて投稿するのが死ぬほど面倒臭かった。
そしてCoffeeScriptだRubyだSwiftだと徐々に他の言語にも手を出し始めると、いちいちやってられっかぁぁーーーって感じになった。
でも、見た目だけはいっちょ前に気になってしまうので、既存のもので何か良い物はないか探していたのであった。
確かこんなものがあったような気がするリスト
SyntaxHighlighter
結構いろんなブログで見かけたような気がする。
これにしようかとも思ったんだけど、どこかの記事でソースコード中の<
とか&
とかをエスケープできていなかったせいで、表示が崩れちゃっているのを見て、なんとなくエスケープは自分で手動なり自動なりでする必要があるなら、あんまり変わらないんじゃないか?と思ってしまったのでやめた。
あと好みのカラースキームが見つからなそうな感じがした(そこまでちゃんと探してない)。Gist
これもかなり有力な候補だったんだけど、一度書いてアップしたあとで貼り付けなければならず、ソースコードの細かい修正とかが面倒そうだなっと思ってしまいやめた。
ある程度まとまったコードならいいけど、一行とかの大量のGistを管理するのは大変そうだし。対応言語の多さと新しい言語への対応の早さは信頼出来るので、これからも要所要所で使うと思う。
エスケープを気にする必要が無いのも良い。はてなブログのシンタックスハイライト
えーと、そうですね、なんか書いてるうちになんかこれでいいんじゃないかって気がしてきてしまったんですけど、エスケープも勝手にやってくれるし、これじゃダメな理由としては、、、う~ん無いですね、なんかあったような気がしたんですけどね。
どちらかと言うとCodeMirror
でやってみたいっていう技術的好奇心の方が大きくて、はてなブログの機能としての欠点は特に無いです。JSFiddleとCODEPEN
実際に使ってみたことはあるのですが、調子に乗って貼りまくってたらものすごく重くなりました。
これもGistと同じで管理が大変そうなのと一行とかのソースコードをたくさん貼るのに向かないかなあって。
シンタックスハイライトのためだけに使うには高カロリー。
CodeMirrorにした理由
とてもパーソナルな理由です。
LightTableを使っている
はい、これ。まずこれなんです。
メモを揉め: LightTableについて
LightTableはUIの描画にHTMLが使われていて、ベースにCodeMirrorが使われています。
CodeMirrorとは、CodeMirror is a JavaScript component that provides a code editor in the browser.
github: CodeMirrorブラウザで動作するJavaScript製のエディタ。
エディタとしての機能はめちゃくちゃ強力なのですが、今回はそれを全く使わず、シンタックスハイライトの機能のみを使おうという魂胆です。
このCodeMirrorにはたくさんの言語モードが用意されていて、全てプラグイン形式になっています。そして、LightTableではカラースキームとしてこのCodeMirrorのカラースキームがおそらくそのまま使われているっぽくて、どうやら互換性があります。
ということは、LightTableで使っているカラースキームをCodeMirrorに持ってこれるのでは?と思ってやってみたら見事成功。ブログのソースコードを自分のエディタ環境と同じ見た目、同じルールにできるので、だいぶ素敵だと思います。
DarkSystemCDというカラースキームがドンピシャ
たまたまLightTableのプラグインマネージャを開いたら新しいテーマがアップロードされていて、それがこのDarkSystemCD
というカラースキーム。github: wds-connections/darksystemcd-lighttable-theme
かっこいい。
これをブログでも使いたいというのが理由。一応フォントは使い慣れている
Souce Code Pro
に変えました。Courier New
も好きなんだけどね。
MarkDownとの併用
ブログはMarkDownで書いているので、できればその中で完結させたいです。
例えばSyntaxHighlighterのように<pre>
にクラスを割り当てて、それにシンタックスハイライトを適用するという仕組みだと、MarkDownでコードブロックを利用した際、クラスを割り当てられません。
回避策としてそこだけHTMLを直に書くという方法も考えましたが、そうすると今度はMarkDownのコードブロックの自動的なエスケープの恩恵を受けられないので、結局別途エスケープする必要が出て振り出しに戻ります。
一つは、<pre>
の前にコメントでアノテーションを入れる方法を思いつきましたが、はてなブログだとコメントが除去されちゃうのでNG。
もう一つは<p>
要素*3にクラスを割り当てて、その要素をアノテーションにする方法。結局今はこの方法で運用している。
ちなみにこの方法はCodeMirror以外にも応用出来るので、MarkDownと組み合わせたい場合にはいいかもしれないです。
RoomMirrorというモジュールにしました
これらの機能をRoomMirror
というnpmのモジュールにしました。
初めてのnpmモジュールです、緊張してます。
デモ
カラースキーム + エディタブル
<p class="rm-a" data-eval="{ mode: 'javascript', readOnly: false }"></p>
というアノテーションをコードブロックの直前に書くことでCodeMirror
がシンタックスハイライトを行うような仕組みになっています。
data-eval
でCodeMirror
にオプションを渡せる。
readOnly
にfalse
を指定しているので以下のデモは全て編集可能です。
darksystemcd
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
monokai
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
solarized
今気づいたけどこれ背景にテクスチャが使われている…。かっこいい。
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
default (in LightTable)
LightTableのデフォルトのテーマです。
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
zenburn
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
paraiso-dark
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
pastel-on-dark
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
the-matrix
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
vibrant-ink
var test = 'test'; /test/i.test(test); function add(a, b) { return a + b; } [0, 1, 2, 3, 4].reduce(add, 0); // 10
CodeMirror
とLightTable
では、同名のスキームでもかなり違いがありました。
ここでは、同名の物は全てLightTable
版のものを使っています。