Using MathJax node in an ES module
rnwst opened this issue · 2 comments
I have a node project which is an ES module (package.json
contains "type": "module"
). I'm trying to use MathJax to typeset an HTML page server-side. The demos use the shebang #! /usr/bin/env -S node -r esm
, which preloads esm. This allows mixing CJS module (require()
and module.exports
) and ESM (import
and export
) syntax. If I use the same shebang, I get the following error:
Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/project/file.js not supported.
Instead change the require of file.js in null to a dynamic import() which is available in all CommonJS modules.] {
code: 'ERR_REQUIRE_ESM'
}
If I change the shebang to #!/usr/bin/env node
, mixed CJSM and ESM syntax no longer works:
(node:23193) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/path/to/project/node_modules/mathjax-full/components/src/node-main/node-main.js:83
export {init};
^^^^^^
SyntaxError: Unexpected token 'export'
Using esm isn't really an acceptable option for me in the first place, as it hasn't seen any commits since 2019 and doesn't support modern Javascript features like optional chaining. Therefore, the real issue it seems to me is that MathJax is mixing CJSM and ESM syntax.
Is there any way I can use MathJax in an ES module?
Version info:
node v19.2.0
mathjax-full@3.2.2
└esm@3.2.25
MathJax's typescript source is compiled into ES5 .js files, and since ES5 predates import
/export
, those .js files use require()
. So the first thing you would ned to do is modify the tsconfig
file to output ES6 my changing
"target": "ES5",
to
"target": "ES6",
and also probably also change the exclude
to list es6
.
Then recompile MathJax using
npm run -s compile
Then if you are using components rather than direct calls to the MathJax modules, you will need to rebuild the components. You may want to adjust the components/webpack.common.js
file to change the es5
references to es6
(so that it builds the components into an es6
directory rather than the current es5
one). There are a couple of copy.json
files that you might want to direct to the es6
directory as well. Use
grep -r es5 components/
to find them and see if they are for components that you will be using.
Then rebuild the components
npm run -s make-components
Then you should be able to import the components from the es6
directory, or the .js
files from the js
directory.
The examples in this demo repository are just samples, not part of MathJax proper, and you should be able to convert the require()
commands to import
commands easily enough, other than the ones in the simple
directory, as those use the components/src/node-main/node-main.js
file, which uses require
and would need to be modified to avoid that. Your best bet is probably the examples in the components
directory (or the direct
directory if you don't want to use the mathJax components architecture).
Many thanks for the detailed instructions!