WordPressで主にプログラミング系の記事を書くので重宝してる「WP Githuber MD」というプラグイン。
Qiitaみたくマークダウンで書けて快適だけど肝心のハイライターがまともに機能してなくて、その対策メモです。
その前に、
えーと、ある程度WordPressがいじれる人専用です
なんかあった場合自分で対応できる人向けです!
必ず自己責任でお願いします。
症状その1、マークダウンでhtmlやjsが表示されない。
まずこのプラグインを単にインストールしただけではハイライターは機能しません。
インストールした状態で記事を更新して初めて機能します。
このプラグインはハイライトの実現のため、JavaScriptで書かれたライブラリの「Prism.js」と「highlighter.js」のどちらかを選択出来ます。
今回はPrism.jsを使うことを前提にして進めていきます。
ソースコードを書いて更新、ところがPrism.jsで使えるはずの言語のハイライトが出来なかったり、言語の種類によって行番号が表示されなかったりしました。
そこでソースコードを覗いてみたところとりあえずの解決策が分かったのでメモしておきます。
まず次のようなマークダウンを書きます。
投稿してページを確認すると
ハイライトされてます。
ところが・・・。
今回の例では
ハイライトされていません。
このプラグインでは「javascript, php, css」などは認識してくれますが、「js, html, xml」などは認識してくれません。
JavascriptはOKで、jsはNGです。
もし記事中に認識された言語が一つでも存在していればハイライトは成功します。
Prism.jsでは「js, html, xml」が認識されますが、このプラグインで認識してくれないのでこの問題が起こるようです。
このプラグインのハイライトの大まかな機能は記事の更新時と表示時に分けられています。
更新時にマークダウンで書かれた記事を解析して、ソースコードに使用されている言語を取得して内容をデータベースに保存しています。
そして表示時に取得された言語があればJavaScriptファイル(Prism.js一式)を読み込みます。
ところがこの解析時にhtmlやjsを認識してくれません。
よって、記事内にソースコード無い場合(認識されない場合を含む)にはPrism.js一式は読み込まれません。
この仕様はソースコードが書かれてない場合は無駄なJavaScript(Prism.js一式)を読み込まず負担を軽減出来る半面、認識されずに読み込めないから困る現象です。
ソースコードレベルの話になりますが、
記事の更新時に呼び出されるwp_insert_post_data
フィルターにGithuber\Controller#detect_code_languages()
が登録されています(Markdown.php参照)。
このフィルタではマークダウンがHTMLに変換された状態のデータを取得できます。
データベースに保存された記事の内容が以下のものになります。
このライブラリは記事を作成時にその内容を解析します。
codeタグのclassに「language-html, language-xml, language-js」が見えます。
ここから、「html, xml, js」を抽出して、自身が持つ言語マップ(Githuber\Module::$prism_codes
)等(もう一つ存在)に存在していればメタデータ(wp_metadata
)に保存されます。
mysql> select * from wp_postmeta where post_id = 147;
mysql> select * from wp_postmeta where post_id = 147;
+---------+---------+-------------------------+--------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+-------------------------+--------------+
| 490 | 147 | _is_githuber_markdown | 1 |
| 496 | 147 | _is_githuber_mermaid | |
| 497 | 147 | _is_githuber_katex | |
| 498 | 147 | _is_githuber_mathjax | |
| 756 | 147 | _githuber_prismjs | |
| 757 | 147 | _githuber_highlightjs | |
| 758 | 147 | _is_githuber_sequence | |
| 759 | 147 | _is_githuber_flow_chart | |
+---------+---------+-------------------------+--------------+
12 rows in set (0.00 sec)
「_githuber_prismjs」が空なことがわかります(いくつかのメタデータを排除してます)
もし「javascript, css, html」のコードを書くと
+---------+---------+-------------------------+----------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+-------------------------+----------------------+
| 490 | 147 | _is_githuber_markdown | 1 |
| 496 | 147 | _is_githuber_mermaid | |
| 497 | 147 | _is_githuber_katex | |
| 498 | 147 | _is_githuber_mathjax | |
| 813 | 147 | _githuber_prismjs | javascript,clike,css |
| 814 | 147 | _githuber_highlightjs | |
| 815 | 147 | _is_githuber_sequence | |
| 816 | 147 | _is_githuber_flow_chart | |
+---------+---------+-------------------------+----------------------+
「javascript, clike, css」が追加されています。clikeはC言語風なで、javascriptと一緒についてきます。
依存関係的なものと考えてください。
一方表示時にはwp_enqueue_scripts
フィルターなどが実行される際にメタデータが読み込まれ、値が一つでもあれば表示時に「Prism.js」関連一式が読み込まれます。
このフィルタの登録はGithuber\Module#init()
で行われています(wp_loaded
フィルターに登録してある)
で、どうしようか、いや、functions.phpなどでこのPrism::$prism_codes
に勝手に追加してやろうと。
VSCode君の調査ではこの値が使用されている箇所を見る限り問題なさそう。
ただPHPのようなスクリプト言語は信用ならんので、もしかしたら問題起こるかもわかりゃーせん。
なので自己責任でお願いします。
add_filter('wp_insert_post_data', function( $post, $postarr ){
if(class_exists(\Githuber\Module\Prism::class))
{
\Githuber\Module\Prism::$prism_codes += [
'html' => 'HTML',
'xml' => 'XML',
'js' => 'JavaScript',
'ts' => 'TypeScript',
'none' => 'Nomal Text',
];
}
return $post;
}, 1, 2);
本家より早いタイミングでPrism::$prism_code
に追加。
注意しないといけないのは、Prism.jsに存在しない言語名を使うこと。
例えばtxt
を追加して使用しても表示時にブラウザからprism-tx.min.js
がねーんだよっ! って怒られます。
なんでも入れていいってもんじゃないんでね。
症状その2、言語によって行番号が表示されない
後気づいたことなんですが、何でか言語によって行番号が表示されていない!
設定側で行番号表示の設定をしているにもかかわらず。
HTMLやCSS,JavaScriptで行番号が表示されない。
PHP、C#、TypeScript、Javaでは表示される。
Prism.jsで行番号を記入するにはCSSクラスにline-numbers
を入れておく。
PRE.line-numbers > CODE[class*="language-xxx"] > *
こんな感じかな。
GitHuberはPrism#front_print_footer_scripts()
でjQueryを用意て後付けでpreに.line-numbers
を刷り込む箇所がありますが、
どうもこれ失敗してる模様。
ブラウザのデベロッパツールで行番号がある言語と無い言語の違いを調べると、
pre>code>span:last-child.line-numbers-rows
が追加されているかどうかのようだ。
調べると、
https://prismjs.com/plugins/line-numbers/
.line-numbersを指定する場所はpreでなくてもいいんかい。
極端な話、BODYに追加してもいいらしい。
ということで、とりあえず困った問題の応急処置は出来た。
後はプラグイン開発者さんが何とかしてくれるまで待つとします。