hugoのsyntax highlightを簡易カスタマイズ

この記事の最終更新日は1年以上前です。
記事の内容が古い場合がありますのでご容赦ください。

hugoで生成したブログサイトにPrismJSを組み込みます。 このブログを即席で立ち上げて最初の投稿から一週間経ってしまいました。
hugoやgo言語について分からないことだらけで試行錯誤しながらサイト構築しています。

ちょうどやっていることが覚書になるので記事にします。

目次 - CLICKで開閉します -

この記事の概要

このブログの仕組みや運用方針については別の機会に書かせていただくとして。
この記事では、「ブログとして一通り機能する状態から、記事を書くためにPrismJSの設定を自分仕様に設定した」事を覚書として記していきます。

前提として、これからやることはhugoで生成したブログサイトのカスタマイズになります.
このブログでは小さなソースコードを多く書いていく予定なので、先ずはシンタックスハイライト機能がまともに機能するようにします.

PrismJSを設定する

PrismJS公式サイトのDownloadページからCSSとJSファイルを生成して、static/css,static/js配下に配置します。 PluginsにLine Numbersのチェックを入れるのを忘れないようにしておきます。

config.tomlにCSSとJSを追加読み込みする設定をしておきます。

config.toml
[params]
  # Custom CSS and JS. Relative to /static/css and /static/js respectively.
  customCSS = ["prism.css", "custom_01.css", "hugo_code_copy.css"]
  customJS = ["prism.js", "hugo_code_copy.js"]
「Chunky Poster」テーマの場合はこのように書けば追加で読込ができます. CSSとJSの追加読み込み機能はテーマによっては用意されていないので、その場合はテンプレートを編集して個別に読み込ませる仕組みが必要です.

標準のsyntax highlightとPrismJSを無効化する

テーマやhugoのバージョンによってPrismJSの設定方法は変わりますが、私の場合は以下のように設定しています。 これをやっておかないと、シンタックスハイライトのライブラリが多重ロードされ、生成されるHTMLコードもやたら入れ子になってしまいます。

hugo標準のシンタックスハイライト機能が効いているとcode部分までのパスが複雑になるので、後々バグらないように不要な処理はここで落としておきます.
config.toml
[params.prismJS]
  enable = false

[markup.highlight]
# 特に何も設定しない

prismJSで行番号を表示する

hugoテーマのprismJSを読み込む機能は無効化してあるので、行番号や開始行の指定、行ハイライトの指定を自前でやる必要があります。 ショートコードやテンプレートで対応しようと思うのですが、先ずはサクッと動かすためにズルをします。

prism.jsのsetLanguage関数内に、行番号表示のための初期化コードを差し込みます.
prism.js setLanguage()
setLanguage: function (element, language) {
  element.className = element.className.replace(RegExp(lang, 'gi'), '');
  element.classList.add('language-' + language);
  element.classList.add('line-numbers');// この行を追加すると行番号を表示
},
言語設定を行う関数の中でついでに行番号の表示設定をしましたが、本来は関数を分けるべきです.
ちゃんとやったバージョンは別途記事を書こうと思います.

PrismJSの行番号とソースコード表示のレイアウトを調整する

行番号表示部分とコード表示部分はデフォルトでは別々のスタイルが適用されます。 その場合、フォントサイズやマージン、パディングが同じになっていないと行番号とコードの位置がずれてしまいます。

行番号とソースコード表示の位置ずれを解消するために、共通のスタイルを用意します.
custom_01.css
code[class*=language-],
pre[class*=language-],
.line-numbers-rows {
  padding-top: 24px;
  font-family: "Source Code Pro", "Roboto Mono", monospace;
  font-size: 16px;
}

ファイル名(キャプション)を差し込む

記事内でソースコードを書く際、markdown形式に沿ってトリプルバッククオートで括っています。

triple backquote sample
```js {fn="ここに表示したいキャプションを指定する"}
function hoge(){
}
```

hugoでは{}内に設定したAttributesと言われるパラメータがHTMLのタグに設定されます。
これをJavaScriptで取得して上部に文字列として表示させます。

Attributesのfnパラメータを取得し、キャプション表示用のdivを生成してHTMLに埋め込みます.
prism_codename.js
(() => {
  'use strict';
  document.querySelectorAll('div.highlight').forEach(elem => {
    let fn = elem.getAttribute('fn');
    if (fn == null) { fn = "Code"; }
    let codeButton = elem.firstElementChild; // 環境によってこのパスは変わります。
    let div = document.createElement('div');
    div.textContent = fn;
    div.classList.add('code-name');
    codeButton.parentNode.insertBefore(div, codeButton);
  });
})();
スタイルはキャプション表示領域となる.code-nameを定義します.
custom_01.css
.code-name {
  position: absolute;
  z-index: 2;
  left: 48px;
  top: 0;
  line-height: 11px;
  color: cornsilk;
  background-color: #333;
  font-family: "JetBrains Mono";
  font-size: 13px;
  font-weight: 400;
  border: 1.25px solid #232326;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-bottom-right-radius: 4px;
  border-bottom-left-radius: 0;
  white-space: nowrap;
  padding: 4px 4px 6px 4px;
  margin: 0 0 0 0;
}

おまけ CSSファイルのURLにMD5クエリを付けて古いファイルがキャッシュされるのを防ぐ

.Site.Params.customCSSはテーマに用意されていたconfig.tomlの設定です。
ヘッダー部分のテンプレートでCSSの読込を変更して古いスタイルシートをキャッシュさせないようにしました。

layouts/partials/head.html
{{- range $num,$style := .Site.Params.customCSS -}}
  {{- $css := printf "%s%s" ("css/" | relURL) $style -}}
  {{- $src := printf "static/%s" $css -}}
  {{- $hash := readFile $src | md5 -}}
  <link rel="stylesheet" href="{{ printf "%s?%s" $css $hash }}">
{{ end -}}
テンプレート書き換え後のHTML出力
<link rel="stylesheet" href="/css/custom_01.css?d8702664ba27a6007b10cd7050427fd4">

まとめ

現時点ではまだ完全ではないので、別途改良後の記事を書こうと思います。
今後はソースコード毎に行をハイライトさせたり、行番号表示の有無や開始行の指定が可能なようにする予定です。

以上、PrismJSを使ってこのブログでソースコードを書くためのsyntax highlightの設定を行いました。



関連記事