Godios.のpjax有効時にPrism.jsを正しく動作させる

当サイトでも使用しているWordPressテーマ「Godios.」はpjaxを有効にするGodモードという機能があります。Prism.jsは軽量なシンタックスハイライターですが、pjaxを有効にした状態ではうまく動作しないことがあるのでひと手間が必要です。

症状

pjaxは遷移先のコンテンツ部分のみを読み込むことで高速化をしているので、外部JavaScriptの実行は基本的に一度きりです。Prism.jsの場合、prism.jsprism.cssの2つの外部ファイルを使いますが、pjax遷移先ではCSSが一部のみ適用された形になってしまいます。

背景色のCSSが当たっていない

遷移先でリロードをすると正しい表示になります。このような挙動はpjaxで必要なJavaScriptが実行されていないことがほとんどです。

なぜ起こるか

Prism.jsはハイライトしたいコードの<code>language-言語名というclassを指定します。

<pre>
<code class="language-javascript">
console.log('Prism.js');
</code>
</pre>

Prism.js実行時には<code class="language-言語名">の親の<pre>に同じクラスを動的に書き加えます。

<!-- prism.jsが実行されるとpreタグにlanguage-javascriptクラスが追加される -->
<pre class="language-javascript">
<code class="language-javascript">
console.log('Prism.js');
</code>
</pre>

したがって、遷移先でPrism.jsが実行されない場合はこの書き換えが発生しないため、一部CSSが適用されず表示が崩れます。

highlightAll()メソッド

pjaxで遷移ごとに動作させたいJavaScriptは<head>で読み込まずにインラインで展開するというのが対策として考えられますが、今回はメソッドをもう一度読んであげれば解決できそうです。

こちらの記事によるとhighlightAll()メソッドを遷移先でもう一度読んであげればエレメントの書き換えができるようです。(参考: Prism.jsのAPI documentation)

実際に遷移後に表示が崩れている状態でDevelopper ToolsのコンソールでPrism.highlightAll();を実行してあげると瞬時に正しい表示に戻ることがわかります。

Godios.のテーマには遷移先での関数の再実行やJavaScriptの再読込を行うgodDispatcher関数というのが用意されているので、これに書き加えればOKです。子テーマの/js/god-dispatcher.jsを編集します。


// /js/god-dispatcher.js
const godDispatcher = function(newPageHTML, newPageHead, newPageBody) {
  // 中略
  Prism.highlightAll();
}

これで遷移先でも正しく表示されるはずです。(この記事はQiitaにも投稿しています。)