Add mhchem extension (#1436)

* A proposal for support of mhchem

* Create extension

* Add index

* Remove arrow function

* Fix lint errors in macros.js

* Remove mhchem from build

* Move code from macros.js to mhchem.js

* Add minified mhchem

* Remove arrow head mods. Disable eslint.

* Fix space handling

* Update code to mhchem v3.3.0

* Tweak arrows to reduce diff

* Raise \tripledash

* Edit docs and webpack

* Update package.json

* Remove wrap. Remove manual.

* Correct second brush stroke in \xrightleftarrows

* Added patch file

* Add import line

* Add mhchem to eslint ignore
This commit is contained in:
Ron Kok
2018-11-24 15:52:25 -08:00
committed by Kevin Barabash
parent 3dfd17d9b4
commit 64745b5c8a
9 changed files with 1962 additions and 6 deletions

View File

@@ -2,3 +2,4 @@
dist/*
website/build/*
**/*.min.js
contrib/mhchem/*

19
contrib/mhchem/README.md Normal file
View File

@@ -0,0 +1,19 @@
# mhchem extension
This extension adds to KaTeX the `\ce` and `\pu` functions from the [mhchem](https://mhchem.github.io/MathJax-mhchem/) package.
### Usage
This extension isn't part of core KaTeX, so the script should be separately included. Write the following line into the HTML page<67>s `<head>`. Place it *after* the line that calls `katex.js`.
```html
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/contrib/mhchem.min.js"></script>
```
### Syntax
See the [mhchem Manual](https://mhchem.github.io/MathJax-mhchem/) for a full explanation of the input syntax, with working examples. The manual also includes a demonstration box.
### Browser Support
This extension has been tested on Chrome, Firefox, Opera, and Edge.

1695
contrib/mhchem/mhchem.js Normal file

File diff suppressed because it is too large Load Diff

235
contrib/mhchem/mhchem.patch Normal file
View File

@@ -0,0 +1,235 @@
0a1
> /* eslint-disable */
5a7,22
> * KaTeX mhchem.js
> *
> * This file implements a KaTeX version of mhchem version 3.3.0.
> * It is adapted from MathJax/extensions/TeX/mhchem.js
> * It differs from the MathJax version as follows:
> * 1. The interface is changed so that it can be called from KaTeX, not MathJax.
> * 2. \rlap and \llap are replaced with \mathrlap and \mathllap.
> * 3. Four lines of code are edited in order to use \raisebox instead of \raise.
> * 4. The reaction arrow code is simplified. All reaction arrows are rendered
> * using KaTeX extensible arrows instead of building non-extensible arrows.
> * 5. \tripledash vertical alignment is slightly adjusted.
> *
> * This code, as other KaTeX code, is released under the MIT license.
> *
> * /*************************************************************
> *
33a51
> // version: "3.3.0" for MathJax and KaTeX
35,37d52
< MathJax.Extension["TeX/mhchem"] = {
< version: "3.3.0"
< };
39c54
< MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () {
---
> // Add \ce, \pu, and \tripledash to the KaTeX macros.
41c56,58
< var TEX = MathJax.InputJax.TeX;
---
> katex.__defineMacro("\\ce", function(context) {
> return chemParse(context.consumeArgs(1)[0], "ce")
> });
43,47c60,62
< //
< // This is the main class for handing the \ce and related commands.
< // Its main method is Parse() which takes the argument to \ce and
< // returns the corresponding TeX string.
< //
---
> katex.__defineMacro("\\pu", function(context) {
> return chemParse(context.consumeArgs(1)[0], "pu");
> });
49,50c64,68
< var CE = MathJax.Object.Subclass({
< string: "", // the \ce string being parsed
---
> // Needed for \bond for the ~ forms
> // Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not
> // a mathematical minus, U+2212. So we need that extra 0.56.
> katex.__defineMacro("\\tripledash", "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu"
> + "\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");
52,55c70
< //
< // Store the string when a CE object is created
< //
< Init: function (string) { this.string = string; },
---
> import katex from "katex";
57,64c72,85
< //
< // This converts the CE string to a TeX string.
< //
< Parse: function (stateMachine) {
< try {
< return texify.go(mhchemParser.go(this.string, stateMachine));
< } catch (ex) {
< TEX.Error(ex);
---
> //
> // This is the main function for handing the \ce and \pu commands.
> // It takes the argument to \ce or \pu and returns the corresponding TeX string.
> //
>
> var chemParse = function (tokens, stateMachine) {
> // Recreate the argument string from KaTeX's array of tokens.
> var str = "";
> var expectedLoc = tokens[tokens.length - 1].loc.start
> for (var i = tokens.length - 1; i >= 0; i--) {
> if(tokens[i].loc.start > expectedLoc) {
> // context.consumeArgs has eaten a space.
> str += " ";
> expectedLoc = tokens[i].loc.start;
65a87,88
> str += tokens[i].text;
> expectedLoc += tokens[i].text.length;
67c90,92
< });
---
> var tex = texify.go(mhchemParser.go(str, stateMachine));
> return tex;
> };
1405,1406c1430,1431
< res += "^{\\smash[t]{\\vphantom{2}}\\llap{"+(b5.b||"")+"}}";
< res += "_{\\vphantom{2}\\llap{\\smash[t]{"+(b5.p||"")+"}}}";
---
> res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(b5.b||"")+"}}";
> res += "_{\\vphantom{2}\\mathllap{\\smash[t]{"+(b5.p||"")+"}}}";
1508,1520c1533,1536
< var arrow = texify._getArrow(buf.r);
< if (b6.rd || b6.rq) {
< if (buf.r === "<=>" || buf.r === "<=>>" || buf.r === "<<=>" || buf.r === "<-->") {
< // arrows that cannot stretch correctly yet, https://github.com/mathjax/MathJax/issues/1491
< arrow = "\\long"+arrow;
< if (b6.rd) { arrow = "\\overset{"+b6.rd+"}{"+arrow+"}"; }
< if (b6.rq) { arrow = "\\underset{\\lower7mu{"+b6.rq+"}}{"+arrow+"}"; }
< arrow = " {}\\mathrel{"+arrow+"}{} ";
< } else {
< if (b6.rq) { arrow += "[{"+b6.rq+"}]"; }
< arrow += "{"+b6.rd+"}";
< arrow = " {}\\mathrel{\\x"+arrow+"}{} ";
< }
---
> var arrow = "\\x" + texify._getArrow(buf.r);
> if (b6.rq) { arrow += "[{" + b6.rq + "}]"; }
> if (b6.rd) {
> arrow += "{" + b6.rd + "}";
1522c1538
< arrow = " {}\\mathrel{\\long"+arrow+"}{} ";
---
> arrow += "{}";
1615c1631
< case "<-->": return "leftrightarrows";
---
> case "<-->": return "rightleftarrows";
1618,1619c1634,1635
< case "<=>>": return "Rightleftharpoons";
< case "<<=>": return "Leftrightharpoons";
---
> case "<=>>": return "rightequilibrium";
> case "<<=>": return "leftequilibrium";
1634,1637c1650,1653
< case "~-": return "{\\rlap{\\lower.1em{-}}\\raise.1em{\\tripledash}}";
< case "~=": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}";
< case "~--": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}";
< case "-~-": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{-}}\\tripledash}";
---
> case "~-": return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";
> case "~=": return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";
> case "~--": return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";
> case "-~-": return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";
1680,1770d1695
<
< //
< // MathJax definitions
< //
< MathJax.Extension["TeX/mhchem"].CE = CE;
<
< /***************************************************************************/
<
< TEX.Definitions.Add({
< macros: {
< //
< // Set up the macros for chemistry
< //
< ce: "CE",
< pu: "PU",
<
< //
< // Make these load AMSmath package (redefined below when loaded)
< //
< xleftrightarrow: ["Extension", "AMSmath"],
< xrightleftharpoons: ["Extension", "AMSmath"],
< xRightleftharpoons: ["Extension", "AMSmath"],
< xLeftrightharpoons: ["Extension", "AMSmath"],
<
< // FIXME: These don't work well in FF NativeMML mode
< longrightleftharpoons: ["Macro", "\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"],
< longRightleftharpoons: ["Macro", "\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{\\leftharpoondown}}"],
< longLeftrightharpoons: ["Macro", "\\stackrel{\\textstyle\\vphantom{{-}}{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"],
< longleftrightarrows: ["Macro", "\\stackrel{\\longrightarrow}{\\smash{\\longleftarrow}\\Rule{0px}{.25em}{0px}}"],
<
< //
< // Needed for \bond for the ~ forms
< // Not perfectly aligned when zoomed in, but on 100%
< //
< tripledash: ["Macro", "\\vphantom{-}\\raise2mu{\\kern2mu\\tiny\\text{-}\\kern1mu\\text{-}\\kern1mu\\text{-}\\kern2mu}"]
< },
< }, null, true);
<
< if (!MathJax.Extension["TeX/AMSmath"]) {
< TEX.Definitions.Add({
< macros: {
< xrightarrow: ["Extension", "AMSmath"],
< xleftarrow: ["Extension", "AMSmath"]
< }
< }, null, true);
< }
<
< //
< // These arrows need to wait until AMSmath is loaded
< //
< MathJax.Hub.Register.StartupHook("TeX AMSmath Ready", function () {
< TEX.Definitions.Add({
< macros: {
< //
< // Some of these are hacks for now
< //
< xleftrightarrow: ["xArrow", 0x2194, 6, 6],
< xrightleftharpoons: ["xArrow", 0x21CC, 5, 7], // FIXME: doesn't stretch in HTML-CSS output
< xRightleftharpoons: ["xArrow", 0x21CC, 5, 7], // FIXME: how should this be handled?
< xLeftrightharpoons: ["xArrow", 0x21CC, 5, 7]
< }
< }, null, true);
< });
<
< TEX.Parse.Augment({
<
< //
< // Implements \ce and friends
< //
< CE: function (name) {
< var arg = this.GetArgument(name);
< var tex = CE(arg).Parse();
< this.string = tex + this.string.substr(this.i); this.i = 0;
< },
<
< PU: function (name) {
< var arg = this.GetArgument(name);
< var tex = CE(arg).Parse('pu');
< this.string = tex + this.string.substr(this.i); this.i = 0;
< }
<
< });
<
< //
< // Indicate that the extension is ready
< //
< MathJax.Hub.Startup.signal.Post("TeX mhchem Ready");
<
< });
<
< MathJax.Ajax.loadComplete("[mhchem]/unpacked/mhchem.js");

View File

@@ -7,8 +7,9 @@ title: Extensions & Libraries
These extensions are provided by KaTeX.
- [Auto-render](autorender.md): Automatically renders all of the math inside text
- [Copy-tex](https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex): When selecting and copying KaTeX-rendered elements, copies their LaTeX source to the clipboard
- [`math/tex` Custom Script Type](https://github.com/KaTeX/KaTeX/tree/master/contrib/mathtex-script-type): Automatically displays LaTeX math inside `script` tags with `type=math/tex`
- [Copy-tex](https://github.com/Khan/KaTeX/tree/master/contrib/copy-tex): When selecting and copying KaTeX-rendered elements, copies their LaTeX source to the clipboard
- [`math/tex` Custom Script Type](https://github.com/Khan/KaTeX/tree/master/contrib/mathtex-script-type): Automatically displays LaTeX math inside `script` tags with `type=math/tex`
- [mhchem](https://github.com/Khan/KaTeX/tree/master/contrib/mhchem): Write beautiful chemical equations easily
## Libraries

View File

@@ -206,7 +206,7 @@ table td {
|\cdot|$\cdot$||
|\cdotp|$\cdotp$||
|\cdots|$\cdots$||
|\ce |<span style="color:firebrick;">Not supported</span>|A PR is pending
|\ce |${\mathrm{C}{\vphantom{X}}_{\smash[t]{6}}\mathrm{H}{\vphantom{X}}_{\smash[t]{5}}{-}\mathrm{CHO}}$|`\ce{C6H5-CHO}` Requires an [extension](https://github.com/KaTeX/KaTeX/tree/master/contrib/mhchem/)|
|\cee|<span style="color:firebrick;">Not supported</span>|Deprecated by mhchem
|\centerdot|$a\centerdot b$|`a\centerdot b`|
|\cf|<span style="color:firebrick;">Not supported</span>|Deprecated by mhchem|
@@ -813,7 +813,7 @@ table td {
|\providecommand|$\providecommand\greet{\text{Hello}} \greet$|`\providecommand\greet{\text{Hello}} \greet`|
|\psi|$\psi$||
|\Psi|$\Psi$||
|\pu||A PR is pending|
|\pu |${123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}$|`\pu{123 kJ//mol}` Requires an [extension](https://github.com/KaTeX/KaTeX/tree/master/contrib/mhchem/)|
## QR

View File

@@ -109,7 +109,8 @@
"collectCoverageFrom": [
"src/**/*.js",
"contrib/**/*.js",
"!src/unicodeMake.js"
"!src/unicodeMake.js",
"!contrib/mhchem/**"
],
"setupTestFrameworkScriptFile": "<rootDir>/test/setup.js",
"snapshotSerializers": [

View File

@@ -325,7 +325,7 @@ s-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47
121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6
s2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11
c0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z
M100 241v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z`,
M100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z`,
// rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
rightarrowabovebar: `M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32

View File

@@ -25,6 +25,10 @@ const targets /*: Array<Target> */ = [
entry: './contrib/auto-render/auto-render.js',
library: 'renderMathInElement',
},
{
name: 'contrib/mhchem',
entry: './contrib/mhchem/mhchem.js',
},
{
name: 'contrib/copy-tex',
entry: './contrib/copy-tex/copy-tex.webpack.js',