TeX no se ejecuta en un navegador. Por eso las herramientas que ponen matemáticas LaTeX en una página web —MathJax y KaTeX— son ambas reimplementaciones de la composición matemática de TeX en JavaScript, y las dos apostaron en sentidos opuestos ante el mismo problema. Componer aquí las mismas 500 fórmulas costó a KaTeX 45 milisegundos y a MathJax 264. Pero elegir solo por velocidad hace tropezar en otro sitio: ninguno de los dos trata $...$ como matemáticas por omisión. Esta página trata de la diferencia de diseño, de los mensajes de error que se ven de verdad y de si el TeX que se pega en una página sigue ahí después.
KaTeX o MathJax: cuál poner en la página
Muchas fórmulas y la velocidad importa: KaTeX. Quiere que el LaTeX escrito pase tal cual: MathJax. La diferencia de velocidad no es cuestión de quién optimizó más, sino de la forma de la API. El katex.renderToString(...) de KaTeX devuelve una cadena de forma síncrona: el HTML está ahí en el momento de la llamada, nada se inyecta después y nada salta. MathJax, en el navegador, está construido en torno a MathJax.typesetPromise(), que hace lo que su nombre indica y devuelve una promesa. Ese vistazo fugaz a un \frac{1}{2} en crudo que a veces atrapa el lector es un efecto colateral de esa asincronía.
<!-- MathJax 3: configure BEFORE the script tag loads -->
<script>
window.MathJax = {
tex: { inlineMath: [["$", "$"], ["\\(", "\\)"]] }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<!-- KaTeX: stylesheet, engine, then the auto-render pass -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body);"></script>Por qué $...$ no se renderiza: el comentario en el propio código de KaTeX
Ninguna de las dos bibliotecas trata $...$ como matemáticas en línea de fábrica. No es un descuido, sino un valor por defecto deliberado. Abra el código del auto-render de KaTeX y la entrada para $ está ahí, comentada, con la razón en la línea de arriba: «LaTeX uses $…$, but it ruins the display of normal $ in text». Dos símbolos de moneda en un párrafo y todo lo que queda en medio se convierte en fórmula. Los valores por defecto de MathJax coinciden: inlineMath es solo \(...\), mientras que displayMath son $$...$$ y \[...\]. Buena parte de los avisos de «mis fórmulas salen como código» se reduce exactamente a esto.
// KaTeX auto-render, default delimiters (dist/contrib/auto-render.js):
// { left: "$$", right: "$$", display: true }
// { left: "\\(", right: "\\)", display: false }
// { left: "\\[", right: "\\]", display: true }
// plus \begin{equation} \begin{align} \begin{alignat} \begin{gather} \begin{CD}
//
// and this line is deliberately commented out in the source:
// // LaTeX uses $...$, but it ruins the display of normal `$` in text:
// // {left: "$", right: "$", display: false},
// turn it on yourself only if the page has no currency amounts:
renderMathInElement(document.body, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
{ left: "\\(", right: "\\)", display: false },
{ left: "\\[", right: "\\]", display: true }
],
ignoredTags: ["script", "noscript", "style", "textarea", "pre", "code"]
});Lo que KaTeX no puede hacer y los mensajes que imprime
KaTeX admite un subconjunto de las matemáticas LaTeX, y lo que queda fuera se lanza como excepción. La redacción es constante: KaTeX parse error: Undefined control sequence: \eqref at position 1: y demás. La carencia más dolorosa es la referencia cruzada a números de ecuación: ni \label ni \eqref están definidos, de modo que un documento que numera sus ecuaciones y remite a ellas no se sostiene solo con KaTeX. La química tampoco pasa: \ce{H2O} exige la extensión aparte mhchem. El otro tropiezo habitual es KaTeX parse error: {align} can be used only in display mode., que aparece cuando se escribe un entorno align entre delimitadores en línea.
Es un malentendido, sin embargo, que KaTeX no admita macros. \newcommand, \def y \gdef funcionan todos y, si se pasa un objeto vacío como opción macros, una definición hecha con \gdef persiste entre llamadas. Así se inyecta una sola vez un preámbulo de macros válido para todo el sitio. MathJax, por su lado, incorpora unas treinta reimplementaciones de paquetes TeX —ams, amscd, mathtools, mhchem, cancel, braket, bussproofs, empheq, colortbl, entre otras— y esa lista es lo que «mayor compatibilidad» significa en concreto. Y si no quiere que una fórmula defectuosa rompa la página, recuerde throwOnError: false: en vez de lanzar una excepción, KaTeX imprime en rojo (#cc0000) el código culpable y sigue adelante.
| Lo que escribió | KaTeX | MathJax |
|---|---|---|
\frac \int \underbrace \text | pasa | pasa |
\newcommand \def \gdef | funciona (persiste vía macros) | funciona (vía la configuración macros) |
\label \eqref | no — Undefined control sequence | funciona (numeración vía la opción tags) |
\ce{H2O} | exige la extensión mhchem aparte | incluido |
align (inline) | {align} can be used only in display mode. | pasa |
¿Se puede usar ya MathML? El hueco cerrado en 2023
Todos los navegadores importantes muestran MathML. El asiento vacío más tiempo fue el de Chrome: la compatibilidad entró, volvió a salir y regresó definitivamente en la versión 109 (Edge desde esa misma 109). Firefox la tiene desde la versión 2 y Safari desde la 10. Dicho esto, aún hay pocas ocasiones de escribir MathML a mano. Importa más que ambas bibliotecas ponen MathML en su salida. KaTeX coloca siempre un elemento <math> junto al HTML visible, y el paquete estándar tex-mml-chtml.js de MathJax carga desde el principio la extensión que añade MathML para tecnologías de asistencia. A esa capa oculta debe un lector de pantalla el poder leer la fórmula.
¿Sobrevive el TeX? De cuál se pueden copiar las fórmulas
Con KaTeX sobrevive; con MathJax, por omisión, no. Todo árbol MathML que KaTeX emite contiene una <annotation encoding="application/x-tex">, y dentro está el TeX original. Déle x^2+1 y la cadena x^2+1 sigue en algún punto de la salida. Además, la distribución trae una extensión copy-tex cuyo propio comentario de código dice: «Replace .katex elements with their TeX source»; cargada, hace que copiar una fórmula seleccionada deje $x^2+1$ en el portapapeles en lugar de una hilera de glifos. La salida HTML habitual de MathJax no lleva el TeX original. Su respuesta es el menú contextual: «Show Math As», desde donde se recupera la forma inicial.
<!-- what KaTeX puts in the DOM for x^2+1 -->
<span class="katex"><span class="katex-mathml"><math
xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow>
<msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mn>1</mn>
</mrow><annotation encoding="application/x-tex">x^2+1</annotation>
</semantics></math></span><span class="katex-html" aria-hidden="true">...</span></span>
<!-- load this and Ctrl-C on a formula yields $x^2+1$, not glyphs -->
<script defer src="https://cdn.jsdelivr.net/npm/katex/dist/contrib/copy-tex.min.js"></script>Llevar sus propias macros hasta el navegador
Aquí pasa la frontera con las herramientas que convierten un documento entero a HTML. MathJax y KaTeX reciben solo fragmentos de matemáticas; ninguno lee su preámbulo. Un \newcommand{\R}{\mathbb{R}} en la cabecera del .tex nunca llega al navegador, y \R aparece indefinido y en rojo. Las macros hay que entregarlas aparte, por el objeto de configuración. La misma trampa aguarda del lado de los conversores: el modo mathjax de make4ht deja las matemáticas como LaTeX dentro del HTML, así que allí tampoco se expanden sus macros. El lado del conversor es asunto de «LaTeX → HTML», pero el remedio es el mismo en ambos sitios: reunir las definiciones de macros en un solo archivo y dárselo a leer tanto a TeX como a JavaScript.
// KaTeX: one shared object, and \gdef survives from call to call
const macros = {};
katex.renderToString("\\gdef\\R{\\mathbb{R}}", { macros });
katex.renderToString("f\\colon \\R \\to \\R", { macros }); // \R resolves
// or declare them up front, the same way for the auto-render pass:
renderMathInElement(document.body, {
macros: { "\\R": "\\mathbb{R}", "\\eps": "\\varepsilon" },
throwOnError: false // print the bad source in red, do not break the page
});
// MathJax 3: the equivalent lives in the config object
window.MathJax = {
tex: {
macros: { R: "\\mathbb{R}", eps: "\\varepsilon" },
tags: "ams" // this is what enables \label and \eqref
}
};- Las fórmulas salen como código → sospeche de los delimitadores.
$...$viene desactivado tanto en KaTeX como en MathJax. - El documento usa
\eqref→ elija MathJax y pongatags: "ams". KaTeX no tiene ninguna maquinaria de numeración. - Una página de listado con cientos de fórmulas → KaTeX. El renderizado síncrono evita que la maquetación salte después.
- Tiene macros propias → páselas en
macros. Su preámbulo nunca llega al navegador. - Una fórmula defectuosa no debe tumbar la página →
throwOnError: falseen KaTeX: la imprime en rojo y sigue. - Quiere el documento entero en la web → eso no es tarea de un renderizador matemático (ver «LaTeX → HTML»).