Hugoのコードブロックのシンタックスハイライトをカスタマイズする

Hugoのカスタマイズをしています。テーマは「hugo-clarity」です。

記事の本文はマークダウンで書きますが、コードを書く部分をいじりたくなりました。

直したいところ

優先順で挙げると

  1. 文字の色を変えたい
  2. 言語表記の色を変えたい
  3. 行数表示をデフォルトにしたい
  4. 折りたたみの表示を変えたい
  5. ツールチップを日本語にしたい
  6. 「...」に「もっと見る」を入れる

です。

好きな配色の文字だと気分も上がります♪

2.と5. は何とかなるのではないかと楽観的に考えています。

用語のおさらい

そもそもの用語を調べました。

コードブロック(Code block)とは

引用元はこちらです。

コードブロックとはプログラミング言語におけるコードのまとまりのことを指します。

記事で見かけるコードのかたまりを指す言葉かと思いきや、広い意味で使われているのですね。

シンタックスハイライト(Syntax highlight)とは

引用元はこちらです。

シンタックスハイライトとは、テキストエディタなどの文字表示に関する機能の一つで、あらかじめ指定された文中の特定の記号やキーワードなどを他とは異なる色で表示すること。

VS Codeでもシンタックスハイライトを設定したことがあったので、認識はあっていたようです。

以前Hugoでもシンタックスハイライトを設定できるライブラリを教えていただいたことがあるのですが、覚えていない...。

文字の色を変える

まずは一番変えたい文字の色表示(シンタックスハイライト)について方法を調べました。

シンタックスハイライトのライブラリ(シンタックスハイライター)

やはりライブラリなるものがありました。

  • Rouge:Qiitaはこれ
  • highlight.js:対応している言語がたくさん
  • Prism:Rubyでできている
  • syntaxhighlighter:白とグレーのしましまの行
  • code-prettify:Google
  • Pygments:Pythonでできている

もっとありました。

赤い画面のhighlight.js!見たことがありました。思い出しました。

ただ、現在のHugoはChromaというライブラリが使われているそうです。

Pygmentsを参考に、Goでできています。

上記の変えたいことを実現できるか分かりませんが、ここは標準で付いているChromaを使おうと思います。

Chromaを使う

以下記事を元に設定していきます。

hugo 単体でシンタックスハイライト適用 - チラシのすきま

If you run with markup.highlight.noClasses=false in your site config, you need a style sheet.

ドキュメントにもこのように書かれていたので、カスタマイズにはcssファイルが必要なようです。

スタイルはこちらから選び、monokaiにしました。

デフォルトはテーマでオリジナルのシンタックスハイライトが設定されているようです。すでに_syntax.sassファイルがあり、「monokai」とは違う配色でした。

コマンドラインに以下のように打ちました。
なお、hugo server でサーバー起動中ではできませんでした。1度停止させます。

hugo gen chromastyles --style=monokai > syntax.css

すると「monokai」のスタイルが入ったsyntax.cssファイルがルートディレクトリにできるので、然るべき場所に移して、読み込むようにします。

テーマ「hugo-clarity」では、/static/css ディレクトリを作り、中にsyntax.cssファイルを配置しました。
ファイルの読み込みはstaticディレクトリ以下が読み込めるように設定されているようです。

README.md には

However, sometimes you may need to load additional style or script files. In such cases, you can add custom .css and .js files by listing them in the config.toml file (see the snippet below). Similar to images, these paths should be relative to the static directory.

とありました。
翻訳は、

しかし、時には追加のスタイルファイルやスクリプトファイルをロードする必要があるかもしれません。そのような場合には、カスタムファイルである .css.jsconfig.toml ファイルに記述して追加します (以下のスニペットを参照してください)。 画像と同様に、これらのパスは static ディレクトリからの相対パスである必要があります。

でした。

スニペットというのは、その下に書かれていた

[params]
...
customCSS = ["css/custom.css"] # Include custom CSS files
customJS = ["js/custom.js"] # Include custom JS files
...

のことのようです。

はじめconfig.tomlにカスタムcssの設定を書かずに
/layouts/partials/head.html ファイルに読み込みについて記述してみたところ、うまくいきました。

<link rel="stylesheet" type="text/css" href="/css/syntax.css">

このあとにconfig.tomlで設定できることを知りました。

どちらでも同じ結果になりますが、config.tomlに書く方がhead.htmlファイルを触らずに済むのでいいなと思いました。

ちなみに複数ファイルを読ませたい場合は

customCSS = ["css/custom1.css", "css/custom2.css"] 

と書くとできました。

Chromaではうまく色分けしてくれない

これで晴れて「monokai」のsyntax.css ファイルを読めるようになったのですが、肝心のシンタクスハイライトに難点が。

試しにphpのコードを入れてみると、<?php ?> の部分がエラー扱いされ、エラーの配色で表示されてしまいました。

これは...嫌です。

言語によって綺麗に色分けされるものと、ところどころうまく色分けされないものとあるのかもしれません。

私の書き方に問題があるのでしょうか(それもありそう)。

ライブラリを変えて解決できるのであればそうしたいです。

ということで、次は highlight.js を試してみます。

highlight.js を使う

以下記事を参考にさせていただきました。

シンタックス・ハイライト・ライブラリ「highlight.js」の使い方 – ラボラジアン

ファイルをダウンロードしてサーバに上げて読み込む方法で行います。

記事にある highlight.pack.js はダウンロードファイルにはなかったので、highlight.min.js を使ってみます(おそらくバージョン違いによるものかと思います)。

highlight.js のテーマにも「monokai」はありましたが、テーマの数が豊富なのであえて別の「Base16/Onedark」にしてみます。

scriptタグの書き方

2つのファイル

  • onedark.min.css
  • highlight.min.js

の読み込みに加えて以下のコードを書く必要があります。

<script>hljs.highlightAll();</script>

highlight.min.js ファイルを読み込んだ後に書きたいのですが、/layouts/partials/head.html ファイルの </footer> の下に書くのでは highlight.min.js のになってしまいます。

これは1行だけどもファイルとして読み込ませるしかなさそうです。

customJS = ["js/highlight.min.js", "js/highlight_script.js"]

として、highlight_script.js ファイルに hljs.highlightAll(); を入れました。

これでうまくhighlight.jsが適用されました!

この時点での表示はこちらです。

なぜか行数が出るようになりました。そして非表示にできなくなりました。

どうやら

  • 指定した言語をサポートしている → 行数が出る(非表示にできない)、
    さらに言語によって色が違ったり、行数を囲むタグも異なる(行数がドラッグ対象になったりならなかったり)
  • 言語未指定 → 行数の表示・非表示切り替えができる(デフォルトは非表示)

しかも、コードブロックの書き方によっても挙動が異なるようです。
☆これらは ''' で囲って書く方法で調べています。

highlight.jsの導入方法に問題がありそうです。

今度はこちらを参考に進めてみます。

hugoでシンタックスハイライトに対応する

記事に忠実に今回はCDNを使います。

行数表示をする

highlight.jsから行番号を表示させるライブラリも見つけたのでこちらも入れてみました。

highlight.jsに行番号を追加する方法 - kotonoha

すると...

言語間で表示が安定しない

スクショを撮るのを忘れてしまいましたが、行番号が表示されたりされなかったり、二重で表示されたり、
コードブロックの機能(コピーなど)ボタンも出てこなくなったり、
さらにはダークモードからライトモードへの切り替えもできなくなったり...うまくいきませんでした。

おそらくconfig.tomlファイルの [markup.highlight] の設定がよろしくないのかなと思います。

Configure Markup | Hugo

こちらを見ながら設定項目を翻訳してtrueにしたりfalseにしたり...いろいろいじってみましたが、Hugoに翻弄されている感がありました。

ここまでの挙動を見ていると、
Chromaとhighlight.jsが両方動いてしまっているために、表示がおかしなことになっているのではないかと思いました。

Chromaをオフにする方法はあるのでしょうか。

...これ以上は技術的に突き詰められなさそうなので、Chromaに戻して調整していきます!

☆Chromaでのphpのエラー表示の問題は、WordPressテンプレートみたいなhtmlとphpが混在しているコードではだめ、ということが判りました。

Chromaで再度調整する

ここまで悪戦苦闘して、いろいろと諦めることにしました。

結局スタイルは、ページの色味に合わせてsolarized-dark256にしました。よいです。

デフォルトで行数表示させたい

themesにあるcode.jsをコピペして、編集したcode.jsを読ませるようにしました。 とある関数の判定で false だったところを true にしました。

問題なく動いています。が、ベストな書き方かどうかは分かりません。

折りたたみの表示を変えたい

こちらもcode.jsを書き換えました。
行数表示のように簡単にはいかず、試行錯誤しました。
(コメントもたくさん書き込んで...このままコミットします)

関数名をわかりやすくするのは大事だなと改めて思いました。

その他の修正

このように変えました。

言語表記の色を変えたい(その他コードブロックの表示調整) → _custom.sass
ツールチップを日本語にしたい → code.js
「...」に「もっと見る」を入れる → 変更するのをやめました

結果、満足のいくコードブロックになりました!

長かった...

Hugoで使われているパーサー

せっかくなのでGoldmarkとBlackfridayを調べました。

Goldmark・・・markdown(マークダウン)をHTMLに変換するパーサー
Blackfriday・・・HugoでGoldmarkの前に使われていたパーサー

だそうです。

以前もマークダウンについて調べていたことを思い出して記事を確認したところ、
Blackfridayについて調べていました。すっかり忘れています。

パーサー」について調べたことも以前あったような気がします。
なんとなくの理解でここは良しとします。

さいごに

今回はてなブログでやっとコードブロックを書くときに言語指定をしました。

色が付くと見栄えがいいですね。

また、最近ではHugoで調べ物をすると、記事がたくさん出てくるようになりました。

2年前はもっと少ない印象でした。

とてもありがたいです。

私はいつになったらブログを移行できるのでしょうか。

おしまい。