Repository: Khan/KaTeX
Pull request #961 (2017-11-12 04:39:40)

Support Unicode Big Operators
This is the sixth in a series of PRs to give KaTeX the ability to recognize Unicode character input.

This is the final PR in this series that will submit characters in bulk. After this, there come only a few characters whose alias or atom type was not obvious. I'll turn in PRs for some of them, too, but only after they are vetted.

ronkok: As in PR #933, 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/unidata.js) map it the same way, (3) possible alternates that I did not use.

  

| **Character** | **Code point** | **Maps to** | **unicode math** | **Cook** | **Not used**        |
|:-------------:|:--------------:|:------------|:----------------:|:--------:|:-------------------:|
| ∏             | U+220F         | \\prod      | ✓                | ✓        |                     |
| ∐             | U+2210         | \\coprod    | ✓                | ✓        |                     |
| ∑             | U+2211         | \\sum       | ✓                | ✓        |                     |
| ∫             | U+222B         | \\int       | ✓                | ✓        | \\intop, \\smallint |
| ∬             | U+222C         | \\iint      | ✓                | ✓        |                     |
| ∭             | U+222D         | \\iiint     | ✓                | ✓        |                     |
| ∮             | U+222E         | \\oint      | ✓                | ✓        |                     |
| ⋀             | U+22C0         | \\bigwedge  | ✓                | ✓        |                     |
| ⋁             | U+22C1         | \\bigvee    | ✓                | ✓        |                     |
| ⋂             | U+22C2         | \\bigcap    | ✓                | ✓        |                     |
| ⋃             | U+22C3         | \\bigcup    | ✓                | ✓        |                     |
| ⨀             | U+2A00         | \\bigodot   | ✓                | ✓        |                     |
| ⨁             | U+2A01         | \\bigoplus  | ✓                | ✓        |                     |
| ⨂             | U+2A02         | \\bigotimes | ✓                | ✓        |                     |
| ⨄             | U+2A04         | \\biguplus  | ✓                | ✓        |                     |
| ⨆             | U+2A06         | \\bigsqcup  | ✓                | ✓        |                     |
edemaine: Thanks! Maybe the wrong code, though because the test fails now. 
ronkok: You would think that I could type ten keystrokes without a typo. But apparently not.

Fixed now.

Patch:
diff --git a/src/functions.js b/src/functions.js
index dce57095..68460768 100644
--- a/src/functions.js
+++ b/src/functions.js
@@ -258,6 +258,13 @@ defineFunction([
     };
 });
 
+const singleCharIntegrals: {[string]: string} = {
+    "\u222b": "\\int",
+    "\u222c": "\\iint",
+    "\u222d": "\\iiint",
+    "\u222e": "\\oint",
+};
+
 // There are 2 flags for operators; whether they produce limits in
 // displaystyle, and whether they are symbols and should grow in
 // displaystyle. These four groups cover the four possible choices.
@@ -297,15 +304,20 @@ defineFunction([
 
 // No limits, symbols
 defineFunction([
-    "\\int", "\\iint", "\\iiint", "\\oint",
+    "\\int", "\\iint", "\\iiint", "\\oint", "\u222b", "\u222c",
+    "\u222d", "\u222e",
 ], {
     numArgs: 0,
 }, function(context) {
+    let fName = context.funcName;
+    if (fName.length === 1) {
+        fName = singleCharIntegrals[fName];
+    }
     return {
         type: "op",
         limits: false,
         symbol: true,
-        body: context.funcName,
+        body: fName,
     };
 });
 
diff --git a/src/functions/op.js b/src/functions/op.js
index 285c279d..f7c93aab 100644
--- a/src/functions/op.js
+++ b/src/functions/op.js
@@ -220,22 +220,43 @@ const mathmlBuilder = (group, options) => {
     return node;
 };
 
+const singleCharBigOps: {[string]: string} = {
+    "\u220F": "\\prod",
+    "\u2210": "\\coprod",
+    "\u2211": "\\sum",
+    "\u22c0": "\\bigwedge",
+    "\u22c1": "\\bigvee",
+    "\u22c2": "\\bigcap",
+    "\u22c3": "\\bigcap",
+    "\u2a00": "\\bigodot",
+    "\u2a01": "\\bigoplus",
+    "\u2a02": "\\bigotimes",
+    "\u2a04": "\\biguplus",
+    "\u2a06": "\\bigsqcup",
+};
+
 defineFunction({
     type: "op",
     names: [
         "\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
         "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
-        "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint",
+        "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F",
+        "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00",
+        "\u2a01", "\u2a02", "\u2a04", "\u2a06",
     ],
     props: {
         numArgs: 0,
     },
     handler: (context, args) => {
+        let fName = context.funcName;
+        if (fName.length === 1) {
+            fName = singleCharBigOps[fName];
+        }
         return {
             type: "op",
             limits: true,
             symbol: true,
-            body: context.funcName,
+            body: fName,
         };
     },
     htmlBuilder,


Test patch:
diff --git a/test/katex-spec.js b/test/katex-spec.js
index e4718866..09142097 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -2634,6 +2634,10 @@ describe("Unicode", function() {
         expect("∈∋∝∼∽≂≃≅≈≊≍≎≏≐≑≒≓≖≗≜≡≤≥≦≧≫≬≳≷≺≻≼≽≾≿").toParse();
     });
 
+    it("should parse big operators", function() {
+        expect("∏∐∑∫∬∭∮⋀⋁⋂⋃⨀⨁⨂⨄⨆").toParse();
+    });
+
     it("should parse more relations", function() {
         expect("⊂⊃⊆⊇⊏⊐⊑⊒⊢⊣⊩⊪⊸⋈⋍⋐⋑⋔⋙⋛⋞⋟⌢⌣⩾⪆⪌⪕⪖⪯⪰⪷⪸⫅⫆").toParse();
     });