Expressions et équations mathématiques en HTML avec MathJax et AsciiMath

Logo

Introduction

L’écriture d’expressions et d’équations mathématiques dans des pages HTML, même si l’usage peut ne pas être courant, voire exceptionnel, a toujours été problématique. Mais parfois on a besoin d’afficher des formules avec un bon rendu ergonomique.

Soit l’expression est brute de fonderie, peu ergonomique et difficilement lisible, notamment avec la présence de fractions, exemple :

f(x) = (x + 2) / (2x + 1)        x ∈ R, x ≠ − 1/2

Soit une image est créée à partir d’outils comme Formule Math dans LibreOffice, image qui doit être recréée si la formule doit être modifiée et pour laquelle le texte ne peut pas être copié par l’internaute :

Equation format image

Au tout début, HTML 5 devait intégrer le standard MathML pour l’écriture d’expressions mathématiques en HTML. Mais les éditeurs de navigateurs en ont décidément autrement. Le support de MathML dans les navigateurs principaux (Chrome, FireFox, MS Internet Explorer, Safari) était disparate et il y avait trop de désaccords sur ce sujet.

Google, l’éditeur de Chrome, a probablement raison d’ailleurs en décidant de ne pas porter MathML en standard dans son navigateur. Les arguments avancés sont l’usage de MathML restreint à un public de scientifiques et l’existence de librairies Javascript très puissantes qui sont en mesure de répondre au besoin.

Et effectivement, MathJax est une librairie Javascript, compatible avec tous les navigateurs, simple et très évoluée pour le rendu des expressions mathématiques en HTML. Le rendu est impressionnant, le codage simple et le contenu des expressions devient ainsi aisément modifiable en cas d’erreur ou de besoin. Voici le rendu de l’exemple ci-dessus avec MathJax (option AsciiMath) :

`f(x) = (x+2)/(2x+1)` `x in RR,\ x !=-1/2`
<div class="cmath"> `f(x) = (x+2)/(2x+1)`          `x in RR,\ x !=-1/2`</div>

MathJax gère plusieurs syntaxes en entrée (Tex/Latex, AsciiMath, MathML - MML), la syntaxe AsciiMath étant de loin la plus aisée pour des besoins simples. D’autres librairies Javascript existent pour formater des expressions mathématiques mais la syntaxe AsciiMath y est très souvent non supportée, la librairie Katex par exemple ne supporte que le langage Tex/Latex.

Cet article n’est pas un tutoriel pour écrire des équations de maths/physique (via MathJax).

Il s’agit ici d’un aide mémoire pour inclure MathJax automatiquement dans des articles si des expressions mathématiques y sont présentes (syntaxes AsciiMath et/ou Tex/Latex). Si par rapport à la syntaxe Tex/Latex, la syntaxe AsciiMath est effectivement la plus facile à utiliser pour des besoins relativement simples, des points et besoins très spécifiques sont très peu documentés en utilisant la syntaxe AsciiMath, points abordés ici :

  • Appliquer du style sur une portion d’équation
  • Mettre en évidence une équation
  • Numéroter des équations
  • Centrer les équations sur le signe =

Mécanique, configuration de MathJax

Pour schématiser la mécanique de MathJax :

Mécanique de la librairie MathJax

Une ou plusieurs syntaxes en entrée sont possibles (AsciiMath, Tex/Latex, MathML) et l’expression mathématique sera traduite graphiquement dans un format de sortie (HTML-CSS, SVG, MathML si le navigateur supporte le langage MathML comme FireFox).

La librairie JavaScript MathJax est typiquement appelée avec la syntaxe ci-dessous :

<chemin d’installation>/MathJax.js?config=<syntaxe(s) en entrée>_<format(s) de sortie>

La documentation officielle décrit les combinaisons de configurations possibles : MathJax - Combined configurations.

Quelques configurations très usuelles :

ConfigDescription
…/MathJax.js?config=AM_CHTML
  • Syntaxe AsciiMath (AM) en entrée
  • Format "Common HTML" en sortie (CHTML)
…/MathJax.js?config=TeX-MML-AM_CHTML
  • Syntaxe Tex/Latex (TeX), ou MathML (MML), ou AsciiMath (AM) en entrée
  • Format "Common HTML" en sortie (CHTML)
…/MathJax.js?config=TeX-AMS_CHTML
  • Syntaxe Tex/Latex (TeX) en entrée incluant les symboles AMS
  • Format "Common HTML" en sortie (CHTML)

La librairie MathJax peut être installée en local, elle est téléchargeable au format zip sur le site GitHub de MathJax : MathJax GitHub Downloads. La librairie MathJax fait environ 70 Mb (version 2.7.8 - août 2019).

Si on n’opte pas pour une installation en local, MathJax 2 est disponible en ligne sur les CDN (Content Delivery Network).

Pour une configuration donnée, AM_CHTML dans les exemples ci-dessous (syntaxe AsciiMath en entrée, Common HTML en format de sortie), dans l’entête de la page en utilisant un contexte CDN en ligne :

<head>…
  <script async="true" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=AM_CHTML"> </script>
…</head>

L’option mathjax@2 dans l’URL du script MathJax.js garantit l’utilisation de la version 2 la plus récente. Si pour une raison quelconque, une version spécifique dans une page ou quelques unes doit être utilisée (bug…), par exemple la version 2.7.6 :

<head>…
  <script async="true" src="https://cdn.jsdelivr.net/npm/mathjax@2.7.6/MathJax.js?config=AM_CHTML"> </script>
…</head>

Les exemples ci-dessus sont des appels classiques et basiques, un prochain paragraphe décrit comment sécuriser et industrialiser l’appel de la librairie MathJax.

MathJax et la syntaxe AsciiMath

AsciiMath est la syntaxe en entrée la plus simple (par rapport à Tex/Latex, MathML) pour un usage relativement basique afin de restituer des expressions mathématiques. Quand des fonctionnalités très avancées sont nécessaires, il faut basculer sur le langage Tex/Latex.

Avec AsciiMath dans la configuration (AM) et sans paramétrage particulier, le tour est joué :

<head>…
  <script async="true" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=AM_CHTML"> </script>
…</head>

Les syntaxes AsciiMath pour une expression mathématique sont délimitées par défaut avec le caractère ` (backtick).

<div class="cmath">
 `f(x)=x^2 + 2x + 1 = 0`             Fonction dérivée : `f^'(x)=2x + 2`
 
 `frac(df(x))(dx) = lim_(h->0)(f(x+h)-f(x))/h`
           
 `f(t) = a_(0)/2 + sum_(n=1)^oo [a_(n) cos(nt) + b_(n) sin(nt)]`

 `x^' = frac(-b -sqrt(Delta))(2a)`
</div>
`f(x)=x^2 + 2x + 1 = 0` Fonction dérivée : `f^'(x)=2x + 2` `frac(df(x))(dx) = lim_(h->0)(f(x+h)-f(x))/h` `f(t) = a_(0)/2 + sum_(n=1)^oo [a_(n) cos(nt) + b_(n) sin(nt)]` `x^' = frac(-b -sqrt(Delta))(2a)`

Les expressions AsciiMath sont écrites ci-dessus dans des blocs div avec la classe cmath. Pour cette classe cmath, la propriété white-space est définie à pre. Cette propriété simplifie la gestion des espaces et des sauts de lignes dans le conteneur.

div.cmath {
  display: block;
  margin: 20px 0px 20px 30px;
  padding-left: 50px; padding-top: 8px; padding-bottom: 8px;
  white-space : pre;
}

Les expressions peuvent être aussi "in line" dans un paragraphe en utilisant des balises span.

<p>Une expression : <span> `sum_(i=1)^n i^3=((n(n+1))/2)^2`</span> au sein d’une phrase.</p>

Une expression : `sum_(i=1)^n i^3=((n(n+1))/2)^2` au sein d’une phrase.

Sécuriser et industrialiser le chargement de la librairie MathJax

Avec peu de lignes de code Javascript, l’industrialisation et l’optimisation du chargement de la librairie MathJax peut être prise en charge par une fonction.

<head>
  …
    <script type="text/javascript" src="./js/lib.js"> </script>
  …
</head>
./js/lib.js
run_maths = function() {
         
  if (document.querySelector('[class*="cmath"]') !== null) {
  
    if (typeof (mjax_path)=='undefined') { mjax_path='https://cdn.jsdelivr.net/npm/mathjax@2'; }
    if (typeof (mjax_config)=='undefined') { mjax_config='AM_CHTML'; }
        
    smjax = document.createElement ('script');
    smjax.setAttribute('src',`${mjax_path}/MathJax.js?config=${mjax_config}`);
    smjax.setAttribute('async',true);
    document.getElementsByTagName('head')[0].appendChild(smjax); 
  }
};
      
if (document.readyState === 'loading') {  window.addEventListener('DOMContentLoaded', run_maths); }
else { run_maths(); }

La fonction run_maths est appelée si l’événement DOMContentLoaded va se produire ou si la propriété document.readyState est déjà à interactive ou complete. Tous les nœuds du document doivent être chargés avant que MathJax ne soit inséré dynamiquement et déclenché.

Dans la fonction run_maths

  • La librairie MathJax est insérée dynamiquement que s’il existe au moins un élément dans le document ayant la classe cmath. Avec cette méhode, la librarie MathJax, qui a un coût non négligeable dans le chargement d’une page, ne sera appelée que si la page en a besoin.
  • Si une configuration n’est pas déjà explicitement indiquée avec la variable mjax_config, une configuration par défaut est appliquée.
    if (typeof (mjax_config)=='undefined') { mjax_config='AM_CHTML'; }
  • Idem pour le chemin vers la librairie MathJax via la variable mjax_path.
    if (typeof (mjax_path)=='undefined') { mjax_path='https://cdn.jsdelivr.net/npm/mathjax@2'; }

Le chemin vers MathJax et/ou la configuration est alors modifiable pour une page donnée en définissant mjax_path et/ou mjax_config pour écraser les valeurs par défaut. Peu importe où la définition est réalisée dans le document, MathJax n’étant chargé qu’après l’événement DOMContentLoaded.

<script> var mjax_config='TeX-MML-AM_CHTML'; </script>
<script> var mjax_path='https://cdn.jsdelivr.net/npm/mathjax@2.7.6'; </script>

Le caractère underscore _ dans les syntaxes AsciiMath : text{ }

Juste un petit mot sur le caractère underscore car les exemples d’équations dans les documentations et tutoriaux abordent très peu ce point. Bien souvent dans les expressions les variables possédent des caractères underscore _ , caractère interprété par AsciiMath pour appliquer des indices. Afin que ce caractère ne soit pas interprété, utiliser l’option text{variable_1}.

<div class="cmath">`R=D/L=frac (text{del_lf_rows})(text{lf_rows}) >= 0,1`</div>
`R=D/L=frac (text{del_lf_rows})(text{lf_rows}) >= 0,1`

Une syntaxe plus légère est possible en protégeant les variables contenant le caractère underscore avec des double quotes :

<div class="cmath">`R=D/L=frac ("del_lf_rows")("lf_rows") >= 0,1`</div>

Avec la syntaxe text{ } ou l’échappement avec des double quotes, malheureusement on perd la typographie mathématique (italique, etc.), pour la recouvrer, il faut forcer la police sur les éléments de la classe .mjx-mtext, classe qui est appliquée par le moteur Mathjax dans ce contexte.

.mjx-mtext > * { font-family: MJXc-TeX-math-I,MJXc-TeX-math-Ix,MJXc-TeX-math-Iw !important; }

Ce problème se produit aussi avec MathJax v3. Pour MathJax 3, la solution de contournement suivante fonctionne :

mjx-mtext > * { font-family: MJXZERO, MJXTEX-I !important; }

La police n’est pas alors forcée sur la classe mjx-mtext mais la balise mjx-mtext. Les polices sont différentes entre MathJax v2 et MathJax v3.

Ce point a été adressé à la communauté MathJax : GitHub MathJax - Italic fonts not applied using AsciiMath and text { } syntax, MathJax 2 and 3..

Problèmatique du backtick comme délimiteur des syntaxes AsciiMath, conflits avec les syntaxes MySQL et Shell

L’utilisation du caractère backtick ` comme délimiteur soulève une question : que se passe-t-il si la page utilise ce caractère dans le corps du texte ou dans une syntaxe MySQL ou Shell qui utilise le backtick ?

insert into `matable` values ...

Aucun problème à ce sujet, les backticks ne sont pas interprétés par MathJax lorsque ce caractère est présent dans les balises HTML ci-dessous :

  • script, noscript
  • style
  • textarea, pre, code
  • annotation, annotation-xml

Pour les syntaxes MySQL et les scripts Shell, sauf cas particulier, les balises pre et code sont généralement utilisées afin de bénéficier de la coloration syntaxique avec les librairies Javascript HighlightJs ou Prism. Pour les autres cas, utiliser la balise code ou encore annotation pour encapsuler le backtick afin que MathJax n’interprète pas le contenu.

<code>`</code> <annotation>`</annotation>

Si le backtick comme délimiteur d’expressions mathématiques AsciiMath génère trop de conflits avec le contenu dans une page, le délimiteur backtick pour AsciiMath peut être modifié dans l’objet global window.MathJax avant l’appel de la librairie MathJax :

<script type="text/javascript">
  window.MathJax = {
    asciimath2jax: {
       delimiters: [['~','~']] 
    }
  };
</script>
<script type="text/javascript" src="./js/lib.js"></script>

Le backtick ` est remplacé par le caractère tilde ~ comme délimiteur dans cet exemple.

Styles CSS et MathJax / AsciiMath

Est-il possible d’appliquer du style CSS sur la totalité ou une portion d’une équation écrite en AsciiMath avec MathJax ? Oui.

Les fonctionnalités abordées dans ce paragraphe ne sont disponibles qu’à partir de la version 2.7.5 de MathJax 2, version dans laquelle AsciiMath 2 est supportée. AsciiMath 2 ajoute quelques notations Latex, dont la notation class{}.

Le format de sortie doit être "Common HTML" (CHTML) dans la configuration.

À propos de MathJax 3, AsciiMath 2 est supporté à partir de la version 3.1.3 (avril 2020).

Pour la lisibilité, il s’avère parfois nécessaire de changer le style (notes …) sur tout ou partie d’une équation. Une des solutions pourrait consister à utiliser des balises span associées à du style CSS, mais il existe la syntaxe class{<classname>}{<code équation>} assurant plus de cohérence dans l’écriture de l’équation et évitant ainsi l’insertion "brute" de balises HTML.

Dans l’exemple ci-dessous on souhaite que la remarque `Delta=b^2-4ac > 0` apparaisse avec un espacement de 100px à gauche, une couleur spécifique et une taille plus petite en guise de note :

`ax^2 + bx + c = 0` `x = frac(-b +- sqrt(Delta))(2a) class{cmjx-note}{ text{rem : } \ Delta=b^2-4ac > 0 }`

La classe CSS cmjx-note est définie à cet effet, dans une feuille de style de la page ou dans le code HTML avec les balises style :

.cmjx-note {
  transform: translate(100px);
  font-size: 0.8em;
  color: #DD4A68;
}

La classe CSS cmjx-note est appliquée sur la portion souhaitée avec la syntaxe : `… class{cmjx-note} { … Delta=b^2-4ac > 0 } …`

<div class="cmath">

 `ax^2 + bx + c = 0`
  
 `x = frac(-b +- sqrt(Delta))(2a) class{cmjx-note}{ text{rem : } \ Delta=b^2-4ac > 0 }`

</div>

Plusieurs classes CSS peuvent être définies dans la portion à formater avec la syntaxe class :


 `x = frac(-b +- sqrt(Delta))(2a) class{cmjx-note cmjx-note1 cmjx-note2}{ text{rem : } \ Delta=b^2-4ac > 0 }`

Connaissant cette astuce pour les syntaxes AsciiMath, les applications pratiques deviennent alors nombreuses :

  • Encadrer des équations avec des bordures pour les mettre en évidence.
  • Numéroter des équations.

Encadrer des équations

Une application pratique immédiate et très simple : mettre en évidence une équation AsciiMath en appliquant une bordure. Elle présente l’avantage de normaliser les bordures avec l’ergonomie du site (couleurs, etc.).

`class{cmjx-highlight} { e^x = lim_(n->oo) (1 + x/n)^n }`
.cmjx-highlight { border: 2px solid #DD4A68; padding: 8px; margin-right: 4px; }
<div class="cmath">
  `class{cmjx-highlight} { e^x = lim_(n->oo) (1 + x/n)^n }`
</div>

Bien moins fréquent, mais cette classe est applicable à des expressions dites "inline" :

Le volume d’une sphère étant `class{cmjx-highlight} {V = 4/3\piR^3} `, donc …

<p> Le volume d’une sphère étant <span class="cmath"> `class{cmjx-highlight} {V = 4/3\piR^3} ` </span>, donc …</p>

Numéroter des équations

La solution n’est pas parfaite mais en utilisant une classe CSS dans laquelle la position est absolue, à 600px sur la gauche par exemple, la numérotation des équations AsciiMath devient assez simple avec la syntaxe class { }.

.cmjx-nb { position: absolute; left: 600px; }
<div class="cmath">
 `cos^2 \theta + sin^2 \theta  = 1 class{cmjx-nb}{(9)}`

 `cos^2 \theta - sin^2 \theta = cos 2\theta class{cmjx-nb}{(10)}`
</div>
`cos^2 \theta + sin^2 \theta = 1 class{cmjx-nb}{(9)}` `cos^2 \theta - sin^2 \theta = cos 2\theta class{cmjx-nb}{(10)}`

La position absolue peut devoir être ajustée via une autre classe en fonction du contexte (complexité des équations …).

Si le rendu sur les appareils mobiles est une préoccupation, pour résumer très sommairement : quand les équations commencent à être numérotées, cela concerne davantage des pages autour de sujets propres aux mathématiques, la physique …, pages qu’il est généralement préférable de consulter en version desktop.

Centrer des équations AsciiMath sur le signe =

Pour centrer des équations AsciiMath sur le signe `=`, les matrices sont utilisées pour la disposition (layout). Avec la syntaxe Tex/Latex, il en est tout autrement.

`{: ( f(x) ,=, (x+2)(x-3) ) , ( ,=, x^2 -3x +2x -6 ) , ( ,=, x^2 -x - 6 ) , ( f^'(x) ,=, 2x -1 ) :}`

Le signe `=` est alors un élément de la matrice et l’élément ouvrant et fermant de la matrice est caché ({: :}) :

<div class="cmath">
`{:
    ( f(x)   ,=, (x+2)(x-3)      ) ,
    (        ,=, x^2 -3x +2x -6  ) ,
    (        ,=, x^2 -x - 6      ) ,
    ( f^'(x)  ,=, 2x -1           ) 
:}`
</div>

Quand les équations sont linéaires de part et d’autre dans la matrice, le rendu est pafait. Dès qu’il y a des fractions, le rendu est moins optimal.

<div class="cmath">
`{:
      ( f(x)      ,=, frac(x+1)(x-2)                                  ) ,
      ( f^'(x)     ,=, frac((x-2) - (x+1))((x-2)^2)                    ) ,
      (           ,=, - frac(3)(x^2 - 4x + 4)                         ) 
:}`
</div>
`{: ( f(x) ,=, frac(x+1)(x-2) ) , ( f^'(x) ,=, frac((x-2) - (x+1))((x-2)^2) ) , ( ,=, - frac(3)(x^2 - 4x + 4) ) :} `

Pour résoudre ce problème de disproportion, définir une classe CSS dans le but d’ajuster plus particulièrement la taille de la police, l’ajustement est réalisé ici avec l’unité rem :

.cmjx-lg { font-size: 1.65rem; padding-bottom:8px;}

L’unité et la valeur à appliquer vont dépendre du contexte de la page et elles sont déterminées empiriquement.

La classe est alors appliquée sur les éléments à ajuster/élargir, ici les fractions :

<div class="cmath">
`{:
      ( f(x)      ,=, class{cmjx-lg} { frac(x+1)(x-2) }                 ) ,
      ( f^'(x)     ,=, class{cmjx-lg} { frac((x-2) - (x+1))((x-2)^2) }   ) ,
      (           ,=, class{cmjx-lg} { - frac(3)(x^2 - 4x + 4) }        ) 
:}`
</div>
`{: ( f(x) ,=, class{cmjx-lg} { frac(x+1)(x-2) } ) , ( f^'(x) ,=, class{cmjx-lg} { frac((x-2) - (x+1))((x-2)^2) } ) , ( ,=, class{cmjx-lg} { - frac(3)(x^2 - 4x + 4) } ) :}`

Combiner les syntaxes AsciiMath et Tex/Latex : comment, quand et pourquoi ?

Quand les expressions mathématiques sont basiques, la simplicité de la syntaxe AsciiMath est idéale. Dès qu’il y a de la complexité, la syntaxe AsciiMath montre ses faiblesses.

Dans une même page, les 2 syntaxes peuvent être combinées. La syntaxe Tex/Latex est alors utilisée dans des blocs d’équations présentant des cas que la syntaxe AsciiMath ne peut pas couvrir.

Pour combiner les 2 syntaxes, la configuration TeX-MML-AM_CHTML est définie lors de l’appel de MathJax. Un peu de paramétrage propre à Tex/Latex est réalisé en amont de l’appel de MathJax via l’objet window.MathJax :

<head> …
    <script>
        window.MathJax = {
           tex2jax : { inlineMath : [ ['##','##'], ["\\(","\\)"] ],
                       displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
                       processEscapes : true
            },
            displayAlign: "left"
         };
    </script>
    <script async="true" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-MML-AM_CHTML"> <script>

… </head>

La fonction run_maths abordée précédemment dans le paragraphe "Sécuriser et industrialiser le chargement de la librairie MathJax" est adaptée pour prédéfinir les propriétés pour les syntaxes Tex/Latex dans l’objet window.MathJax :

./js/lib.js
  run_maths = function() {
  
    if (document.querySelector('[class*="cmath"]') !== null) {
  
      if (typeof (mjax_path)=='undefined') { mjax_path='https://cdn.jsdelivr.net/npm/mathjax@2'; }
      if (typeof (mjax_config)=='undefined') { mjax_config='AM_CHTML'; }
      
      if (typeof(window.MathJax) == 'undefined') { window.MathJax = { }; }
      
      if (mjax_config.toLowerCase().indexOf('tex') >= 0) {
            m = window.MathJax;
            if (typeof(m.displayAlign) == 'undefined') { m.displayAlign = 'left'; }
            if (typeof(m.tex2jax) == 'undefined') { m.tex2jax = { }; } 
            if (typeof(m.tex2jax.inlineMath) == 'undefined')     { m.tex2jax.inlineMath     = [ ['##','##'], ["\\(","\\)"] ]; }
            if (typeof(m.tex2jax.displayMath) == 'undefined')    { m.tex2jax.displayMath    = [ ['$$','$$'], ["\\[","\\]"] ]; }
            if (typeof(m.tex2jax.processEscapes) == 'undefined') { m.tex2jax.processEscapes = true; }       
      }
      
      smjax = document.createElement ('script');
      smjax.setAttribute('src',`${mjax_path}/MathJax.js?config=${mjax_config}`);
      smjax.setAttribute('async',true);
      document.getElementsByTagName('head')[0].appendChild(smjax);
    }
  };
  
  if (document.readyState === 'loading') {  window.addEventListener('DOMContentLoaded', run_maths); }
  else { run_maths(); }

Pour une page ayant besoin de la combinaison des 2 syntaxes (AsciiMath et Latex), définir la variable mjax_config et affecter la valeur TeX-MML-AM_CHTML:

…
<script> var mjax_config='TeX-MML-AM_CHTML'; </script>
…
<script type="text/javascript" src="./js/lib.js"> </script>
…

Pourquoi un code aussi compliqué dans la fonction ? En vérifiant si chaque objet ou propriété existe déjà ou non, la fonction garantit qu’aucune propriété personnalisée nécessaire dans une page n’est écrasée, encore moins l’objet window.MathJax. Exemple :

…
<script>
  window.MathJax = {
    tex2jax : { inlineMath: [ ['~~','~~'] ]; }
  };
</script>
<script> var mjax_config='TeX-MML-AM_CHTML'; </script>
<script type="text/javascript" src="./js/lib.js"> </script>
…

Dans la configuration par défaut appliquée par la fonction run_maths, pour une page combinant les 2 syntaxes :

SyntaxeModeÉcriture du code
AsciiMathBloc ou "inline"`… code AsciiMath …`
LatexBloc$$… code Latex …$$ \[… code Latex …\]
Latex"inline"##… code Latex …## \(… code Latex …\)

Par défaut, les expressions écrites en Latex en mode bloc sont centrées dans le conteneur parent (div …). La propriété displayAlign dans l’objet window.MathJax écrase ce comportement par défaut. Dans cet article, l’alignement à gauche est forcé (displayAlign: 'left').

Dans les sous paragraphes qui suivent, quelques cas dans lequels la syntaxe Latex résout des problématiques rencontrés avec la syntaxe AsciiMath.

Matrices avec fractions (dfrac)

Dans une matrice contenant des fractions, avec AsciiMath les fractions sont mal dimensionnées. On peut appliquer la classe CSS cmjx-lg (font-size: 1.65rem) afin d’ajuster les éléments à redimensionner, mais ça ne résout pas le problème sur le caractère ouvrant et fermant de la matrice, des décalages sautent aux yeux :

<div class="cmath">
 `[bbrho] = ( ( 1/2 , 0   ),
              ( 0   , 1/2 )
            )`
 </div>
`[bbrho] = ((1/2,0), (0,1/2))`
<div class="cmath">
 `[bbrho] = ( ( class{cmjx-lg}{1/2} , 0                   ),
              ( 0                   , class{cmjx-lg}{1/2} )
            )`
</div>
`[bbrho] = ( ( class{cmjx-lg}{1/2}, 0), (0, class{cmjx-lg}{1/2}) )`

La syntaxe Latex est plus lourde, certes, mais le rendu est parfait. Avec AsciiMath, ce serait techniquement impossible. Le caractère ouvrant et fermant de la matrice enveloppe les éléments de celle-ci :

<div class="cmath">$$
    [\pmb{\rho}] =
      \begin{pmatrix}
        \dfrac{1}{2} & 0            \\
        0            & \dfrac{1}{2} \\
      \end{pmatrix}
$$</div>
$$[\pmb{\rho}] = \begin{pmatrix} \dfrac{1}{2} & 0 \\ 0 & \dfrac{1}{2} \\ \end{pmatrix}$$

Pourquoi \dfrac et non \frac dans la syntaxe Latex ? En indiquant \dfrac (displaystyle), on demande à la fraction de ne pas s’ajuster à la ligne de la matrice mais de prendre le style global.

Fractions continues (cfrac)

L’écriture de fractions continues avec la syntaxe AsciiMath est mal formatée, pas de solutions techniques simples (classes CSS…) :

<div class="cmath">
  `x = frac(1)(sqrt2 + frac(1)(sqrt2 + frac(1)(sqrt2 + ...)))`
</div>
`x = frac(1)(sqrt2 + frac(1)(sqrt2 + frac(1)(sqrt2 + ...)))`

Avec la syntaxe Latex et cfrac, le formatage est correct et le code est même plus lisible :

<div class="cmath">$$
  x = \cfrac{1}{\sqrt{2}+
        \cfrac{1}{\sqrt{2}+
          \cfrac{1}{\sqrt{2}+\dotsb}
        }
    }
$$</div>
$$x = \cfrac{1}{\sqrt{2}+ \cfrac{1}{\sqrt{2}+ \cfrac{1}{\sqrt{2}+\dotsb} } }$$

Centrer des équations sur le signe =

Avec AsciiMath, quand les équations sont linéaires de part et d’autre du signe `=`, aucun problème pour centrer sur le signe `=` en utilisant les matrices pour les mises en forme. Dès qu’il y a une fraction à gauche ou à droite, ça se complique dans le rendu avec la syntaxe AsciiMath, les fractions apparaissent en plus petit : ce problème est résolu en appliquant sur les éléments à ajuster la classe CSS cmjx-lg (font-size: 1.65rem).

<div class="cmath">
`{:
      ( f(x)      ,=, class{cmjx-lg} { frac(x+1)(x-2)               }  ) ,
      ( f^'(x)     ,=, class{cmjx-lg} { frac((x-2) - (x+1))((x-2)^2) }  ) ,
      (           ,=, class{cmjx-lg} { - frac(3)(x^2 - 4x + 4)      }  )
:}`
</div>
`{: ( f(x) ,=, class{cmjx-lg} { frac(x+1)(x-2) } ) , ( f^'(x) ,=, class{cmjx-lg} { frac((x-2) - (x+1))((x-2)^2) } ) , ( ,=, class{cmjx-lg} { - frac(3)(x^2 - 4x + 4) } ) :}`

Avec la syntaxe Latex, l’ajustement des fractions n’est plus une préoccupation. La syntaxe Latex n’est pas plus ou moins complexe que la syntaxe AsciiMath pour réaliser le centrage :

<div class="cmath">$$
    \begin{align}
      f(x)   &= \frac{x+1}{x-2} \\ \\
      f'(x)  &= \frac{(x-2) - (x+1)}{(x-2)^2} \\ \\
             &= - \frac{3}{x^2 - 4x + 4}
    \end{align}
$$</div>
$$\begin{align} f(x) &= \frac{x+1}{x-2} \\ \\ f'(x) &= \frac{(x-2) - (x+1)}{(x-2)^2} \\ \\ &= - \frac{3}{x^2 - 4x + 4} \end{align}$$

Numéroter des équations, signets

Dans la syntaxe Tex/Latex avec \tag, la numérotation des équations est simple, ce qui n’est pas le cas avec la syntaxe AsciiMath. On fait d’une pierre deux coups : le numéro de l’équation est correctement centré dans la partie droite de son conteneur et les équations peuvent être centrées sur le signe `=`.

<div class="cmath">$$
    \begin{align}
        \cos 2\theta                   &= \cos^2 \theta - \sin^2 \theta   \tag{9}  \label{cos2x} \\ \\
        
        \cos^2 \theta + \sin^2 \theta  &= 1                               \tag{10} \label{10}    \\ \\
    \end{align}
$$</div>
$$ \begin{align} \cos 2\theta &= \cos^2 \theta - \sin^2 \theta \tag{9} \label{cos2x} \\ \\ \cos^2 \theta + \sin^2 \theta &= 1 \tag{10} \label{10} \\ \\ \end{align} $$

Avec \label dans l’exemple ci-dessus, des signets sont très facilement définis. Il n’est pas nécessaire que le label ait le même nom que le tag. Très pratique pour renvoyer, en utilisant \ref de la syntaxe Latex, vers une expression décrite ailleurs dans la page :

<div class="cmath">
À partir des formules \( \ref{cos2x} \) et \( \ref{10} \), on en déduit :
$$
    \begin{align}
      \cos 2\theta       &= \cos^2 \theta + \sin^2 \theta - \sin^2 \theta - \sin^2 \theta \\ \\
                         &= 1 - 2\sin^2\theta 
    \end{align}
$$</div>
À partir des formules \( \ref{cos2x} \) et \( \ref{10} \), on en déduit : $$ \begin{align} \cos 2\theta &= \cos^2 \theta + \sin^2 \theta - \sin^2 \theta - \sin^2 \theta \\ \\ &= 1 - 2\sin^2\theta \end{align} $$

Le menu MathJax

Un menu MathJax très pratique est alors disponible avec un clic droit sur une expression mathématique :

À partir du menu "Show Math As", le code source AsciiMath ou Tex/Latex peut être récupéré facilement pour être copié. La syntaxe en entrée (AsciiMath, Tex/Latex) est automatiquement détecté.

Clic droit - Menu MathJax - AsciiMath code AsciiMath clic droit Clic droit - Menu MathJax - Tex code Tex clic droit

Le menu "Math SettingsMath Renderer" propose quant à lui de réaliser le rendu dans d’autres formats de sortie que celui défini dans la configuration (Common HTML, HTML-CSS, SVG, MathML…) :

Menu MathJax - Math renderer

Bien pratique à des fins de debug, c’est à partir de cette fonctionnalité dans le menu MathJax que l’on détecte que l’utilisation des classes dans les syntaxes AsciiMath ou Tex/Latex n’est possible que si le format de sortie est "Common HTML" (CHTML).

Comme mentionné dans l’introduction, MathML n’est pas devenu un standard avec HTML 5 et n’est pas nécessairement disponible dans le navigateur utilisé, donc le rendu au format de sortie MathML ne fonctionnera pas toujours. Avec Google Chrome: statut KO.

MathJax Chrome - MathML non supporté