Repository: Khan/KaTeX
Pull request #933 (2017-10-14 23:13:26)

Support Unicode relations
This is the first in a series of PRs to give KaTeX the ability to recognize Unicode character input. The code in this PR follows the style of PR #410.

All the characters in this PR will produce `rel` atoms. I’ll submit PRs for other atom types later.

ronkok: I’ve omitted, for now, some characters because they are HTML reserved characters, or because they need `stackrel` macros, or because they are of ambiguous atom type or ambiguous name. Omissions include: `<`, `>`, `:`, `⊥`, `⊨`,`|`, all triangles, `≔`, `≕`, `≛`, `≝`, etc. Follow up on these omissions will come later. So will arrows and negated relations.
ronkok: Earlier KaTeX efforts toward Unicode input have stalled for fear of future broken content. So I’ve collected some data for use in vetting this work. The following table shows: (1) the KaTeX function to which each character is mapped, (2) 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/unicode-latex.html) map it the same way, (3) possible alternates that I did not use.

  

| **Character** | **Code point** | **Maps to**     | **unicode math** | **Cook**              | **Not used**                   |
|:-------------:|:--------------:|:----------------|:----------------:|:---------------------:|:-------------------------------|
| ∈             | U+2208         | \\in            | ✓                | both                  | \\varin                        |
| ∋             | U+220B         | \\ni            | ✓                | \\ni, \\varni         | \\owns, \\backepsilon, \\varni |
| ∝             | U+221D         | \\propto        | ✓                | both                  | \\varpropto                    |
| ∼             | U+223C         | \\sim           | ✓                | all                   | \\thicksim, \\difference       |
| ∽             | U+223D         | \\backsim       | ✓                | ✓                     |                                |
| ≂             | U+2242         | \\eqsim         | ✓                | ✓                     |                                |
| ≃             | U+2243         | \\simeq         | ✓                | ✓                     | \\sime                         |
| ≅             | U+2245         | \\cong          | ✓                | ✓                     |                                |
| ≈             | U+2248         | \\approx        | ✓                | both                  | \\thickapprox                  |
| ≊             | U+224A         | \\approxeq      | ✓                | ✓                     |                                |
| ≍             | U+224D         | \\asymp         | ✓                | ✓                     |                                |
| ≎             | U+224E         | \\Bumpeq        | ✓                | ✓                     |                                |
| ≏             | U+224F         | \\bumpeq        | ✓                | ✓                     |                                |
| ≐             | U+2250         | \\doteq         | ✓                | ✓                     |                                |
| ≑             | U+2251         | \\Doteq         | ✓                | ✓                     | \\doteqdot                     |
| ≒             | U+2252         | \\fallingdotseq | ✓                | ✓                     |                                |
| ≓             | U+2253         | \\risingdotseq  | ✓                | ✓                     |                                |
| ≖             | U+2256         | \\eqcirc        | ✓                | ✓                     |                                |
| ≗             | U+2257         | \\circeq        | ✓                | ✓                     |                                |
| ≜             | U+225C         | \\triangleq     | ✓                | ✓                     |                                |
| ≡             | U+2261         | \\equiv         | ✓                | ✓                     |                                |
| ≤             | U+2264         | \\leq           | ✓                | ✓                     | \\le                           |
| ≥             | U+2265         | \\geq           | ✓                | ✓                     | \\ge                           |
| **≦**         | U+2266         | \\leqq          | ✓                | ✓                     |                                |
| ≧             | U+2267         | \\geqq          | ✓                | ✓                     |                                |
| ≫             | U+226B         | \\gg            | ✓                | ✓                     |                                |
| ≬             | U+226C         | \\between       | ✓                | ✓                     |                                |
| ≳             | U+2273         | \\gtrsim        | ✓                | ✓                     |                                |
| ≷             | U+2277         | \\gtrless       | ✓                | ✓                     |                                |
| ≺             | U+227A         | \\prec          | ✓                | ✓                     |                                |
| ≻             | U+227B         | \\succ          | ✓                | ✓                     |                                |
| ≼             | U+227C         | \\preccurlyeq   | ✓                | ✓                     |                                |
| ≽             | U+227D         | \\succcurlyeq   | ✓                | ✓                     |                                |
| ≾             | U+227E         | \\precsim       | ✓                | ✓                     |                                |
| ≿             | U+227F         | \\succsim       | ✓                | ✓                     |                                |
| ⊂             | U+2282         | \\subset        | ✓                | ✓                     |                                |
| ⊃             | U+2283         | \\supset        | ✓                | ✓                     |                                |
| ⊆             | U+2286         | \\subseteq      | ✓                | ✓                     |                                |
| ⊇             | U+2287         | \\supseteq      | ✓                | ✓                     |                                |
| ⊏             | U+228F         | \\sqsubset      | ✓                | ✓                     |                                |
| ⊐             | U+2290         | \\sqsupset      | ✓                | ✓                     |                                |
| ⊑             | U+2291         | \\sqsubseteq    | ✓                | ✓                     |                                |
| ⊒             | U+2292         | \\sqsupseteq    | ✓                | ✓                     |                                |
| ⊢             | U+22A2         | \\vdash         | ✓                | ✓                     |                                |
| ⊣             | U+22A3         | \\dashv         | ✓                | ✓                     |                                |
| ⊩             | U+22A9         | \\Vdash         | ✓                | ✓                     |                                |
| ⊪             | U+22AA         | \\Vvdash        | ✓                | ✓                     |                                |
| ⊸             | U+22B8         | \\multimap      | ✓                | ✓                     |                                |
| ⋈             | U+22C8         | \\bowtie        | ✓                | ✓                     | \\Join                         |
| ⋍             | U+22CD         | \\backsimeq     | ✓                | ✓                     |                                |
| ⋐             | U+22D0         | \\Subset        | ✓                | ✓                     |                                |
| ⋑             | U+22D1         | \\Supset        | ✓                | ✓                     |                                |
| ⋔             | U+22D4         | \\pitchfork     | ✓                | ✓                     |                                |
| ⋙             | U+22D9         | \\ggg           | ✓                | ✓                     | \\gggtr                        |
| ⋛             | U+22DB         | \\gtreqless     | ✓                | ✓                     |                                |
| ⋞             | U+22DE         | \\curlyeqprec   | ✓                | ✓                     |                                |
| ⋟             | U+22DF         | \\curlyeqsucc   | ✓                | ✓                     |                                |
| ⌢             | U+2322         | \\frown         | ✓                | \\frown, \\smallfrown | \\smallfrown, \\overparen      |
| ⌣             | U+2323         | \\smile         | ✓                | \\smile, \\smallsmile | \\smallsmile, \\underparen     |
| ⩾             | U+2A7E         | \\geqslant      | ✓                | ✓                     |                                |
| ⪆             | U+2A86         | \\gtrapprox     | ✓                | ✓                     |                                |
| ⪌             | U+2A8C         | \\gtreqqless    | ✓                | ✓                     |                                |
| ⪕             | U+2A95         | \\eqslantless   | ✓                | ✓                     |                                |
| ⪖             | U+2A96         | \\eqslantgtr    | ✓                | ✓                     |                                |
| ⪯             | U+2AAF         | \\preceq        | ✓                | ✓                     |                                |
| ⪰             | U+2AB0         | \\succeq        | ✓                | ✓                     |                                |
| ⪷             | U+2AB7         | \\precapprox    | ✓                | ✓                     |                                |
| ⪸             | U+2AB8         | \\succapprox    | ✓                | ✓                     |                                |
| ⫅             | U+2AC5         | \\subseteqq     | ✓                | ✓                     |                                |
| ⫆             | U+2AC6         | \\supseteqq     | ✓                | ✓                     |                                |


kevinbarabash: @ronkok is `unicode math` in the header of the table mean that you used the [unicode-math](https://ctan.org/pkg/unicode-math?lang=en)?  As we start adding support for more characters, I'd like to add a way for us to track which package each mapping is coming from.  The reason being is that eventually I'd like for there to be a way to configure which "packages" are active.
kevinbarabash: I see that you added `, true);` to a various `defineSymbol` calls.  Does this mean that our existing mapping just happened to line up with `unicode-math`?
kevinbarabash: The `unicode math` link in the third comment is really useful. 
ronkok: Yes, the `unicode math` heading in the table does refer to the package that CTAN keeps at: https://ctan.org/pkg/unicode-math?lang=en.  In fact, that column in the table is verified from a script that parses the file at: http://ctan.sharelatex.com/tex-archive/macros/latex/contrib/unicode-math/unicode-math-table.tex

This particular PR does have a one-to-one match between `unicode math` and the KaTeX `symbols.js` file. In the PRs to come that will often be true but not always. There are some conflicts to come. I omitted any conflicts from this PR. I am trying to submit the easy cases first. After they are out of the way, we can focus attention on the hard cases.
kevinbarabash: In terms of conflicts I think we should defer to using `unicode-math` for now.  That way whenever we introduce the concept of the "packages" sometime in the future we'll have a consistent situation where all of our unicode chars came from that one package.
ronkok: When you see all the `unicode math` choices, I predict that you will disagree with a few of them. 

1. A few of their function names conflict with names from other packages, like `mathtools`.
2. A couple of their names conflict with AMS!

Again, we don't have to settle the hard cases now.  That can come later.
kevinbarabash: Well that's not cool.  😞 
ronkok: Most of the `unicode math` mappings are good ones. There are just a few head scratchers in there. 
ronkok: Also, here's the [data](https://www.johndcook.com/unidata.js) behind John Cook's conversion page.
edemaine: We can add unicode-math to #793 (which i or one of us should turn into a contrib file so that relevant PRs can easily add to it). 
ronkok: The most recent commit fixes a brain cramp of mine. After going to the trouble to create a [table](https://github.com/Khan/KaTeX/pull/933#issuecomment-336673998) that documents a good mapping, the script I used to edit `symbol.js` then made its selection from column 1 instead of from column 3 of the table. 

Fixed now.

Patch:
diff --git a/src/symbols.js b/src/symbols.js
index ac15f152..5bf55011 100644
--- a/src/symbols.js
+++ b/src/symbols.js
@@ -74,29 +74,29 @@ const textord = "textord";
 // Now comes the symbol table
 
 // Relation Symbols
-defineSymbol(math, main, rel, "\u2261", "\\equiv");
-defineSymbol(math, main, rel, "\u227a", "\\prec");
-defineSymbol(math, main, rel, "\u227b", "\\succ");
-defineSymbol(math, main, rel, "\u223c", "\\sim");
+defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
+defineSymbol(math, main, rel, "\u227a", "\\prec", true);
+defineSymbol(math, main, rel, "\u227b", "\\succ", true);
+defineSymbol(math, main, rel, "\u223c", "\\sim", true);
 defineSymbol(math, main, rel, "\u22a5", "\\perp");
-defineSymbol(math, main, rel, "\u2aaf", "\\preceq");
-defineSymbol(math, main, rel, "\u2ab0", "\\succeq");
-defineSymbol(math, main, rel, "\u2243", "\\simeq");
+defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
+defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
+defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
 defineSymbol(math, main, rel, "\u2223", "\\mid");
 defineSymbol(math, main, rel, "\u226a", "\\ll");
-defineSymbol(math, main, rel, "\u226b", "\\gg");
-defineSymbol(math, main, rel, "\u224d", "\\asymp");
+defineSymbol(math, main, rel, "\u226b", "\\gg", true);
+defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
 defineSymbol(math, main, rel, "\u2225", "\\parallel");
-defineSymbol(math, main, rel, "\u22c8", "\\bowtie");
-defineSymbol(math, main, rel, "\u2323", "\\smile");
-defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq");
-defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq");
-defineSymbol(math, main, rel, "\u2250", "\\doteq");
-defineSymbol(math, main, rel, "\u2322", "\\frown");
-defineSymbol(math, main, rel, "\u220b", "\\ni");
-defineSymbol(math, main, rel, "\u221d", "\\propto");
-defineSymbol(math, main, rel, "\u22a2", "\\vdash");
-defineSymbol(math, main, rel, "\u22a3", "\\dashv");
+defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
+defineSymbol(math, main, rel, "\u2323", "\\smile", true);
+defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
+defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
+defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
+defineSymbol(math, main, rel, "\u2322", "\\frown", true);
+defineSymbol(math, main, rel, "\u220b", "\\ni", true);
+defineSymbol(math, main, rel, "\u221d", "\\propto", true);
+defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
+defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
 defineSymbol(math, main, rel, "\u220b", "\\owns");
 
 // Punctuation
@@ -288,66 +288,66 @@ defineSymbol(math, ams, open, "\u2514", "\\llcorner");
 defineSymbol(math, ams, close, "\u2518", "\\lrcorner");
 
 // AMS Binary Relations
-defineSymbol(math, ams, rel, "\u2266", "\\leqq");
+defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
 defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant");
-defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless");
+defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
 defineSymbol(math, ams, rel, "\u2272", "\\lesssim");
 defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox");
-defineSymbol(math, ams, rel, "\u224a", "\\approxeq");
+defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
 defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
 defineSymbol(math, ams, rel, "\u22d8", "\\lll");
 defineSymbol(math, ams, rel, "\u2276", "\\lessgtr");
 defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr");
 defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr");
 defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
-defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq");
-defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq");
-defineSymbol(math, ams, rel, "\u223d", "\\backsim");
-defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq");
-defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq");
-defineSymbol(math, ams, rel, "\u22d0", "\\Subset");
-defineSymbol(math, ams, rel, "\u228f", "\\sqsubset");
-defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq");
-defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec");
-defineSymbol(math, ams, rel, "\u227e", "\\precsim");
-defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox");
+defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
+defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
+defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
+defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
+defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
+defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
+defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
+defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
+defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
+defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
+defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
 defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
 defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
 defineSymbol(math, ams, rel, "\u22a8", "\\vDash");
-defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash");
+defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
 defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
 defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
-defineSymbol(math, ams, rel, "\u224f", "\\bumpeq");
-defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq");
-defineSymbol(math, ams, rel, "\u2267", "\\geqq");
-defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant");
-defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr");
-defineSymbol(math, ams, rel, "\u2273", "\\gtrsim");
-defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox");
+defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
+defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
+defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
+defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
+defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
+defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
+defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
 defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
-defineSymbol(math, ams, rel, "\u22d9", "\\ggg");
-defineSymbol(math, ams, rel, "\u2277", "\\gtrless");
-defineSymbol(math, ams, rel, "\u22db", "\\gtreqless");
-defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless");
-defineSymbol(math, ams, rel, "\u2256", "\\eqcirc");
-defineSymbol(math, ams, rel, "\u2257", "\\circeq");
-defineSymbol(math, ams, rel, "\u225c", "\\triangleq");
+defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
+defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
+defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
+defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
+defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
+defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
+defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
 defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
 defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
-defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq");
-defineSymbol(math, ams, rel, "\u22d1", "\\Supset");
-defineSymbol(math, ams, rel, "\u2290", "\\sqsupset");
-defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq");
-defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc");
-defineSymbol(math, ams, rel, "\u227f", "\\succsim");
-defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox");
+defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
+defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
+defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
+defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
+defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
+defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
+defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
 defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
 defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
-defineSymbol(math, ams, rel, "\u22a9", "\\Vdash");
+defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
 defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
 defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
-defineSymbol(math, ams, rel, "\u226c", "\\between");
-defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork");
+defineSymbol(math, ams, rel, "\u226c", "\\between", true);
+defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
 defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
 defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft");
 defineSymbol(math, ams, rel, "\u2234", "\\therefore");
@@ -358,9 +358,9 @@ defineSymbol(math, ams, rel, "\u22d8", "\\llless");
 defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
 defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
 defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
-defineSymbol(math, ams, rel, "\u2242", "\\eqsim");
+defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
 defineSymbol(math, main, rel, "\u22c8", "\\Join");
-defineSymbol(math, ams, rel, "\u2251", "\\Doteq");
+defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true);
 
 // AMS Binary Operators
 defineSymbol(math, ams, bin, "\u2214", "\\dotplus");
@@ -401,7 +401,7 @@ defineSymbol(math, ams, rel, "\u21b0", "\\Lsh");
 defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows");
 defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft");
 defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft");
-defineSymbol(math, ams, rel, "\u22b8", "\\multimap");
+defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
 defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow");
 defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows");
 defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows");
@@ -511,25 +511,25 @@ defineSymbol(math, main, rel, "=", "=");
 defineSymbol(math, main, rel, "<", "<");
 defineSymbol(math, main, rel, ">", ">");
 defineSymbol(math, main, rel, ":", ":");
-defineSymbol(math, main, rel, "\u2248", "\\approx");
-defineSymbol(math, main, rel, "\u2245", "\\cong");
+defineSymbol(math, main, rel, "\u2248", "\\approx", true);
+defineSymbol(math, main, rel, "\u2245", "\\cong", true);
 defineSymbol(math, main, rel, "\u2265", "\\ge");
-defineSymbol(math, main, rel, "\u2265", "\\geq");
+defineSymbol(math, main, rel, "\u2265", "\\geq", true);
 defineSymbol(math, main, rel, "\u2190", "\\gets");
 defineSymbol(math, main, rel, ">", "\\gt");
-defineSymbol(math, main, rel, "\u2208", "\\in");
+defineSymbol(math, main, rel, "\u2208", "\\in", true);
 defineSymbol(math, main, rel, "\u2209", "\\notin");
 defineSymbol(math, main, rel, "\u0338", "\\not");
-defineSymbol(math, main, rel, "\u2282", "\\subset");
-defineSymbol(math, main, rel, "\u2283", "\\supset");
-defineSymbol(math, main, rel, "\u2286", "\\subseteq");
-defineSymbol(math, main, rel, "\u2287", "\\supseteq");
+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, main, rel, "\u22a8", "\\models");
 defineSymbol(math, main, rel, "\u2190", "\\leftarrow");
 defineSymbol(math, main, rel, "\u2264", "\\le");
-defineSymbol(math, main, rel, "\u2264", "\\leq");
+defineSymbol(math, main, rel, "\u2264", "\\leq", true);
 defineSymbol(math, main, rel, "<", "\\lt");
 defineSymbol(math, main, rel, "\u2260", "\\ne");
 defineSymbol(math, main, rel, "\u2260", "\\neq");


Test patch:
diff --git a/test/katex-spec.js b/test/katex-spec.js
index ec4a95c8..0e5ec5cd 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -2616,6 +2616,14 @@ describe("Unicode", function() {
     it("should parse 'ΓΔΘΞΠΣΦΨΩ'", function() {
         expect("ΓΔΘΞΠΣΦΨΩ").toParse();
     });
+
+    it("should parse relations", function() {
+        expect("∈∋∝∼∽≂≃≅≈≊≍≎≏≐≑≒≓≖≗≜≡≤≥≦≧≫≬≳≷≺≻≼≽≾≿").toParse();
+    });
+
+    it("should parse more relations", function() {
+        expect("⊂⊃⊆⊇⊏⊐⊑⊒⊢⊣⊩⊪⊸⋈⋍⋐⋑⋔⋙⋛⋞⋟⌢⌣⩾⪆⪌⪕⪖⪯⪰⪷⪸⫅⫆").toParse();
+    });
 });
 
 describe("The maxSize setting", function() {