コードブロックに行番号を実装する
ブログやサイトなどでのコードブロック(ソースコード表示)に、highlight.js や Google Code Prettify、Prism などのシンタックスハイライターを用いたり、pre
要素と code
要素をそのまま使っている方は多いと思います。
そのようなコードブロックに行番号が付いていると、コードの各行を参照しやすくなり、解説やデバッグの際にも役立ちます。
そこで今回は、JavaScript と CSS で手軽にソースコードに行番号を実装する方法をご紹介します。
JavaScript で行番号表示部分を作成
こちらの JavaScript のコードを </body>
の上あたり(できれば直前) に設置すると、pre
要素と code
要素を用いた2行以上のコードブロックの HTML を行番号仕様に書き換えることができます。コードが1行のときは何も変化しません。
<script>
(function(){
const code = document.querySelectorAll('pre code');
if(code.length == 0) return;
for(let i = 0; i < code.length; i++){
if(!/\n/.test(code[i].innerHTML)) continue;
code[i].innerHTML = code[i].innerHTML.split('\n').map(line => {
return `<span class="line-wrap"><span class="line-number"></span><span class="line-code">${line}</span></span>`;
}).join('');
}
})();
</script>
Blogger で使う場合は、コードの <script>
を <script>//<![CDATA[
に、</script>
を //]]></script>
にそれぞれ置き換えてください。
備忘録がてらコードの解説をしてみます。
例えばこんな感じのコードブロックがあるとします。変化がわかりやすいように1行目に色を付けています。
const x = 5;
const y = 10;
console.log(x + y)
まず、このコードブロックに対して split('\n')
を用いて code
要素内の内部テキストを改行毎に分割し、配列にします。
['const x = 5;', 'const y = 10;', 'console.log(x + y);']
次に、map()
で配列の各要素に対して行番号表示の HTML タグを追加し、新しい配列を作成します。
['<span class="line-wrap"><span class="line-number"></span><span class="line-code">const x = 5;</span></span>', '<span class="line-wrap"><span class="line-number"></span><span class="line-code">const y = 10;</span></span>', '<span class="line-wrap"><span class="line-number"></span><span class="line-code">console.log(x + y);</span></span>']
ソースコードを 1 行ごとに span.line-wrap
で囲み、その中に行番号を表示させるための span.line-number
と、もともとのソースコードを表示させるための span.line-code
を追加しています。
最後に、join('')
で上で作成した新しい配列の要素を再び結合し、一つの文字列にして code
内を書き換えます。
<span class="line-wrap"><span class="line-number"></span><span class="line-code">const x = 5;</span></span>
<span class="line-wrap"><span class="line-number"></span><span class="line-code">const y = 10;</span></span>
<span class="line-wrap"><span class="line-number"></span><span class="line-code">console.log(x + y);</span></span></code></pre>
こうして行番号を表示するための HTML 要素を追加することができました。
CSS カウンターで行番号を付与
前項で作成した行番号表示用の HTML に行番号を振っていきます。
番号を付与する処理は innerText
やら textContent
なりを使えば JavaScript でも行えますが、pre
や code
の中身をコピーするボタンを使うと行番号までコピーされてしまうためベストな方法ではありません。
CSS カウンターという、この用途にうってつけのものが存在しますので、これを .line-number
の疑似要素 ::before
に使っていきます。
::before
, ::after
の content
に指定された文字列は DOM に存在しないため、直接的にはコピーできません。詳しい解説は以下のリンク先を御覧ください。
以下がコードブロック全体の CSS のサンプルです。環境によっては表示が崩れる場合もあるので、適宜変更してください。
pre{
display: block;
line-height: 1.6;
margin: 32px 0;
font-size: 14px;
background: #333;
color: #fff;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
pre code{
counter-reset: line; /* カウンター line を 0 に初期化 */
display: block;
margin: 0;
padding: 32px 16px 16px;
max-height: 320px;
overflow: auto;
}
.line-wrap{
display: flex;
margin: 0;
padding: 0;
}
.line-number{
flex-shrink:0;
flex-basis: 40px;
padding: 0 8px 0 0;
height: auto;
font-size: 12px;
text-align: right;
border-right: 1px solid var(--text);
}
.line-number::before{
counter-increment: line; /* カウンター line を 1 増加 */
content: counter(line); /* カウンターの値を表示 */
}
.line-code{
flex: 1;
margin: 0;
padding:0 0 0 16px;
}
CSS カウンターに関わる部分はコードにコメントを入れてあります。個別のプロパティについて詳しく知りたい方はこちらの MDN の記事を参照してください。
- counter-reset - CSS: カスケーディングスタイルシート | MDN
- counter-increment - CSS: カスケーディングスタイルシート | MDN
- counter() - CSS: カスケーディングスタイルシート | MDN
使っている CSS は上記のものと若干違いますが、本記事で実際に行番号スクリプトを導入しています。見え方を確認していただけたら幸いです。