Hi — thanks for maintaining this plugin. I'm reporting a latent bug that surfaces when the kblog_mathjax_custom_location override is used to load MathJax v3 or v4 from a CDN. I hit this while auditing a production WordPress site that's been on v4 for a while.
Summary
When kblog_mathjax_custom_location is set to a v3/v4 MathJax URL (e.g. https://cdnjs.cloudflare.com/ajax/libs/mathjax/4.0.0/tex-chtml.min.js), the plugin loads the v4 runtime successfully, but:
-
class-mathjax-latex.php:223 unconditionally emits wp_add_inline_script('mathjax', 'MathJax.Hub.Config(' . wp_json_encode($mathjax_config) . ');') whenever the mathjax_config filter returns a non-empty array. MathJax.Hub does not exist in v3 or v4 — it was removed. The inline script throws TypeError: MathJax.Hub is undefined / ReferenceError: MathJax is not defined on every page load where the shortcode is present and a mathjax_config filter is registered.
-
class-mathjax-latex.php::script_loader_tag() rewrites inline scripts on the mathjax handle from <script type='text/javascript'> to <script type='text/x-mathjax-config'>. That type is v2-specific — MathJax v3/v4 ignores it — so even the replacement wouldn't run.
-
add_query_arg('config', $config, $mathjax_location) appends ?config=default to the script URL. v4 ignores this (its configuration model is window.MathJax = {...} set before the script loads), and for sites pointing at tex-chtml.min.js the query string is noise.
Visual rendering still works on v4-configured sites because v4's auto-typesetter runs independently of any Hub.Config() call — so the bug is often invisible to users but pollutes DevTools on every page load, and any customization registered via the mathjax_config filter is silently dropped on v4.
Reproduction
- Install this plugin on a site with MathJax enabled.
- In Settings → MathJax, set the custom location to
https://cdnjs.cloudflare.com/ajax/libs/mathjax/4.0.0/tex-chtml.min.js (or any v3/v4 URL).
- Register a
mathjax_config filter that returns any non-empty array, e.g.:
add_filter('mathjax_config', fn() => ['TeX' => ['equationNumbers' => ['autoNumber' => 'AMS']]]);
- Visit any page containing the
[mathjax] shortcode and open DevTools → Console.
- Observe:
ReferenceError: MathJax is not defined at the emitted MathJax.Hub.Config({...}) inline script.
Suggested fix
Detect the loaded version from the script URL and branch config emission:
- If URL matches a v3/v4 pattern (e.g.
/mathjax/[34]\., or ends with tex-chtml, tex-mml-chtml, tex-svg, etc.):
- Emit
window.MathJax = {...} as an inline script with position 'before' (so it runs before the library loads and is picked up by v4's config reader).
- Translate v2 config keys to v4 equivalents where possible (
TeX.equationNumbers.autoNumber: 'AMS' → tex.tags: 'ams', tex2jax.inlineMath → tex.inlineMath, etc.).
- Skip the
script_loader_tag type rewrite for v3/v4.
- Don't append
?config=default to the URL.
- Otherwise, keep the existing v2 behavior (fully backward compatible).
A helper is_mathjax_v4($url) of ~5 lines handles the detection. The branching in add_script() and script_loader_tag() is maybe 20 lines total. The v2→v4 config key translation can start minimal (just tex.tags and tex.inlineMath / tex.displayMath) and expand over time — or just emit the raw dict under a tex key and let the filter author write v4-shape config directly.
Workaround for site owners
Until upstream has a fix, site owners on v4 can avoid the error by either:
- Not registering any
mathjax_config filter (the plugin emits nothing if the filter returns empty)
- Emitting their own
window.MathJax = {...} via wp_head instead of the filter
Offer
Happy to submit a PR if that would be useful. Let me know if there's a preferred approach for the v2→v4 config translation (full mapping vs pass-through vs something in between) and I'll match that.
Cheers!
Hi — thanks for maintaining this plugin. I'm reporting a latent bug that surfaces when the
kblog_mathjax_custom_locationoverride is used to load MathJax v3 or v4 from a CDN. I hit this while auditing a production WordPress site that's been on v4 for a while.Summary
When
kblog_mathjax_custom_locationis set to a v3/v4 MathJax URL (e.g.https://cdnjs.cloudflare.com/ajax/libs/mathjax/4.0.0/tex-chtml.min.js), the plugin loads the v4 runtime successfully, but:class-mathjax-latex.php:223unconditionally emitswp_add_inline_script('mathjax', 'MathJax.Hub.Config(' . wp_json_encode($mathjax_config) . ');')whenever themathjax_configfilter returns a non-empty array.MathJax.Hubdoes not exist in v3 or v4 — it was removed. The inline script throwsTypeError: MathJax.Hub is undefined/ReferenceError: MathJax is not definedon every page load where the shortcode is present and amathjax_configfilter is registered.class-mathjax-latex.php::script_loader_tag()rewrites inline scripts on themathjaxhandle from<script type='text/javascript'>to<script type='text/x-mathjax-config'>. That type is v2-specific — MathJax v3/v4 ignores it — so even the replacement wouldn't run.add_query_arg('config', $config, $mathjax_location)appends?config=defaultto the script URL. v4 ignores this (its configuration model iswindow.MathJax = {...}set before the script loads), and for sites pointing attex-chtml.min.jsthe query string is noise.Visual rendering still works on v4-configured sites because v4's auto-typesetter runs independently of any
Hub.Config()call — so the bug is often invisible to users but pollutes DevTools on every page load, and any customization registered via themathjax_configfilter is silently dropped on v4.Reproduction
https://cdnjs.cloudflare.com/ajax/libs/mathjax/4.0.0/tex-chtml.min.js(or any v3/v4 URL).mathjax_configfilter that returns any non-empty array, e.g.:[mathjax]shortcode and open DevTools → Console.ReferenceError: MathJax is not definedat the emittedMathJax.Hub.Config({...})inline script.Suggested fix
Detect the loaded version from the script URL and branch config emission:
/mathjax/[34]\., or ends withtex-chtml,tex-mml-chtml,tex-svg, etc.):window.MathJax = {...}as an inline script with position'before'(so it runs before the library loads and is picked up by v4's config reader).TeX.equationNumbers.autoNumber: 'AMS'→tex.tags: 'ams',tex2jax.inlineMath→tex.inlineMath, etc.).script_loader_tagtype rewrite for v3/v4.?config=defaultto the URL.A helper
is_mathjax_v4($url)of ~5 lines handles the detection. The branching inadd_script()andscript_loader_tag()is maybe 20 lines total. The v2→v4 config key translation can start minimal (justtex.tagsandtex.inlineMath/tex.displayMath) and expand over time — or just emit the raw dict under atexkey and let the filter author write v4-shape config directly.Workaround for site owners
Until upstream has a fix, site owners on v4 can avoid the error by either:
mathjax_configfilter (the plugin emits nothing if the filter returns empty)window.MathJax = {...}viawp_headinstead of the filterOffer
Happy to submit a PR if that would be useful. Let me know if there's a preferred approach for the v2→v4 config translation (full mapping vs pass-through vs something in between) and I'll match that.
Cheers!