Escribiendo fórmulas con LaTeX en Jekyll

Dado que este sitio web viene de la mano de un matemático y va a estar enfocado a la estadística en general, sospecho que más pronto que tarde harán acto de presencia fórmulas y demás expresiones matemáticas. Así pues, esta mañana he investigado ligeramente cómo integrar la escritura de ecuaciones con , a través de MathJax, usando el generador de sitios web estáticos Jekyll.

Primera aproximación: muy fácil parecía…

En el apartado de la documentación oficial de Jekyll relacionado con este aspecto, apenas figura un párrafo indicando cómo incluir MathJax en nuestros sitios web. No obstante, comparte el enlace a esta excelente entrada, que nos ofrece una orientación magnífica para utilizar en nuestros artículos.

Para empezar, debemos modificar las plantillas en las que sospechemos vayamos a escribir fórmulas matemáticas. En mi caso, por el momento, la anterior afirmación se va a restringir a los artículos del blog, cuya plantilla asociada es post.html y se encuentra a través de la ruta \_includes\themes\hooligan. Abrimos dicho archivo con nuestro editor de texto plano favorito y colocamos al principio del mismo el siguiente bloque de código:

<script type="text/javascript"
    src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

Sin embargo, aunque he seguido al pie de letra todos y cada uno de los pasos que su autor transmite, me he topado con un curiosa situación:

  • En primer lugar, un hecho ciertamente preocupante: las fórmulas se reproducían localmente de manera impecable, pero cuando actualizaba los archivos en el servidor éstas desaparecían por completo.
  • En segundo lugar, un comportamiento anecdótico (en comparación con el problema descrito en el punto anterior): salvando los números, el resto de elementos de las expresiones matemáticas se mostraban teñidos de color violeta.

Confieso que habré dedicado alrededor de una hora experimentando, con apenas éxito, diversas variaciones para solucionar el primer inconveniente, un escollo debido principalmente a extrañas interacciones entre Markdown y MathJax, amén de ciertos obstáculos extras que aporta el propio funcionamiento de GitHub Pages. Al final decidí cortar por lo sano y dejar este tema de lado un rato, que la frustración empezaba a alcanzar niveles importantes.

Segunda aproximación: It’s alive! It’s alive!

Unas horas después, con la mente un tanto más despejada, retomé este asunto, encontrando un magnífico artículo que me permitió resolver el problema planteado en la sección anterior, y así poder visualizar las expresiones matemáticas generadas con MathJax en los archivos subidos a GitHub Pages.

El proceso no es tan rápido y sencillo como el mostrado arriba, pero tampoco es excesivamente complejo. Empezaremos creando un archivo en el directorio _includes\, al que denominaremos mathjax.html y que contendrá las siguientes líneas:

{% if page.mathjax %}
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
</script>
<script
  type="text/javascript"
  charset="utf-8"
  src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
>
</script>
<script
  type="text/javascript"
  charset="utf-8"
  src="https://vincenttam.github.io/javascripts/MathJaxLocal.js"
>
</script>
{% endif %}

En el siguiente paso, buscaremos en la carpeta _includes\themes\hooligan la plantilla default.html y la examinaremos con nuestro editor de texto plano favorito. Entre las etiquetas <head> y </head> añadiremos la siguiente línea:

{% include mathjax.html %}

Para que os hagáis una idea, en mi caso, utilizando el tema Hooligan, la mencionada parte de la plantilla ha quedado como sigue:

<head>
  <meta charset="utf-8">
  <title>
    {% if page.title %}
      {{ page.title }} - 
    {% endif %}
    {{ site.title }}
  </title>
  {% if page.description %}<meta name="description" content="{{ page.description }}">{% endif %}
  <meta name="author" content="{{ site.author.name }}">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- HTML5 shim, for IE6-8 support of HTML elements -->
  <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->

  <link href="{{ ASSET_PATH }}/bootstrap/css/bootstrap.min.css" rel="stylesheet">
  <link href="{{ ASSET_PATH }}/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
  <link rel="stylesheet" type="text/css" href="{{ ASSET_PATH }}/css-social-buttons/css/zocial.stripped.css">
  <link href="{{ ASSET_PATH }}/css/pygments.css" rel="stylesheet" type="text/css" media="all">
  <link href="{{ ASSET_PATH }}/css/darkstrap.css" rel="stylesheet" type="text/css" media="all">
  <link href="{{ ASSET_PATH }}/css/style.css?body=1" rel="stylesheet" type="text/css" media="all">
	
  {% include mathjax.html %}
	
  <!-- fav and touch icons -->
  <!-- Update these with your own images
    <link rel="shortcut icon" href="images/favicon.ico">
    <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
  -->
</head>

Ahora ya únicamente nos resta añadir la línea mathjax: true en la cabecera de cualquier documento de nuestra web en el que sepamos vamos a utilizar expresiones matemáticas generadas con MathJax. Por ejemplo, sin ir más lejos, la asociada a este artículo ha quedado como sigue:

---
title: "Escribiendo fórmulas con *LaTeX* en *Jekyll*"
date: 2017-08-20 06:00:00
mathjax: true
---

¡Eso es todo! Ya estamos en condiciones de utilizar para escribir nuestras expresiones matemáticas. Ahora bien, ¿cómo podemos hacerlo? De manera muy sencilla:

  • Si encerramos la expresión entre los símbolos \\( y \\) (o bien entre $), aparecerá en la misma línea.
  • Si ubicamos la fórmula entre los símbolos \\[ y \\] (o bien entre $$), se mostrará centrada en la siguiente línea.

Ilustremos los puntos anteriores mediante algunos ejemplos. Si escribimos en nuestro documento:

"La media muestral, $\bar x$, es un estimador insesgado de la media poblacional, $\mu$, por lo que..."

el resultado que observaremos en el artículo será el siguiente: “La media muestral, , es un estimador insesgado de la media poblacional, , por lo que…”. Por otro lado, para mostrar la función de densidad de una distribución normal, podríamos teclear:

\\[
f(x) = \frac{1}{\sqrt{2\sigma^2\pi}}\exp{\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)},\ x\in\mathbb{R}.
\\]

Consiguiendo entonces el efecto que se muestra acto seguido:

Así pues, tenemos a nuestra disposición una maravillosa herramienta para escribir complicadas expresiones matemáticas con un resultado excelente y muy agradable a la vista. Eso sí, en color violeta. Tras el correspondiente suspiro de rigor, demos comienzo a la siguiente batalla.

Tercera aproximación: diciendo adiós al violeta

No es que tenga nada en contra del color violeta. Es más, hasta me habría parecido un comportamiento curioso para destacar la expresión matemática del texto en sí. No obstante, como todo no podía ser perfecto, el hecho de que no tiña todos sus elementos (los números conservan el color declarado para la fuente del texto normal) ha provocado que busque cómo abordar este problema.

Tras unos minutos investigando, he ido a parar a esta cuestión, planteada para un tema de Jekyll distinto a Hooligan (que es el que en su momento estuvo instalado para este sitio web), pero de gran utilidad para resolver el asunto no obstante. Resulta que existe cierto conflicto entre las clases de los estilos definidas para resaltar el código fuente de un lenguaje de programación y las expresiones matemáticas que produce MathJax. La solución es sencilla y consiste simplemente en anteceder con .highlight la declaración de clases que se lleva a cabo en el archivo pygments.css, ubicado en el directorio \assets\themes\hooligan\css. Si estáis usando el mismo tema que yo en vuestro sitio web, no tenéis más que copiar y pegar el siguiente bloque de código:

.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */

Nos despedimos así, con infinita pena, del color violeta que teñía parcialmente nuestras expresiones matemáticas.

¿Cuál es la situación para los temas So Simple y Minimal Mistakes?

Aunque apenas habrá pasado un mes desde que originalmente publiqué este artículo, el sitio web ha experimentado numerosos cambios en lo que a aspecto visual respecta. A la vuelta de Navidad, el tema So Simple captó poderosamente mi atención, animándome a utilizarlo para Infinitos Contrastes. Un par de semanas después, debido a ciertas limitaciones que encontré en él de cara a gestionar la sección de proyectos, decidí optar por Minimal Mistakes. Examinemos la situación de ambos en lo que se refiere a la escritura de expresiones matemáticas con .

En primer lugar, con la instalación de So Simple tenemos de serie todo aquello que figura descrito en secciones anteriores. Simplemente debemos añadir en la cabecera de nuestros artículos mathjax: true allí donde sospechemos que aparecerán fórmulas. En segundo lugar, si optamos por Minimal Mistakes tendremos que trabajar un poquito, puesto que no soporta el uso de MathJax por defecto (lo cual, resulta un tanto curioso, puesto que ambos temas están desarrollados por el mismo autor).

Para activar la posibilidad de escribir expresiones matemáticas utilizando MathJax, simplemente hemos de editar el archivo scripts.html, que se encuentra ubicado en el directorio _includes\, de manera que al final presente el siguiente aspecto:

<script src="{{ '/assets/js/main.min.js' | absolute_url }}"></script>

{% if page.mathjax %}
<script type="text/javascript" async
  src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
{% endif %}

{% include analytics.html %}
{% include /comments-providers/scripts.html %}

La modificación, como salta a la vista, es la parte que ha quedado encerrada en el bloque condicional if. Ahora no tenemos más que escribir mathjax: true en la cabecera de aquellas páginas o posts donde vayamos a escribir fórmulas para así poder disfrutar de la potencia que ofrece el uso de la librería MathJax.

En este último, la redacción de expresiones matemáticas es un tanto diferente a aquella descrita en secciones anteriores. En Minimal Mistakes, encerraremos las fórmulas siempre entre $$, y MathJax se encargará automáticamente de gestionar su correcta visualización (bien mostrándolas en línea, bien centrándolas aparte).

Nota: cualquier comentario relacionado con el texto precedente se puede llevar a cabo a través de su correspondiente entrada en el blog.

Publicado: