• jekyll 3.7.4
  • highlight.js v9.13.1

GitHub PagesとJekyllを使っているという前提ですが、QiitaのようにMarkdownのコードブロックでファイル名を表示できるようにします。

file name to code block

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>

これで一応コードブロックにファイル名を表示することができました。

file name to code block but no syntax

しかしシンタックスハイライトが効いていません。

何故なら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の中ではまだhljsclassは追加されていなくて、その挙動に依存しているからです。