Repository: Khan/KaTeX
Pull request #952 (2017-10-25 17:09:33)

Support Unicode Negated Relations
This is the fifth in a series of PRs to give KaTeX the ability to recognize Unicode character input.

All the characters in this PR will produce `rel` atoms.

ronkok: As in PR #933, the following table shows the KaTeX function to which each character is mapped and confirmation whether [unicode math](http://ctan.sharelatex.com/tex-archive/macros/latex/contrib/unicode-math/unicode-math-table.tex) and/or John Cook’s [conversion page](https://www.johndcook.com/unidata.js) map it the same way.

| **Character** | **Code point** | **Maps to**             | **unicode math** | **Cook**  | **Other**                  |
|:-------------:|:--------------:|:------------------------|:----------------:|:---------:|:---------------------------|
| ∉             | U+2209         | \\notin                 | ✓                | ✓         |                            |
| ∤             | U+2224         | \\nmid                  | ✓                | ✓         | \\nshortmid                |
| ∦             | U+2226         | \\nparallel             | ✓                | ✓         | \\nshortparallel           |
| ≁             | U+2241         | \\nsim                  | ✓                | ✓         |                            |
| ≆             | U+2246         | \\ncong<sup>(AMS)</sup> | \\simneqq        | \\simneqq |                            |
| ≠             | U+2260         | \\ne                    | ✓                | ✓         | \\neq \\textdoublebarslash |
| ≨             | U+2268         | \\lneqq                 | ✓                | ✓         |                            |
| ≩             | U+2269         | \\gneqq                 | ✓                | ✓         |                            |
| ≮             | U+226E         | \\nless                 | ✓                | ✓         |                            |
| ≯             | U+226F         | \\ngtr                  | ✓                | ✓         |                            |
| ≰             | U+2270         | \\nleq                  | ✓                | ✓         |                            |
| ≱             | U+2271         | \\ngeq                  | ✓                | ✓         |                            |
| ⊀             | U+2280         | \\nprec                 | ✓                | ✓         |                            |
| ⊁             | U+2281         | \\nsucc                 | ✓                | ✓         |                            |
| ⊈             | U+2288         | \\nsubseteq             | ✓                | ✓         |                            |
| ⊉             | U+2289         | \\nsupseteq             | ✓                | ✓         |                            |
| ⊊             | U+228A         | \\subsetneq             | ✓                | ✓         | \\varsubsetneq             |
| ⊋             | U+228B         | \\supsetneq             | ✓                | ✓         | \\varsupsetneq             |
| ⊬             | U+22AC         | \\nvdash                | ✓                | ✓         |                            |
| ⊭             | U+22AD         | \\nvDash                | ✓                | ✓         |                            |
| ⊮             | U+22AE         | \\nVdash                | ✓                | ✓         |                            |
| ⊯             | U+22AF         | \\nVDash                | ✓                | ✓         |                            |
| ⋠             | U+22E0         | \\npreceq<sup>(AMS)</sup>   | \\npreccurlyeq   | \\npreccurlyeq   |                            |
| ⋡             | U+22E1         | \\nsucceq<sup>(AMS)</sup>   | \\nsucccurlyeq   | \\nsucccurlyeq   |                            |
| ⋦             | U+22E6         | \\lnsim                 | ✓                | ✓         |                            |
| ⋧             | U+22E7         | \\gnsim                 | ✓                | ✓         |                            |
| ⋨             | U+22E8         | \\precnsim              | ✓                | ✓         |                            |
| ⋩             | U+22E9         | \\succnsim              | ✓                | ✓         |                            |
| ⋬             | U+22EC         | \\ntrianglelefteq       | ✓                | ✓         |                            |
| ⋭             | U+22ED         | \\ntrianglerighteq      | ✓                | ✓         |                            |
| ⪇             | U+2A87         | \\lneq                  | ✓                | ✓         |                            |
| ⪈             | U+2A88         | \\gneq                  | ✓                | ✓         |                            |
| ⪉             | U+2A89         | \\lnapprox              | ✓                | ✓         |                            |
| ⪊             | U+2A8A         | \\gnapprox              | ✓                | ✓         |                            |
| ⪵             | U+2AB5         | \\precneqq              | ✓                | ✓         |                            |
| ⪶             | U+2AB6         | \\succneqq              | ✓                | ✓         |                            |
| ⪹             | U+2AB9         | \\precnapprox           | ✓                | ✓         |                            |
| ⪺             | U+2ABA         | \\succnapprox           | ✓                | ✓         |                            |
| ⫋             | U+2ACB         | \\subsetneqq            | ✓                | ✓         | \\varsubsetneqq            |
| ⫌             | U+2ACC         | \\supsetneqq            | ✓                | ✓         | \\varsupsetneqq            |
ronkok: Good point about the omission of aliases from the code. I'll write them in.

Patch:
diff --git a/src/symbols.js b/src/symbols.js
index 2d168220..c7341189 100644
--- a/src/symbols.js
+++ b/src/symbols.js
@@ -179,55 +179,58 @@ defineSymbol(math, main, rel, "\u2196", "\\nwarrow");
 defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons");
 
 // AMS Negated Binary Relations
-defineSymbol(math, ams, rel, "\u226e", "\\nless");
+defineSymbol(math, ams, rel, "\u226e", "\\nless", true);
 defineSymbol(math, ams, rel, "\ue010", "\\nleqslant");
 defineSymbol(math, ams, rel, "\ue011", "\\nleqq");
-defineSymbol(math, ams, rel, "\u2a87", "\\lneq");
-defineSymbol(math, ams, rel, "\u2268", "\\lneqq");
+defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
+defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
 defineSymbol(math, ams, rel, "\ue00c", "\\lvertneqq");
-defineSymbol(math, ams, rel, "\u22e6", "\\lnsim");
-defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox");
-defineSymbol(math, ams, rel, "\u2280", "\\nprec");
-defineSymbol(math, ams, rel, "\u22e0", "\\npreceq");
-defineSymbol(math, ams, rel, "\u22e8", "\\precnsim");
-defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox");
-defineSymbol(math, ams, rel, "\u2241", "\\nsim");
+defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
+defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
+defineSymbol(math, ams, rel, "\u2280", "\\nprec", true);
+// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
+defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
+defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
+defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
 defineSymbol(math, ams, rel, "\ue006", "\\nshortmid");
-defineSymbol(math, ams, rel, "\u2224", "\\nmid");
-defineSymbol(math, ams, rel, "\u22ac", "\\nvdash");
-defineSymbol(math, ams, rel, "\u22ad", "\\nvDash");
+defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
+defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
+defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
 defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
-defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq");
-defineSymbol(math, ams, rel, "\u228a", "\\subsetneq");
+defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
+defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
 defineSymbol(math, ams, rel, "\ue01a", "\\varsubsetneq");
-defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq");
+defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
 defineSymbol(math, ams, rel, "\ue017", "\\varsubsetneqq");
-defineSymbol(math, ams, rel, "\u226f", "\\ngtr");
+defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
 defineSymbol(math, ams, rel, "\ue00f", "\\ngeqslant");
 defineSymbol(math, ams, rel, "\ue00e", "\\ngeqq");
-defineSymbol(math, ams, rel, "\u2a88", "\\gneq");
-defineSymbol(math, ams, rel, "\u2269", "\\gneqq");
+defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
+defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
 defineSymbol(math, ams, rel, "\ue00d", "\\gvertneqq");
-defineSymbol(math, ams, rel, "\u22e7", "\\gnsim");
-defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox");
-defineSymbol(math, ams, rel, "\u2281", "\\nsucc");
-defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq");
-defineSymbol(math, ams, rel, "\u22e9", "\\succnsim");
-defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox");
-defineSymbol(math, ams, rel, "\u2246", "\\ncong");
+defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
+defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
+defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true);
+// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
+defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
+defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true);
+// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
+defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
 defineSymbol(math, ams, rel, "\ue007", "\\nshortparallel");
-defineSymbol(math, ams, rel, "\u2226", "\\nparallel");
-defineSymbol(math, ams, rel, "\u22af", "\\nVDash");
+defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
+defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
 defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
-defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq");
+defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
 defineSymbol(math, ams, rel, "\ue018", "\\nsupseteqq");
-defineSymbol(math, ams, rel, "\u228b", "\\supsetneq");
+defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
 defineSymbol(math, ams, rel, "\ue01b", "\\varsupsetneq");
-defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq");
+defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
 defineSymbol(math, ams, rel, "\ue019", "\\varsupsetneqq");
-defineSymbol(math, ams, rel, "\u22ae", "\\nVdash");
-defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq");
-defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq");
+defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
+defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
+defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
 defineSymbol(math, ams, rel, "\ue016", "\\nsubseteqq");
 defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
 defineSymbol(math, ams, bin, "\u22b5", "\\unrhd");
@@ -518,25 +521,25 @@ defineSymbol(math, main, rel, "\u2265", "\\geq", true);
 defineSymbol(math, main, rel, "\u2190", "\\gets");
 defineSymbol(math, main, rel, ">", "\\gt");
 defineSymbol(math, main, rel, "\u2208", "\\in", true);
-defineSymbol(math, main, rel, "\u2209", "\\notin");
+defineSymbol(math, main, rel, "\u2209", "\\notin", true);
 defineSymbol(math, main, rel, "\u0338", "\\not");
 defineSymbol(math, main, rel, "\u2282", "\\subset", true);
 defineSymbol(math, main, rel, "\u2283", "\\supset", true);
 defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
 defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
-defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq");
-defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq");
+defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
+defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
 defineSymbol(math, main, rel, "\u22a8", "\\models");
 defineSymbol(math, main, rel, "\u2190", "\\leftarrow");
 defineSymbol(math, main, rel, "\u2264", "\\le");
 defineSymbol(math, main, rel, "\u2264", "\\leq", true);
 defineSymbol(math, main, rel, "<", "\\lt");
-defineSymbol(math, main, rel, "\u2260", "\\ne");
+defineSymbol(math, main, rel, "\u2260", "\\ne", true);
 defineSymbol(math, main, rel, "\u2260", "\\neq");
 defineSymbol(math, main, rel, "\u2192", "\\rightarrow");
 defineSymbol(math, main, rel, "\u2192", "\\to");
-defineSymbol(math, ams, rel, "\u2271", "\\ngeq");
-defineSymbol(math, ams, rel, "\u2270", "\\nleq");
+defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
+defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
 defineSymbol(math, main, spacing, null, "\\!");
 defineSymbol(math, main, spacing, "\u00a0", "\\ ");
 defineSymbol(math, main, spacing, "\u00a0", "~");


Test patch:
diff --git a/test/katex-spec.js b/test/katex-spec.js
index 7bf73b8f..ad1ffbb2 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -2626,6 +2626,10 @@ describe("Unicode", function() {
         expect("ΓΔΘΞΠΣΦΨΩ").toParse();
     });
 
+    it("should parse negated relations", function() {
+        expect("∉∤∦≁≆≠≨≩≮≯≰≱⊀⊁⊈⊉⊊⊋⊬⊭⊮⊯⋠⋡⋦⋧⋨⋩⋬⋭⪇⪈⪉⪊⪵⪶⪹⪺⫋⫌").toParse();
+    });
+
     it("should parse relations", function() {
         expect("∈∋∝∼∽≂≃≅≈≊≍≎≏≐≑≒≓≖≗≜≡≤≥≦≧≫≬≳≷≺≻≼≽≾≿").toParse();
     });