Hugo Academic でダーク・ライト両モードに対応した Chroma によるシンタックスハイライト
前提
Academic テーマ のデフォルト設定は ドキュメントにもある通り highlight.js を使ったもので、 この仕組みに乗っておけば基本的には問題ありません。
ただし highlight.js には一つ問題があって… EmacsLisp に対応していません (Lisp には対応)。
具体的には with-eval-after-load
のような独自のマクロや、
DocString 中のクオテーションといった EmacsLisp 方言には対応出来ません。
一方、 Hugo 標準の Syntax Highlighting は Chroma を使ったもので、 こちらは EmacsLisp に対応しています 。
(ox-hugo の作者さんが過去に Issue に挙げてくれていた 模様…感謝 🙏)
CodePen と Chroma Playground とでそれぞれの出力結果を比べてみるとよく分かります:
(defvar hoge "fuga"
"Doc String 中の `QUOTE' はどうなるかな?")
(with-eval-after-load 'foo
(unless (eq t nil) "EmacsLisp 独自キーワードはどうなるかな?")
そこで、 Academic を使いつつ、 Hugo 標準のハイライトの仕組みを使いたい というのが動機となります。
Academic 標準のコードハイライトを無効にする
ドキュメント に書かれている通り、 config.toml
で params.highlight
オプションを無効にする必要があります。
Academic Kickstart をベースにしている場合、 params.toml
で以下のように設定します:
# Enable source code highlighting? true/false
# Documentation: https://sourcethemes.com/academic/docs/writing-markdown-latex/#highlighting-options
highlight = false
Hugo のコードハイライトを有効にする
Academic Kickstart をベースにしている場合、 config.toml
で以下のように
Hugo のコードハイライトが無効にされていると思います:
[markup.highlight]
codeFences = false # Disable Hugo's code highlighter as it conflicts with Academic's highligher.
これを以下のように変更します:
[markup.highlight]
codeFences = true
noClasses = false
noClasses = false
としているのは、 ダーク・ライトの両方のモードに対応させるため です。
noClasses
が true
の場合、スタイル指定が HTML 中に埋め込まれます。
これだとモードの変更に追従して動的にスタイルを変更するということが出来ないため、
CSS クラスだけを HTML に埋め込んでもらうようにします。
ダークモード用とライトモード用の Chroma スタイルを決める
Chroma Style Gallery ギャラリーを参考に、 ダークモード時に使うスタイルとライトモード時に使うスタイルをそれぞれ決めます 。 モードの切り替わりに応じて、シンタックスハイライトのスタイル自体を変更してしまいます。
選定の際の注意事項として、 スタイルによって細かいクラス指定に対応していない場合があります 。
具体的には、 EmacsLisp の defvar
などは NameBuiltin
としてパースされ、
.nb
というクラスが指定されるのですが、これが含まれていないスタイルがいくつかあります。
参考までに、調査した結果を以下に列挙します:
light スタイル
NameBuiltin
が含まれるもの
- abap
- algol
- algol_nu
- arduino
- autumn
- colorful
- emacs
- friendly
- github
- lovelace
- manni
- murphy
- pastie
- perldoc
- pygments
- dash
- light
- tango
- trac
- vim
- xcode
NameBuiltin
が含まれないもの
dark スタイル
NameBuiltin
が含まれるもの
NameBuiltin
が含まれないもの
Chroma 用の CSS を生成する
スタイルを決めたら以下のように CSS を生成します。
生成された CSS は標準出力に吐き出されるため、適当なファイルにリダイレクトするか、 pbcopy
等にパイプしてクリップボードに格納しましょう:
hugo gen chromastyles --style=pygments
hugo gen chromastyles --style=native
この後多少手を加える必要があるので、やりやすいように CSS 2 SASS/SCSS CONVERTER 等で SCSS に変換しておくとよいです。
Academic のテーマと競合しないようにする
生成した CSS(SCSS) は Academic のドキュメント に従い custom.css
に追加します。
ただし、Academic には標準のハイライトのためのスタイル指定があるため、 Chroma が生成したスタイル指定をそのまま組込むと若干コンフリクトします。
そこで、多少手を加えてやります。
まずライトモード時のスタイルについては、
background-color
や color
が指定されていない場合があるため( pygments
等)、
Chroma Playground の出力結果を参考にしてスタイル指定を追加します。
また、 Academic 組込みの code
へのスタイル指定より優先度が高くなるように、
セレクタを pre.chroma, .chroma code
とします。
最終的に以下のようになります:
pre.chroma, .chroma code {
background-color: #f5f5f5;
color: #4a4a4a;
次にダークモード時のスタイルについては、
基本的に background-color
や color
も指定されていると思うので、
セレクタのみ .dark pre.chroma, .dark .chroma code
としてあげます。
以上で、 Hugo Academic を使いつつ、 Chroma でシンタックスハイライト が実現出来ました。