WordPressでMathJaxを利用しているが…

 WordPressのバージョンが6.9になって数式を入力できるブロックが追加されたのだが、使い勝手が悪く、それ以前から使っていたMathJaxを利用することにしている。ただ、MathJaxを利用するには記事のページにJavaScriptを記入しなければいけない。最初は「カスタムHTML」ブロックに記入していた。その後、記事の編集ページに「カスタムJavaScript」という項目があることに気づき、そこに記入することにしていた。ただ、記入するコードのコピー&ペーストが面倒に感じていた。PCの「付箋」にでも記入しておいて、そこからコピーすれば良いのかもしれないが、別の方法はないか考えて、WordPressのショートコード機能が使えないかと試すことにした。

 ちなみに、「カスタムHTML」は私が利用しているテーマ Cocoon の独自ブロックであることは知っていたが、「カスタムJavaScript」も Cocoon の独自機能であることは、今日、知った。

 まず、私が「カスタムHTML」ブロックに記入していたコードは次のとおりである。

<script>
window.MathJax = {
  loader: {load: ['[tex]/empheq']},
  tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['\\(', '\\)']]}
};
</script>
<script id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js">
</script>

 「カスタムHTML」を使う方法の欠点は、WordPressのページが複数ある場合に、このブロックが存在するページしか数式表示ができないことである。それに対して「カスタムJavaScript」を使う方法だと、一つの記入で全てのページで数式が使えるようになる。ただ、この「カスタムJavaScript」の仕様には気になることがあって、JavaScriptのコードのみを記入し、scriptタグは不要だということである。すると、上記のコードのようにscriptタグにsrcを指定する場合はどうしたら良いのか? 駄目元で上記のコードを入力したら機能したのだが、今日、改めて確認したら次のように最初と最後のscriptタグが消えていた。

window.MathJax = {
  loader: {load: ['[tex]/empheq']},
  tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['\\(', '\\)']]}
};
</script>
<script id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js">

 ただ、公開したページのHTMLコードを見たら、bodyタグの最後の方に次のようにscriptタグで囲まれていた。

<!-- cocoon Custom JS -->
<script>window.MathJax = {
  loader: {load: ['[tex]/empheq']},
  tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['\\(', '\\)']]}
};
</script>
<script id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js"></script>

 「カスタムHTML」も「カスタムJavaScript」もbodyタグの中にJavaScriptのコードを記入しているのだが、Geminiによると「WordPressの処理の論理的な順序パフォーマンスに反する」という理由で推奨されず、次のように注意された。

wp_enqueue_scripts の目的: WordPressでは、wp_enqueue_scripts アクションフックを使ってスクリプトをエンキュー(登録)し、最終的にHTMLの**<head> 内**にまとめて出力するのが標準的な手順です。

 そんなGeminiに、ショートコードを記事内に記入するだけでMathJaxを使った数式が表示されるようにするために、テーマファイルエディターの functions.php に記入するコードを教えてもらった。

// 数式を表示するショートコード [mathjax_load] の登録
// MathJaxのロードが必要かを示すフラグを定義
$GLOBALS['mathjax_needed'] = false;

// 1. ショートコードの登録(コンテンツ自体には何も出力しない)
function mathjax_shortcode_handler( $atts, $content = null ) {
	return '';
}
add_shortcode( 'mathjax_load', 'mathjax_shortcode_handler' );


// 2. MathJaxロードが必要か、最も適切なタイミング(wp_enqueue_scriptsの直前)でチェックする
/**
 * MathJaxロードが必要か、テンプレートリダイレクト前にチェックする
 * これが最も確実かつパフォーマンスに優しいチェック方法です。
 */
function mathjax_check_on_template_redirect() {
	global $post;

	// 現在が投稿または固定ページであり、公開されている場合のみチェック
	if ( is_singular() && isset($post) ) {
		// ページのコンテンツ全体を取得し、ショートコードの有無を確認
		if ( has_shortcode( $post->post_content, 'mathjax_load' ) ) {
			$GLOBALS['mathjax_needed'] = true;
		}
	}
}
// wp_enqueue_scriptsよりも早く実行される template_redirect にフック
add_action( 'template_redirect', 'mathjax_check_on_template_redirect' );


// 3. MathJaxスクリプトを条件付きでエンキューする関数
function conditionally_enqueue_mathjax_scripts() {
	
	// フラグが立っているかチェック
	if ( $GLOBALS['mathjax_needed'] ) {
		
		// --- MathJaxの設定(ロードより先に実行する必要がある) ---
		$mathjax_config = "
		window.MathJax = {
			loader: {load: ['[tex]/empheq']},
			tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['\\(', '\\)']]}
		};
		";
		// 設定を登録し、インラインで追加
		wp_register_script( 'mathjax-config', '', [], null );
		wp_add_inline_script( 'mathjax-config', $mathjax_config, 'before' );
		wp_enqueue_script( 'mathjax-config' );

		// --- MathJaxメインスクリプトのロード ---
		// 設定が読み込まれた後にロードされるように依存関係を設定
		wp_enqueue_script( 'mathjax-main', 'https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js', [ 'mathjax-config' ], '4.0', array( 'in_footer' => false, 'async' => true ) );
	}
}
// スクリプトのエンキュー処理をフック
add_action( 'wp_enqueue_scripts', 'conditionally_enqueue_mathjax_scripts' );

 記事内に次のように記入するだけでMathJaxが使える。

[mathjax_load]

 このコードで、headタグ内に次のようなコードが生成された。

<script id="mathjax-config-js-before">
/* <![CDATA[ */
		window.MathJax = {
			loader: {load: ['[tex]/empheq']},
			tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['\(', '\)']]}
		};
		
//# sourceURL=mathjax-config-js-before
/* ]]> */
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js?ver=4.0" id="mathjax-main-js"></script>

 このコードで機能するのだが、 functions.php に記入するにはコードが複雑すぎる。このコードに至るまで、Geminiは別のコードも作ったのだが、それは機能しなかった。何度か作り直した後に示されたのが上記のコードである。このような複雑なコードになったのは、前述のような「scriptはheadタグ内に作る」というGeminiの拘りがあるからで、ショートコードの位置に前述の「カスタムHTML」内のコードと同じコードを生成する functions.php のコードをGeminiに作ってもらったら、次のようなシンプルなコードになった。

/**
 * MathJax設定とロードスクリプトをショートコードの位置に出力する
 */
function mathjax_inline_shortcode_output( $atts, $content = null ) {
	$output = '
	<script>
	window.MathJax = {
	  loader: {load: [\'[tex]/empheq\']},
	  tex: {packages: {\'[+]\': [\'empheq\']}, tags: \'ams\', inlineMath: [[\'$\', \'$\'],[\'(\', \')\']]}
	};
	</script>
	<script id="MathJax-script" async
	  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js">
	</script>
	';
	// 改行やタブを削除してHTMLエラーを防ぐ(任意)
	return trim($output); 
}
// ショートコードを登録
add_shortcode( 'mathjax_load', 'mathjax_inline_shortcode_output' );

 これで問題なく機能した。「カスタムHTML」に記入する方法で機能したのだから当たり前かもしれない。これも記事に次のコードを記入することでMathJaxが使えるようになる。

[mathjax_load]

 実は、ショートコードの位置にコードを記入する方法は、functions.php を使わなくても、Cocoonの独自機能である定型文登録機能で実現できる。

 定型文の編集はビジュアルエディタでもコードエディタでも記入できるが、私はコードエディタで記入した。その際に、scriptタグだけを記入して保存したら、自動的にpタグで囲まれてしまったので、次のようにdivタグで囲んで記入した。この場合はpタグで囲まれることはなかった。

<div><script>
window.MathJax = {
  loader: {load: ['[tex]/empheq']},
  tex: {packages: {'[+]': ['empheq']}, tags: 'ams', inlineMath: [['$', '$'],['(', ')']]}
};
</script><script id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js">
</script></div>

 注意として、タグの間に改行があると、保存後に自動的に<br />が追加されてしまうので、改行しない方が良い。
 後は、記事の編集中に「テンプレート」リストから選択すれば良い。ただ、記事の編集画面に表示されるのは、例えば次のようなショートコードで数式表示用だと分かりにくい。

[temp id=1]

 functions.php にコードを記入する方法も同じだが、Cocoonの機能で定型文を用意して編集画面にショートコードだけを記入する方法は、MathJaxのコードを変えると、古い記事にも自動的に適用されるメリットがある。「カスタムHTML」や「カスタムJavaScript」を使う方法では、古い記事では古いコードのままである。もしかしたら古いコードのままの方が良い場合もあるかもしれないが…。

未分類
管理人のマストドンアカウントへのリンクなど

コメント

タイトルとURLをコピーしました