Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use MathJax in TypeScript project? #2385

Closed
ghost opened this issue Mar 26, 2020 · 13 comments
Closed

How to use MathJax in TypeScript project? #2385

ghost opened this issue Mar 26, 2020 · 13 comments

Comments

@ghost
Copy link

ghost commented Mar 26, 2020

I built a custom combined component file with a modified subclass of the output jax CHTML and incorporated it into my project. My combined component file custom-component.js is written in plain JavaScript, just like the examples in the MathJax-demos-web repo. I included my webpacked custom-component.min.js with a <script> tag in my index.html and everything worked fine. I used JavaScript in my other scripts in index.html as well.
Now, however, I am looking to move to TypeScript, since now that I have made the connection to MathJax by being able to configure and access the output jax in the ways I want, I am ready to write my own code, and that, I want to do in TypeScript.
That's why I am looking to get rid of all the plain JavaScript in my index.html and move all the logic (and MathJax loading) to an index.ts file.
That's where I am running into problems though. Since I would like to have just a single <script> tag that I need to include in my index.html, I want even the MathJax loading to be done in my index.ts. And although I can import my own combined component file, I can't setup the global MathJax object because TypeScript does not recognize it.
I looked into the code a little bit about how the global is set up, but I don't understand how to solve my problem anyway.

My question now is, what I am doing wrong here. Am I taking a wrong approach? Should I rewrite my custom component file to be a TypeScript file and not a plain JavaScript one? And also, why were all the components written in JavaScript and not in TypeScript like the rest of the project? Is there some easy way to connect to the MathJax source with a TypeScript project like mine?

@ghost
Copy link
Author

ghost commented Mar 26, 2020

I hope for a quick answer this is making me mad :(

@ghost
Copy link
Author

ghost commented Mar 30, 2020

I don't know if my problem is clear but what I basically want to do is just use and initialize MathJax in TypeScript (and include it) rather than initializing it via plain JS.
Something like this:

import {MathJaxObject} from 'mathjax-full/js/components/global.js';

const MathJax: MathJaxObject = new MathJaxObject([
    options: {
        renderActions: {
            addMenu: [0, '', ''],
        }
    },
    chtml: {
        scale: 2.5
    }
]);

// with auto-complete/suggestions and documentation (IntelliSense)
let html = MathJax.tex2chtml('\frac{abc}{123}');
document.body.appendChild(html);

I don't think this is possible at the moment, since I think (as far as I could see) the whole interface with the component system is set out to be used in JS only (correct me if I'm wrong).

But I would really love to use MathJax like that. How much work do you think would this be? Do you think re-writing the interface to be TS compatible would be hard? I would love doing that myself but I would really like to hear your expert opinion on this before starting something that's too big.

@ghost
Copy link
Author

ghost commented Apr 6, 2020

Is this not possible...?

@dpvc
Copy link
Member

dpvc commented Apr 6, 2020

The MathJax components are designed around the need to run MathJax from a CDN with potential for dynamic loading of components and custom configurations without requiring authors to package their own copies of MathJax. The source files for the components are small wrapper files that load the needed (compiled) typescript files, and register themselves with the component startup system. These seemed minor enough not to need the power of Typescript.

While it is possible to bundle these comports in different ways, and to call on the files in components/src, if you are going to be using MathJax through Typescript, the usual approach for that is to call on the MathJax modules directly. There are example of this in the MathJax node demos repository's direct directory. The direct approach does not use the MathJax object for configuration; that is only for the components, as it is used to coordinate among the different pieces. In this approach, you import the modules that you need and configure them as you instantiate the needed objects. This would give you full access to the Typescript types.

@winstxnhdw
Copy link

winstxnhdw commented Sep 21, 2022

Sorry for bumping this 2 years later, but this is first in the Google search results when you look for MathJax and TypeScript. The MathJax documentation for TypeScript is absolutely horrendous, especially the 'direct' examples that aren't written in TypeScript, containing an endless amount of useless boilerplate.

The following code block contains the most minimal TypeScript code to convert a TeX string into an SVG string. Please be warned to set your module to CommonJS in your tsconfig.json file if you are using ts-node.

import { mathjax } from 'mathjax-full/js/mathjax'
import { TeX } from 'mathjax-full/js/input/tex'
import { SVG } from 'mathjax-full/js/output/svg'
import { AllPackages } from 'mathjax-full/js/input/tex/AllPackages'
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor'
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html'

const adaptor = liteAdaptor()
RegisterHTMLHandler(adaptor)

const mathjax_document = mathjax.document('', {
  InputJax: new TeX({ packages: AllPackages }),
  OutputJax: new SVG({ fontCache: 'local' })
})

const mathjax_options = {
  em: 16,
  ex: 8,
  containerWidth: 1280
}

export function get_mathjax_svg(math: string): string {
  const node = mathjax_document.convert(math, mathjax_options)
  return adaptor.innerHTML(node)
}

@mustafasalahuldin
Copy link

mustafasalahuldin commented May 14, 2023

@winstxnhdw Would you please give one more example when output is to be MathML?

@winstxnhdw
Copy link

winstxnhdw commented May 14, 2023

Hey, @mustafasalahuldin. I believe it is as simple as switching TeX to MathML.

import { mathjax } from 'mathjax-full/js/mathjax'
import { MathML} from 'mathjax-full/js/input/mathml'
import { SVG } from 'mathjax-full/js/output/svg'
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor'
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html'

const adaptor = liteAdaptor()
RegisterHTMLHandler(adaptor)

const mathjax_document = mathjax.document('', {
  InputJax: new MathML(),
  OutputJax: new SVG({ fontCache: 'local' })
})

const mathjax_options = {
  em: 16,
  ex: 8,
  containerWidth: 1280
}

export function get_mathjax_svg(math: string): string {
  const node = mathjax_document.convert(math, mathjax_options)
  return adaptor.innerHTML(node)
}

@mustafasalahuldin
Copy link

@winstxnhdw I adjusted your code with whatever I could found in the website, found here.
I got something like this:
` const adaptor = liteAdaptor();
RegisterHTMLHandler(adaptor);

            const MathJax = {
                enableAssistiveMml: true,
                scale: 1,                                                       // global scaling factor for all expressions
                minScale: .5,                                                   // smallest scaling factor to use
                mtextInheritFont: false,                                        // true to make mtext elements use surrounding font
                merrorInheritFont: true,                                        // true to make merror text use surrounding font
                mathmlSpacing: false,                                           // true for MathML spacing rules, false for TeX rules
                skipAttributes: {},                                             // RFDa and other attributes NOT to copy to the output
                exFactor: .5,                                                   // default size of ex in em units
                displayAlign: 'center',                                         // default for indentalign when set to 'auto'
                displayIndent: '0',                                             // default for indentshift when set to 'auto'
                matchFontHeight: true,                                          // true to match ex-height of surrounding font
                fontURL: '[mathjax]/components/output/chtml/fonts/woff-v2',     // The URL where the fonts are found
                adaptiveCSS: false                                               // true means only produce CSS that is used in the processed equations
            };

            const mathjax_document = mathjax.document('', {
                InputJax: new TeX({ packages: AllPackages }),
                OutputJax: new CHTML(MathJax)
            });

            const mathjax_options = {
                em: 16,
                ex: 8,
                containerWidth: 1280
            };

            let math = "\\frac{\\sqrt[3]{27x^6y^7}}{\\sqrt{x^4y^2}} + \\sqrt[4]{\\frac{x^8}{y^4}} * \\frac{10y^2\\sqrt{3xy^2}}{5x\\sqrt{4y}}\\";
            const node = mathjax_document.convert(math, mathjax_options);
            renderer.innerHTML = adaptor.innerHTML(node);`

The tags are generated but it has no values, any advice?

@mustafasalahuldin
Copy link

Hey, @mustafasalahuldin. I believe it is as simple as switching TeX to MathML.

import { mathjax } from 'mathjax-full/js/mathjax'
import { MathML} from 'mathjax-full/js/input/mathml'
import { SVG } from 'mathjax-full/js/output/svg'
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor'
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html'

const adaptor = liteAdaptor()
RegisterHTMLHandler(adaptor)

const mathjax_document = mathjax.document('', {
  InputJax: new MathML(),
  OutputJax: new SVG({ fontCache: 'local' })
})

const mathjax_options = {
  em: 16,
  ex: 8,
  containerWidth: 1280
}

export function get_mathjax_svg(math: string): string {
  const node = mathjax_document.convert(math, mathjax_options)
  return adaptor.innerHTML(node)
}

I need to render from Lax to MML3

@mustafasalahuldin
Copy link

@winstxnhdw And I need to enable the accessibility aria tags feature too, please

@zsviczian
Copy link

Any idea how to get around this?

Please be warned to set your module to CommonJS in your tsconfig.json file if you are using ts-node.

because if I change module to CommonJS from ES2015 I get this error:

Error: Incompatible tsconfig option. Module resolves to 'CommonJS'. This is incompatible with Rollup, please use 'module: "ES2015"', 'module: "ES2020"', or 'module: "ESNext"'.

...and I'd love to avoid having to rework my rollup.config.js

@zsviczian
Copy link

I managed to get the code working with module "es2015".

  • it works with "mathjax-full": "3.2.2"
  • and node 16
    with node 18 I get runtime errors...

@winstxnhdw
Copy link

I managed to get it to work with ESNext but I am no longer using ts-node but swc instead.

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

No branches or pull requests

4 participants