2021-03-15

Prism.js の prism-php を利用した際に出るエラー `TypeError: Cannot read property 'tokenizePlaceholders' of undefined.` の解消方法

TL;DR

当ブログのシンタックスハイライトでもお世話になっている Prism.js で、PHP のシンタックスハイライトを利用しようとしたところエラーが発生したので対処方法をメモ。

prism-php を読み込む前に prism-markup-templating を読み込むと解消します。

バージョン

Prism.js ^1.23.0

エラー詳細

prism-php を読み込んでシンタックスハイライト適用時、下記のエラーが発生する。(PHP 以外の言語は正常に動作する)

import Prism from 'prismjs';
import 'prismjs/components/prism-php';

const code = `echo "hello, world";`
const html = Prism.highlight(code, Prism.languages.php, 'php');

// TypeError: Cannot read property 'tokenizePlaceholders' of undefined
// あるいは
// TypeError: Cannot read property 'buildPlaceholders' of undefined

解決方法

prism-php を読み込む前に prism-markup-templating を読み込むようにすると、正常に動作します。

import Prism from 'prismjs';
import 'prismjs/components/prism-markup-templating';
import 'prismjs/components/prism-php';

原因は prism-php.js:L301-L312 の下記箇所です。しっかり他モジュールに依存していますね。

prism-php.js

(function (Prism) {

    // 省略

    Prism.hooks.add('before-tokenize', function(env) {
        if (!/<\?/.test(env.code)) {
            return;
        }

        var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/ig;
        Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
    });

    Prism.hooks.add('after-tokenize', function(env) {
        Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php');
    });

}(Prism));

以上です

参考

https://github.com/PrismJS/prism/issues/1400