GitHub Pagesでコードブロックにファイル名を表示する
- jekyll 3.7.4
- highlight.js v9.13.1
GitHub PagesとJekyllを使っているという前提ですが、QiitaのようにMarkdownのコードブロックでファイル名を表示できるようにします。
JavaScriptとCSSでファイル名を表示
JavaScript
以下のようにmyscript.js
というファイルを作成してみましょう。ここではassets/js
フォルダに置いています。
document.addEventListener('DOMContentLoaded', () => {
const code = document.getElementsByTagName('code');
Array.from(code).forEach(el => {
if (el.className) {
const s = el.className.split(':');
const highlightLang = s[0];
const filename = s[1];
if (filename) {
el.classList.remove(el.className);
el.classList.add(highlightLang);
el.parentElement.setAttribute('data-lang', filename);
el.parentElement.classList.add('code-block-header');
}
}
});
});
簡単に説明すると
DOMContentLoaded
をしてHTMLの読み込みが完了したら、<code>
タグを持つ要素を取得します。結果はHTMLCollection
として返ります。-
そのHTMLCollectionを
forEach
で回して、それぞれの要素がclass名を持っていればそのclass名を:
文字で分割します。 -
もし
:
文字がない場合は分割できないのでhighlightLang
にはそのままclass名が入り、filename
はundefinedになります。 -
if (filename)
の中では一旦もとのclass名を削除して:hoge.rb
を除いたclass名を再度追加しています。 - それから
<code>
タグの親要素である<pre>
タグにdata-lang="hoge.rb"
とcode-block-header
というclassを追加します。class名は任意です。
CSS
.code-block-header
の中身は以下のようにします。適当なsassファイルに追加して下さい。
.code-block-header {
position: relative;
padding-top: 32px;
&::before {
content: attr(data-lang);
background: darken(#f6f8fa, 8%);
color: darken(#f6f8fa, 50%);
display: block;
font-size: 13px;
font-weight: 700;
padding: 1px 10px;
position: absolute;
top: 0;
left: 0;
z-index: 10;
}
}
data-
属性とCSSの::before
を使っています。
JavaScriptを読み込む
最後に作成したmyscript.js
を読み込みましょう。
HTMLの<head>
タグの中に追加します。
<script src="/assets/js/myscript.js"></script>
これで一応コードブロックにファイル名を表示することができました。
しかしシンタックスハイライトが効いていません。
何故ならGitHub Pagesがデフォルトで使うRougeは、例えばruby:hoge.rb
ならlanguage-ruby:hoge.rb
というclass名を使うことになるからです。
Rougeの代わりにhighlight.jsを使う
DOMが構築された後にJavaScriptでいろいろな操作をしているので、RougeよりもJavaScriptのライブラリのほうが都合が良いです。ここではhighlight.jsを使います。
Rougeを無効にする
詳しくはこちらを参照してください。
markdown: kramdown
kramdown:
syntax_highlighter_opts:
disable: true
highlight.jsをダウンロード
公式サイトからhighlight.pack.js
と好きなテーマのCSSファイルをダウンロードして読み込みます。ここではgithub-gist
というテーマを選びました。
<link rel="stylesheet" href="/assets/css/github-gist.css">
<script src="/assets/js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
<pre>
タグと<code>
タグのbackground-colorが違う場合は修正しましょう。
以上で完了です。
補足
myscript.js
のコードは改良の余地があります。というのも生成されたHTMLを見てみると<code>
タグには言語毎のclassの他にhljs
というclassが追加されています。classが2つ以上あると上記のコードではたぶんうまく動かないと思います。
なぜちゃんと動いているかというと、DOMContentLoaded
の中ではまだhljs
classは追加されていなくて、その挙動に依存しているからです。