🏠 back to Observable

Defining LaTeX Macros


#1

Is it possible to define LaTeX macros in a notebook? For example, I would like to write ${tex`\def\reals{\mathbb{R}`} somewhere and then be able to refer to ${tex`\reals`} elsewhere (ideally, across different blocks).


#2

There are a few ways to do this, but the best option may be to augment the standard library slightly to allow passing options through to KaTeX.

We’re using KaTeX 0.10-beta, which does support \def, but this only affects the given input to tex—it doesn’t persistently change the behavior of tex. This is good because it avoids mutable state and nondeterministic behavior. (KaTeX also appears to support \gdef, which sounds like it would persistently change the behavior of tex, but I couldn’t get it to work and wouldn’t recommend it anyway.)

Defining a macro to use it once isn’t especially useful, but it works:

tex`\def\reals{\mathbb{R}} \reals^2`

To make reusable macros, you could have a macros cell to define your macros, and then embed them wherever you call tex. Note you’ll need String.raw to avoid double-backslashes.

macros = String.raw`\def\reals{\mathbb{R}}`
tex`${macros}\reals^2`

You can go one step further and define a wrapper for tex that has your macros in it:

function mtex() {
  return tex`
\def\reals{\mathbb{R}}
${String.raw.apply(String, arguments)}
`;
}
mtex`\reals`

If you want total control, here’s how do define your own template literal using KaTeX directly:

katex = require("katex")
function mtex() {
  const root = document.createElement("div");
  katex.render(String.raw.apply(String, arguments), root, {
    macros: {
      "\\reals": "\\mathbb{R}"
    }
  });
  return root.removeChild(root.firstChild);
}

In the future, I’d like something like this:

mtex = tex.options({
  macros: {
    "\\reals": "\\mathbb{R}"
  }
})