diff --git a/services/web/app/src/infrastructure/ExpressLocals.mjs b/services/web/app/src/infrastructure/ExpressLocals.mjs index c20a883fc4..297880288e 100644 --- a/services/web/app/src/infrastructure/ExpressLocals.mjs +++ b/services/web/app/src/infrastructure/ExpressLocals.mjs @@ -168,7 +168,7 @@ export default async function (webRouter, privateApiRouter, publicApiRouter) { return chunks.map(chunk => staticFilesBase + chunk) } - res.locals.mathJaxPath = `/js/libs/mathjax-${PackageVersions.version.mathjax}/es5/tex-svg-full.js` + res.locals.mathJaxPath = `/js/libs/mathjax-${PackageVersions.version.mathjax}/tex-svg.js` res.locals.dictionariesRoot = `/js/dictionaries/${PackageVersions.version.dictionaries}/` res.locals.lib = PackageVersions.lib diff --git a/services/web/app/src/infrastructure/PackageVersions.js b/services/web/app/src/infrastructure/PackageVersions.js index f2e22fc86e..2b01d72b16 100644 --- a/services/web/app/src/infrastructure/PackageVersions.js +++ b/services/web/app/src/infrastructure/PackageVersions.js @@ -1,5 +1,5 @@ const version = { - mathjax: '3.2.2', + mathjax: '4.1.2', dictionaries: '0.0.3', } diff --git a/services/web/cypress/support/shared/commands/mathjax.ts b/services/web/cypress/support/shared/commands/mathjax.ts index ed4cb0213c..1476826538 100644 --- a/services/web/cypress/support/shared/commands/mathjax.ts +++ b/services/web/cypress/support/shared/commands/mathjax.ts @@ -24,7 +24,7 @@ window.MathJax = { export const interceptMathJax = () => { // NOTE: this is just a URL to be intercepted with the stub, not the real (versioned) MathJax URL - const url = '/js/libs/mathjax/es5/tex-svg-full.js' + const url = '/js/libs/mathjax/es5/tex-svg.js' cy.window().then(win => { win.metaAttributesCache.set('ol-mathJaxPath', url) }) diff --git a/services/web/frontend/js/features/mathjax/load-mathjax.ts b/services/web/frontend/js/features/mathjax/load-mathjax.ts index c80d8a3d85..7c3471f137 100644 --- a/services/web/frontend/js/features/mathjax/load-mathjax.ts +++ b/services/web/frontend/js/features/mathjax/load-mathjax.ts @@ -22,7 +22,7 @@ export const loadMathJax = async (options?: { inlineMath.push(['$', '$']) } - // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html + // https://docs.mathjax.org/en/stable/options/index.html window.MathJax = { // https://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block tex: { @@ -30,10 +30,6 @@ export const loadMathJax = async (options?: { // Implements support for the \bm command from the bm package. It bolds the argument in math mode. // https://github.com/mathjax/MathJax/issues/1219#issuecomment-341059843 bm: ['\\boldsymbol{#1}', 1], - // MathJax 3 renders \coloneq as :- whereas the mathtools package - // renders it as :=. Here we override the \coloneq macro to produce - // the := symbol. - coloneq: '\\coloneqq', }, inlineMath, displayMath: [ @@ -44,12 +40,15 @@ export const loadMathJax = async (options?: { '[-]': [ 'html', // avoid creating HTML elements/attributes 'require', // prevent loading disabled packages + 'textmacros', // text macros are loaded by default in v4, disable them ], }, processEscapes: true, processEnvironments: true, useLabelIds: options.useLabelIds, - tags: options.numbering, + }, + output: { + displayOverflow: 'linebreak', }, loader: { load: [ @@ -62,14 +61,13 @@ export const loadMathJax = async (options?: { startup: { typeset: false, pageReady() { - // disable the "Math Renderer" option in the context menu, - // as only SVG is available + // disable the "Math Renderer" option in the context menu, as only SVG is available window.MathJax.startup.document.menu.menu - .findID('Renderer') + .findID('Settings', 'Renderer') .disable() }, - ready() { - window.MathJax.startup.defaultReady() + async ready() { + await window.MathJax.startup.defaultReady() // remove anything from the "font-family" attribute after a semicolon // so it's not added to the style attribute @@ -79,11 +77,31 @@ export const loadMathJax = async (options?: { safe.filterMethods.filterFontFamily = ( _safe: any, family: string - ) => family.split(/;/)[0] + ) => { + return family.split(/;/)[0] + } }, }, } + // "tags" set separately as tags: undefined throws an error + if (options.numbering) { + window.MathJax.tex.tags = options.numbering + } + + // if the menu is disabled, disable all the accessibility features, for performance + // https://docs.mathjax.org/en/stable/options/accessibility.html#accessibility-extensions-options + if (!options.enableMenu) { + window.MathJax.options.menuOptions = { + settings: { + enrich: false, + speech: false, + braille: false, + assistiveMml: false, + }, + } + } + const script = document.createElement('script') const path = getMeta('ol-mathJaxPath') if (!path) { diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/math.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/math.ts index dc1c6f3e61..3541fcfaa9 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/math.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/math.ts @@ -25,14 +25,17 @@ export class MathWidget extends WidgetType { view.dispatch(placeSelectionInsideBlock(view, event as MouseEvent)) }) } - this.renderMath(element) - .catch(() => { - element.classList.add('ol-cm-math-error') - }) - .finally(() => { - view.requestMeasure() - }) - + // in a timeout so the element can be rendered for metrics + window.setTimeout(() => { + this.renderMath(element) + .catch(() => { + element.classList.add('ol-cm-math-error') + }) + .finally(() => { + view.requestMeasure() + }) + }) + // TODO: re-render on element resize return element } diff --git a/services/web/frontend/stories/source-editor/source-editor.stories.tsx b/services/web/frontend/stories/source-editor/source-editor.stories.tsx index bd2e44b4e6..af130cacea 100644 --- a/services/web/frontend/stories/source-editor/source-editor.stories.tsx +++ b/services/web/frontend/stories/source-editor/source-editor.stories.tsx @@ -263,7 +263,7 @@ export const Visual: Story = { }) useMeta({ - 'ol-mathJaxPath': 'https://unpkg.com/mathjax@3.2.2/es5/tex-svg-full.js', + 'ol-mathJaxPath': 'https://unpkg.com/mathjax@4.1.2/tex-svg.js', 'ol-project_id': '63e21c07946dd8c76505f85a', }) diff --git a/services/web/package.json b/services/web/package.json index 03862b03ea..be929e0a1a 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -352,7 +352,7 @@ "knip": "^5.64.1", "lottie-react": "^2.4.1", "match-sorter": "^6.2.0", - "mathjax": "^3.2.2", + "mathjax": "^4.1.2", "mediatr-ts": "^2.0.1", "mensch": "^0.3.4", "micromark": "^4.0.0", diff --git a/services/web/webpack.config.js b/services/web/webpack.config.js index bcb81de06f..82c55d414b 100644 --- a/services/web/webpack.config.js +++ b/services/web/webpack.config.js @@ -363,37 +363,25 @@ module.exports = { // Copy the required files for loading MathJax from MathJax NPM package // https://www.npmjs.com/package/mathjax#user-content-hosting-your-own-copy-of-the-mathjax-components { - from: 'es5/tex-svg-full.js', - to: `js/libs/mathjax-${PackageVersions.version.mathjax}/es5`, - toType: 'dir', - context: mathjaxDir, - }, - { - from: 'es5/input/tex/extensions/**/*.js', + from: 'tex-svg.js', to: `js/libs/mathjax-${PackageVersions.version.mathjax}`, toType: 'dir', context: mathjaxDir, }, { - from: 'es5/ui/**/*', + from: 'input/tex/extensions/**/*.js', to: `js/libs/mathjax-${PackageVersions.version.mathjax}`, toType: 'dir', context: mathjaxDir, }, { - from: 'es5/a11y/**/*', + from: 'ui/**/*', to: `js/libs/mathjax-${PackageVersions.version.mathjax}`, toType: 'dir', context: mathjaxDir, }, { - from: 'es5/input/mml.js', - to: `js/libs/mathjax-${PackageVersions.version.mathjax}/es5/input`, - toType: 'dir', - context: mathjaxDir, - }, - { - from: 'es5/sre/**/*', + from: 'sre/**/*', to: `js/libs/mathjax-${PackageVersions.version.mathjax}`, toType: 'dir', context: mathjaxDir, diff --git a/yarn.lock b/yarn.lock index e3dafc0bc0..d5b52a18af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4740,6 +4740,13 @@ __metadata: languageName: node linkType: hard +"@mathjax/mathjax-newcm-font@npm:^4.1.2": + version: 4.1.2 + resolution: "@mathjax/mathjax-newcm-font@npm:4.1.2" + checksum: 10c0/23867a672706a5cc1a9cfe835a188466202ff5502bd9f65a75343532638184cb53c6a11a76473c37a4e6231b38f6781b1a20a6eb3a3f1ba46144bf533bd25026 + languageName: node + linkType: hard + "@maxmind/geoip2-node@npm:^5.0.0": version: 5.0.0 resolution: "@maxmind/geoip2-node@npm:5.0.0" @@ -7381,7 +7388,7 @@ __metadata: lru-cache: "npm:^7.10.1" marked: "npm:^4.1.0" match-sorter: "npm:^6.2.0" - mathjax: "npm:^3.2.2" + mathjax: "npm:^4.1.2" mediatr-ts: "npm:^2.0.1" mensch: "npm:^0.3.4" method-override: "npm:^2.3.3" @@ -23448,10 +23455,12 @@ __metadata: languageName: node linkType: hard -"mathjax@npm:^3.2.2": - version: 3.2.2 - resolution: "mathjax@npm:3.2.2" - checksum: 10c0/26c8557f948d1ef76ce2b0bc1ad66128c9a78a7e4f3d96587f90b23dd25cfbf14c9b58a1c75a7d8d35f92b72bab054eab61873443babe646b7bfd6b40bb717e6 +"mathjax@npm:^4.1.2": + version: 4.1.2 + resolution: "mathjax@npm:4.1.2" + dependencies: + "@mathjax/mathjax-newcm-font": "npm:^4.1.2" + checksum: 10c0/3d842708029c65bdcaaf621f80aed1248a2f29f180d4e5a42e6e48e935cdf891be1505575e323193ea44347112149b636a3b08b0a72ed2b203004c18044f5dc8 languageName: node linkType: hard