ブログを書いていると、よくソースコードを貼る時にタイトルを挿入したい事がよくあります。
ただこのブログはHugoを使ってMarkdownで書いているので、コードのタイトルを良い感じのレイアウトで挿入するのは少し難しいです。
そこで、Qiitaにあるようなコードのタイトルをコードブロック内に埋め込むレイアウトをJava ScriptとCSSを用いて実現してみたいと思います。
作るのはこういう感じのやつ
HugoでSyntax Highlightを有効にする
まずは、HugoでSyntax Highlightを有効化します。
公式Documentはこちら
Config.tomlを編集
基本的にはconfigを変更するだけです。
↓ 既にタイトルを表示している(完成イメージ)
pygmentsUseClasses = true
pygmentsCodefences = true
- pygmentsUseClasses
pygmentsUseClasses=true
でSyntax Highlightを有効にします
- pygmentsCodefences
Hugoには
{{< highlight go >}}
hoge := 1
{{< highlight >}}
のような言語を指定したSyntax Highlight用のShortcodeが用意されているのですが、 普段Markdownを書いている人はコードブロックを以下のようなバッククォート3つで囲むのが普通だと思います。
```go
hoge := 1
```
その場合にpygmentsCodefences=true
にしてバッククォートでのSyntax Highlightを有効化します。
Themeを適用
config.tomlでSyntax Highlightを有効化したら、次にThemeを適用します。
Theme一覧がこちら
にあるので、好みのThemeを決めたら以下のコマンドを入力します。
保存先はどこでも良いのですが、慣例的にCSSファイルはstatic/css
以下に配置するのが良いでしょう。
hugo gen chromastyles --style [theme name] > static/css/syntax-highlight.css
CSSが作成されたら、CSSを読み込みましょう。Themeによってはconfig.tomlに追記すればCSSを読み込んでくれるものもあります。
コードブロックにタイトルを付ける
Syntax Highlightを有効化したら、コードブロックにタイトルを付けていきます。
タグ構造
Qiitaでは以下のように、言語指定の後ろをコロンで区切ってコードブロックにタイトルを付けます。 この仕様はQiita独自仕様なのですが、慣れているので同じ仕様にしたいと思います。
```go:hoge.go
hoge := 1
```
上記のコードブロックのHTMLタグ構造を調べます。
<div class="highlight">
<pre class="chroma">
<code class="language-go:hoge.go" data-lang="go:hoge.go">
...
</code>
</pre>
</div>
Hugoで作成したページのHTMLを見てみると、コードブロックはhighlight
クラスのdiv
タグで囲まれていて、その下にchroma
クラスのpre
タグがあることがわかります。この2つのタグに関してはHugoで作成したコードブロックでは固定の値が入ります。
preタグ直下のcode
タグのクラス名にコロン区切りでタイトルが付与されているのがわかります。
今回は、このタグを利用してHTMLタグをJavaScriptでパースしていきます。
JavaScript
完成したコードは以下のようになりました。(jsは全然書かないので合ってるかわからない)
var list = document.body.getElementsByClassName("highlight");
for(i=0; i <= list.length-1; i++){
var code = list[i].firstElementChild.firstElementChild
var codeName = code ? code.className.split(":")[1] : null;
if(codeName) {
var div = document.createElement('div');
div.textContent = codeName;
div.classList.add('code-name');
code.parentNode.insertBefore(div, code);
}
}
簡単に説明をすると、highlight
のクラス名を持つタグのリスト一覧から、子要素のクラス名をコロンでパースして、code-name
をクラス名に持つdiv
タグをpre
タグの前に挿入します。
上記のJavaScriptで変更したHTMLのタグ構造はこのようになります。
<div class="highlight">
<div class="code-name">hoge.go</div>
<pre class="chroma">
<code class="language-go:hoge.go" data-lang="go:hoge.go">
...
</code>
</pre>
</div>
このjsファイルの読み込みはHTMLの下の方で行いましょう。
完成したファイルはCSSと同様static/js
配下に配置しています。
<script src="/js/code-title.js"></script>
CSSを追加
HTML自体を変更する事が出来れば、あとはCSSで調整するだけです。
pre.chroma code {
margin-top: -28px;
padding-top: 40px;
padding-bottom: 12px;
}
.code-name {
display: inline-block;
position: relative;
padding: 4px 8px;
background-color: #E7E9EB;
color: #485A60;
font-size: 13px;
font-weight: 400;
}
pre
タグにマイナスmarginとpaddingを入れて、タイトルが入ったdiv
タグがコードブロック内に重なるようにしています。あとは好みの色を付ければ完成です。
まとめ
以上の設定でコードブロックが、このようになりました。
(将来テーマを変えた時の為、画像にしてます)
Qiitaのような、コードブロックのタイトル表示に成功しました。ブログをHugoに移してから不便に思っていたことの1つなので解消出来て良かったです。参考になれば。