Skip to content

Self-hosting instructions don't cover font extensions #3610

Description

@daniil-berg

Issue Summary

When self-hosting MathJax v4.0, font extensions are still fetched from cdn.jsdelivr.net (even though the main font is configured to load locally). The self-hosting documentation only covers whole font packages via output.font and/or output.fontPath.

The dependency is content-triggered, so it can survive testing and only appear once someone writes e.g. chemistry or blackboard-bold markup.

Steps to Reproduce

  1. Self-host MathJax 4.0.0 plus a local copy of @mathjax/mathjax-newcm-font, and set output.fontPath to it as documented.
  2. Typeset \ce{H2O}.
  3. Observe in the network tab: GET https://cdn.jsdelivr.net/npm/@mathjax/mathjax-mhchem-font-extension/chtml.js

Same for \bbm, \bboldx and \dsfont with their respective extension packages.

The cause seems to be the fontExtension helper:

export function fontExtension(id, name, pkg = `@mathjax/${name}`) {
  if (MathJax.loader) {
    const FONTPATH = hasWindow ? `https://cdn.jsdelivr.net/npm/${pkg}` : pkg;
    const path = name.replace(/-font-extension$/, '-extension');
    const jax = (MathJax.config?.startup?.output || 'chtml');
    combineDefaults(MathJax.config.loader, 'paths', {[path]: FONTPATH});
    ...
  }
}

I could not find the resulting key names documented anywhere. You can find the config I got working below; the key is the package name with -font-extension replaced with -extension.

I expect the self-hosting documentation to cover font extensions alongside fonts. Sites that self-host specifically to avoid third-party requests (GDPR compliance, in our case a German university, the TU Berlin) are otherwise left with a CDN call they have no reason to expect. The only reason I even caught this, is because our CSP blocked those requests breaking fonts in some tests, which users then reported.

v4.1 seems to introduce a [fonts] prefix which may make this simpler, but it does not exist in v4.0. This whole issue arose on a custom Moodle 5.2 instance, so it is unclear if an upgrade to MathJax v4.1 is even supported.

Technical details

  • MathJax Version: 4.0.0 (self-hosted, @mathjax/src@4.0.0 bundle)
  • Client OS: Debian 13 (trixie)
  • Browser: Librewolf

The following MathJax configuration actually worked:

MathJax = {
  loader: {
    paths: {
      "mathjax-mhchem-extension": "<our-server>/font-extensions/mathjax-mhchem-font-extension",
      "mathjax-bbm-extension":    "<our-server>/font-extensions/mathjax-bbm-font-extension",
      "mathjax-bboldx-extension": "<our-server>/font-extensions/mathjax-bboldx-font-extension",
      "mathjax-dsfont-extension": "<our-server>/font-extensions/mathjax-dsfont-font-extension"
    }
  },
  output: {
    fontPath: "<our-server>/MathJax/v4.0.0/output/fonts/mathjax-newcm"
  }
};

The loader.paths entries are the undocumented fix. Without them, and with only the documented output.fontPath set, the jsdelivr requests occur.

and loading MathJax via

<script src="<our-server>/MathJax/v4.0.0/tex-mml-chtml-safe.js"></script>

Supporting information

I cannot share a public live example because the affected pages are behind authentication. But you can reproduce this with any self-hosted 4.0.0 install. Set output.fontPath locally, omit the loader.paths entries above, and typeset \ce{H2O}.

Activity

  1. dpvc commented on Sep 17, 2026

    @dpvc
    Member

    Yes, the self-hosting documentation needs to be improved. It is on my list for a re-write for the next release.

    I would encourage you to move up from v4.0.0, however, as there were several important updates since then. See the releases page for more details about what has changed. You point out that v4.1 added the [font] prefix in order to make your situation easier to manage.

    This whole issue arose on a custom Moodle 5.2 instance, so it is unclear if an upgrade to MathJax v4.1 is even supported.

    The API for v4.0 and v4.1 should be compatible, so I would not expect to have trouble if you update to v4.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions