highlight.jsに行番号を追加する方法
シンタックス・ハイライト・ライブラリhighlight.jsに簡単に行番号を追加する方法をご紹介します。自作プラグインで楽々実装
更新:
環境:windows10/Microsoft Edge/VS Code
PREPARATION
想定する読者と前提条件
基本的なパソコン操作ができること。HTML及びJavaScriptの基礎程度の知識が必要です。
START
highlight.jsのとは?
highlight.jsは、ブログ等でプログラムコードを掲載する場合、予約語などのキーワードを 色分けし、視認性を高めるライブラリです。今回はこのライブラリに行番号を追加し視認性を向上させてみましょう。 最終的には以下のようなものを作成いたします。
2022年3月3日現在最新バージョン:11.4.0です。
<div class="row text-center mb-2 mt-5 justify-content-center">
<div class="col-8 col-md-4 mx-auto">
<h2 class="cairo c-r h3 d-inline-block">
<img decoding="async" class="ai" alt="" src="/img/ai/ai2.png"><br>
COMPLATE</h2>
<hr class=" ai-border">
</div>
</div>
highlight.jsの設置
下記公式サイトにアクセスし、最新の設置方法を確認してください。最も簡単な方法はcdnjsを利用します。
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"></script>
プラグインを作ろう!
ここでは、highlight.jsの機能拡張を行い、行番号を表示させてみましょう。 highlight.jsに機能を追加ためには、addPluginを利用することで、簡単なプラグインを作ることができます。プラグインの最も簡単な作り方は以下の通りです。
after:highlightBlockは非推奨となりました。after:highlightElementを使用してください。 result.valueでは書き換え不可になりました。el.innerHTMLを書き換える必要があります。
hljs.addPlugin( {
'after:highlightElement': ({el, result}) => {
//ここに処理を書く
....
}
});
行番号追加機能を作ろう
ここからが本題です。プラグインの雛形がわかりましたが、resultやelといった値が何を 意味しているのか、知ることから始めましょう。
after:highlightElement({el, result})
after:highlightElementは、highlightjsによって整形が完了した後(画面に表示する前)に実行され、以下の3つのオブジェクトが渡されます。
- el
-
強調表示を行うHTML要素(つまりcode要素)
- result
-
highlightjsによって強調表示された結果オブジェクト
result.valueには、強調表示されたHTMLが格納されています。
整形後のHTMLを書き換える方法
elオブジェクトのinnerHTMLには、強調表示されたHTML要素がそのまま格納されています。 このinnerHTMLを書き換えることで、highlightjsによって強調表示されたHTMLの結果を変更することができます。
実際にel.innerHTMLどのような値が格納されているのか見てみましょう。キーワードがspan要素で囲まれ、1行1行の区切りは改行で表現されています。
<span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span>
<span class="hljs-tag"><<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">head</span>></span>
<span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">title</span>></span>Document<span class="hljs-tag"></<span class="hljs-name">title</span>></span>
<span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
<span class="hljs-attr">href</span>=<span class="hljs-string">"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/default.min.css"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
<span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initHighlightingOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span>
<span class="hljs-tag"></<span class="hljs-name">head</span>></span>
<span class="hljs-tag"><<span class="hljs-name">body</span>></span>
<span class="hljs-tag"><<span class="hljs-name">pre</span>></span><span class="hljs-tag"><<span class="hljs-name">code</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"html"</span>></span>...<span class="hljs-tag"></<span class="hljs-name">code</span>></span><span class="hljs-tag"></<span class="hljs-name">pre</span>></span>
<span class="hljs-tag"></<span class="hljs-name">body</span>></span>
<span class="hljs-tag"></<span class="hljs-name">html</span>></span>
ここまで分かればやることは簡単ですね。各行の先頭に行番号を表示する要素(span)を追加すれば良いだけです。実際に作ってみましょう。
プラグインの完成
hljs.addPlugin({
'after:highlightElement': ({ el, result}) => {
el.innerHTML = result.value.replace(/^/gm,'<span class="row-number"></span>');
}
});
行番号をCSSで表示しよう
各行の先頭に<span class="row-number">要素を追加していますので、 この要素に擬似要素を追加し行番号を表示させてみましょう。疑似要素で作成することで、行番号は文字選択から排除されます。 CSSで連番を振るには、countersを用いることで簡単に行えます。複数のコードを追加することも考え、pre要素でカウンターリセットも忘れずに!
pre{
counter-reset: rowNumber;
}
pre span.row-number{
counter-increment: rowNumber;
}
pre span.row-number::before {
content:counter(rowNumber);
/* 以下少しだけ装飾 */
width: 2rem;
display: inline-block;
color: #aaa;
}
QUESTION
行番号左固定バージョン
pre{
counter-reset: rowNumber;
}
pre code{
padding-left:2rem !important;/* 行番号表示用余白 */
}
pre span.row-number{
counter-increment: rowNumber;
}
pre span.row-number::before {
content:counter(rowNumber);
/* 以下少しだけ装飾 */
width: 2rem;
display: inline-block;
color: #aaa;
position:absolute;
left:0;
padding-left:4px;/* 文字位置の調整 */
background:#f0f0f0;/* 背景色は設定しましょう */
}
COMPLETE
HTML全体
<!DOCTYPE html>
<html lang="ja-JP">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/default.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<style>
pre{
counter-reset: rowNumber;
}
pre span.row-number{
counter-increment: rowNumber;
}
pre span.row-number::before {
content:counter(rowNumber);
width: 2rem;
display: inline-block;
color: #aaa;
}
</style>
</head>
<body>
<script>
hljs.addPlugin({
'after:highlightElement': ({ el, result }) => {
el.innerHTML = result.value.replace(/^/gm,'<span class="row-number"></span>');
}
});
</script>
</body>
</html>