この記事は 広島大学ITエンジニア Advent Calendar 2020の6日目です。
昨日アドベンドカレンダーの5日目を書くためにサイトを作成したのですが、とてもじゃないほどデザインがひどく大変読みにくかったので、highlight.js
の導入を中心にデザイン変更の内容を書いていきます。
highlight.jsの導入
highlight.jsを導入することで、コードをハイライトすることができます。JavaScriptライブラリでは他にもGoogle Code PrettifyやPrism.jsなどがあったのですが、メンテナンスされていなかったり、導入が少し面倒であるなどの理由で、こちらを導入することにしました。
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.4.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.4.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
一般的には以上のコードをHTMLの<head>
内に入れることで、簡単に導入することができます。最新のCDNはこちらにあります。
上手くいかない場合
原因
document.create_element("div").innerHTML = code;
もし以上のようにinnerHTML
を用いたりして動的にソースコードを挿入している場合、ページがロードされた後にしかハイライトをしないため、上手くいきません。
自分は前回の記事にあるように、どうしてもリアルタイムでMarkdownからHTMLに変換したいという謎願望により、YewでinnerHTML
を使用していました。そのためソースコードのハイライトが上手く反映されませんでした。
対処
highlight.jsのライブラリAPIにhighlightBlock(block)
というhljs
オブジェクトの関数が用意されています。これをDOMを生成した後に実行するとソースコードがハイライトされるようになります。
var pre_code_nodes = document.querySelectorAll("pre code");
for(var i = 0; i < pre_code_nodes.length; ++i){
hljs.highlightBlock(pre_code_nodes[i]);
}
以上のようにDOMを生成した後に実行すると、<pre><code>
内のソースコードがハイライトされます。
またまた問題点
自分はJavaScriptが苦手で使い方がわからず、苦戦し今回の原因を見つけることで精一杯で、アドベントカレンダーの公開予定日となり、記事を早急に書く必要がありました。(rustwasmの本にも書いてある通り、JavaScriptの知識があった方がいいらしいです...)
wasm_bindgen`を使ってFFI的なのをする方法をあまり調べられなかったので、どうしようかと思っていたら、JavaScriptで簡単に代用する方法を思いつき、今だけ代替え案として実装にすることにしました。
function initHLJS(){
var pre_code_nodes = document.querySelectorAll("pre code");
for(var i = 0; i < pre_code_nodes.length; ++i){
hljs.highlightBlock(pre_code_nodes[i]);
}
}
setInterval("initHLJS()", 3000);
どのタイミングでDOMが生成されるかわからないとき、以上のような荒業(非推奨)で簡単に実装できます。
終わりに
自分の場合Rustを使用しているため実装の観点からsyntectというRust製のシンタクスハイライトクレートを使用する手段もありました。しかしwasmファイルのデータが増大することを考慮して今回はhighlight.jsで対処することにしました。
皆さんが読んでいるころにはちゃんとwasm_bindgenを用い実装しているはずです。 (12/8追記:wasm_bindgenを用いた実装に変更しました)
焦ってはいいコードが書けず結局書き直すことになるので、アドベントカレンダーの記事は前以て完成させておくべきだということを学びました。次回はそうならないようにします...
最後までお読みいただき、ありがとうございました。