mathjax / MathJax-demos-node

A repository with examples using mathjax-v3 in NodeJS
Apache License 2.0
98 stars 42 forks source link

SVG Output with Node Different from Web Rendered Content? #35

Closed fireflysemantics closed 3 years ago

fireflysemantics commented 3 years ago

I'm trying out the simple textosvg demo. This is a stackblitz of the CDN rendering of the tex:

https://stackblitz.com/edit/mathjax-cdn-demo-custom-markup

This is the Latex string:

    <div>
      $$MAD = \frac{\sum_{i=1}^n | x_i - \bar{x} |} n$$
    </div>

When I take that and put it in the SVG demo like this:

#! /usr/bin/env -S node -r esm

/*************************************************************************
 *
 *  simple/tex2svg
 *
 *  Uses MathJax v3 to convert a TeX string to an SVG string.
 *
 * ----------------------------------------------------------------------
 *
 *  Copyright (c) 2019 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.
 */

//
//  The default TeX packages to use
//
const PACKAGES = 'base, autoload, require, ams, newcommand';

const latex = `$$MAD = \frac{\sum_{i=1}^n | x_i - \bar{x} |} n$$`

//
//  Minimal CSS needed for stand-alone image
//
const CSS = [
  'svg a{fill:blue;stroke:blue}',
  '[data-mml-node="merror"]>g{fill:red;stroke:red}',
  '[data-mml-node="merror"]>rect[data-background]{fill:yellow;stroke:none}',
  '[data-frame],[data-line]{stroke-width:70px;fill:none}',
  '.mjx-dashed{stroke-dasharray:140}',
  '.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}',
  'use[data-c]{stroke-width:3px}'
].join('');

//
//  Get the command-line arguments
//
var argv = require('yargs')
    .demand(0).strict()
    .usage('$0 [options] "math" > file.svg')
    .options({
        inline: {
            boolean: true,
            describe: "process as inline math"
        },
        em: {
            default: 16,
            describe: 'em-size in pixels'
        },
        ex: {
            default: 8,
            describe: 'ex-size in pixels'
        },
        width: {
            default: 80 * 16,
            describe: 'width of container in pixels'
        },
        packages: {
            default: PACKAGES,
            describe: 'the packages to use, e.g. "base, ams"; use "*" to represent the default packages, e.g, "*, bbox"'
        },
        styles: {
            boolean: true,
            default: true,
            describe: 'include css styles for stand-alone image'
        },
        container: {
            boolean: true,
            describe: 'include <mjx-container> element'
        },
        css: {
            boolean: true,
            describe: 'output the required CSS rather than the HTML itself'
        },
        fontCache: {
            boolean: true,
            default: true,
            describe: 'whether to use a local font cache or not'
        },
        assistiveMml: {
            boolean: true,
            default: false,
            describe: 'whether to include assistive MathML output'
        },
        dist: {
            boolean: true,
            default: false,
            describe: 'true to use webpacked version, false to use MathJax source files'
        }
    })
    .argv;

//
// Load MathJax and initialize MathJax and typeset the given math
//
require('mathjax-full').init({
    //
    //  The MathJax configuration
    //
    options: {
        enableAssistiveMml: argv.assistiveMml
    },
    loader: {
        source: (argv.dist ? {} : require('mathjax-full/components/src/source.js').source),
        load: ['adaptors/liteDOM', 'tex-svg']
    },
    tex: {
        packages: argv.packages.replace('\*', PACKAGES).split(/\s*,\s*/)
    },
    svg: {
        fontCache: (argv.fontCache ? 'local' : 'none')
    },
    startup: {
        typeset: false
    }
}).then((MathJax) => {
    //
    //  Typeset and display the math
    //
    MathJax.tex2svgPromise(latex, {
        display: !argv.inline,
        em: argv.em,
        ex: argv.ex,
        containerWidth: argv.width
    }).then((node) => {
        const adaptor = MathJax.startup.adaptor;
        //
        //  If the --css option was specified, output the CSS,
        //  Otherwise, output the typeset math as SVG
        //
        if (argv.css) {
            console.log(adaptor.textContent(MathJax.svgStylesheet()));
        } else {
            let html = (argv.container ? adaptor.outerHTML(node) : adaptor.innerHTML(node));
            console.log(argv.styles ? html.replace(/<defs>/, `<defs><style>${CSS}</style>`) : html);
        };
    });
}).catch(err => console.log(err));

It produces this:

https://stackblitz.com/edit/mathjax-svg-node?file=index.html

And the output does not render properly. Any ideas?

dpvc commented 3 years ago

Because backslashes are special characters in Javascript strings (so that you can get a newline with '\n' and a tab with '\t'), if you want a literal backslash in a Javascript string, you need to double it. So you should use

const latex = `$$MAD = \\frac{\\sum_{i=1}^n | x_i - \\bar{x} |} n$$`

instead.

fireflysemantics commented 3 years ago

AH! OK Brilliant - THANK YOU SOOOOOOO MUCH!!

dpvc commented 3 years ago

No problem. Good luck!