From ec5e48578d6983c82efc6ae5d53db3d4f828d257 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 11 Sep 2026 15:51:15 -0400 Subject: [PATCH 1/9] Update node-main to work in (webpacked) browser as well as node, and rename node-main to main --- components/mjs/core/core.js | 24 +-- components/mjs/core/locale.js | 2 +- components/mjs/main/browser/browser.d.ts | 16 ++ components/mjs/main/browser/browser.js | 37 +++++ components/mjs/main/browser/config.json | 13 ++ components/mjs/main/browser/json.cjs | 1 + components/mjs/main/browser/json.d.cts | 1 + components/mjs/main/browser/webpack.cjs | 17 ++ components/mjs/main/config.json | 13 ++ components/mjs/main/json.cjs | 4 + components/mjs/main/json.d.cts | 1 + components/mjs/main/main.d.ts | 16 ++ components/mjs/main/main.js | 9 ++ components/mjs/main/node/config.json | 15 ++ components/mjs/main/node/node.cjs | 14 ++ components/mjs/main/node/node.d.cts | 3 + components/mjs/main/node/node.d.ts | 16 ++ components/mjs/main/node/node.js | 6 + components/mjs/main/node/setup.d.ts | 2 + components/mjs/main/node/setup.js | 55 +++++++ components/mjs/main/node/webpack.cjs | 14 ++ components/mjs/main/webpack.cjs | 14 ++ .../mjs/mml-chtml-nofont/mml-chtml-nofont.js | 12 +- components/mjs/mml-chtml/mml-chtml.js | 12 +- .../mjs/mml-svg-nofont/mml-svg-nofont.js | 12 +- components/mjs/mml-svg/mml-svg.js | 12 +- components/mjs/node-main/config.json | 17 -- components/mjs/node-main/node-main-setup.cjs | 5 - components/mjs/node-main/node-main.cjs | 5 - components/mjs/node-main/node-main.d.cts | 7 - components/mjs/node-main/node-main.d.mts | 7 - components/mjs/node-main/node-main.js | 106 ------------- components/mjs/node-main/node-main.mjs | 4 - components/mjs/node-main/webpack.cjs | 8 - components/mjs/startup/init.d.ts | 1 + components/mjs/startup/init.js | 34 +++- components/mjs/startup/startup.js | 8 +- .../mjs/tex-chtml-nofont/tex-chtml-nofont.js | 12 +- components/mjs/tex-chtml/tex-chtml.js | 12 +- .../tex-mml-chtml-nofont.js | 12 +- components/mjs/tex-mml-chtml/tex-mml-chtml.js | 12 +- .../tex-mml-svg-nofont/tex-mml-svg-nofont.js | 12 +- components/mjs/tex-mml-svg/tex-mml-svg.js | 12 +- .../mjs/tex-svg-nofont/tex-svg-nofont.js | 12 +- components/mjs/tex-svg/tex-svg.js | 12 +- package.json | 21 ++- testsuite/src/setupTex.ts | 2 +- ts/a11y/explorer/Region.ts | 2 +- ts/a11y/semantic-enrich.ts | 1 + ts/components/cjs/json.ts | 2 +- ts/components/loader.ts | 17 +- ts/components/mjs/json.ts | 3 +- ts/components/package.ts | 30 ++-- ts/components/startup.ts | 38 ++--- ts/output/common/FontData.ts | 2 +- ts/types/Components.ts | 150 ++++++++++++------ ts/types/Types.ts | 97 +++++++++-- ts/types/dom/html.ts | 25 --- ts/types/dom/lite.ts | 19 --- ts/types/{mjx.ts => mathjax.ts} | 65 +++++++- tsconfig/cjs.json | 3 +- tsconfig/worker-cjs.json | 12 +- tsconfig/worker.json | 7 +- 63 files changed, 730 insertions(+), 405 deletions(-) create mode 100644 components/mjs/main/browser/browser.d.ts create mode 100644 components/mjs/main/browser/browser.js create mode 100644 components/mjs/main/browser/config.json create mode 100644 components/mjs/main/browser/json.cjs create mode 100644 components/mjs/main/browser/json.d.cts create mode 100644 components/mjs/main/browser/webpack.cjs create mode 100644 components/mjs/main/config.json create mode 100644 components/mjs/main/json.cjs create mode 100644 components/mjs/main/json.d.cts create mode 100644 components/mjs/main/main.d.ts create mode 100644 components/mjs/main/main.js create mode 100644 components/mjs/main/node/config.json create mode 100644 components/mjs/main/node/node.cjs create mode 100644 components/mjs/main/node/node.d.cts create mode 100644 components/mjs/main/node/node.d.ts create mode 100644 components/mjs/main/node/node.js create mode 100644 components/mjs/main/node/setup.d.ts create mode 100644 components/mjs/main/node/setup.js create mode 100644 components/mjs/main/node/webpack.cjs create mode 100644 components/mjs/main/webpack.cjs delete mode 100644 components/mjs/node-main/config.json delete mode 100644 components/mjs/node-main/node-main-setup.cjs delete mode 100644 components/mjs/node-main/node-main.cjs delete mode 100644 components/mjs/node-main/node-main.d.cts delete mode 100644 components/mjs/node-main/node-main.d.mts delete mode 100644 components/mjs/node-main/node-main.js delete mode 100644 components/mjs/node-main/node-main.mjs delete mode 100644 components/mjs/node-main/webpack.cjs rename ts/types/{mjx.ts => mathjax.ts} (56%) diff --git a/components/mjs/core/core.js b/components/mjs/core/core.js index d583d93559..b33fc2ea49 100644 --- a/components/mjs/core/core.js +++ b/components/mjs/core/core.js @@ -14,16 +14,18 @@ if (MathJax.startup) { if (MathJax.loader) { const config = MathJax.config.loader; const {mathjax} = MathJax._.mathjax; - mathjax.asyncLoad = (name) => { - if (name.match(/\.json$/)) { + if (!mathjax.asyncLoad) { + mathjax.asyncLoad = (name) => { + if (name.match(/\.json$/)) { name = Package.resolvePath(name); - return (config.json || mathjax.json)(name).then((data) => data.default ?? data); - } - return name.substring(0, 5) === 'node:' - ? config.require(name) - : MathJax.loader.load(name).then(result => result[0]); - }; - mathjax.json = mathjax.context.window - ? (file) => fetch(file).then((data) => data.json()) - : (file) => import( /* webpackIgnore: true */ file, {with: {type: 'json'}}); + return (config.json || mathjax.json)(name).then((data) => data.default ?? data); + } + return name.substring(0, 5) === 'node:' + ? config.require(name) + : MathJax.loader.load(name).then(result => result[0]); + }; + mathjax.json = mathjax.context.window + ? (file) => fetch(file).then((data) => data.json()) + : (file) => import( /* webpackIgnore: true */ file, {with: {type: 'json'}}); + } } diff --git a/components/mjs/core/locale.js b/components/mjs/core/locale.js index 6009400c7f..0da87f4b3e 100644 --- a/components/mjs/core/locale.js +++ b/components/mjs/core/locale.js @@ -1,4 +1,4 @@ import {Locale} from '#js/util/Locale.js'; Locale.isComponent = true; - +Locale.locations.locale[0] = 'locale/__locales__'; diff --git a/components/mjs/main/browser/browser.d.ts b/components/mjs/main/browser/browser.d.ts new file mode 100644 index 0000000000..6453d2888c --- /dev/null +++ b/components/mjs/main/browser/browser.d.ts @@ -0,0 +1,16 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'browser' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; diff --git a/components/mjs/main/browser/browser.js b/components/mjs/main/browser/browser.js new file mode 100644 index 0000000000..f35fc18dbf --- /dev/null +++ b/components/mjs/main/browser/browser.js @@ -0,0 +1,37 @@ +import { MathJax, combineConfig, combineDefaults } from '#js/components/global.js'; +import { Loader } from '#js/components/loader.js'; +import { hasWindow } from '#js/util/context.js'; + +if (hasWindow) { + window.exports ??= {}; +} + +export function makeInit(nodeSetup = null, adaptor = '') { + return async function init(config, component = 'startup') { + Loader.preLoaded('loader', 'core'); + MathJax.config.loader.failed = (err) => {throw err}; + if (hasWindow) { + MathJax.config.loader.paths.mathjax = 'https://cdn.jsdelivr.net/npm/mathjax'; + } + if (nodeSetup) { + await nodeSetup(); + } + combineConfig(MathJax.config, config); + if (adaptor) { + const CONFIG = MathJax.config.loader; + CONFIG.load ??= []; + if (CONFIG.load.filter((name) => name.substring(0, 9) === 'adaptors/').length === 0) { + CONFIG.load.unshift(adaptor); + } + } + MathJax.loader = Loader; + if (component) { + await Loader.load(component); + } + await MathJax.startup?.promise ?? Promise.resolve(); + return MathJax; + } +}; + +export default MathJax; +export const init = makeInit(); diff --git a/components/mjs/main/browser/config.json b/components/mjs/main/browser/config.json new file mode 100644 index 0000000000..900c418e9a --- /dev/null +++ b/components/mjs/main/browser/config.json @@ -0,0 +1,13 @@ +{ + "copy": { + "to": "[bundle]/main", + "from": ".", + "copy": [ + "browser.d.ts" + ] + }, + "webpack": { + "name": "main/browser", + "noDTS": true + } +} diff --git a/components/mjs/main/browser/json.cjs b/components/mjs/main/browser/json.cjs new file mode 100644 index 0000000000..dbc35b5aff --- /dev/null +++ b/components/mjs/main/browser/json.cjs @@ -0,0 +1 @@ +export const json = (file) => fetch(file).then((data) => data.json()) diff --git a/components/mjs/main/browser/json.d.cts b/components/mjs/main/browser/json.d.cts new file mode 100644 index 0000000000..1cdd6211c2 --- /dev/null +++ b/components/mjs/main/browser/json.d.cts @@ -0,0 +1 @@ +export const json: (file: string) => Promise; diff --git a/components/mjs/main/browser/webpack.cjs b/components/mjs/main/browser/webpack.cjs new file mode 100644 index 0000000000..e2034fa070 --- /dev/null +++ b/components/mjs/main/browser/webpack.cjs @@ -0,0 +1,17 @@ +const webpack = require('webpack'); + +module.exports = (pkg) => { + pkg.output.library = { + type: 'commonjs-static', + } + pkg.plugins.push( + new webpack.NormalModuleReplacementPlugin( + /mjs\/components\/mjs\/json\.js/, + '../../../components/mjs/main/browser/json.cjs' + ), + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }) + ); + return pkg; +} diff --git a/components/mjs/main/config.json b/components/mjs/main/config.json new file mode 100644 index 0000000000..1469e74c95 --- /dev/null +++ b/components/mjs/main/config.json @@ -0,0 +1,13 @@ +{ + "copy": { + "to": "[bundle]/main", + "from": ".", + "copy": [ + "main.d.ts" + ] + }, + "webpack": { + "name": "main/main", + "noDTS": true + } +} diff --git a/components/mjs/main/json.cjs b/components/mjs/main/json.cjs new file mode 100644 index 0000000000..844aa717d0 --- /dev/null +++ b/components/mjs/main/json.cjs @@ -0,0 +1,4 @@ +let REQUIRE; +try { REQUIRE = eval("require") } catch (_) { REQUIRE = () => {} } +export const json = (file) => Promise.resolve().then(() => REQUIRE(file)); + diff --git a/components/mjs/main/json.d.cts b/components/mjs/main/json.d.cts new file mode 100644 index 0000000000..1cdd6211c2 --- /dev/null +++ b/components/mjs/main/json.d.cts @@ -0,0 +1 @@ +export const json: (file: string) => Promise; diff --git a/components/mjs/main/main.d.ts b/components/mjs/main/main.d.ts new file mode 100644 index 0000000000..b658d16696 --- /dev/null +++ b/components/mjs/main/main.d.ts @@ -0,0 +1,16 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; diff --git a/components/mjs/main/main.js b/components/mjs/main/main.js new file mode 100644 index 0000000000..f10b04cf6d --- /dev/null +++ b/components/mjs/main/main.js @@ -0,0 +1,9 @@ +import { MathJax } from '#js/components/global.js'; +import { hasWindow } from '#js/util/context.js'; +import { setup, adaptor } from './node/setup.js'; +import { init as browserInit, makeInit } from './browser/browser.js'; + +MathJax.init = hasWindow ? browserInit : makeInit(setup, adaptor); + +export { MathJax }; +export const init = MathJax.init; diff --git a/components/mjs/main/node/config.json b/components/mjs/main/node/config.json new file mode 100644 index 0000000000..766ac7309e --- /dev/null +++ b/components/mjs/main/node/config.json @@ -0,0 +1,15 @@ +{ + "copy": { + "to": "[bundle]/main", + "from": ".", + "copy": [ + "node.cjs", + "node.d.cts", + "node.d.ts" + ] + }, + "webpack": { + "name": "main/node", + "noDTS": true + } +} diff --git a/components/mjs/main/node/node.cjs b/components/mjs/main/node/node.cjs new file mode 100644 index 0000000000..c4ccc73416 --- /dev/null +++ b/components/mjs/main/node/node.cjs @@ -0,0 +1,14 @@ +let REQUIRE; +try { REQUIRE = eval("require") } catch(_) { REQUIRE = () => {} } +const path = REQUIRE("path"); +const fs = REQUIRE("fs"); + +let source = null; +if (fs.existsSync(path.resolve(__dirname, '..', '..', 'source.js'))) { + source = async () => {return (await import(/* webpackIgnore: true */ '../../source.js')).source}; +} + +module.exports.REQUIRE = REQUIRE; +module.exports.path = path; +module.exports.source = source; + diff --git a/components/mjs/main/node/node.d.cts b/components/mjs/main/node/node.d.cts new file mode 100644 index 0000000000..a9877412ce --- /dev/null +++ b/components/mjs/main/node/node.d.cts @@ -0,0 +1,3 @@ +export const REQUIRE: (file: string) => any; +export const path: any; +export const source: () => Promise<{ [component: string]: string }>; diff --git a/components/mjs/main/node/node.d.ts b/components/mjs/main/node/node.d.ts new file mode 100644 index 0000000000..b658d16696 --- /dev/null +++ b/components/mjs/main/node/node.d.ts @@ -0,0 +1,16 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; diff --git a/components/mjs/main/node/node.js b/components/mjs/main/node/node.js new file mode 100644 index 0000000000..6b986b0102 --- /dev/null +++ b/components/mjs/main/node/node.js @@ -0,0 +1,6 @@ +import { MathJax } from '#js/components/global.js'; +import { makeInit } from '../browser/browser.js'; +import { setup, adaptor } from './setup.js'; + +export default MathJax; +export const init = makeInit(setup, adaptor); diff --git a/components/mjs/main/node/setup.d.ts b/components/mjs/main/node/setup.d.ts new file mode 100644 index 0000000000..3bd2bbeb75 --- /dev/null +++ b/components/mjs/main/node/setup.d.ts @@ -0,0 +1,2 @@ +export function setup(): void; +export const adaptor: string; diff --git a/components/mjs/main/node/setup.js b/components/mjs/main/node/setup.js new file mode 100644 index 0000000000..765a5d8161 --- /dev/null +++ b/components/mjs/main/node/setup.js @@ -0,0 +1,55 @@ +import { MathJax, combineDefaults } from '#js/components/global.js'; +import { Package } from '#js/components/package.js'; +import { mathjax } from '#js/mathjax.js'; +import { isCJS } from '#js/util/context.js'; +import { resolvePath } from '#js/util/AsyncLoad.js'; + +export async function setup() { + const CONFIG = MathJax.config.loader; + const { REQUIRE, path, source } = await import(/* webpackIgnore: true */ './node.cjs'); + // + // If the path was not able to be determined, try to find the mathjax packages + // and use those if found. The user can still override it. + // + if (CONFIG.paths.mathjax === '/' || CONFIG.paths.mathjax === 'file:///') { + try { + REQUIRE.resolve('@mathjax/src/package.json'); + CONFIG.paths.mathjax = '@mathjax/src/bundle'; + } catch (_) { + try { + REQUIRE.resolve('mathjax/package.json'); + CONFIG.paths.mathjax = '@mathjax'; + } catch (_) {} + } + } + // + // If we are loading from the components main directory, + // load the source file mapping into the source configuration, + // and set the paths for mathjax and sre. + // + if (source) { + CONFIG.source = await source(); + } + // + // If asyncLoad hasn't been specified, use REQUIRE + // + if (!mathjax.asyncLoad) { + mathjax.asyncLoad = function (name) { + if (name.substring(0, 5) !== 'node:') { + name = Package.resolvePath(name); + } + return REQUIRE( + resolvePath(name, (file) => path.resolve(CONFIG.paths.mathjax, file)) + ); + }; + mathjax.asyncIsSynchronous = true; + } + // + // Use dynamic imports for require. + // + combineDefaults(MathJax.config, 'loader', { + require: (file) => REQUIRE(file), + }); +} + +export const adaptor = 'adaptors/liteDOM'; diff --git a/components/mjs/main/node/webpack.cjs b/components/mjs/main/node/webpack.cjs new file mode 100644 index 0000000000..993c359f3e --- /dev/null +++ b/components/mjs/main/node/webpack.cjs @@ -0,0 +1,14 @@ +const webpack = require('webpack'); + +module.exports = (pkg) => { + pkg.output.library = { + type: 'commonjs-static', + } + pkg.plugins.push( + new webpack.NormalModuleReplacementPlugin( + /mjs\/components\/mjs\/json\.js/, + '../../../components/mjs/main/json.cjs' + ), + ); + return pkg; +} diff --git a/components/mjs/main/webpack.cjs b/components/mjs/main/webpack.cjs new file mode 100644 index 0000000000..993c359f3e --- /dev/null +++ b/components/mjs/main/webpack.cjs @@ -0,0 +1,14 @@ +const webpack = require('webpack'); + +module.exports = (pkg) => { + pkg.output.library = { + type: 'commonjs-static', + } + pkg.plugins.push( + new webpack.NormalModuleReplacementPlugin( + /mjs\/components\/mjs\/json\.js/, + '../../../components/mjs/main/json.cjs' + ), + ); + return pkg; +} diff --git a/components/mjs/mml-chtml-nofont/mml-chtml-nofont.js b/components/mjs/mml-chtml-nofont/mml-chtml-nofont.js index b405059190..d6a13c0f6a 100644 --- a/components/mjs/mml-chtml-nofont/mml-chtml-nofont.js +++ b/components/mjs/mml-chtml-nofont/mml-chtml-nofont.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'mml-chtml-nofont'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/chtml', 'ui/menu' ); -Loader.saveVersion('mml-chtml-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/mml-chtml/mml-chtml.js b/components/mjs/mml-chtml/mml-chtml.js index 171c9a6ab0..721bc46039 100644 --- a/components/mjs/mml-chtml/mml-chtml.js +++ b/components/mjs/mml-chtml/mml-chtml.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'mml-chtml'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/chtml', 'ui/menu' ); -Loader.saveVersion('mml-chtml'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/components/mjs/mml-svg-nofont/mml-svg-nofont.js b/components/mjs/mml-svg-nofont/mml-svg-nofont.js index cc3004f574..160b20dcc1 100644 --- a/components/mjs/mml-svg-nofont/mml-svg-nofont.js +++ b/components/mjs/mml-svg-nofont/mml-svg-nofont.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'mml-svg-nofont'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/svg', 'ui/menu' ); -Loader.saveVersion('mml-svg-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/mml-svg/mml-svg.js b/components/mjs/mml-svg/mml-svg.js index fc19bdc55a..2ee60f6418 100644 --- a/components/mjs/mml-svg/mml-svg.js +++ b/components/mjs/mml-svg/mml-svg.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'mml-svg'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/svg', 'ui/menu' ); -Loader.saveVersion('mml-svg'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/components/mjs/node-main/config.json b/components/mjs/node-main/config.json deleted file mode 100644 index 3bd87da548..0000000000 --- a/components/mjs/node-main/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "copy": { - "to": "[bundle]", - "from": ".", - "copy": [ - "node-main.mjs", - "node-main.cjs", - "node-main-setup.cjs", - "node-main.d.mts", - "node-main.d.cts" - ] - }, - "webpack": { - "name": "node-main", - "noDTS": true - } -} diff --git a/components/mjs/node-main/node-main-setup.cjs b/components/mjs/node-main/node-main-setup.cjs deleted file mode 100644 index 293652c51d..0000000000 --- a/components/mjs/node-main/node-main-setup.cjs +++ /dev/null @@ -1,5 +0,0 @@ -global.require = require; -const path = require("path"); - -if (!global.MathJax) global.MathJax = {}; -global.MathJax.__dirname = __dirname; diff --git a/components/mjs/node-main/node-main.cjs b/components/mjs/node-main/node-main.cjs deleted file mode 100644 index a431849a08..0000000000 --- a/components/mjs/node-main/node-main.cjs +++ /dev/null @@ -1,5 +0,0 @@ -if (!global.MathJax) global.MathJax = {}; - -global.MathJax.__dirname = __dirname; - -module.exports = require('./node-main.js').MathJax; diff --git a/components/mjs/node-main/node-main.d.cts b/components/mjs/node-main/node-main.d.cts deleted file mode 100644 index 364865e3f8..0000000000 --- a/components/mjs/node-main/node-main.d.cts +++ /dev/null @@ -1,7 +0,0 @@ -import { EMPTY } from '@mathjax/src/mjs/types/Types.js'; -import { COMPONENT_LIST } from '@mathjax/src/mjs/types/mjx.js'; -import { LITE_DOM, MATHJAX_CONFIG, MATHJAX_OBJECT } from '@mathjax/src/mjs/types/dom/lite.js'; - -export function init = EMPTY>( - config: MATHJAX_CONFIG -): Promise>; diff --git a/components/mjs/node-main/node-main.d.mts b/components/mjs/node-main/node-main.d.mts deleted file mode 100644 index 364865e3f8..0000000000 --- a/components/mjs/node-main/node-main.d.mts +++ /dev/null @@ -1,7 +0,0 @@ -import { EMPTY } from '@mathjax/src/mjs/types/Types.js'; -import { COMPONENT_LIST } from '@mathjax/src/mjs/types/mjx.js'; -import { LITE_DOM, MATHJAX_CONFIG, MATHJAX_OBJECT } from '@mathjax/src/mjs/types/dom/lite.js'; - -export function init = EMPTY>( - config: MATHJAX_CONFIG -): Promise>; diff --git a/components/mjs/node-main/node-main.js b/components/mjs/node-main/node-main.js deleted file mode 100644 index bbb67b9ab4..0000000000 --- a/components/mjs/node-main/node-main.js +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************* - * - * Copyright (c) 2019-2026 The MathJax Consortium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Load the needed MathJax components - */ - -import '../startup/init.js'; -import {Loader, CONFIG} from '#js/components/loader.js'; -import {MathJax, combineDefaults, combineConfig} from '#js/components/global.js'; -import {resolvePath} from '#js/util/AsyncLoad.js'; -import {context} from '#js/util/context.js'; -import '../core/core.js'; -import '../adaptors/liteDOM/liteDOM.js'; -import {source} from '../source.js'; -import {mathjax} from '#js/mathjax.js'; -import {Locale} from '#js/util/Locale.js'; -import {Package} from '#js/components/package.js'; - -const REQUIRE = eval('require'); // get require from node, not webpack -const path = REQUIRE("path"); -const dir = context.path(MathJax.config.__dirname); // set up by node-main.mjs or node-main.cjs - -/* - * Set up the initial configuration - */ -combineDefaults(MathJax.config, 'loader', { - paths: {'mathjax-newcm': '@mathjax/mathjax-newcm-font'}, - require: eval("(file) => import(file)"), // use dynamic imports - failed: (err) => {throw err} // pass on error message to init()'s catch function -}); -combineDefaults(MathJax.config, 'output', {font: 'mathjax-newcm'}); - -/* - * Mark the preloaded components - */ -Loader.preLoaded('loader', 'startup', 'core', 'adaptors/liteDOM'); - -/* - * Set the paths. - */ -if (path.basename(dir) === 'node-main') { - CONFIG.paths.esm = CONFIG.paths.mathjax; - CONFIG.paths.sre = '[esm]/sre'; - CONFIG.paths.mathjax = path.resolve(dir, '..', '..', '..', 'bundle'); - combineDefaults(CONFIG, 'source', source); -} else { - CONFIG.paths.mathjax = dir; -} - -/* - * Set the asynchronous loader to handle json files - */ -mathjax.asyncLoad = function (name) { - return REQUIRE( - resolvePath( - name, - (name) => path.resolve(CONFIG.paths.mathjax, name), - (name) => Package.resolvePath(name) - ) - ); -}; -mathjax.asyncIsSynchronous = true; - -/* - * The initialization function. Use as: - * - * require('mathjax').init({ ... }).then((MathJax) => { ... }); - * - * or - * - * import {init} from 'mathjax'; - * init({...}).then((MathJax) => {...}); - * - * where the argument to init() is a MathJax configuration (what would be set as MathJax = {...}). - * The init() function returns a promise that is resolved when MathJax is loaded and ready, and that - * is passed the MathJax global variable when it is called. - */ -const init = MathJax.init = (config = {}) => { - combineConfig(MathJax.config, config); - return Locale.setLocale(MathJax.config.locale ?? Locale.current) - .then(() => Loader.load(...CONFIG.load)) - .then(() => CONFIG.ready()) - .then(() => MathJax.startup.promise) // Wait for MathJax to finish starting up - .then(() => MathJax) // Pass MathJax global as argument to subsequent .then() calls - .catch(error => CONFIG.failed(error)); -} - -/* - * Export MathJax (with its init() function) - */ -export {MathJax}; diff --git a/components/mjs/node-main/node-main.mjs b/components/mjs/node-main/node-main.mjs deleted file mode 100644 index 0276610bea..0000000000 --- a/components/mjs/node-main/node-main.mjs +++ /dev/null @@ -1,4 +0,0 @@ -import './node-main-setup.cjs'; -import {MathJax} from './node-main.js'; -export default MathJax; -export const init = MathJax.init; diff --git a/components/mjs/node-main/webpack.cjs b/components/mjs/node-main/webpack.cjs deleted file mode 100644 index 28f1a59514..0000000000 --- a/components/mjs/node-main/webpack.cjs +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = (pkg) => { - pkg.output.library = { - name: 'MathJax', - type: 'commonjs', - export: ['MathJax'], - } - return pkg; -} diff --git a/components/mjs/startup/init.d.ts b/components/mjs/startup/init.d.ts index cad7a25876..9e91f1164b 100644 --- a/components/mjs/startup/init.d.ts +++ b/components/mjs/startup/init.d.ts @@ -1 +1,2 @@ export function startup(ready: () => Promise): Promise; +export function readyAfter(component: string, setup: () => Promise): Promise; diff --git a/components/mjs/startup/init.js b/components/mjs/startup/init.js index e51fbf1a42..96cb8be184 100644 --- a/components/mjs/startup/init.js +++ b/components/mjs/startup/init.js @@ -15,6 +15,15 @@ combineDefaults(MathJax.config.loader, 'paths', paths); combineDefaults(MathJax.config.loader, 'provides', provides); combineDefaults(MathJax.config.loader, 'source', compatibility); +/** + * Perform the startup actions: + * - Set the locale + * - Load the configured components + * - Perform the ready action, if any + * - Do the loader's ready() function + * - If an error, do the loader's failed() function + * - If that throws an error, reject the startup promise + */ export function startup(ready) { let locale = MathJax.config.locale ?? Locale.current; try { locale = localStorage.getItem('MathJax-locale') ?? locale; } catch (_err) {} @@ -22,5 +31,28 @@ export function startup(ready) { .then(() => Loader.load(...CONFIG.load)) .then(() => (ready || function () {})()) .then(() => CONFIG.ready()) - .catch(error => CONFIG.failed(error)); + .catch((error) => CONFIG.failed(error)) + .catch((error) => MathJax.startup.promiseReject(error)); +} + +/** + * Use the checkReady() function for the component to wait for the + * startup actions to complete before the component is considered + * fully loaded. + */ +export function readyAfter(component, startup) { + const load = new Promise((resolve) => { + MathJax.config.loader[component] ??= {}; + const config = MathJax.config.loader[component]; + const ready = config.checkReady; + config.checkReady = + () => load.then(() => { + if (ready) { + config.checkReady = ready; + return ready(); + } + }); + startup().then(resolve); + }); + return load; } diff --git a/components/mjs/startup/startup.js b/components/mjs/startup/startup.js index 96a5862f09..2046eee234 100644 --- a/components/mjs/startup/startup.js +++ b/components/mjs/startup/startup.js @@ -1,3 +1,7 @@ -import {startup} from './init.js'; +import { startup, readyAfter } from './init.js'; +import { Loader } from '#js/components/loader.js'; -startup(); +const COMPONENT = 'startup'; + +Loader.saveVersion(COMPONENT); +readyAfter(COMPONENT, startup); diff --git a/components/mjs/tex-chtml-nofont/tex-chtml-nofont.js b/components/mjs/tex-chtml-nofont/tex-chtml-nofont.js index a76417c015..797341570b 100644 --- a/components/mjs/tex-chtml-nofont/tex-chtml-nofont.js +++ b/components/mjs/tex-chtml-nofont/tex-chtml-nofont.js @@ -1,17 +1,19 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-chtml-nofont'; + Loader.preLoaded( 'core', 'input/tex', 'output/chtml', 'ui/menu' ); -Loader.saveVersion('tex-chtml-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/tex-chtml/tex-chtml.js b/components/mjs/tex-chtml/tex-chtml.js index 914858dcf1..d9528ebc35 100644 --- a/components/mjs/tex-chtml/tex-chtml.js +++ b/components/mjs/tex-chtml/tex-chtml.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-chtml'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/chtml', 'ui/menu' ); -Loader.saveVersion('tex-chtml'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/components/mjs/tex-mml-chtml-nofont/tex-mml-chtml-nofont.js b/components/mjs/tex-mml-chtml-nofont/tex-mml-chtml-nofont.js index ccb4ea1be2..8bbc61befc 100644 --- a/components/mjs/tex-mml-chtml-nofont/tex-mml-chtml-nofont.js +++ b/components/mjs/tex-mml-chtml-nofont/tex-mml-chtml-nofont.js @@ -1,12 +1,14 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-mml-chtml-nofont'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -14,6 +16,6 @@ Loader.preLoaded( 'output/chtml', 'ui/menu' ); -Loader.saveVersion('tex-mml-chtml-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/tex-mml-chtml/tex-mml-chtml.js b/components/mjs/tex-mml-chtml/tex-mml-chtml.js index c9baf3e49e..375d684397 100644 --- a/components/mjs/tex-mml-chtml/tex-mml-chtml.js +++ b/components/mjs/tex-mml-chtml/tex-mml-chtml.js @@ -1,12 +1,14 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/chtml/chtml.js'; +import { loadFont } from '../output/chtml/chtml.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-mml-chtml'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -14,6 +16,6 @@ Loader.preLoaded( 'output/chtml', 'ui/menu' ); -Loader.saveVersion('tex-mml-chtml'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/components/mjs/tex-mml-svg-nofont/tex-mml-svg-nofont.js b/components/mjs/tex-mml-svg-nofont/tex-mml-svg-nofont.js index 934f9880b5..c13f8c6841 100644 --- a/components/mjs/tex-mml-svg-nofont/tex-mml-svg-nofont.js +++ b/components/mjs/tex-mml-svg-nofont/tex-mml-svg-nofont.js @@ -1,12 +1,14 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-mml-svg-nofont'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -14,6 +16,6 @@ Loader.preLoaded( 'output/svg', 'ui/menu' ); -Loader.saveVersion('tex-mml-svg-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/tex-mml-svg/tex-mml-svg.js b/components/mjs/tex-mml-svg/tex-mml-svg.js index d4c06ee5e2..59510ab28f 100644 --- a/components/mjs/tex-mml-svg/tex-mml-svg.js +++ b/components/mjs/tex-mml-svg/tex-mml-svg.js @@ -1,12 +1,14 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; import '../input/mml/mml.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-mml-svg'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -14,6 +16,6 @@ Loader.preLoaded( 'output/svg', 'ui/menu' ); -Loader.saveVersion('tex-mml-svg'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/components/mjs/tex-svg-nofont/tex-svg-nofont.js b/components/mjs/tex-svg-nofont/tex-svg-nofont.js index 308c355a8b..6af9375fff 100644 --- a/components/mjs/tex-svg-nofont/tex-svg-nofont.js +++ b/components/mjs/tex-svg-nofont/tex-svg-nofont.js @@ -1,17 +1,19 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-svg-nofont'; + Loader.preLoaded( 'core', 'input/tex', 'output/svg', 'ui/menu' ); -Loader.saveVersion('tex-svg-nofont'); +Loader.saveVersion(COMPONENT); -loadFont(startup); +readyAfter(COMPONENT, () => loadFont(startup)); diff --git a/components/mjs/tex-svg/tex-svg.js b/components/mjs/tex-svg/tex-svg.js index a3d23875c4..e409c49e0f 100644 --- a/components/mjs/tex-svg/tex-svg.js +++ b/components/mjs/tex-svg/tex-svg.js @@ -1,11 +1,13 @@ -import {startup} from '../startup/init.js'; -import {Loader} from '#js/components/loader.js'; +import { startup, readyAfter } from '../startup/init.js'; +import { Loader } from '#js/components/loader.js'; import '../core/core.js'; import '../input/tex/tex.js'; -import {loadFont} from '../output/svg/svg.js'; +import { loadFont } from '../output/svg/svg.js'; import '../ui/menu/menu.js'; import '../a11y/util.js'; +const COMPONENT = 'tex-svg'; + Loader.preLoaded( 'loader', 'startup', 'core', @@ -13,6 +15,6 @@ Loader.preLoaded( 'output/svg', 'ui/menu' ); -Loader.saveVersion('tex-svg'); +Loader.saveVersion(COMPONENT); -loadFont(startup, true); +readyAfter(COMPONENT, () => loadFont(startup, true)); diff --git a/package.json b/package.json index 5dc4f53f07..07f5b2479c 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,20 @@ "type": "module", "main": "components/mjs/node-main/node-main.js", "exports": { - ".": { - "import": "./bundle/node-main.mjs", - "require": "./bundle/node-main.cjs" - }, + ".": "./bundle/main/main.js", + "./node": "./bundle/main/node.js", + "./browser": "./bundle/main/browser.js", "./source": { - "import": "./components/mjs/node-main/node-main.mjs", - "require": "./components/cjs/node-main/node-main.cjs" + "import": "./components/mjs/main/main.js", + "require": "./components/cjs/main/main.js" + }, + "./node/source": { + "import": "./components/mjs/main/node/node.js", + "require": "./components/cjs/main/node/node.js" + }, + "./browser/source": { + "import": "./components/mjs/main/browser/browser.js", + "require": "./components/cjs/main/browser/browser.js" }, "./js/*": { "import": "./mjs/*", @@ -103,7 +110,7 @@ "cjs:bundle:clean": "pnpm --silent clean:dir bundle-cjs", "cjs:bundle:finalize": "pnpm --silent log:single 'Finalize cjs bundle'; echo '{\n \"type\": \"commonjs\"\n}' > bundle-cjs/package.json;", "cjs:compile": "pnpm --silent cjs:copy:components && pnpm --silent cjs:copy:ts && pnpm --silent cjs:compile:tsc", - "cjs:compile:tsc": "pnpm --silent log:single 'Compiling cjs typescript files' && pnpm tsc --project tsconfig/worker-cjs.json && pnpm tsc --project tsconfig/cjs.json", + "cjs:compile:tsc": "pnpm --silent log:single 'Compiling cjs typescript files' && pnpm tsc --project tsconfig/cjs.json && pnpm tsc --project tsconfig/worker-cjs.json", "cjs:components:build": "pnpm --silent log:comp 'Building cjs components'; pnpm --silent cjs:components:src:build && pnpm --silent clean:dir bundle-cjs && pnpm --silent cjs:components:make --build", "cjs:components:clean": "pnpm --silent log:single \"Cleaning cjs components\"; pnpm rimraf components/cjs", "cjs:components:compile": "pnpm --silent log:single 'Compiling component files'; pnpm tsc --project tsconfig/components.json", diff --git a/testsuite/src/setupTex.ts b/testsuite/src/setupTex.ts index f88459e6c7..80ee088af8 100644 --- a/testsuite/src/setupTex.ts +++ b/testsuite/src/setupTex.ts @@ -17,7 +17,7 @@ import { mathjax } from '#js/mathjax.js'; import { OptionList } from '#js/util/Options.js'; import { tmpJsonFile } from '#src/constants.js'; import * as fs from 'fs'; -import { init } from '#source/node-main/node-main.mjs'; +import { init } from '#source/main/main.js'; import { expect } from '@jest/globals'; import { source } from '#source/source.js'; import { Locale } from '#js/util/Locale.js'; diff --git a/ts/a11y/explorer/Region.ts b/ts/a11y/explorer/Region.ts index ae2d2c7594..475c820fd6 100644 --- a/ts/a11y/explorer/Region.ts +++ b/ts/a11y/explorer/Region.ts @@ -115,7 +115,7 @@ export abstract class AbstractRegion implements Region { * @returns {string} The stylesheet ID */ public static get sheetId(): string { - return 'MJX-' + this.name + '-styles'; + return this.className + '-styles'; } /** diff --git a/ts/a11y/semantic-enrich.ts b/ts/a11y/semantic-enrich.ts index 82a9d93f45..7408159ccf 100644 --- a/ts/a11y/semantic-enrich.ts +++ b/ts/a11y/semantic-enrich.ts @@ -447,6 +447,7 @@ export function EnrichedMathDocumentMixin< */ constructor(...args: any[]) { super(...args); + this.options.sre.locale = Locale.current; MmlJax.setMmlFactory(this.mmlFactory); const ProcessBits = (this.constructor as typeof AbstractMathDocument) .ProcessBits; diff --git a/ts/components/cjs/json.ts b/ts/components/cjs/json.ts index ae4a23afd0..fd738eb02b 100644 --- a/ts/components/cjs/json.ts +++ b/ts/components/cjs/json.ts @@ -27,4 +27,4 @@ import { context } from '../../util/context.js'; export const json = context.window ? (file: string) => fetch(file).then((data) => data.json()) - : (file: string) => require(file); + : (file: string) => require(/* webpackIgnore: true */ file); diff --git a/ts/components/loader.ts b/ts/components/loader.ts index d4853edd81..a44119c1d8 100644 --- a/ts/components/loader.ts +++ b/ts/components/loader.ts @@ -41,6 +41,7 @@ import { FunctionList } from '../util/FunctionList.js'; import { mjxRoot } from '#root/root.js'; import { context } from '../util/context.js'; import { OPTIONAL } from '../types/Types.js'; +import { EXPANDABLE_LIST_OF } from '../util/Options.js'; import { Locale } from '../util/Locale.js'; import { COMPONENT } from '../core/__locales__/Component.js'; @@ -70,7 +71,7 @@ export type LOADER_OPTIONS = { ready: PackageReady; // A function to call when MathJax is ready failed: PackageFailed; // A function to call when MathJax fails to load require: (url: string) => any; // A function for loading URLs - json: (url: string) => any; // A function for loading JSON files + json: (url: string) => Promise; // A function for loading JSON files pathFilters: PathFilterList; // List of path filters (and optional priorities) to add versionWarnings: boolean; // True means warn when extension version doesn't match MJ version }; @@ -78,9 +79,7 @@ export type LOADER_OPTIONS = { /** * The loader config option types. It allows for package-specific configuration. */ -export interface LOADER_CONFIG extends LOADER_OPTIONS { - [component: string]: any; // should be PackageConfig, but that causes problems with LOADER_TYPES -} +export type LOADER_CONFIG = EXPANDABLE_LIST_OF & LOADER_OPTIONS; /** * Functions used to filter the path to a package @@ -306,7 +305,7 @@ export const Loader = { */ defaultReady() { if (typeof MathJax.startup !== 'undefined') { - MathJax.config.startup.ready(); + MathJax.config.startup.ready.call(MathJax.startup, MathJax); } }, @@ -396,7 +395,7 @@ const options: LOADER_OPTIONS = { export type LOADER_TYPES = { component: { loader: true }; config: { - loader: LOADER_CONFIG; + loader: LOADER_OPTIONS; }; properties: { loader: typeof Loader; @@ -443,6 +442,12 @@ if (typeof MathJax.loader === 'undefined') { Loader.pathFilters.add(filter); } } +} else if (MathJax.loader !== Loader) { + MathJax.loader.versions = Loader.versions; + MathJax.loader.pathFilters = Loader.pathFilters; + for (const [name, value] of Package.packages.entries()) { + MathJax._.components.package.Package.packages.add(name, value); + } } /** diff --git a/ts/components/mjs/json.ts b/ts/components/mjs/json.ts index f23bba2d07..0abfdf4918 100644 --- a/ts/components/mjs/json.ts +++ b/ts/components/mjs/json.ts @@ -25,4 +25,5 @@ import { context } from '../../util/context.js'; export const json = context.window ? (file: string) => fetch(file).then((data) => data.json()) - : (file: string) => import(file, { with: { type: 'json' } }); + : (file: string) => + import(/* webpackIgnore: true */ file, { with: { type: 'json' } }); diff --git a/ts/components/package.ts b/ts/components/package.ts index 0948fe599c..a638d07758 100644 --- a/ts/components/package.ts +++ b/ts/components/package.ts @@ -22,7 +22,7 @@ * @author dpvc@mathjax.org (Davide Cervone) */ -import { CONFIG, Loader } from './loader.js'; +import { CONFIG, Loader, MathJax, MathJaxObject } from './loader.js'; import { context } from '../util/context.js'; import { localize } from '../core/__locales__/Component.js'; @@ -45,8 +45,9 @@ export class PackageError extends Error { /** * Types for ready() and failed() functions and for promises */ -export type PackageReady = (name: string) => string | void; -export type PackageFailed = (message: PackageError) => void; +export type PackageReady = (name: string, mjx: MathJaxObject) => string | void; +export type PackageFailed = (message: PackageError, mjx: MathJaxObject) => void; +export type PackageCheck = (mjx: MathJaxObject) => Promise | void; export type PackagePromise = ( resolve: PackageReady, reject: PackageFailed @@ -59,7 +60,7 @@ export type PackagePromise = ( export interface PackageConfig { ready?: PackageReady; // Function to call when package is loaded successfully failed?: PackageFailed; // Function to call when package fails to load - checkReady?: () => Promise; // Function called to see if package is fully loaded + checkReady?: PackageCheck; // Function called to see if package is fully loaded // (may cause additional packages to load, for example) extraLoads?: string[]; // Extra packages to load after this one rendererExtensions?: string[]; // Font extensions to load when renderer changes @@ -164,7 +165,9 @@ export class Package { ? Loader.load(...config.extraLoads) : Promise.resolve(); const checkReady = config.checkReady || (() => Promise.resolve()); - return promise.then(() => checkReady()) as Promise; + return promise.then(() => + checkReady.call(Loader, MathJax) + ) as Promise; } /** @@ -267,7 +270,7 @@ export class Package { const config = (CONFIG[this.name] || {}) as PackageConfig; if (config.ready) { promise = promise.then((_name: string) => - config.ready(this.name) + config.ready.call(Loader, this.name, MathJax) ) as Promise; } // @@ -286,9 +289,14 @@ export class Package { // Add a catch to handle the error // if (config.failed) { - promise.catch((message: string) => - config.failed(new PackageError(message, this.name)) - ); + promise = promise.catch((message: string) => { + config.failed.call( + Loader, + new PackageError(message, this.name), + MathJax + ); + return ''; + }); } // // Return the promise that represents when this file is loaded @@ -367,7 +375,7 @@ export class Package { for (const provided of this.provided) { provided.loaded(); } - this.resolve(this.name); + this.resolve.call(Loader, this.name, MathJax); } /** @@ -381,7 +389,7 @@ export class Package { protected failed(message: string) { this.hasFailed = true; this.isLoading = false; - this.reject(new PackageError(message, this.name)); + this.reject.call(Loader, new PackageError(message, this.name), MathJax); } /** diff --git a/ts/components/startup.ts b/ts/components/startup.ts index bc9f6cae22..4e95302256 100644 --- a/ts/components/startup.ts +++ b/ts/components/startup.ts @@ -50,6 +50,8 @@ import { DOM, DOM_TYPES, N, T, D, OPTIONAL } from '../types/Types.js'; import { TeX } from '../input/tex.js'; +export type ReadyFunction = (mjx: MathJaxObject) => T; + /** * The option types for the startup component. */ @@ -61,8 +63,8 @@ export type STARTUP_OPTIONS = { document: any; // The document (or fragment or string) to work in elements: any[]; // The elements to typeset (default is document body) typeset: boolean; // Perform initial typeset? - ready: () => void; // Function to perform when components are ready - pageReady: () => void; // Function to perform when page is ready + ready: ReadyFunction; // Function to perform when components are ready + pageReady: ReadyFunction>; // Function to perform when page is ready invalidOption?: 'fatal' | 'warn'; // Do invalid options produce a warning, or throw an error? optionError?: (message: string, key: string) => void; // Function to report invalid options loadAllFontFiles: boolean; // true means force all dynamic font files to load initially @@ -72,30 +74,18 @@ export type STARTUP_OPTIONS = { /** * Generic types for the standard MathJax objects */ -export type MATHDOCUMENT
= MathDocument< - N
, - T
, - D
-> & { +/* prettier-ignore */ +export type MATHDOCUMENT
= MathDocument, T
, D
> & { menu?: { loadingPromise: Promise }; options: { elements?: N
[] }; }; export type HANDLER
= Handler, T
, D
>; -export type DOMADAPTOR
= DOMAdaptor< - N
, - T
, - D
->; -export type INPUTJAX
= InputJax< - N
, - T
, - D
->; -export type OUTPUTJAX
= OutputJax< - N
, - T
, - D
->; +/* prettier-ignore */ +export type DOMADAPTOR
= DOMAdaptor, T
, D
>; +/* prettier-ignore */ +export type INPUTJAX
= InputJax, T
, D
>; +/* prettier-ignore */ +export type OUTPUTJAX
= OutputJax, T
, D
>; /* prettier-ignore */ export type COMMONJAX
= CommonOutputJax, T
, D
, any, any, any, any, any, any, any, any>; @@ -327,7 +317,7 @@ export abstract class Startup { Startup.getComponents(); Startup.makeMethods(); Startup.pagePromise - .then(() => CONFIG.pageReady()) // usually the initial typesetting call + .then(() => CONFIG.pageReady.call(Startup, MathJax)) // usually the initial typesetting call .then(() => Startup.promiseResolve()) .catch((err) => Startup.promiseReject(err)); } @@ -347,7 +337,7 @@ export abstract class Startup { ? (Startup.output as COMMONJAX).font.loadDynamicFiles() : Promise.resolve() ) - .then(() => Startup.document.menu?.loadingPromise) + .then(() => Startup.document?.menu?.loadingPromise) .then( CONFIG.typeset && MathJax.typesetPromise ? () => Startup.typesetPromise(CONFIG.elements) diff --git a/ts/output/common/FontData.ts b/ts/output/common/FontData.ts index d7b17cbc4c..d068c9524d 100644 --- a/ts/output/common/FontData.ts +++ b/ts/output/common/FontData.ts @@ -1270,7 +1270,7 @@ export class FontData< COMPONENT, 'FontData/CantLoad', dynamic.file, - err.message + err.message ?? err ); return (dynamic.promise = Promise.resolve()); } diff --git a/ts/types/Components.ts b/ts/types/Components.ts index 5de7dc243e..057c986d9a 100644 --- a/ts/types/Components.ts +++ b/ts/types/Components.ts @@ -34,7 +34,10 @@ import type { N, T, D, + EMPTY, } from './Types.js'; +import type { LITE_DOM } from './dom/lite.js'; +import type { HTML_DOM } from './dom/html.js'; import type { STARTUP_TYPES } from '../components/startup.js'; import type { LOADER_TYPES } from '../components/loader.js'; @@ -109,6 +112,8 @@ import type { SafeMathDocument, } from '../ui/safe/SafeHandler.js'; +type COMBINED = U | 'startup' | EMPTY_COMPONENT; + /** * The mapping of component names to their component definitions. * @@ -135,46 +140,46 @@ export type COMPONENTS = { > | '__base__'; - '[tex]/action': EMPTY_COMPONENT<'[tex]/action'>; + '[tex]/action': TEX_PACKAGE<'action'>; '[tex]/ams': TEX_PACKAGE<'ams', AMS_OPTIONS>; '[tex]/amscd': TEX_PACKAGE<'amscd', AMSCD_OPTIONS>; '[tex]/autoload': TEX_PACKAGE<'autoload', AUTOLOAD_OPTIONS>; '[tex]/bbm': TEX_PACKAGE<'bbm', BBM_OPTIONS>; '[tex]/bboldx': TEX_PACKAGE<'bboldx', BBOLDX_OPTIONS>; - '[tex]/bbox': EMPTY_COMPONENT<'[tex]/bbox'>; + '[tex]/bbox': TEX_PACKAGE<'bbox'>; '[tex]/begingroup': TEX_PACKAGE<'begingroup', BEGINGROUP_OPTIONS>; - '[tex]/boldsymbol': EMPTY_COMPONENT<'[tex]/boldsymbol'>; - '[tex]/braket': EMPTY_COMPONENT<'[tex]/braket'>; - '[tex]/bussproofs': EMPTY_COMPONENT<'[tex]/bussproofs'>; - '[tex]/cancel': EMPTY_COMPONENT<'[tex]/cancel'>; - '[tex]/cases': EMPTY_COMPONENT<'[tex]/cases'>; - '[tex]/centernot': EMPTY_COMPONENT<'[tex]/centernot'>; + '[tex]/boldsymbol': TEX_PACKAGE<'boldsymbol'>; + '[tex]/braket': TEX_PACKAGE<'braket'>; + '[tex]/bussproofs': TEX_PACKAGE<'bussproofs'>; + '[tex]/cancel': TEX_PACKAGE<'cancel'>; + '[tex]/cases': TEX_PACKAGE<'cases'>; + '[tex]/centernot': TEX_PACKAGE<'centernot'>; '[tex]/color': TEX_PACKAGE<'color', COLOR_OPTIONS>; - '[tex]/colorv2': EMPTY_COMPONENT<'[tex]/colorv2'>; + '[tex]/colorv2': TEX_PACKAGE<'colorv2'>; '[tex]/configmacros': TEX_PACKAGE<'configmacros', CONFIGMACROS_OPTIONS>; '[tex]/dsfont': TEX_PACKAGE<'dsfont', DSFONT_OPTIONS>; - '[tex]/empheq': EMPTY_COMPONENT<'[tex]/empheq'>; - '[tex]/enclose': EMPTY_COMPONENT<'[tex]/enclose'>; - '[tex]/extpfeil': EMPTY_COMPONENT<'[tex]/extpfeil'>; - '[tex]/fontsizev3': EMPTY_COMPONENT<'[tex]/fontsizev3'>; - '[tex]/gensymb': EMPTY_COMPONENT<'[tex]/gensymb'>; - '[tex]/html': EMPTY_COMPONENT<'[tex]/html'>; + '[tex]/empheq': TEX_PACKAGE<'empheq'>; + '[tex]/enclose': TEX_PACKAGE<'enclose'>; + '[tex]/extpfeil': TEX_PACKAGE<'extpfeil'>; + '[tex]/fontsizev3': TEX_PACKAGE<'fontsizev3'>; + '[tex]/gensymb': TEX_PACKAGE<'gensymb'>; + '[tex]/html': TEX_PACKAGE<'html'>; '[tex]/mathtools': TEX_PACKAGE<'mathtools', MATHTOOLS_OPTIONS>; - '[tex]/mhchem': EMPTY_COMPONENT<'[tex]/mhchem'>; + '[tex]/mhchem': TEX_PACKAGE<'mhchem'>; '[tex]/newcommand': TEX_PACKAGE<'newcommand', NEWCOMMAND_OPTIONS>; - '[tex]/noerrors': EMPTY_COMPONENT<'[tex]/noerrors'>; + '[tex]/noerrors': TEX_PACKAGE<'noerrors'>; '[tex]/noundefined': TEX_PACKAGE<'noundefined', NOUNDEFINED_OPTIONS>; '[tex]/physics': TEX_PACKAGE<'physics', PHYSICS_OPTIONS>; '[tex]/require': TEX_PACKAGE<'require', REQUIRE_OPTIONS>; '[tex]/setoptions': TEX_PACKAGE<'setoptions', SETOPTIONS_OPTIONS>; '[tex]/tagformat': TEX_PACKAGE<'tagformat', TAGFORMAT_OPTIONS>; '[tex]/texhtml': TEX_PACKAGE<'texhtml', TEXHTML_OPTIONS>; - '[tex]/textcomp': EMPTY_COMPONENT<'[tex]/textcomp'>; + '[tex]/textcomp': TEX_PACKAGE<'textcomp'>; '[tex]/textmacros': TEX_PACKAGE<'textmacros', TEXTMACROS_OPTIONS>; - '[tex]/unicode': EMPTY_COMPONENT<'[tex]/unicode'>; + '[tex]/unicode': TEX_PACKAGE<'unicode'>; '[tex]/units': TEX_PACKAGE<'units', UNITS_OPTIONS>; - '[tex]/upgreek': EMPTY_COMPONENT<'[tex]/upgreek'>; - '[tex]/verb': EMPTY_COMPONENT<'[tex]/verb'>; + '[tex]/upgreek': TEX_PACKAGE<'upgreek'>; + '[tex]/verb': TEX_PACKAGE<'verb'>; '[mml]/mml3': MML_PACKAGE<'mml3', MML3_OPTIONS>; 'input/mml/entities': EMPTY_COMPONENT<'input/mml/entities'>; @@ -220,35 +225,59 @@ export type COMPONENTS = { startup: STARTUP_TYPES & LOADER_TYPES & - DOC_OPTIONS & HTMLDOMSTRINGS_OPTIONS>; - loader: LOADER_TYPES; + DOC_OPTIONS & HTMLDOMSTRINGS_OPTIONS> & { + config: { locale: string }; + }; + loader: LOADER_TYPES & { config: { locale: string } }; - 'mml-chtml': - 'input/mml' | 'output/chtml' | 'ui/menu' | '__a11y__' | 'startup'; - 'mml-chtml-nofont': 'mml-chtml'; - 'mml-svg': 'input/mml' | 'output/svg' | 'ui/menu' | '__a11y__' | 'startup'; - 'mml-svg-nofont': 'mml-svg'; - 'tex-chtml': - 'input/tex' | 'output/chtml' | 'ui/menu' | '__a11y__' | 'startup'; - 'tex-chtml-nofont': 'tex-chtml'; - 'tex-mml-chtml': - | 'input/tex' - | 'input/mml' - | 'output/chtml' - | 'ui/menu' - | '__a11y__' - | 'startup'; - 'tex-mml-chtml-nofont': 'tex-mml-chtml'; - 'tex-svg': 'input/tex' | 'output/svg' | 'ui/menu' | '__a11y__' | 'startup'; - 'tex-svg-nofont': 'tex-svg'; - 'tex-mml-svg': - | 'input/tex' - | 'input/mml' - | 'output/svg' - | 'ui/menu' - | '__a11y__' - | 'startup'; - 'tex-mml-svg-nofont': 'tex-mml-svg'; + 'mml-chtml': COMBINED< + 'mml-chtml', + 'input/mml' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'mml-chtml-nofont': COMBINED< + 'mml-chtml-nofont', + 'input/mml' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'mml-svg': COMBINED< + 'mml-svg', + 'input/mml' | 'output/svg' | 'ui/menu' | '__a11y__' + >; + 'mml-svg-nofont': COMBINED< + 'mml-svg-nofont', + 'input/mml' | 'output/svg' | 'ui/menu' | '__a11y__' + >; + 'tex-chtml': COMBINED< + 'tex-chtml', + 'input/tex' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'tex-chtml-nofont': COMBINED< + 'tex-chtml-nofont', + 'input/tex' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'tex-mml-chtml': COMBINED< + 'tex-mml-chtml', + 'input/tex' | 'input/mml' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'tex-mml-chtml-nofont': COMBINED< + 'tex-mml-chtml-nofont', + 'input/tex' | 'input/mml' | 'output/chtml' | 'ui/menu' | '__a11y__' + >; + 'tex-svg': COMBINED< + 'tex-svg', + 'input/tex' | 'output/svg' | 'ui/menu' | '__a11y__' + >; + 'tex-svg-nofont': COMBINED< + 'tex-svg-nofont', + 'input/tex' | 'output/svg' | 'ui/menu' | '__a11y__' + >; + 'tex-mml-svg': COMBINED< + 'tex-mml-svg', + 'input/tex' | 'input/mml' | 'output/svg' | 'ui/menu' | '__a11y__' + >; + 'tex-mml-svg-nofont': COMBINED< + 'tex-mml-svg-nofont', + 'input/tex' | 'input/mml' | 'output/svg' | 'ui/menu' | '__a11y__' + >; __base__: TEX_CONFIG; __PACKAGES__: @@ -261,4 +290,27 @@ export type COMPONENTS = { | '[tex]/autoload' | '[tex]/require'; __a11y__: 'a11y/explorer' | 'input/mml'; + __NONE__: EMPTY; +}; + +/** + * The DOM adaptor definitions + */ +export type ADAPTORS = { + liteDOM: { + component: COMPONENTS['adaptors/liteDOM']; + DOM: LITE_DOM; + }; + jsdom: { + component: COMPONENTS['adaptors/jsdom']; + DOM: HTML_DOM; + }; + linkedom: { + component: COMPONENTS['adaptors/linkedom']; + DOM: HTML_DOM; + }; + browser: { + component: EMPTY; + DOM: HTML_DOM; + }; }; diff --git a/ts/types/Types.ts b/ts/types/Types.ts index fb9e0c6b73..30073f392f 100644 --- a/ts/types/Types.ts +++ b/ts/types/Types.ts @@ -72,6 +72,11 @@ export type JAXLIST = { [jax: string]: true }; */ export type COMPONENTLIST = { [name: string]: true }; +/** + * A list with tex package names as keys + */ +export type PACKAGELIST = { [name: string]: true }; + /** * A component configuration object */ @@ -81,6 +86,7 @@ export type COMPONENT_DEF = { input?: JAXLIST; output?: JAXLIST; component?: COMPONENTLIST; + tex_package?: PACKAGELIST; }; /** @@ -184,7 +190,49 @@ export type LOADER = : EMPTY; /** - * Define document options + * Restrict the loader.load array to the components that were specified. + * + * @template T The configurtation object + * @template C The components that can be loaded + */ +/* prettier-ignore */ +export type LOAD = + T extends { loader: { load: string[] } } + ? Omit & { loader: Omit & { load: C[] } } + : T; + +/** + * Restrict the tex.package array to the packages that were loaded. + * + * @template T The configurtation object + * @template C The packages that were loaded + */ +/* prettier-ignore */ +export type PACKAGES = + T extends { tex: { packages: string[] } } + ? Omit & { tex: Omit & { packages: C[] } } + : T; + +/** + * Give a proper type for the argument to ready() and pageRady(). + * + * @template T The configurtation object + * @template M The MathJax object type to use + */ +/* prettier-ignore */ +export type READY = + T extends { startup: { ready: any, pageReady: any } } + ? Omit & + { + startup: Omit & { + ready(mjx: M): void; + pageReady(mjx: M): Promise; + } + } + : T; + +/** + * Define document options. * * @template C The options to define */ @@ -195,7 +243,7 @@ export type DOC_OPTIONS = { }; /** - * Define the startup document type + * Define the startup document type. * * @template T The document type to use */ @@ -222,9 +270,10 @@ export type EMPTY_COMPONENT = { * @template N The name of the package * @template C The package options */ -export type TEX_PACKAGE = { +export type TEX_PACKAGE = { component: { [name in N as `[tex]/${name}`]: true }; config: { tex: C }; + tex_package: { [name in N]: true }; }; /** @@ -283,17 +332,29 @@ export type OUTPUTJAX = { /** * Create the `config` property from the definition's `config` and `component` properties + * + * @template T The component configuration object + * @template D The DOM node types + * @template R True if ready functions should be modified, false if not */ /* prettier-ignore */ -export type CONFIG = - OPTIONAL>; +export type CONFIG = + OPTIONAL< + LOAD< + PACKAGES< + R extends true ? READY> : T['config'], + keyof T['tex_package'] + >, + keyof COMPONENTS_OF + > & LOADER + >; /** * Add types for the MathJax.startup.mathjax.document function so its * options are checked, and its output reflects the type of the * document created by the loaded components. * - * @template T The typ eobject to modify + * @template T The type object to modify */ /* prettier-ignore */ export type ADD_MATHJAX = @@ -308,6 +369,14 @@ export type ADD_MATHJAX = } & Omit : T; +/** + * The (merged) component object (whose keys are the name sof the components) + * in the given component definition list. + * + * @template T The definitions of the components to include (as DEF1 & ... & DEFn) + */ +export type COMPONENTS_OF = T['component']; + /** * The type for the MathJax object based on a collection of component definitions. * This is for both configuration and after Mathjax is loaded. @@ -318,8 +387,8 @@ export type ADD_MATHJAX = /* prettier-ignore */ export type TYPES2MJX = ADD_MATHJAX<{ version?: string, _?: any } & - OPTIONAL>> & - { config?: CONFIG } & + OPTIONAL>> & + { config?: CONFIG } & CONVERTJAX>; /** @@ -327,19 +396,21 @@ export type TYPES2MJX = * * @template T The definitions of the components to include (as DEF1 & ... & DEFn) * @template D The DOM node types to use + * @template R True to adjust ready() and pageReady() parameters */ /* prettier-ignore */ -export type TYPES2MJX_OBJECT = +export type TYPES2MJX_OBJECT = ADD_MATHJAX<{ version: string, _: any } & T['properties'] & - { config: CONFIG_ARRAYS> } & + { config: CONFIG_ARRAYS> } & CONVERTJAX>; /** * The type for the MathJax object as a config object (before loading MathJax). * * @template T The definitions of the components to include (as DEF1 & ... & DEFn) + * @template D The DOM node types to use */ -export type TYPES2MJX_CONFIG = CONFIG_ARRAYS< - CONFIG ->; +/* prettier-ignore */ +export type TYPES2MJX_CONFIG = + CONFIG_ARRAYS>; diff --git a/ts/types/dom/html.ts b/ts/types/dom/html.ts index 6bcfd712f0..bc8c2e46c1 100644 --- a/ts/types/dom/html.ts +++ b/ts/types/dom/html.ts @@ -1,5 +1,4 @@ import { DOM } from '../Types.js'; -import { COMPONENT_LIST, MJX, MJX_OBJECT, MJX_CONFIG } from '../mjx.js'; /** * The HTML DOM elements @@ -8,27 +7,3 @@ export type N = HTMLElement; export type T = Text; export type D = Document; export type HTML_DOM = DOM; - -/** - * The type for the MathJax object based on a collection of component names. - * This is for both configuration and after Mathjax is loaded. - * - * @template T The union of component names, array of names, or definitions. - */ -export type MATHJAX> = MJX; - -/** - * The type for the completed MathJax object (after MathJax is loaded). - * - * @template T The union of component names, array of names, or definitions. - */ -/* prettier-ignore */ -export type MATHJAX_OBJECT> = MJX_OBJECT; - -/** - * The type for the MathJax object as a config object (before loading MathJax). - * - * @template T The union of component names, array of names, or definitions. - */ -/* prettier-ignore */ -export type MATHJAX_CONFIG> = MJX_CONFIG; diff --git a/ts/types/dom/lite.ts b/ts/types/dom/lite.ts index acd01fb296..39a8a4568c 100644 --- a/ts/types/dom/lite.ts +++ b/ts/types/dom/lite.ts @@ -3,7 +3,6 @@ import { LiteDocument } from '../../adaptors/lite/Document.js'; import { LiteText } from '../../adaptors/lite/Text.js'; import { DOM } from '../Types.js'; -import { COMPONENT_LIST, MJX, MJX_OBJECT, MJX_CONFIG } from '../mjx.js'; /** * The HTML DOM elements @@ -12,21 +11,3 @@ export type N = LiteElement; export type T = LiteText; export type D = LiteDocument; export type LITE_DOM = DOM; - -/** - * The type for the MathJax object based on a collection of component names. - * This is for both configuration and after Mathjax is loaded. - */ -export type MATHJAX> = MJX; - -/** - * The type for the completed MathJax object (after MathJax is loaded). - */ -/* prettier-ignore */ -export type MATHJAX_OBJECT> = MJX_OBJECT; - -/** - * The type for the MathJax object as a config object (before loading MathJax). - */ -/* prettier-ignore */ -export type MATHJAX_CONFIG> = MJX_CONFIG; diff --git a/ts/types/mjx.ts b/ts/types/mathjax.ts similarity index 56% rename from ts/types/mjx.ts rename to ts/types/mathjax.ts index 14aa0ee4d9..c9732fd1d1 100644 --- a/ts/types/mjx.ts +++ b/ts/types/mathjax.ts @@ -24,12 +24,13 @@ import type { DOM_TYPES, COMPONENT_DEF, + COMPONENTS_OF, COMBINE, TYPES2MJX, TYPES2MJX_OBJECT, TYPES2MJX_CONFIG, } from './Types.js'; -import { COMPONENTS } from './Components.js'; +import type { COMPONENTS, ADAPTORS } from './Components.js'; /** * A union of component names, array of names, or explicit component definitions. @@ -37,6 +38,11 @@ import { COMPONENTS } from './Components.js'; export type COMPONENT_LIST = COMPONENT_DEF | keyof COMPONENTS | (keyof COMPONENTS)[]; +/** + * The list of adaptor names; + */ +export type ADAPTOR_LIST = keyof ADAPTORS; + /** * Map component names to their type defintions, leaving explicit definitions as they are. * @@ -60,6 +66,16 @@ export type MJX_TYPES, D extends DOM_TYPES> = export type MJX_DEF, D extends DOM_TYPES> = COMBINE)[] ? T[number] : T, D>>; +/** + * They components available in the list of component definitions + * + * @template T The union of component names, array of names, or definitions. + * @template D The DOM node types to use in the types that need them. + */ +/* prettier-ignore */ +export type MJX_COMPONENTS, D extends DOM_TYPES> = + keyof COMPONENTS_OF>; + /** * The type for the MathJax object based on a collection of component names and DOM element types. * This is for both configuration and after Mathjax is loaded. @@ -89,4 +105,49 @@ export type MJX_OBJECT, D extends DOM_TYPES> = */ /* prettier-ignore */ export type MJX_CONFIG, D extends DOM_TYPES> = - TYPES2MJX_CONFIG>; + TYPES2MJX_CONFIG, D>; + +export type ADAPTOR_DOM = ADAPTORS[A]['DOM']; + +/** + * The type for the MathJax object based on a collection of component names and DOM adatpor. + * This is for both configuration and after Mathjax is loaded. + * + * @template T The union of component names, array of names, or definitions. + * @template A The DOM adaptor to use (default is liteDOM). + */ +/* prettier-ignore */ +export type MATHJAX>, A extends ADAPTOR_LIST = 'liteDOM'> = + MJX>; + +/** + * The type for the completed MathJax object (after MathJax is loaded) + * for a given set of components and a DOM adaptor. + * + * @template T The union of component names, array of names, or definitions. + * @template A The DOM adaptor to use (default is liteDOM). + */ +/* prettier-ignore */ +export type MATHJAX_OBJECT>, A extends ADAPTOR_LIST = 'liteDOM'> = + MJX_OBJECT>; + +/** + * The type for the MathJax object as a config object (before loading MathJax) + * for a given set of components and a DOM adaptor. + * + * @template T The union of component names, array of names, or definitions. + * @template A The DOM adaptor to use (default is liteDOM). + */ +/* prettier-ignore */ +export type MATHJAX_CONFIG>, A extends ADAPTOR_LIST = 'liteDOM'> = + MJX_CONFIG>; + +/** + * The components that are configured in the MathJax object. + * + * @template T The union of component names, array of names, or definitions. + * @template A The DOM adaptor to use (default is liteDOM). + */ +/* prettier-ignore */ +export type MATHJAX_COMPONENTS>, A extends ADAPTOR_LIST = 'liteDOM'> = + MJX_COMPONENTS>; diff --git a/tsconfig/cjs.json b/tsconfig/cjs.json index a9f859ec08..c38aa96c5a 100644 --- a/tsconfig/cjs.json +++ b/tsconfig/cjs.json @@ -18,6 +18,7 @@ "exclude": [ "../ts/**/mjs/*", "../ts/util/asyncLoad/esm.ts", - "../ts/a11y/sre/speech-worker.ts" + "../ts/a11y/sre/speech-worker.ts", + "../ts/components/cjs/json.ts" ] } diff --git a/tsconfig/worker-cjs.json b/tsconfig/worker-cjs.json index 3f84e5284f..d040695913 100644 --- a/tsconfig/worker-cjs.json +++ b/tsconfig/worker-cjs.json @@ -1,15 +1,15 @@ { - "extends": "./mjs.json", + "extends": "./cjs.json", "compilerOptions": { "removeComments": false, - "rootDir": "../ts/a11y/sre", - "outDir": "../cjs/a11y/sre", - "module": "preserve", - "moduleResolution": "bundler" + "rootDir": "../ts/", + "outDir": "../cjs", + "module": "CommonJS" }, "files": [ "../ts/a11y/sre/speech-worker.ts", - "../ts/a11y/sre/worker_threads.d.ts" + "../ts/a11y/sre/worker_threads.d.ts", + "../ts/components/cjs/json.ts" ], "include": [], "exclude": [] diff --git a/tsconfig/worker.json b/tsconfig/worker.json index dba37cdc28..a807bf2696 100644 --- a/tsconfig/worker.json +++ b/tsconfig/worker.json @@ -1,13 +1,14 @@ { "extends": "./mjs.json", "compilerOptions": { - "rootDir": "../ts/a11y/sre", - "outDir": "../mjs/a11y/sre", + "rootDir": "../ts/", + "outDir": "../mjs/", "removeComments": false, }, "files": [ "../ts/a11y/sre/speech-worker.ts", - "../ts/a11y/sre/worker_threads.d.ts" + "../ts/a11y/sre/worker_threads.d.ts", + "../ts/components/mjs/json.ts" ], "include": [], "exclude": [] From c11b9099645c1f4fa1575abde52c252e06fb5cc5 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 14 Sep 2026 06:45:19 -0400 Subject: [PATCH 2/9] Fix incorrect export for main.js --- components/mjs/main/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mjs/main/main.js b/components/mjs/main/main.js index f10b04cf6d..22ae582ad7 100644 --- a/components/mjs/main/main.js +++ b/components/mjs/main/main.js @@ -5,5 +5,5 @@ import { init as browserInit, makeInit } from './browser/browser.js'; MathJax.init = hasWindow ? browserInit : makeInit(setup, adaptor); -export { MathJax }; +export default MathJax; export const init = MathJax.init; From bc3d466f300a3bc93d0a37fea6c8de029ec785b3 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 14 Sep 2026 07:56:21 -0400 Subject: [PATCH 3/9] Prevent trying to load the same files twice (when startup is used to load a combined component) --- components/mjs/startup/init.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/mjs/startup/init.js b/components/mjs/startup/init.js index 96cb8be184..4af9905f9c 100644 --- a/components/mjs/startup/init.js +++ b/components/mjs/startup/init.js @@ -27,10 +27,13 @@ combineDefaults(MathJax.config.loader, 'source', compatibility); export function startup(ready) { let locale = MathJax.config.locale ?? Locale.current; try { locale = localStorage.getItem('MathJax-locale') ?? locale; } catch (_err) {} + const load = CONFIG.load; + CONFIG.load = []; return Locale.setLocale(locale) - .then(() => Loader.load(...CONFIG.load)) + .then(() => Loader.load(...load)) .then(() => (ready || function () {})()) .then(() => CONFIG.ready()) + .then(() => CONFIG.load = load) .catch((error) => CONFIG.failed(error)) .catch((error) => MathJax.startup.promiseReject(error)); } From dc3c97ef0db2b8fcd779a449f8429d3ac7d476b8 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 14 Sep 2026 15:27:09 -0400 Subject: [PATCH 4/9] Fixes to get locales to load properly, and to get startup to synchronize its loading. --- components/mjs/core/locale.js | 3 ++- components/mjs/loader/loader.js | 8 +++++++- components/mjs/startup/init.js | 5 ++++- ts/a11y/semantic-enrich.ts | 3 +-- ts/a11y/speech/SpeechUtil.ts | 2 +- ts/ui/menu/Menu.ts | 2 +- ts/util/Locale.ts | 8 ++++---- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/components/mjs/core/locale.js b/components/mjs/core/locale.js index 0da87f4b3e..c62b28e903 100644 --- a/components/mjs/core/locale.js +++ b/components/mjs/core/locale.js @@ -1,4 +1,5 @@ import {Locale} from '#js/util/Locale.js'; Locale.isComponent = true; -Locale.locations.locale[0] = 'locale/__locales__'; +Locale.locations.locale[0] = '[mathjax]/locale/__locales__'; +Locale.locations.core[0] = '[mathjax]/core/__locales__'; diff --git a/components/mjs/loader/loader.js b/components/mjs/loader/loader.js index 51f00bf9b9..2cb4c79396 100644 --- a/components/mjs/loader/loader.js +++ b/components/mjs/loader/loader.js @@ -15,7 +15,13 @@ combineDefaults(MathJax.config.loader, 'provides', provides); let locale = MathJax.config.locale ?? Locale.current; try { locale = localStorage.getitem('MathJax-locale') ?? locale; } catch (_err) {} +if (MathJax.config.options?.sre) { + combineDefaults(MathJax.config.options, 'sre', { locale }); +} +const load = CONFIG.load; +CONFIG.load = []; Locale.setLocale(locale) - .then(() => Loader.load(...CONFIG.load)) + .then(() => Loader.load(...load)) .then(() => CONFIG.ready()) + .then(() => CONFIG.load = load) .catch((message, name) => CONFIG.failed(message, name)); diff --git a/components/mjs/startup/init.js b/components/mjs/startup/init.js index 4af9905f9c..40be49def5 100644 --- a/components/mjs/startup/init.js +++ b/components/mjs/startup/init.js @@ -8,7 +8,7 @@ import {dependencies, paths, provides, compatibility} from '../dependencies.js'; import {Loader, CONFIG} from '#js/components/loader.js'; import {Locale} from '#js/util/Locale.js'; -Loader.preLoaded('loader', 'startup', 'core'); +Loader.preLoaded('loader', 'core'); combineDefaults(MathJax.config.loader, 'dependencies', dependencies); combineDefaults(MathJax.config.loader, 'paths', paths); @@ -27,6 +27,9 @@ combineDefaults(MathJax.config.loader, 'source', compatibility); export function startup(ready) { let locale = MathJax.config.locale ?? Locale.current; try { locale = localStorage.getItem('MathJax-locale') ?? locale; } catch (_err) {} + if (MathJax.config.options?.sre) { + combineDefaults(MathJax.config.options, 'sre', { locale }); + } const load = CONFIG.load; CONFIG.load = []; return Locale.setLocale(locale) diff --git a/ts/a11y/semantic-enrich.ts b/ts/a11y/semantic-enrich.ts index 7408159ccf..d3250d9ff2 100644 --- a/ts/a11y/semantic-enrich.ts +++ b/ts/a11y/semantic-enrich.ts @@ -320,7 +320,7 @@ export interface SRE_OPTIONS { */ const SRE_options: SRE_OPTIONS = { speech: 'none', - locale: Locale.default, + locale: Locale.current, domain: 'clearspeak', style: 'default', braille: 'nemeth', @@ -447,7 +447,6 @@ export function EnrichedMathDocumentMixin< */ constructor(...args: any[]) { super(...args); - this.options.sre.locale = Locale.current; MmlJax.setMmlFactory(this.mmlFactory); const ProcessBits = (this.constructor as typeof AbstractMathDocument) .ProcessBits; diff --git a/ts/a11y/speech/SpeechUtil.ts b/ts/a11y/speech/SpeechUtil.ts index 7b07e9e3bc..5cb4e111d0 100644 --- a/ts/a11y/speech/SpeechUtil.ts +++ b/ts/a11y/speech/SpeechUtil.ts @@ -213,7 +213,7 @@ export function buildLabel( */ export function buildSpeech( speech: string, - locale: string = Locale.default, + locale: string = Locale.current, rate: string = '100' ): [string, SsmlElement[]] { return ssmlParsing( diff --git a/ts/ui/menu/Menu.ts b/ts/ui/menu/Menu.ts index fc189af8d2..112f6a2298 100644 --- a/ts/ui/menu/Menu.ts +++ b/ts/ui/menu/Menu.ts @@ -128,7 +128,7 @@ const options: Omit & { settings: SETTINGS & A11Y } = { zoom: 'NoZoom', zscale: '200%', renderer: 'CHTML', - locale: Locale.default, + locale: Locale.current, alt: true, cmd: false, ctrl: false, diff --git a/ts/util/Locale.ts b/ts/util/Locale.ts index 590ecd86d8..5b56bad424 100644 --- a/ts/util/Locale.ts +++ b/ts/util/Locale.ts @@ -85,10 +85,10 @@ export class Locale { prefix: string = component ) { if (!this.locations[component]) { - this.locations[component] = [ - `${this.isComponent ? component : prefix}/__locales__`, - new Set(), - ]; + if (this.isComponent) { + prefix = (component.charAt(0) === '[' ? '' : '[mathjax]/') + component; + } + this.locations[component] = [`${prefix}/__locales__`, new Set()]; } } From 21d88a3d6201bbef9dee71f7762b258fba45638a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Tue, 15 Sep 2026 08:57:34 -0400 Subject: [PATCH 5/9] Changes to make the main packges work with cjs applications --- components/mjs/core/locale.js | 5 +++-- components/mjs/main/browser/browser.cjs | 2 ++ components/mjs/main/browser/browser.d.cts | 19 +++++++++++++++++++ components/mjs/main/browser/browser.d.mts | 19 +++++++++++++++++++ components/mjs/main/browser/browser.d.ts | 4 ++++ components/mjs/main/browser/browser.js | 2 +- components/mjs/main/browser/browser.mjs | 4 ++++ components/mjs/main/browser/config.json | 2 ++ components/mjs/main/browser/webpack.cjs | 9 +++++---- components/mjs/main/config.json | 1 + components/mjs/main/main.cjs | 1 + components/mjs/main/main.d.cts | 19 +++++++++++++++++++ components/mjs/main/main.d.mts | 19 +++++++++++++++++++ components/mjs/main/main.d.ts | 3 +++ components/mjs/main/main.js | 9 ++++++--- components/mjs/main/main.mjs | 4 ++++ components/mjs/main/node/config.json | 6 ++++-- components/mjs/main/node/data.cjs | 14 ++++++++++++++ components/mjs/main/node/data.d.cts | 16 ++++++++++++++++ components/mjs/main/node/node.cjs | 15 +-------------- components/mjs/main/node/node.d.cts | 22 +++++++++++++++++++--- components/mjs/main/node/node.d.mts | 19 +++++++++++++++++++ components/mjs/main/node/node.d.ts | 3 +++ components/mjs/main/node/node.js | 2 +- components/mjs/main/node/node.mjs | 4 ++++ components/mjs/main/node/setup.js | 2 +- components/mjs/main/node/webpack.cjs | 7 ++++--- components/mjs/main/webpack.cjs | 7 ++++--- package.json | 21 +++++++++++++++------ 29 files changed, 217 insertions(+), 43 deletions(-) create mode 100644 components/mjs/main/browser/browser.cjs create mode 100644 components/mjs/main/browser/browser.d.cts create mode 100644 components/mjs/main/browser/browser.d.mts create mode 100644 components/mjs/main/browser/browser.mjs create mode 100644 components/mjs/main/main.cjs create mode 100644 components/mjs/main/main.d.cts create mode 100644 components/mjs/main/main.d.mts create mode 100644 components/mjs/main/main.mjs create mode 100644 components/mjs/main/node/data.cjs create mode 100644 components/mjs/main/node/data.d.cts create mode 100644 components/mjs/main/node/node.d.mts create mode 100644 components/mjs/main/node/node.mjs diff --git a/components/mjs/core/locale.js b/components/mjs/core/locale.js index c62b28e903..98f9a95f1f 100644 --- a/components/mjs/core/locale.js +++ b/components/mjs/core/locale.js @@ -1,5 +1,6 @@ import {Locale} from '#js/util/Locale.js'; Locale.isComponent = true; -Locale.locations.locale[0] = '[mathjax]/locale/__locales__'; -Locale.locations.core[0] = '[mathjax]/core/__locales__'; +for (const location of Object.values(Locale.locations)) { + location[0].replace(/^(?:\.\.\/)*ts\//, '[mathjax]/'); +} diff --git a/components/mjs/main/browser/browser.cjs b/components/mjs/main/browser/browser.cjs new file mode 100644 index 0000000000..49d3174b1b --- /dev/null +++ b/components/mjs/main/browser/browser.cjs @@ -0,0 +1,2 @@ +module.exports = require('./browser.js').default +; diff --git a/components/mjs/main/browser/browser.d.cts b/components/mjs/main/browser/browser.d.cts new file mode 100644 index 0000000000..bd4dc50684 --- /dev/null +++ b/components/mjs/main/browser/browser.d.cts @@ -0,0 +1,19 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'browser' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/browser/browser.d.mts b/components/mjs/main/browser/browser.d.mts new file mode 100644 index 0000000000..bd4dc50684 --- /dev/null +++ b/components/mjs/main/browser/browser.d.mts @@ -0,0 +1,19 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'browser' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/browser/browser.d.ts b/components/mjs/main/browser/browser.d.ts index 6453d2888c..afe72092fb 100644 --- a/components/mjs/main/browser/browser.d.ts +++ b/components/mjs/main/browser/browser.d.ts @@ -6,6 +6,7 @@ import type { MATHJAX_COMPONENTS, ADAPTOR_DOM, } from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; export function init< T extends COMPONENT_LIST> = 'startup', @@ -14,3 +15,6 @@ export function init< config: MATHJAX_CONFIG, component?: MATHJAX_COMPONENTS ): Promise>; + +export const MathJax: MathJaxObject; + diff --git a/components/mjs/main/browser/browser.js b/components/mjs/main/browser/browser.js index f35fc18dbf..2cda7c285d 100644 --- a/components/mjs/main/browser/browser.js +++ b/components/mjs/main/browser/browser.js @@ -33,5 +33,5 @@ export function makeInit(nodeSetup = null, adaptor = '') { } }; +export const init = MathJax.init = makeInit(); export default MathJax; -export const init = makeInit(); diff --git a/components/mjs/main/browser/browser.mjs b/components/mjs/main/browser/browser.mjs new file mode 100644 index 0000000000..97646728f3 --- /dev/null +++ b/components/mjs/main/browser/browser.mjs @@ -0,0 +1,4 @@ +import MathJax from './browser.js'; + +export default MathJax; +export const init = MathJax.init; diff --git a/components/mjs/main/browser/config.json b/components/mjs/main/browser/config.json index 900c418e9a..114d0c68b7 100644 --- a/components/mjs/main/browser/config.json +++ b/components/mjs/main/browser/config.json @@ -3,6 +3,8 @@ "to": "[bundle]/main", "from": ".", "copy": [ + "browser.mjs", + "browser.d.mts", "browser.d.ts" ] }, diff --git a/components/mjs/main/browser/webpack.cjs b/components/mjs/main/browser/webpack.cjs index e2034fa070..e8d8076298 100644 --- a/components/mjs/main/browser/webpack.cjs +++ b/components/mjs/main/browser/webpack.cjs @@ -2,16 +2,17 @@ const webpack = require('webpack'); module.exports = (pkg) => { pkg.output.library = { - type: 'commonjs-static', - } + type: 'commonjs2', + export: ['default'], + }; pkg.plugins.push( new webpack.NormalModuleReplacementPlugin( /mjs\/components\/mjs\/json\.js/, - '../../../components/mjs/main/browser/json.cjs' + '../../../components/mjs/main/browser/json.cjs', ), new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, - }) + }), ); return pkg; } diff --git a/components/mjs/main/config.json b/components/mjs/main/config.json index 1469e74c95..2326979909 100644 --- a/components/mjs/main/config.json +++ b/components/mjs/main/config.json @@ -3,6 +3,7 @@ "to": "[bundle]/main", "from": ".", "copy": [ + "main.mjs", "main.d.ts" ] }, diff --git a/components/mjs/main/main.cjs b/components/mjs/main/main.cjs new file mode 100644 index 0000000000..a7857cb884 --- /dev/null +++ b/components/mjs/main/main.cjs @@ -0,0 +1 @@ +module.exports = require('./main.js').default; diff --git a/components/mjs/main/main.d.cts b/components/mjs/main/main.d.cts new file mode 100644 index 0000000000..9136dd6161 --- /dev/null +++ b/components/mjs/main/main.d.cts @@ -0,0 +1,19 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/main.d.mts b/components/mjs/main/main.d.mts new file mode 100644 index 0000000000..9136dd6161 --- /dev/null +++ b/components/mjs/main/main.d.mts @@ -0,0 +1,19 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/main.d.ts b/components/mjs/main/main.d.ts index b658d16696..9136dd6161 100644 --- a/components/mjs/main/main.d.ts +++ b/components/mjs/main/main.d.ts @@ -6,6 +6,7 @@ import type { MATHJAX_COMPONENTS, ADAPTOR_DOM, } from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; export function init< T extends COMPONENT_LIST> = 'startup', @@ -14,3 +15,5 @@ export function init< config: MATHJAX_CONFIG, component?: MATHJAX_COMPONENTS ): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/main.js b/components/mjs/main/main.js index 22ae582ad7..a5d0b4b8e7 100644 --- a/components/mjs/main/main.js +++ b/components/mjs/main/main.js @@ -1,9 +1,12 @@ import { MathJax } from '#js/components/global.js'; import { hasWindow } from '#js/util/context.js'; import { setup, adaptor } from './node/setup.js'; -import { init as browserInit, makeInit } from './browser/browser.js'; +import { makeInit } from './browser/browser.js'; -MathJax.init = hasWindow ? browserInit : makeInit(setup, adaptor); +if (!hasWindow) { + MathJax.init = makeInit(setup, adaptor); +} -export default MathJax; export const init = MathJax.init; +export default MathJax; + diff --git a/components/mjs/main/main.mjs b/components/mjs/main/main.mjs new file mode 100644 index 0000000000..54a691063e --- /dev/null +++ b/components/mjs/main/main.mjs @@ -0,0 +1,4 @@ +import MathJax from './main.js'; + +export default MathJax; +export const init = MathJax.init; diff --git a/components/mjs/main/node/config.json b/components/mjs/main/node/config.json index 766ac7309e..508e84cfd1 100644 --- a/components/mjs/main/node/config.json +++ b/components/mjs/main/node/config.json @@ -3,8 +3,10 @@ "to": "[bundle]/main", "from": ".", "copy": [ - "node.cjs", - "node.d.cts", + "data.cjs", + "data.d.cts", + "node.mjs", + "node.d.mts", "node.d.ts" ] }, diff --git a/components/mjs/main/node/data.cjs b/components/mjs/main/node/data.cjs new file mode 100644 index 0000000000..c4ccc73416 --- /dev/null +++ b/components/mjs/main/node/data.cjs @@ -0,0 +1,14 @@ +let REQUIRE; +try { REQUIRE = eval("require") } catch(_) { REQUIRE = () => {} } +const path = REQUIRE("path"); +const fs = REQUIRE("fs"); + +let source = null; +if (fs.existsSync(path.resolve(__dirname, '..', '..', 'source.js'))) { + source = async () => {return (await import(/* webpackIgnore: true */ '../../source.js')).source}; +} + +module.exports.REQUIRE = REQUIRE; +module.exports.path = path; +module.exports.source = source; + diff --git a/components/mjs/main/node/data.d.cts b/components/mjs/main/node/data.d.cts new file mode 100644 index 0000000000..b658d16696 --- /dev/null +++ b/components/mjs/main/node/data.d.cts @@ -0,0 +1,16 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; diff --git a/components/mjs/main/node/node.cjs b/components/mjs/main/node/node.cjs index c4ccc73416..6cb8cac30d 100644 --- a/components/mjs/main/node/node.cjs +++ b/components/mjs/main/node/node.cjs @@ -1,14 +1 @@ -let REQUIRE; -try { REQUIRE = eval("require") } catch(_) { REQUIRE = () => {} } -const path = REQUIRE("path"); -const fs = REQUIRE("fs"); - -let source = null; -if (fs.existsSync(path.resolve(__dirname, '..', '..', 'source.js'))) { - source = async () => {return (await import(/* webpackIgnore: true */ '../../source.js')).source}; -} - -module.exports.REQUIRE = REQUIRE; -module.exports.path = path; -module.exports.source = source; - +module.exports = require('./node.js').default; diff --git a/components/mjs/main/node/node.d.cts b/components/mjs/main/node/node.d.cts index a9877412ce..9136dd6161 100644 --- a/components/mjs/main/node/node.d.cts +++ b/components/mjs/main/node/node.d.cts @@ -1,3 +1,19 @@ -export const REQUIRE: (file: string) => any; -export const path: any; -export const source: () => Promise<{ [component: string]: string }>; +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/node/node.d.mts b/components/mjs/main/node/node.d.mts new file mode 100644 index 0000000000..9136dd6161 --- /dev/null +++ b/components/mjs/main/node/node.d.mts @@ -0,0 +1,19 @@ +import type { + COMPONENT_LIST, + ADAPTOR_LIST, + MATHJAX_CONFIG, + MATHJAX_OBJECT, + MATHJAX_COMPONENTS, + ADAPTOR_DOM, +} from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; + +export function init< + T extends COMPONENT_LIST> = 'startup', + A extends ADAPTOR_LIST = 'liteDOM' +>( + config: MATHJAX_CONFIG, + component?: MATHJAX_COMPONENTS +): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/node/node.d.ts b/components/mjs/main/node/node.d.ts index b658d16696..9136dd6161 100644 --- a/components/mjs/main/node/node.d.ts +++ b/components/mjs/main/node/node.d.ts @@ -6,6 +6,7 @@ import type { MATHJAX_COMPONENTS, ADAPTOR_DOM, } from '@mathjax/src/mjs/types/mathjax.js'; +import type { MathJaxObject } from '@mathjax/src/mjs/components/startup.js'; export function init< T extends COMPONENT_LIST> = 'startup', @@ -14,3 +15,5 @@ export function init< config: MATHJAX_CONFIG, component?: MATHJAX_COMPONENTS ): Promise>; + +export const MathJax: MathJaxObject; diff --git a/components/mjs/main/node/node.js b/components/mjs/main/node/node.js index 6b986b0102..05c2ea8f72 100644 --- a/components/mjs/main/node/node.js +++ b/components/mjs/main/node/node.js @@ -2,5 +2,5 @@ import { MathJax } from '#js/components/global.js'; import { makeInit } from '../browser/browser.js'; import { setup, adaptor } from './setup.js'; +export const init = MathJax.init = makeInit(setup, adaptor); export default MathJax; -export const init = makeInit(setup, adaptor); diff --git a/components/mjs/main/node/node.mjs b/components/mjs/main/node/node.mjs new file mode 100644 index 0000000000..32f3007a62 --- /dev/null +++ b/components/mjs/main/node/node.mjs @@ -0,0 +1,4 @@ +import MathJax from './node.js'; + +export default MathJax; +export const init = MathJax.init; diff --git a/components/mjs/main/node/setup.js b/components/mjs/main/node/setup.js index 765a5d8161..29eaafdb04 100644 --- a/components/mjs/main/node/setup.js +++ b/components/mjs/main/node/setup.js @@ -6,7 +6,7 @@ import { resolvePath } from '#js/util/AsyncLoad.js'; export async function setup() { const CONFIG = MathJax.config.loader; - const { REQUIRE, path, source } = await import(/* webpackIgnore: true */ './node.cjs'); + const { REQUIRE, path, source } = await import(/* webpackIgnore: true */ './data.cjs'); // // If the path was not able to be determined, try to find the mathjax packages // and use those if found. The user can still override it. diff --git a/components/mjs/main/node/webpack.cjs b/components/mjs/main/node/webpack.cjs index 993c359f3e..12e423d32b 100644 --- a/components/mjs/main/node/webpack.cjs +++ b/components/mjs/main/node/webpack.cjs @@ -2,12 +2,13 @@ const webpack = require('webpack'); module.exports = (pkg) => { pkg.output.library = { - type: 'commonjs-static', - } + type: 'commonjs2', + export: ['default'], + }; pkg.plugins.push( new webpack.NormalModuleReplacementPlugin( /mjs\/components\/mjs\/json\.js/, - '../../../components/mjs/main/json.cjs' + '../../../components/mjs/main/json.cjs', ), ); return pkg; diff --git a/components/mjs/main/webpack.cjs b/components/mjs/main/webpack.cjs index 993c359f3e..12e423d32b 100644 --- a/components/mjs/main/webpack.cjs +++ b/components/mjs/main/webpack.cjs @@ -2,12 +2,13 @@ const webpack = require('webpack'); module.exports = (pkg) => { pkg.output.library = { - type: 'commonjs-static', - } + type: 'commonjs2', + export: ['default'], + }; pkg.plugins.push( new webpack.NormalModuleReplacementPlugin( /mjs\/components\/mjs\/json\.js/, - '../../../components/mjs/main/json.cjs' + '../../../components/mjs/main/json.cjs', ), ); return pkg; diff --git a/package.json b/package.json index 07f5b2479c..7c5beda7f2 100644 --- a/package.json +++ b/package.json @@ -25,20 +25,29 @@ "type": "module", "main": "components/mjs/node-main/node-main.js", "exports": { - ".": "./bundle/main/main.js", - "./node": "./bundle/main/node.js", - "./browser": "./bundle/main/browser.js", + ".": { + "import": "./bundle/main/main.mjs", + "require": "./bundle/main/main.js" + }, + "./node": { + "import": "./bundle/main/node.mjs", + "require": "./bundle/main/node.js" + }, + "./browser": { + "import": "./bundle/main/browser.mjs", + "require": "./bundle/main/browser.js" + }, "./source": { "import": "./components/mjs/main/main.js", - "require": "./components/cjs/main/main.js" + "require": "./components/cjs/main/main.cjs" }, "./node/source": { "import": "./components/mjs/main/node/node.js", - "require": "./components/cjs/main/node/node.js" + "require": "./components/cjs/main/node/node.cjs" }, "./browser/source": { "import": "./components/mjs/main/browser/browser.js", - "require": "./components/cjs/main/browser/browser.js" + "require": "./components/cjs/main/browser/browser.cjs" }, "./js/*": { "import": "./mjs/*", From 137cae2f74ead08e44fabf32c06157737034bf4a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Tue, 15 Sep 2026 09:10:19 -0400 Subject: [PATCH 6/9] Missed one file that needed to be copied --- components/mjs/main/browser/browser.cjs | 3 +-- components/mjs/main/config.json | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mjs/main/browser/browser.cjs b/components/mjs/main/browser/browser.cjs index 49d3174b1b..5927d0d21b 100644 --- a/components/mjs/main/browser/browser.cjs +++ b/components/mjs/main/browser/browser.cjs @@ -1,2 +1 @@ -module.exports = require('./browser.js').default -; +module.exports = require('./browser.js').default; diff --git a/components/mjs/main/config.json b/components/mjs/main/config.json index 2326979909..fd5df7bd86 100644 --- a/components/mjs/main/config.json +++ b/components/mjs/main/config.json @@ -4,6 +4,7 @@ "from": ".", "copy": [ "main.mjs", + "main.d.mts", "main.d.ts" ] }, From 03efc2d5a09d95ac0d01083e8f776cbc975e84fe Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Wed, 16 Sep 2026 14:44:08 -0400 Subject: [PATCH 7/9] Update to make lab work with changed timing in startup sequence --- lab/preload-locale.js | 3 +++ ts/util/Locale.ts | 1 + 2 files changed, 4 insertions(+) create mode 100644 lab/preload-locale.js diff --git a/lab/preload-locale.js b/lab/preload-locale.js new file mode 100644 index 0000000000..cb8573374d --- /dev/null +++ b/lab/preload-locale.js @@ -0,0 +1,3 @@ +export const locale = 'en'; +export const data = {}; + diff --git a/ts/util/Locale.ts b/ts/util/Locale.ts index 5b56bad424..fdfd85a8fa 100644 --- a/ts/util/Locale.ts +++ b/ts/util/Locale.ts @@ -258,6 +258,7 @@ export class Locale { public static async setLocale( locale: string = this.current ): Promise { + if (locale === '') return Promise.resolve([]); if (!this.syncLoad && !this.asyncLoad) { const { mathjax } = await import('../mathjax.js'); if (mathjax.asyncIsSynchronous) { From 2ade0816c0070dc63763b75bf2fd699a46068bd6 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 24 Sep 2026 08:18:25 -0400 Subject: [PATCH 8/9] Update package.json Co-authored-by: Volker Sorge --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c5beda7f2..5a2df40a8d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "url": "https://github.com/mathjax/Mathjax-src" }, "type": "module", - "main": "components/mjs/node-main/node-main.js", + "main": "components/mjs/main/main.js", "exports": { ".": { "import": "./bundle/main/main.mjs", From 91063847c5ac1ee6b66ec7db890c34427f394779 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 25 Sep 2026 08:06:57 -0400 Subject: [PATCH 9/9] Add jsdoc, as requested in review --- components/mjs/main/browser/browser.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/components/mjs/main/browser/browser.js b/components/mjs/main/browser/browser.js index 2cda7c285d..ceadaaf59d 100644 --- a/components/mjs/main/browser/browser.js +++ b/components/mjs/main/browser/browser.js @@ -6,6 +6,19 @@ if (hasWindow) { window.exports ??= {}; } +/** + * This funciton is called below and by ../main.js in order to create + * the needed init() function that is exported for initializing + * MathJax and returning the completed MathJax object. For use in node, + * the nodeSetup function is called to do extra setup (like setting the + * the asyncLoad function and getting the path to the MathJax files), and + * the adaptor will be added to the loading list if one isnt already + * inclkuded there. + * + * @param {() => void} nodeSetup The function to do extra setup for node + * @param {string} adaptor The adaptor to use for node + * @returns {(config} => MathJax} The init() function for export + */ export function makeInit(nodeSetup = null, adaptor = '') { return async function init(config, component = 'startup') { Loader.preLoaded('loader', 'core');