現在このブログでは、ソースコードのハイライト表示で google-code-prettify を使っていますが、それについてまとめてみました。
google-code-prettifyの導入
google-code-prettify は <pre>
〜 </pre>
で囲われた整形済みのソースコードなどを自動的に言語判断して、コードカラーリングを行ってくれるものです。
他にもソースコードをハイライト表示できるライブラリで SyntaxHighlighter などがありますが、google-code-prettify の方がシンプルで使い勝手がいいのでこっちを使っています。
ファイルのダウンロード
まずは、http://code.google.com/p/google-code-prettify/ にある Downloads から ライブラリ一式をダウンロードします。
特に中身をいじらなければ軽いファイルがいいので Minimized source files の方を選びます。
ダウンロードされた zipファイル を解凍すると、jsファイル と cssファイル が一式揃ったフォルダが展開されます。
その中でコアとなる jsファイルは prettify.js で、コードのカラーリングを設定しているのは prettify.css となるので、HTML の <head>
内にインクルードするときは、そちらのパスを指定することになります。
ファイルのアップロード
展開した google-code-prettifyフォルダを、好きな場所にそのままフォルダごとアップロードします。
とりあえず今回は、google-code-prettify を使う HTMLファイルと同じ階層にいます。
HTMLのHEAD内の編集
HTML の <head>
内に prettify.js と prettify.css のパスを追加します。
<link href="google-code-prettify/prettify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="google-code-prettify/prettify.js"></script>
その後に、HTML が onload したときに prettyPrint()
を呼び出します。
このとき、google-code-prettify を紹介してるブログではだいたい <body onload="prettyPrint()">
という感じで onload
の呼び出しを使っていますが、そのやり方は他のライブラリとの併用を考えるとあまり良くないのでイベントリスナーを使います。
また、Internet Explorer では addEventListener()
メソッドが使えないので、代わりに attachEvent()
メソッドを使用します。
<script type="text/javascript"> // <![CDATA[ (function(){ function init(event){ prettyPrint(); } if(window.addEventListener)window.addEventListener("load",init,false); else if(window.attachEvent)window.attachEvent("onload",init); })(); // ]]> </script>
一応ここら辺は Google のリファレンスに従っています。
HTMLの整形済みのソースコードの記述
あとは、ハイライトしたい PREタグに prettyprint
というクラス名を指定することで、ソースコードのカラーリングが適応されます。
<pre class="prettyprint">
更に行番号を表示したい場合は、続けて linenums
というクラス名を追加して下さい。
<pre class="prettyprint linenums">
1行ごとに番号を振りわけるためのCSSの編集
クラス名に linenums
を指定して行番号を表示しましたが、このとき、デフォルトの状態だと5行ごとに番号が振られています。
これを 1行ごとに番号を振るようにする場合は、prettify.css にある li.L0…li.L8 の指定をコメントアウトすればできるのですが、自分は元のソースコードをいじくるのがあまり好きじゃないので、新たにCSSを上書きするようにしました。
ライブラリの JavaScript の処理で、PREタグの中身が書き変わると linenums
というクラス名のついたOLタグが生成されるので、これを利用します。
<style type="text/css"> ol.linenums li { list-style: decimal outside; } </style>
見栄えを調整するためのCSSの編集
もう少し見やすくするために番号の横にラインを付け加えたりと、色々調整していきます。
これは好みに合わせて下さい。
<style type="text/css"> pre.prettyprint { background-color: rgb(248, 248, 248); color: gray; padding: 0 0 0 3px; } ol.linenums li { list-style: decimal outside; line-height: 1.5; border-left: solid 3px #6CE26C; padding-left: 3px; margin-left: .7em; background-color: white; } ol.linenums li.L1, ol.linenums li.L3, ol.linenums li.L5, ol.linenums li.L7, ol.linenums li.L9 {background-color: rgb(248, 248, 248)} </style>
- Example:google-code-prettifyを使ったサンプル
AutoPagerize対応
Firefox の “Greasemonkey” や “Safari 機能拡張” などに、AutoPagerize というページ分割されたWebサイトを自動的に下に継ぎ足して表示するスクリプトがありますが、これを使われているときに継ぎ足された記事はハイライト表示されません。(当たり前ですが)
で、これに対応させるというマニアックな処理を付け加えたいと思います。
イベントリスナーの登録
AutoPagerize でのページが継ぎ足されたときは AutoPagerize_DOMNodeInserted
というイベントが呼び出されるみたいなので、そのイベントリスナーを登録します。
また、今回の場合は Firefox とか Safari での AutoPagerize の対応のため addEventListener()
メソッドのみを使用しています。
if(document.body.addEventListener){ document.body.addEventListener('AutoPagerize_DOMNodeInserted',function(e){ // ページが継ぎ足されたときの処理 },false); }
ページが継ぎ足されたときの処理
ページが継ぎ足されたときに、そのまま prettyPrint()
メソッドを呼び出してしまうと、すでにハイライトされたPREタグも含めてハイライト処理がかかってしまうので、一度PREタグのクラス名を全て空にしてから新たに追加されたPREタグのみをハイライト処理します。
- 新たに追加されたPREタグのクラス名を一時保存
- 全てのPREタグのクラス名を空にする
- 新たに追加されたPREタグのクラス名を戻す
- ハイライト処理
- 全てのPREタグのクラス名を戻す
// 全てのPREタグの情報 var pre=document.getElementsByTagName("pre"); var leng=pre.length; var tmp=new Array(leng); // 新たに追加されたPREタグの情報 var new_pre=e.target.getElementsByTagName("pre"); var new_leng=new_pre.length; var new_tmp=new Array(new_leng); // 1. 新たに追加されたPREタグのクラス名を一時保存 for(var i=0;i<new_leng;i++){ new_tmp[i]=new_pre[i].className; } // 2. 全てのPREタグのクラス名を空にする for(var i=0;i<leng;i++){ tmp[i]=pre[i].className; pre[i].className=''; } // 3. 新たに追加されたPREタグのクラス名を戻す for(var i=0;i<new_leng;i++){ new_pre[i].className=new_tmp[i]; } // 4. ハイライト処理 prettyPrint(); // 5. 全てのPREタグのクラス名を戻す for(var i=0;i<leng;i++){ pre[i].className=tmp[i]; }
まとめ
最終的な記述はこれになります。
<script type="text/javascript"> // <![CDATA[ (function(){ function init(event){ prettyPrint(); if(document.body.addEventListener){ document.body.addEventListener('AutoPagerize_DOMNodeInserted',function(e){ var pre=document.getElementsByTagName("pre"); var leng=pre.length; var tmp=new Array(leng); var new_pre=e.target.getElementsByTagName("pre"); var new_leng=new_pre.length; var new_tmp=new Array(new_leng); for(var i=0;i<new_leng;i++){ new_tmp[i]=new_pre[i].className; } for(var i=0;i<leng;i++){ tmp[i]=pre[i].className; pre[i].className=''; } for(var i=0;i<new_leng;i++){ new_pre[i].className=new_tmp[i]; } prettyPrint(); for(var i=0;i<leng;i++){ pre[i].className=tmp[i]; } },false); } } if(window.addEventListener)window.addEventListener("load",init,false); else if(window.attachEvent)window.attachEvent("onload",init); })(); // ]]> </script>
“Firefox” か “Google Chrome” か “Safari” で AutoPagerize をインストールしたら、以下のページで試してみて下さい。
以上です。