Repository: Khan/KaTeX
Pull request #973 (2017-11-19 19:47:27)

Single-character macros like active characters
This tiny PR adds support for redefining single characters by arbitrary macros, while also simplifying the code slightly.  I don't see a reason not to allow this, and it would be immediately useful for resolving #967, as well as e.g. users adding support for Unicode characters that KaTeX doesn't already support, or which KaTeX already supports but the user wants to override in a different way.  Overall seems like a win.

ronkok: Cool. This will be helpful for double-struck Unicode characters like ℂ or ℕ.
edemaine: @ronkok Great! More motivation for this change. 
kevinbarabash: @edemaine thanks for make this change.  It's really going to help with the unicode effort.

Patch:
diff --git a/README.md b/README.md
index 0cc76674..9d8ea012 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ You can provide an object of options as the last argument to `katex.render` and
 - `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`)
 - `throwOnError`: `boolean`. If `true`, KaTeX will throw a `ParseError` when it encounters an unsupported command. If `false`, KaTeX will render the unsupported command as text in the color given by `errorColor`. (default: `true`)
 - `errorColor`: `string`. A color string given in the format `"#XXX"` or `"#XXXXXX"`. This option determines the color which unsupported commands are rendered in. (default: `#cc0000`)
-- `macros`: `object`. A collection of custom macros. Each macro is a property with a name like `\name` (written `"\\name"` in JavaScript) which maps to a string that describes the expansion of the macro.
+- `macros`: `object`. A collection of custom macros. Each macro is a property with a name like `\name` (written `"\\name"` in JavaScript) which maps to a string that describes the expansion of the macro. Single-character keys can also be included in which case the character will be redefined as the given macro (similar to TeX active characters).
 - `colorIsTextColor`: `boolean`. If `true`, `\color` will work like LaTeX's `\textcolor`, and take two arguments (e.g., `\color{blue}{hello}`), which restores the old behavior of KaTeX (pre-0.8.0). If `false` (the default), `\color` will work like LaTeX's `\color`, and take one argument (e.g., `\color{blue}hello`).  In both cases, `\textcolor` works as in LaTeX (e.g., `\textcolor{blue}{hello}`).
 - `maxSize`: `number`. If non-zero, all user-specified sizes, e.g. in `\rule{500em}{500em}`, will be capped to `maxSize` ems. Otherwise, users can make elements and spaces arbitrarily large (the default behavior).
 
diff --git a/src/MacroExpander.js b/src/MacroExpander.js
index 92abd09c..75fd57d6 100644
--- a/src/MacroExpander.js
+++ b/src/MacroExpander.js
@@ -84,7 +84,7 @@ export default class MacroExpander implements MacroContextInterface {
             // Consume all spaces after \macro (but not \\, \', etc.)
             this.consumeSpaces();
         }
-        if (!(isMacro && this.macros.hasOwnProperty(name))) {
+        if (!this.macros.hasOwnProperty(name)) {
             // Fully expanded
             this.pushToken(topToken);
             return topToken;


Test patch:
diff --git a/test/katex-spec.js b/test/katex-spec.js
index fb33a71b..52b26229 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -2633,6 +2633,12 @@ describe("A macro expander", function() {
         expect("X \\implies Y").toBuild();
         expect("X \\impliedby Y").toBuild();
     });
+
+    it("should allow aliasing characters", function() {
+        compareParseTree("x’=c", "x'=c", {
+            "’": "'",
+        });
+    });
 });
 
 describe("A parser taking String objects", function() {