はてなブログのソースコードに行番号を表示する
他の Syntax Highlight の記法は使えない
Javascriptで処理してCSSのcounter-increment
を使って、はてなブログでソースコードに行番号を表示させます。あくまでMarkdown記法が前提です。
普段 Hugo の Markdown で記事を書いているので、そのSyntax Highlight
の書き方と同じ記法で行番号を表示させたいですが無理です。根本的な問題はSyntax Highlight
のコード色付けそのものが効かなくなることです。これでは意味がありません。
Hugo のSyntax Highlight
で行番号を表示するには言語名の指定に続けて{linenos=table}
のように書きます。例えばpython
なら次のような形です。
```python {linenos=table} ...ソースコード... ```
この{linenos=table}
の部分で行番号を表示するのですが、Hugo とはてなブログでは Markdownパーサが違うので、はてなブログでは当然何も変わりません。幸いなことに、はてなブログのMarkdownでは、この部分はまるごとクラス名になって、ブラウザ画面上では表示されません。つまりよくありがちなパーサが解釈できない部分を文字列としてデロっと表示したりはしないようです。
実際のHTML上では次のようになってます。
<pre class="code python {linenos=table}" data-lang="python {linenos=table}" data-unlink> ..........ソースコードの内容........ </pre>
ところが問題があって、普通なら言語指定の部分が<pre class="code lang-python" data-lang="python" data-unlink>
となるべきところ、このlang-
が消えてしまいます。おそらく Markdownパーサがコードブロックを処理する前にこの改変部分が邪魔になるので、Syntax Highlight
の処理がされなくなってしまうのだと思われます。
全てのソースコードに行番号を表示させたいなら、余計な記法を付加する必要は無いので何も問題ないのですが、あるコードには行番号を付けて、ある番号には付けないといった分岐をさせたい場合、どうやって区別するかが問題です。ここが注意点で、おそらく他の方がやっておられるJavascriptのコードは、そのままでは使えないと思われ工夫が必要です。
はてなブログのMarkdownパーサが何というものかは知りませんが、おそらく他所で使える独自仕様の行番号表示の記法でも、Syntax Highlight
の言語名指定の部分を弄る場合は同じことだと思います。
独自クラスのDIVタグで囲む
いろいろ考えてもいい方法が思いつかず、結局ありきたりですが独自クラスのDIVタグで囲むという方法におちつきました。
こんな感じになります。
def ask_ok(prompt, retries=4, reminder='Please try again!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise ValueError('invalid user response') print(reminder)
code-linenos
クラスの付いたDIVで囲まれたソースコードのみ、行番号を表示する形です。もちろんこのクラス名は勝手に決めたもので任意でかまいません。
<div class="code-linenos"> ```python def ask_ok(prompt, retries=4, reminder='Please try again!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise ValueError('invalid user response') print(reminder) ``` </div>
Javascriptでの処理
こちらの方法を参考にさせていただいたのですが、行番号を表示したりしなかったりしたかったので、Javascriptのコードはかなり違ってます。
以下のコードをscriptタグ
で囲んで、管理画面の「デザイン」からフッターに書き込みます。
/* Add line number to source code */ const addLineNumber = (block) => { let source_code = block.innerHTML.slice(-1) === '\n' ? block.innerHTML.slice(0, -1) : block.innerHTML; let lines = source_code.split(/\n/); let code_block = ""; lines.forEach(function(line){ line += line === '' ? '\n' : ''; code_block += '<div class="code-line">' + line + '</div>'; }) block.innerHTML = code_block; } document.addEventListener('DOMContentLoaded', (event) => { const codeBlocks = document.getElementsByClassName('code-linenos'); codeBlocks.forEach((block)=>{ addLineNumber(block.firstElementChild); }); }, false);
CSSの処理
同じく管理画面の「デザイン」からカスタムCSSに以下を書き込みます。
/* Style add line number of source code */ .code-line { counter-increment: linenumber; } .code-line::before { content: counter(linenumber); display:inline-block; color: yellowgreen; text-align: right; width: 35px; margin-right: 1.0em; padding: 0 0.5em 0 0; border-right: 1px solid #333; }
一応3桁の行番号に対応できる幅にしました。3桁なんて使わないと思いますが(笑)
Hugo の Markdown で書いた記事とは多少記法を変える必要があり、面倒ですが仕方ありません。ただ、行番号を表示したくない場合はcode-linenos
クラス付きのDIVで囲まなければいいだけなので分岐できます。