Repository: KaTeX/KaTeX (js)

Issue:
globalGroup adversely affects \color and tall right delimiters
PR #2091 has an unintended consequence. When the rendering option `globalGroup` is set to `true`, then `\color` escapes its group and affects tall right delimiters.

The KaTeX function`\color` works by creating a macro `\current@color` and assigning a color to it. When `globalGroup` is true, then this macro escapes its group. Tall right delimiters are then given that color in line https://github.com/KaTeX/KaTeX/blob/21c4bc355c04cfa13bb79dd9dd06627f5b04f54d/src/functions/delimsizing.js#L155. I don't know why tall right delimiters get that treatment, but there it is.

The stated reason for PR #2091 was to give global scope to `\newcommand`.  But its effect is more sweeping than that. I think that @edemaine's [comment](https://github.com/KaTeX/KaTeX/pull/2091#issuecomment-527243164) was correct. We need some mechanism that gives global scope to `\newcommand`, not to all macros.



Pull request description:
fix: Prevent global group from adversely affecting color.
Fix<!--don't close--> #2637. Close #2640.

This PR is an alternative to PR #2640. Either this one or that one, but not both, should be approved and merged. I would prefer PR#2640, but it seems unlikely that anyone will approve it. We should get this bug fixed before the next release so this PR is the next best thing.

Patch:
diff --git a/src/parseTree.js b/src/parseTree.js
index 26270fba..c1cd3df9 100644
--- a/src/parseTree.js
+++ b/src/parseTree.js
@@ -18,10 +18,16 @@ const parseTree = function(toParse: string, settings: Settings): AnyParseNode[]
         throw new TypeError('KaTeX can only parse string typed expression');
     }
     const parser = new Parser(toParse, settings);
+
     // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
     delete parser.gullet.macros.current["\\df@tag"];
+
     let tree = parser.parse();
 
+    // Prevent a color definition from persisting between calls to katex.render().
+    delete parser.gullet.macros.current["\\current@color"];
+    delete parser.gullet.macros.current["\\color"];
+
     // If the input used \tag, it will set the \df@tag macro to the tag.
     // In this case, we separately parse the tag and wrap the tree.
     if (parser.gullet.macros.get("\\df@tag")) {


Test patch:
diff --git a/test/katex-spec.js b/test/katex-spec.js
index 715513e7..ac10e482 100644
--- a/test/katex-spec.js
+++ b/test/katex-spec.js
@@ -869,6 +869,7 @@ describe("A color parser", function() {
         const macros = {};
         expect(oldColorExpression).toParseLike(r`\textcolor{#fA6}{x}y`, {
             colorIsTextColor: true,
+            globalGroup: true,
             macros: macros,
         });
         expect(macros).toEqual({});