highlight.jsでHTML上のコードを色付け
コードを紹介するブログを作成していて、そのうち適用しようと思っていたコードの色付け(ハイライト)を今になってようやく導入しましたので、合わせて使い方を紹介したいと思います。
このページで利用しているのはhighlight.jsです。
執筆時点でのバージョンは10.5.0で、BSD三条項ライセンスで、GitHubで上ソースも公開されています。
基本的な使い方
使い方は簡単です。
- スクリプトを書く
<pre><code>タグの内側に色づけ(ハイライト)したいコードを書きます。
preもcodeもHTML5の要素です。preはタグの内側にあるのスペースや改行をそのまま表示するものです。codeはプログラムコードであることを示すタグです。highlight.jsはこれらのタグを使ってコードの記述を見つけるのでどちらも必須です。
少し手間なのはコード内の<>&はHTMLのタグと混同されてしまうので変換しておく必要があります。順に<>&となります。元のコードをテキストエディタにコピーしてまとめて置換すると楽です(&から置換してください)。
- highlight.jsの読み込み。
highlight.jsはCSSファイルとJavascriptファイルの2種で構成されています。これらを取り込む記述をします。これらは通常のHTMLにおけるCSSの読み込みやJavascriptの読み込みと同じです。
<link rel="stylesheet" href="/path/to/styles/default.css"> <script src="/path/to/highlight.min.js"></script>
CSSを変えることでテーマを変えることができます。テーマを変えると背景や文字色などの見た目を変えることができます。CSSの探し方は次項で紹介します。
- Javascriptのコードを書く。
bodyタグを閉じる手前ぐらいがいいと思いますが、次のスクリプトを記述します。hljsというオブジェクトはhighlight.jsを読み込んだ際に設定されるようになっています。
<script>hljs.initHighlightingOnLoad();</script>
基本的にはこれでコードハイライトができます。
自サーバーでホストする
highlight.jsのコードは自サーバーでホストする方法と、CDNを使う方法どちらも存在します。
まず自サーバーでホストする場合の方法です。
ファイルは公式ページ:「download」よりダウンロードできます。この時ハイライト対象となる言語を選択できます。
デフォルトでサポートしている言語は次の39種です(HTMLとXMLは一緒とみなしています)
デフォルトの他にも、DNS ZoneやCMakeなど多くの言語をオプションとして指定できます。
対象言語を絞った場合にどれくらいサイズが軽減されるかですが、デフォルト39種から約半分にして次のコードに絞り込んでみました。
結果は展開したフォルダの状態で365KBから318KBとなりました。
CDNを使う
このページではUNPKGのCDNを利用しています。
https://unpkg.com/@highlightjs/cdn-assets@10.5.0/highlight.min.js
CSSファイルはlinkタグで、.jsファイルはscriptタグで取り込みます。混同しないように注意してください。
他、dnjs、jsdelivrでもホストしているようです。そちらに関してのアドレスは公式ページ:「hosted」を確認してください。
CDNのほうでもCSSの変更ができます。UNPKG.comではhttps://unpkg.com/@highlightjs/cdn-assets@10.5.0/styles/にアクセスするとリストが表示されます。URLの入力時は最後の/を忘れずに入力してください。
highlight.min.jsファイルはデフォルトの言語セットですが、これとは別に言語毎の単体ファイルにも存在します。それらはhttps://unpkg.com/browse/@highlightjs/cdn-assets@10.5.0/languages/にあります。絞り込みたかったり、追加する場合はこのファイルを使って言語単体で指定します。
テーマを変える
公式のページでテーマのサンプルを見られます。テーマ名をたよりにCSSファイルを探します。自サイトでホストするためにhighlight.jsダウロードして展開したのならルートフォルダの直下にあるstylesフォルダ内にCSSがすべて入っているので、そこからファイルを見つけてファイル名を確認して指定します。サンプルが表示されるWebページで表示されるテーマ名のブランクになっているところが_でつなげられるのか、-でつなげられるのが基準がないようです。またCDNでは圧縮されそのしるしとしてminがついている場合もあります。
対象のCSSファイルを見つけたら、先のlinkタグの「default.css」となっているファイル名の部分を差し替えます。
テーマの選別は自由ですが、中にはコメントがイタリック(斜字)になるものがあります。日本語のイタリック体は読みづらいので、コメントを同時に記載する場合はそうでないものを選ぶといいでしょう。
対象の言語を明示的に指定する
通常はコードのプログラミング言語を自動的に判別してくれますが、codeタグのクラスに言語名を設定することにより、明示的な指定ができます。
例えば、Typescriptを指定する場合は次のようにします。
もしかしたら、同名のクラスを他に利用していてCSSの競合がおきるかもしれません。そのような場合にはlanguage-やlang-を加えた形でも同様の指定ができます。
逆にハイライトさせたくないという場合は「plaintext」または「nohighlight」を使います。
動的にテーマを変える
一度ページを読み込んだ後にテーマを変えたかったり、遅延読み込みをしたい場合はinitHighlightingOnLoad()は使えません。かわりにhljs.highlightBlock(node)を使います。nodeには、getElementByIdで取得したElementや、document.querySelectorAllから取得するNodeListの中にあるNode、getElementsByTagNameから取得するHTMLCollectionから得られるNodeを指定できます。
//cssファイルの変更(テーマの変更)
//htmlファイルのheadでcssをid="hljscss"として読み込んでいる前提です
//<link rel="stylesheet" href="./default.css" id="hljscss">
document.getElementById("hljscss").href = "./arduino-light.css";
//次のような形で反映させます
//パターン1
let htmlcollection = document.getElementsByTagName('code');
for(let i = 0; i < htmlcollection.length; i++) {
hljs.highlightBlock(htmlcollection.item(i));
}
//パターン2
let nodelist = document.querySelectorAll('pre code')
nodelist.forEach(n => hljs.highlightBlock(n));
//パターン3
//目的のcodeタグにid="test"がついている前提です
let element = document.getElementById('test');
hljs.highlightBlock(element);
pre code以外のタグを使いたい
公式ページではpreとcode要素で囲むことを強く推奨していますが、先のhighlightBlockを使った方法を用いれば 他のタグ内でも機能するようです。
その際はCSSで該当の要素にwhite-space:preスタイルを適用すると、空白や改行をpre同様に表示することができます。
遅延読み込み
遅延読み込みをするには次のようにします。この時、highlight.jsを適用させるためのスクリプトをファイル化して保存しておけば、サイトで共通して使えてサイト単位でのテーマ変更を一括で行えるようになります。
スクリプトファイル(load-highlightjs.js)では無名関数を()で囲うことで式にし、式に()をつけることで定義と同時にされるようにします。
htmlファイルではscriptタグにdeferを加えることでHTML読み込み(parse)終了後にスクリプトが実行されるようにします。
load-highlightjs.js
(function() {
//CSSとスクリプトのURLをセット(サンプルはUNPKGのCDN)
let urlCss='https://unpkg.com/@highlightjs/cdn-assets@10.5.0/styles/arduino-light.min.css';
let urlScript='https://unpkg.com/@highlightjs/cdn-assets@10.5.0/highlight.min.js';
let nodelist = document.querySelectorAll('pre code');
if (0 < nodelist.length) {
let elCss = document.createElement('link');
elCss.rel = 'stylesheet';
elCss.href = urlCss;
document.head.appendChild(elCss);
let elScript = document.createElement('script');
elScript.type ='text/javascript';
elScript.src=urlScript;
//onloadでスクリプトロード後に実行させる関数を記述しておく
//load前にhljsが呼ばれてエラーになるのを防止。
elScript.onload=function() { nodelist.forEach(n => hljs.highlightBlock(n))};
document.body.appendChild(elScript);
}
})();
index.html
...
<script src="./load-highlightjs.js" defer></scrpt>
</body>