wordpress

WordPressでJavascriptではなくPHPを使ってシンタックスハイライトを行う手順


Photo by Chris Ried on Unsplash

はじめに

シンタックスハイライトを行うライブラリとしてJavascriptのhighlight.jsが有名ですが、JavascriptではなくPHP版のhighlight.phpというものがあります。JavascriptではなくPHPだと何が嬉しいかと言うと、AMPではJavascriptが基本的に動作できないため、highlight.jsを使用することができません。そこでPHP版のhighlight.phpを使用すれば、サーバーサイドでのハイライターとして動作します。つまりJavascriptを使わない、すなわちAMP対応のページでも問題なく動作します。AMP対応のWebサイトでない場合でも、読み込むJavascriptを減らせるので表示速度の高速化が期待できます。
この記事では、WordPressでhighlight.phpを使用する手順をまとめます。

前提と環境

以下の通りです。

  • PHPはインストール済とする。バージョン情報は後述
  • WordPressで使用しているテーマのディレクトリにComposerがインストール済とする
  • 確認したOS : Ubuntu18.04、Cloud Linux

PHPのバージョン情報は以下です。

$ php -v
PHP 7.3.3 (cli) (built: Mar  7 2019 10:02:44) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.3, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.3, Copyright (c) 1999-2018, by Zend Technologies

なお、PHPのパッケージ管理システムであるComposerを以降の手順で使用します。もしまだComposerをインストールしていない場合は、はじめにComposerをインストールする必要があります。以下にComposerのインストール手順をまとめていますので、必要な方は見てみてください。レンタルサーバのような共有環境でもインストール可能です。

LinuxにComposerをインストールする手順

PHPのパッケージ管理システムであるComposerをUbuntu、Cloud Linuxの両方に入れる機会があったのでその手順をメモします。UbuntuとCloud Linuxで手順は同じです。また、グローバル、ローカルそれぞれにインストール手順もまとめます。

Composerを使ってhighlight.phpをインストールする

ここでは、WordPressにて実際に使用しているテーマファイルのディレクトリにComposerを使ってhighlight.phpをインストールします。Composerはグローバル環境、ローカル環境のどちらにインストールされていても問題ありません。ここでは、WordPressのテーマファイルのディレクトリをmythemeとし、mytheme/binにComposerがインストールされている前提で進めます。
Composerがインストールされていればhighlight.phpのインストールは簡単で、以下のコマンドを実行するだけです。

/wp-content/themes/mytheme$ bin/composer require scrivo/highlight.php
Using version v9.15.6.1 for scrivo/highlight.php
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing scrivo/highlight.php (v9.15.6.1): Downloading (100%)         
Writing lock file
Generating autoload files

以上でhighlight.phpのインストールは完了です。自身のテーマファイルのディレクトリにvendorというディレクトリが作成され、そこの中にhighlight.phpがインストールされています。続いて実際にWordPressでhighlight.phpを使うための手順を説明します。

function.phpに追記する

highlight.phpをWordPressのテーマファイル内で使用するために、function.phpにいくつか追記します。
まず、Composerでインストールしたhighlight.phpを読み込むために、以下をfunction.phpに追記します。

/wp-content/themes/mytheme/function.php<?php
require_once __DIR__ . '/vendor/autoload.php';
use Highlight\Highlighter;
(...以下省略...)

また、WordPressの記事本文の中から、コード部分に相当する部分(例えば、<pre><code> ~ </code></pre>など)を探してシンタックスハイライトを適用するために以下の関数をfunction.phpに追加します。追加箇所はfunction.phpの一番最後で大丈夫です。

/wp-content/themes/mytheme/function.php<?php
require_once __DIR__ . '/vendor/autoload.php';
use Highlight\Highlighter;

(...途中省略...)

function applySyntaxHighlighting($content) {
  // 以下の正規表現で、記事本文の中から<pre><code> ~ </code></pre>等を探し出す。
  $pattern = '~<pre><code[^>]*>\K.*(?=</code></pre>)~Uis';

  return preg_replace_callback($pattern, function ($match) {
    $highlighter = new Highlighter();

    // 以下でシンタックスハイライトを行いたい言語を追加しておきます。 
    // 以下の中からhighlight.phpが自動でハイライトルールを選択します。
    $highlighter->setAutodetectLanguages([
      'html', 
      'php', 
      'css', 
      'javascript', 
      'shell',
      'ruby',
      'java'
    ]);
    $input = htmlspecialchars_decode($match[0]);

    return $highlighter->highlightAuto($input)->value;
  }, $content);
}

// WordPressのthe_content関数のフィルターとして使用する
add_filter('the_content', 'applySyntaxHighlighting', 10);

上記のapplySyntaxHighlightingという関数は自分で定義した関数であり、WordPress記事本文の中に含まれるコード部分を検索し、ハイライト処理を行ないます。
重要なのは以下3点です。それぞれについて後述します。

  • $patternに記事本文のコード部分の検索を行うための正規表現を指定します。
  • setAutodetectLanguagesに渡す引数にハイライトしたい言語を指定します。
  • add_filterでWordPressのthe_content関数のフィルターとして登録します。

正規表現を使ってコード部分を検索する

以下の正規表現によって、<pre><code> ~ </code></pre>を検索することができます。

/wp-content/themes/mytheme/function.php// <pre><code> ~ </code></pre> を検索する
  $pattern = '~<pre><code[^>]*>\K.*(?=</code></pre>)~Uis';

また、もし<pre><code> ~ </code></pre>ではなく、例えば何かしらCSSのクラスを使用しているような場合は、検索がマッチするよう正規表現をそれぞれの状況に合わせて調整する必要があります。例えばこのサイトでは、<pre><span class="code-title">~</span><code> ~ </code></pre>というように、<pre><code>の間に<span>が入っている場合と入っていない場合の両方があります。よって、これを検索するには正規表現を以下のようにします。

/wp-content/themes/mytheme/function.php// <pre><span class="code-title">~</span><code> ~ </code></pre> のようなパターンを検索したい場合は以下
  $pattern = '~<pre>(<span class="code-title">.*</span>)?<code[^>]*>\K.*(?=</code></pre>)~Uis';

ここの正規表現で正しく自身のコード相当部分を検索できないとハイライトできません。

setAutodetectLanguagesにハイライトしたい言語を指定する

以下のように、ハイライトしたい言語を事前に指定しておく必要があります。

/wp-content/themes/mytheme/function.php$highlighter->setAutodetectLanguages([
      'html', 
      'php', 
      'css', 
      'javascript', 
      'shell',
      'ruby',
      'java'
    ]);

highlight.phpでは、highlight.jsと同様に現在185言語に対応しています。対応言語は以下から確認できますので、自身の記事の中で使うであろう言語を指定しておきます。

add_filterを使ってフィルターとして登録する

WordPressでは、the_contentという関数によって記事本文を出力することができます。そしてこの出力前後で記事本文に対して何かしらの修正を加える方法としてadd_filterが用意されています。なお、the_content関数は通常だと記事の出力に使われており、当然ながらthe_content関数に対するフィルターは全ての記事に影響します。したがって、事前に思っている動作をするかをテスト環境などで確認することをおすすめします。
ここではadd_filterの詳細は省略しますが、以下の記事が大変参考になりました。

WordPress the_content で本文が展開される前または後にフィルターをかけるには – Qiita

記事本文を加工・解析したい場合は `the_content` に対してフィルターをかけます。

以上でfunction.phpへの追記は完了です。
なお、上記の関数については以下の記事を参考にさせて頂きました。ありがとうございました。

stefanzweifel.io

Syntax Highlighting doesn’t always have to be run on the client side.

ハイライト用のCSSを追加する

最後に、ハイライト用に使用するCSSスタイルを自身のWordPressテーマに追加します。highlight.phpではhighlight.jsと同じスタイルが使用でき、以下のサイトから好きなものを選択します。以下ページを開いて左側のメニューの「Styles」から好きなものをクリックしてどのような見た目になるかを確認できます。

このサイトではTomorrow Night Eightiesを使用しています。使用したいスタイルが決まったら、今度は以下のページに全てのスタイルのCSSファイルが置いてあるので決めたスタイルファイルを開きます。

例えばTomorrow Night Eightiesならばtomorrow-night-eighties.cssを開きます。以下のような中身になっているのでこれを全てコピーします。

tomorrow-night-eighties.css/* Tomorrow Night Eighties Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */

/* Tomorrow Comment */
.hljs-comment,
.hljs-quote {
  color: #999999;
}

(...途中省略...)

.hljs-strong {
  font-weight: bold;
}

あとは上記CSSを自身のテーマファイルのCSSに追記すれば完了です。もちろん、highlight用のCSSファイルをダウンロードしてインポートしてもOKです。
ちなみに、このスタイルが反映されるには、<pre><code class="hljs"> ~ </code></pre>のようにhljsクラスが指定された<code>タグが必要です。
もしこれまでに公開済の自分の記事内のコード部分で<code>タグでhljsが指定されていない場合は、指定しない限りハイライトは有効になりません。記事が少ない場合は手作業でも良いですが、記事が多い場合は、WordPressのMySQLデータベースをエクスポートして一括置換してしまうのが一番はやいです。

まとめ

AMP対応にあったってシンタックスハイライトをJavascriptを使わずに実現する方法が意外にネット上にも情報が少なかったのでメモとして残しておきます。

SPONSORED LINK

2 thoughts on “WordPressでJavascriptではなくPHPを使ってシンタックスハイライトを行う手順

  1. Hi! Many thanks for the article, everything turned out to be done! You manual only network on this topic, is no longer found. Please tell me how to make syntax highlighting work in the comments?

  2. It work:

    require_once __DIR__ . '/vendor/autoload.php';
    use Highlight\Highlighter;

    function applySyntaxHighlighting($comment) {

    $pattern = '~<pre[^>]*><code[^>]*>\K.*(?=</code></pre>)~Uis';

    return preg_replace_callback($pattern, function ($match) {
    $highlighter = new Highlighter();

    $highlighter->setAutodetectLanguages([
    'html',
    'php',
    'css',
    'javascript'
    ]);
    $input = htmlspecialchars_decode($match[0]);

    return $highlighter->highlightAuto($input)->value;
    }, $comment);
    }
    add_filter('comment_text', 'applySyntaxHighlighting', 10);

    But can it be combined into one function? Help please 😉

コメントを残す

メールアドレスが公開されることはありません。