remarkjs/remark-math

MathJax error -- TypeError: Cannot read properties of null (reading '4')

rrcobb opened this issue · 11 comments

Initial checklist

Affected packages and versions

remark-mathjax@5.0.0, remark-math@6.0.0

Link to runnable example

No response

Steps to reproduce

index.js

import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import remarkMath from 'remark-math';
import rehypeMathjax from 'rehype-mathjax';
import rehypeStringify from "rehype-stringify";
import { unified } from "unified";

const source = `
Lift($$L$$) can be determined by Lift Coefficient ($$C_L$$) like the following
equation.

$$
L = \frac{1}{2} \rho v^2 S C_L
$$
`;
const htmlResult = await unified()
  .use(remarkParse)
  .use(remarkMath)
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeMathjax)
  .use(rehypeStringify, { allowDangerousHtml: true })
  .process(source);

console.log(htmlResult);

package.json

{
  "name": "repro",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "rehype-mathjax": "^5.0.0",
    "rehype-stringify": "^10.0.0",
    "remark-math": "^6.0.0",
    "remark-parse": "^11.0.0",
    "remark-rehype": "^11.0.0",
    "unified": "^11.0.3"
  }
}

Expected behavior

This should process and render without errors. Instead, it hits an error within mathjax.

Actual behavior

range[4] && mo.attributes.set('mathvariant', range[4]);
         ^

TypeError: Cannot read properties of null (reading '4')
    at Object.Other [as item] (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex/base/BaseConfiguration.js:79:10)
    at SubHandler.parse (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex/MapHandler.js:92:39)
    at TexParser.parse (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex/TexParser.js:111:54)
    at TexParser.Parse (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex/TexParser.js:143:18)
    at new TexParser (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex/TexParser.js:76:14)
    at TeX.compile (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/input/tex.js:118:26)
    at AbstractMathItem.compile (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/core/MathItem.js:56:39)
    at Object.renderMath (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/core/MathDocument.js:119:65)
    at RenderList.renderConvert (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/core/MathDocument.js:171:35)
    at AbstractMathItem.convert (/Users/rob/dev/kibo/product/repro/node_modules/.pnpm/mathjax-full@3.2.2/node_modules/mathjax-full/js/core/MathItem.js:52:32)

Node.js v18.12.1

Runtime

Node v16

Package manager

pnpm

OS

macOS

Build and bundle tools

No response

Welcome @rrcobb! 👋
Sorry you ran into a spot of trouble.
These dependencies are compatible, here is a sandbox showing them working together https://stackblitz.com/edit/github-eju95a?file=src%2Fmain.ts,package.json with vite, and working on as a plain node script https://stackblitz.com/edit/stackblitz-starters-xug1ib?file=index.js
Most likely you are running into an issue with either a build tool (most likely) or with pnpm (also possible).

Hi! This was closed. Team: If this was fixed, please add phase/solved. Otherwise, please add one of the no/* labels.

Welcome @rrcobb! 👋 Sorry you ran into a spot of trouble. These dependencies are compatible, here is a sandbox showing them working together https://stackblitz.com/edit/github-eju95a?file=src%2Fmain.ts,package.json with vite, and working on as a plain node script https://stackblitz.com/edit/stackblitz-starters-xug1ib?file=index.js Most likely you are running into an issue with either a build tool (most likely) or with pnpm (also possible).

Huh, super weird! It looks like there is an issue when running on pnpm: https://stackblitz.com/edit/stackblitz-starters-kwh7sk?file=index.js

I'll take compare the package-lock.json and pnpm-lock.yml to see if there's a difference in the modules that are getting resolved

It seems like it's probably a peer module resolution issue? https://pnpm.io/how-peers-are-resolved seems like the most likely difference in the resolution algorithms that pnpm and npm use

Huh. it seems like it's not a pnpm issue after all, but is instead a parsing error because I used invalid syntax, and it threw this weird index error.

I had the (bad, not working):

const source = `
Lift($$L$$) can be determined by Lift Coefficient ($$C_L$$) like the following
equation.

$$
L = \frac{1}{2} \rho v^2 S C_L
$$
`;

where your repro had the (good, working):

const source = `
Lift($$L$$) can be determined by Lift Coefficient ($$C_L$$) like the following
equation.

$$
L = \\frac{1}{2} \\rho v^2 S C_L
$$
`;

note the double \\ in the string.

Maybe should be a better error message, but not a package manager issue.

fwiw, I had copied mine right from https://github.com/remarkjs/remark-math#example-katex

I assumed it was correct as rendered, but it was not!

I assumed it was correct as rendered, but it was not!

What is going on here is that you paste markdown inside a JavaScript string and assume it works exactly the same.
That is not the case.
If you paste \ inside a JavaScript string, it crashes.
What seems to be going on here is that \f in JS means things, which it doesn’t in markdown.

I assumed this was an error on our side, but it’s not in micromark/mdast:

import {micromark} from 'micromark'
import {math, mathHtml} from 'micromark-extension-math'

const source = `
Lift($$L$$) can be determined by Lift Coefficient ($$C_L$$) like the following
equation.

$$
L = \frac{1}{2} \rho v^2 S C_L
$$
`

const output = micromark(source, {
  extensions: [math()],
  htmlExtensions: [mathHtml()]
})

console.log(output)

->

    var self = new Error(error);
               ^

ParseError: KaTeX parse error: Unexpected character: '
                                                      ' at position 5: L = 
ho v…                                                                      ̲rac{1}{2} 
    at new ParseError (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:147:16)
    at Lexer.lex (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:14950:13)
    at MacroExpander.future (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:16146:33)
    at MacroExpander.popToken (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:16157:10)
    at MacroExpander.expandOnce (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:16359:25)
    at MacroExpander.expandNextToken (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:16431:16)
    at Parser.fetch (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:17168:36)
    at Parser.consumeSpaces (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:17719:17)
    at Parser.parseAtom (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:17421:12)
    at Parser.parseExpression (file:///Users/tilde/Projects/oss/micromark-extension-math/node_modules/katex/dist/katex.mjs:17271:23) {
  position: 4,
  length: 1,
  rawMessage: "Unexpected character: '\f'"
}

Node.js v20.5.1

KaTeX throws a rather readable error.
Looking at your error again, the error is in mathjax.

You’re supplying a \f (form feed) in the math, but the tools you use don’t understand that as math. Escape it: \\f.

Hi team! Could you describe why this has been marked as external?

Thanks,
— bb

Thanks @wooorm that clarifies things quite a bit. The rendered version in github is different from what the raw string in js should be, which tripped me up.

I'lll open an issue in MathJax about the error message, it looks like it's on their end not the unified ecosystem

I'll open an issue in MathJax about the error message, it looks like it's on their end not the unified ecosystem

Passing an invalid character into MathJax, and it reporting that it is invalid doesn't feel like a bug in unified or MathJax.
It's more understanding how template strings work.