MathJax icon indicating copy to clipboard operation
MathJax copied to clipboard

4.0.0-beta.7 TypeError: text.match is not a function

Open olafes opened this issue 1 year ago • 1 comments

Issue Summary

There is a possible TypeError in [email protected] node package, in Tex input processing pipeline. If this is due to me using the "direct" api incorrectly, please provide some help. I've modified one of the node demos so that it imports 4.0.0-beta.7. packages. My goal is to make it process a full html document with mathjax blocks in it. The error is in html.render() function.

file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/util/Styles.js:189
        if (!text.match(PATTERN.sanitize)) {
                  ^

TypeError: text.match is not a function
    at Styles.sanitizeValue (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/util/Styles.js:189:19)
    at get cssText [as cssText] (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/util/Styles.js:204:48)
    at LiteAdaptor.setStyle (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/adaptors/liteAdaptor.js:303:48)
    at LiteAdaptor.setAttributes (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/core/DOMAdaptor.js:17:22)
    at LiteAdaptor.node (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/core/DOMAdaptor.js:8:14)
    at CHTML.html (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/output/common.js:330:29)
    at CHTML.getTestElement (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/output/common.js:258:22)
    at CHTML.getMetricMaps (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/output/common.js:222:40)
    at CHTML.getMetrics (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/output/common.js:190:27)
    at HTMLDocument.getMetrics (file:///home/[user]/math/min/tex/notes/html/node_modules/mathjax-full/mjs/core/MathDocument.js:278:28)

Node.js v20.18.0

package.json:

{
  "main": "src/index.mjs",
  "dependencies": {
    "mathjax-full": "^4.0.0-beta.7",
    "mathjax-schola-font": "^4.0.0-beta.7"
  }
}

src/index.mjs:

import { readFileSync } from 'node:fs';

import { AssistiveMmlHandler } from 'mathjax-full/js/a11y/assistive-mml.js';
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor.js';
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html.js';
import { mathjax } from 'mathjax-full/js/mathjax.js';
import { TeX } from 'mathjax-full/js/input/tex.js';
import { CHTML } from 'mathjax-full/js/output/chtml.js';
import { MathJaxScholaFont } from 'mathjax-schola-font/mjs/chtml.js';

const INPUT = readFileSync('index.html', 'utf8');

const adaptor = liteAdaptor();
const handler = RegisterHTMLHandler(adaptor);

const tex = new TeX({ inlineMath: [['$','$']] });
const chtml = new CHTML({
    fontData: MathJaxScholaFont,
    //fontPath: './node_modules/%%FONT%%-font/es5/output/fonts/%%FONT%%',
    fontPath: './fonts/mathjax-schola',
    exFactor: 0.5
});
const html = mathjax.document(INPUT, { InputJax: tex, OutputJax: chtml });

html.render(); // error on this line

if (Array.from(html.math).length === 0) adaptor.remove(html.outputJax.chtmlStyles);
console.log(adaptor.doctype(html.document));
console.log(adaptor.outerHTML(adaptor.root(html.document)));

It seems that this.sanitizeValue expects text to be string, but some styles (width, for example) have values stored as numbers. After changing styles.push(name + ': ' + this.sanitizeValue(this.styles[name]) + ';'); to styles.push(name + ': ' + this.sanitizeValue(this.styles[name].toString()) + ';'); everything appears to work properly. Is this simple to fix on the TS side? If so, I can submit a PR.

node_modules/mathjax-full/mjs/util/Styles.js

    sanitizeValue(text) {
        let PATTERN = this.constructor.pattern;
        if (!text.match(PATTERN.sanitize)) {
            return text;
        }
        text = text.replace(PATTERN.value, '$1');
        const test = text.replace(/\\./g, '').replace(/(['"]).*?\1/g, '').replace(/[^'"]/g, '');
        if (test.length) {
            text += test.charAt(0);
        }
        return text;
    }
    get cssText() {
        const styles = [];
        for (const name of Object.keys(this.styles)) {
            const parent = this.parentName(name);
            if (!this.styles[parent]) {
                styles.push(name + ': ' + this.sanitizeValue(this.styles[name]) + ';');
            }
        }
        return styles.join(' ');
    }

olafes avatar Oct 28 '24 11:10 olafes

For example, this LiteElement has width that is a number.

LiteElement {
  kind: 'mjx-left-box',
  attributes: { style: 'display: inline-block;' },
  children: [],
  styles: Styles { styles: { display: 'inline-block', width: 0 } }
}

olafes avatar Oct 28 '24 11:10 olafes

Fixed in v4.0

dpvc avatar Aug 13 '25 14:08 dpvc