2012/10/25

Synatax Highlighter のハイライト処理

ソースも付いてることなので、もう少し中身の処理を追ってみました。 javascript自体、まだまだよく分かっていないレベルですが、デバッガが優秀なので、私のようなjavascript初心者でも処理は追っていけますね。 

そのうち、キーワードをハイライト処理するようなエディタを作ってみたいと思っているので、その勉強も兼ねて。

まずは、処理の開始から。
SyntaxHighlighter.all();

てっきり、このall()メソッドを呼び出すことで処理が開始されると考えていましたが、単にwindowオブジェクトのloadイベントで実行するようにメソッドを仕掛けていただけでした。autoloader使用時も、all()メソッドはスクリプトの読み込み終了のフラグを立てるだけで、ハイライト処理へは、スクリプト読み込み完了のイベントから飛んでいます。 

処理が移ると、brushファイルのスクリプトを呼び出し、正規表現パターンを配列として用意します(例えば、"\/\/.*$"のパターンは//コメント抽出用、等)。
正規表現はjavascriptだと6種類、c#だと9種類のパターンが定義されていました。
意外に少ない印象です。

そして、そのパターンを使ってコードにマッチしていく部分を調べるのですが、ここの処理も自分の予想と違い、大変勉強になりました。

予想だとコードを1行ずつ読み込んで、マッチするキーワードを全てのパターンで探すのかと思っていたのですが、実際は”各正規表現パターンずつ”コードの最初から最後まで一通り調べ、マッチする部分を全てピックアップしていくという処理になっています。

例えば、//コメントの部分だけ、まず全部抜き出す訳です。抜き出したキーワードはオブジェクトに格納し、抜き出したコードの位置や抜き出した文字の長さ、適用するスタイル情報等も格納します。そしてそのオブジェクトは配列にして追加していきます。

その次は、/**/コメントの部分だけ、次は""の文字列部分だけ…という風に用意された正規表現パターンを順番に使用し、該当する部分を全て抜き出します。

最後に、そうやって抜き出したキーワード(格納用オブジェクト)の配列を出現順にソートして(格納している文字列の開始位置を使って)、準備完了です。
さて、準備が出来たらいよいよハイライト処理の本番です。
ここではハイライトしない文字列+ハイライトする文字列というHTMLの作成が一つの処理単位になっていました。

準備で抜き出したキーワードの格納用オブジェクトを一つ取り出します。
一つ前のキーワードの終了位置から、今取り出したキーワードの開始位置まではハイライトしない文字列になるので、該当する文字列をinnerHTMLから取り出し(無い場合もアリ)、通常色で表示するためcodeタグで括り、スタイル適用。次にハイライトする文字列は既に取り出しているので、それをcodeタグで括り、格納用オブジェクトにある情報を元にスタイルを適用。最後に次のハイライトしない文字列を取得するための文字位置を更新。

これを抜き出したキーワード分全て繰り返すと、ハイライトされたHTMLが完成しているという塩梅です。

ハイライト済みのHTMLは改行を目印に行単位に分けられるので、必要があれば1行ずつdivタグで括り、行番号のスタイルも適用しています。
細かい処理(タブの処理や、連続スペースの処理等)は省いて書きましたが、大雑把にこの様な処理になっていました。

こうやってソースを追ってみると、自分の発想とは違う処理が行われていて目から鱗、とても勉強になります。
その他の記事