Blue Leaf

ブログにソースコードを記載するなら「highlight.js」が軽くて簡単

作成日:

今年の3月にブログを始めてから、Wordpressのカスタマイズを通して色々なコトを勉強してきました。学んだことを記事にして残そうと思っているのですが、各種コードを紹介されている方達のブログを見ると表示がオシャレ!シンタックスハイライトで綺麗に色付けされ、行番号が表示されている。

どうやっているのかなと調べると、Wordpressのプラグインで Crayon Syntax HighlighterSyntaxHighlighter Evolved などなど、色々なプラグインがあるらしい。

とりあえず、「Crayon Syntax Highlighter」をインストールしてみると、凄く簡単に綺麗なコードを記載できました。が、色々と調べていくうちに「Crayon Syntax Highlighter」は重いらしいことが判明。

たしかに、「css」や「js」ファイルを色々と読み込んでいる・・・。他に何かいいモノはないかなと調べていくうちに、たどり着いたのが highlight.js

シンタックスハイライトは「highlight.js」が軽くて簡単

この記事を書いている時点でのバージョン:9.0.0

CDN版のほうが簡単

CDNで必要なファイルを読み込むか、自サーバーに置くかを選べます。このブログではCDN版を利用させてもらっています。CDNで読込むには、他のjavascriptやcssファイルと同じように扱えばいいので、Wordpressの header.phpfooter.php に下記のコードを記載。

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

これで準備は完了。

あとはブログの記事を書くときに、表示したいコードを、

<pre><code>...</code></pre>

のタグで記載するだけ。

これだけで綺麗にシンタックスハイライトで表示されます、簡単!

自サーバーに置くときは

自サーバーに「js」と「css」を置くときは、公式サイトの「Get」ボタンを押して進み、「言語」を選ぶかデフォルトのままで必要なファイルをダウンロード。

ダウンロードしたファイルの中で使うのは、「highlight.pack.js」と「css」ファイルだけ。

必要なファイルをサーバーにアップロードして、ファイルを読み込むために、「header.php」か「footer.php」に下記のコードを記載。

<link rel="stylesheet" href="/path/to/styles/default.css">
<script src="/path/to/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

パスはサイトに合わせて書き換えが必要。

軽い

外部から読み込んでくるファイルは、「css」と「highlight.js」の2種類だけなので軽い!

カスタマイズ

言語の指定方法、ハイライトカラーのテーマ選択の方法です。

言語の指定

何もしなくても、自動的に記載しているコードの言語を判別してくれますが、希望通りにいかない時は class="言語名" で明示的に指定。

<pre><code class="PHP">....</code></pre>

<pre><code class="css">....</code></pre>

などなど。

ハイライトカラーのテーマを選択

公式サイトのライブデモで、ハイライトカラーを「言語」と「スタイル」を切り替えながら選ぶことができます。

気に入ったスタイルが見つかったら、CDN版は以下の規則のファイル名で「css」を読み込みます。

小文字にする+半角空白は「-」(ハイフン)にする+拡張子は「.min.css」

このブログで選択したスタイルはSublime Text風の「Monokai Sublime」です。

cssのファイル名は、monokai-sublime.min.css になります。

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/monokai-sublime.min.css">

最終的に、上記のように記載をします。

ポイント

  1. ソースコードを記載するときは、<> などなどの記号を、実体参照というモノに置き換える必要があります。下記のサイトなどで、コードを貼り付けて変換ボタンを押せば瞬時に置き換えをしてくれます。
    文字列 → 数値実体参照変換

  2. highlight.jsは行番号の表示には対応していないようです。

非同期と必要なページでのみ読み込む方法

使用方法は上記までの内容で充分なのですが、このままだと以下の2つの問題があります。

  1. 「jsファイル」と「css」ファイルの読み込みが完了するまで、ページが表示できない。なので、GoogleのPagespeed Insightsで「スクロールせずに見えるコンテンツのレンダリングをブロックしている JavaScript/CSS を排除する」と指摘されます。
  2. Wordpressの「header.php」か「footer.php」に記載をするので、全てのページで「jsファイル」と「css」を読み込むタグが排出されてしまう。

この2つの問題を解決する方法を以下に記載します。

非同期読み込み

上記までの状態だと、「jsファイル」と「css」ファイルの読み込みが完了するまでブラウザがレンダリングを開始できないので、非同期でファイルを読み込ませてあげるように記述をします。分かりやすいように、「css」と「js」を分けて以下で説明します。

「cssファイル」の非同期読み込み

下記のコードを「footer.php」に記載。

<script>
(function(d){
var s = d.getElementsByTagName('script')[0];
var c1 = d.createElement('link');
c1.rel = 'stylesheet';
c1.href = '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/monokai-sublime.min.css';
s.parentNode.insertBefore(c1, s);
})(document);
</script>

htmlの構造が壊れないように、スクリプトで「css」を読み込むようにします。

「javascript」の非同期読み込み

下記のコードも「footer.php」に記載。

<script>
function loadScript(src, callback) {
    var done = false;
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.src = '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js';
    head.appendChild(script);
    // Attach handlers for all browsers
    script.onload = script.onreadystatechange = function() {
        if ( !done && (!this.readyState ||
                this.readyState === "loaded" || this.readyState === "complete") ) {
            done = true;
            callback();
            // Handle memory leak in IE
            script.onload = script.onreadystatechange = null;
            if ( head && script.parentNode ) {
                head.removeChild( script );
            }
        }
    };
}
loadScript("highlight.min.js", function() {
    hljs.initHighlightingOnLoad();
});
</script>

highlight.min.js が読み込まれたのを確認してから、スクリプト hljs.initHighlightingOnLoad() を実行し、ブラウザにレンダリングさせます。

「css」と「js」ファイルを非同期で読み込むことで、PageSpeedInsightsでの「highlight.js」に関する指摘事項がなくなります。

必要なページのみで読み込む

今のままだと全てのページで「highlight.js」を読み込むタグが排出されてしまうので、必要なページでのみ読み込む方法です。

色々な方法が考えられますが、シンプルな方法はWordpressの以下の関数で実現できます。

<?php is_single($post); ?>

$post は「記事のID」になります。

ただ、上記の関数だと1ページのみの指定しかできないので、複数ページを指定するときは、以下の関数を使います。

<?php is_single(array(17,'beef-stew','Irish Stew')); ?>

上記の関数だと、記事IDやスラッグが複数指定できます。

仮に、記事のIDが1008と1010の2つの記事で読み込みをさせたい時は、if文 と関数を組み合わせて、

<?php if ( is_single(array(1008,1010) )) :?>
#highlight.jsに必要な記述
<?php endif; ?>

上記のようになります。

ただ、この関数だと記事を作成するたびに記事IDを追加・編集していく必要があります。私の場合なのですが、「footer.php」を編集するのが面倒になってしまい、

  1. カスタムフィールドで条件を立てて分岐
  2. プラグインのAdvanced Custom Fieldsでチェックボックスを作り分岐

と、徐々に使いやすく改良をしていきました。「Advanced Custom Fields」で条件分岐ができるようにすれば、条件を立てている記事を「記事一覧画面」で確認することも簡単にできるので、すごく便利になるのでオススメです。

オススメなのですが、説明をするのに「カスタムフィールドの知識」や「画像」を使用するのが大変なので、申し訳ないですが省略します。

非同期と必要なページでのみ読み込む方法の最終形

「非同期で読み込む方法」・「必要なページでのみ読み込む方法」を組み合わせた最終的な形は以下のコードになります。

<?php
if ( is_single(array(1008,1010) )) :?>
<script>
(function(d){
var s = d.getElementsByTagName('script')[0];
var c1 = d.createElement('link');
c1.rel = 'stylesheet';
c1.href = '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/monokai-sublime.min.css';
s.parentNode.insertBefore(c1, s);
})(document);
</script>
<script>
function loadScript(src, callback) {
    var done = false;
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.src = '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js';
    head.appendChild(script);
    // Attach handlers for all browsers
    script.onload = script.onreadystatechange = function() {
        if ( !done && (!this.readyState ||
                this.readyState === "loaded" || this.readyState === "complete") ) {
            done = true;
            callback();
            // Handle memory leak in IE
            script.onload = script.onreadystatechange = null;
            if ( head && script.parentNode ) {
                head.removeChild( script );
            }
        }
    };
}
loadScript("highlight.min.js", function() {
    hljs.initHighlightingOnLoad();
});
</script>
<?php endif; ?>

意外とシンプルに記述ができます。このコードを、footer.php などに記述をします。

まとめ

軽くて使い方もシンプルなので気に入りました。綺麗なテーマが色々あって悩ましいですけど、なんだか楽しいです!