勉強日記

チラ裏

はてなブログのコードハイライトをhighlight.jsでオーバライドした


こんなのはてなブログに書いたら怒られそうだけど

動機

  • はてなブログのマークダウン記法モードでは、コードブロック(```で囲むやつ)を構文解析してシンタックスハイライトしてくれる機能がある。 (以下、デフォルトハイライトと呼称)
  • ハイライトの配色をdarcula等の有名なテーマに寄せたくなった
  • しかし、デフォルトハイライトの構文解析では実現不可能。自前で実装するか、highlight.js等のライブラリを利用する必要がある
  • すでにデフォルトハイライトを利用してしまっている記事が過去1年分ある。全部修正するのはつらい
  • ので、既存の記事には手を加えず、ページ表示時に動的にハイライトをオーバライドするスクリプトを書いた

オーバライドするコード

下記コードをブログの設定 > 詳細設定 > headに要素を追加に貼り付ける

<style>
 pre.code {
     background: #2B2B2B;
     color: #A9B7C6;
 }
</style>
<link rel="stylesheet"
      href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.17.1/build/styles/darcula.min.css">
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.17.1/build/highlight.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

<script>

 // はてなブログデフォルトのハイライト解除、
 // codeタグで囲む
 function resetHatenaHighlight() {
     $('pre.code').each(function () {
         const text = $(this).text();
         const lang = $(this).attr('data-lang');
         const code = $('<code>').text(text).addClass(lang);
         $(this).text('').append(code);
     })
 }

 // コードブロックにテーマ適用
 $(function () {
     resetHatenaHighlight();
     $('pre code').each(function () {
         if ($(this).parent().attr('data-lang')) {
             hljs.highlightBlock(this);
         }
     });
 });
</script>

やってること

はてなブログでは、例えば ```php...``` で囲まれた部分が

<pre class="code lang-php" data-lang="php">
  ...
</pre>

に展開される。

これを、highlight.js用に

<pre>
  <code class="php">
    ...
  </code>
</pre>

に置換する。

置換前の...の部分にはデフォルトハイライト用のマークアップ(<span class="synIdentifier">とか)が含まれるため、これを取り除くためにinnerTextを取得している。(jQueryなのでtext())