t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

Prism.jsの紹介と日本語文字列が認識されない件の対応方法

目次

Prism.js(プリズム)とは

Prism.jsとはWebサイトやブログにプログラムのソースコードを掲載する際、要素ごとに色付けしてくれるツールである。

以下は、Prism.jsの適用前と適用後のイメージ。
f:id:t-hom:20170729152610p:plain

私のWebサイトの一部では同種のツール「SyntaxHighlighterと」を利用しているが、Prism.jsの方がサイズが軽量で動作も速いとのことなのでこちらに乗り換えようかと検討中。

※ちなみに、はてなブログはわざわざツールを使わなくでもコードの色分機能が最初から備わっている。今回は別のサイトの話。

さて、今回Prism.jsを試してみたところソースコード中に日本語の文字列が出てきたときにうまく認識されない問題でハマったので、備忘録として残しておく。

その前に使い方から説明しよう。

Prismの入手

※画像は2017年7月29日現在のものです。

以下のURLにアクセスし、
http://prismjs.com/

Downloadボタンでダウンロードページを開く。
f:id:t-hom:20170729155612p:plain


すると、下の方にいろいろと選択できる画面が出てくる。
f:id:t-hom:20170729155932p:plain

まず一番上のラジオボタンから説明
Compression level: ←圧縮レベル
Development version ←開発版
Minified version ←圧縮版なので、こちらでOK

この圧縮というのはJavaScriptのソースから実行に不要なスペース等を除いたもの。
開発版は人間が読みやすいようにスペースでインデントされている。

そのすぐ下にあるCoreはプログラムの中核部分。当然必要なのでチェックは外せなくなっている。

Themesはデザインの違いなので好きなものを選べばよい。

Languagesは自分がWebに掲載するであろうソースコードの言語を選択する。
最初からMarkup、CSS、C-like、JavaScriptにチェックが入っているが、これらのコードを掲載する予定がなければ外して良い。

私はVBAを掲載したいけれど、選択肢が無いのでVB.Netにチェックを付けた。こうするとBASICにも自動でチェックが入るが、これはVB.Netの言語定義がBASICの言語定義に依存しているため。

Pluginsは必要に応じてチェック。コードの色分けだけならプラグインは不要なので、こちらの解説は他サイトに譲る。

あとは一番下までスクロールして、JSとCSSの2つをダウンロードする。
f:id:t-hom:20170729161640p:plain

Prismの使い方

ダウンロードしたcssとjsファイルをheadタグ内で参照させて、コードを書く際はpreタグとcodeタグで囲む。
codeタグのclassに"language-対象の言語名"を指定することでその言語用にハイライトされる。

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<link rel="stylesheet" href="prism.css" />
	<script src="prism.js"></script>
	<title></title>
</head>
<body>
	<pre>
		<code class="language-vbnet">
Sub Hoge()
    Dim Age As Long: Age = InputBox("年齢を入力し@てください。")
    MsgBox "あなたは" &amp; IIf(Age &gt;= 20, "成年", "未成年") &amp; "です。"
End Sub
		</code>
	</pre>
	
</body>
</html>

日本語文字列の問題

Prism.jsは軽量で使い勝手も良さそうだが、残念なことに現時点(2017/7/29)では日本語に対応していない様子。
文字列中に日本語があると表示が崩れてしまう。
f:id:t-hom:20170729162606p:plain
※今回はvbnetのみで、他の言語では試してないので不明。

Prism.jsを日本語文字列に対応させる方法

そもそもの原因は、Prism.jsのここの部分↓
f:id:t-hom:20170729163044p:plain

「string(文字列)とは」という定義が正規表現で書かれているけれど、これが半角文字しか考慮されていない。
ここを次のように編集する。

まず編集前がこちら。

string:/"(?:""|[!#$%&'()*,\/:;<=>?^_ +\-.A-Z\d])*"/i

編集後がこちら。

string:/"(?:""|[^\"])*"/i

編集前はこれとこれとこれと。。という風に全文字を網羅しようとしてたけれど、「"」以外もしくは「""」を文字とした正規表現に変更した。
よく見ると元の正規表現だとアットマークも漏れてるし、問題は全角だけじゃなかったようだ。

本当はgithubでプルリク(?)とかした方が良いんでしょうけど、今のところgithubは全然素人なのでTwitterで直接@prismjsさんに突撃中。

7/30 追記:コード中のコメントもおかしいのでPrism.jsを再修正

うまくいったと思ったけどまだ問題があった。
コメント中の文字列やキーワードまで色分けされてしまう。

これは評価順がstring→commentの順に並んでいるから最初にマッチした方にヒットしてしまうためだ。

Prism.jsのコードで以下の赤字と青字の部分を入れ替えれば改善される。
Prism.languages.basic={string:/"(?:""|[^\"])*"/i,comment:{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},number:(以降省略

↓修正後
Prism.languages.basic={comment:{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},string:/"(?:""|[^\"])*"/i,number:(以降省略

【注意】ブラウザの表示上改行が入って見えるかもしれませんが、実際には1行です。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。