mizusame

コードブロックに行番号を実装する

ブログやサイトなどでのコードブロック(ソースコード表示)に、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 でも行えますが、precode の中身をコピーするボタンを使うと行番号までコピーされてしまうためベストな方法ではありません。

CSS カウンターという、この用途にうってつけのものが存在しますので、これを .line-number の疑似要素 ::before に使っていきます。

::before , ::aftercontent に指定された文字列は 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 の記事を参照してください。

使っている CSS は上記のものと若干違いますが、本記事で実際に行番号スクリプトを導入しています。見え方を確認していただけたら幸いです。

    編集
    ホーム