aboutsummaryrefslogtreecommitdiff
path: root/js/mathjax/extensions/TeX/begingroup.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/mathjax/extensions/TeX/begingroup.js')
-rw-r--r--js/mathjax/extensions/TeX/begingroup.js294
1 files changed, 294 insertions, 0 deletions
diff --git a/js/mathjax/extensions/TeX/begingroup.js b/js/mathjax/extensions/TeX/begingroup.js
new file mode 100644
index 0000000..f750fc5
--- /dev/null
+++ b/js/mathjax/extensions/TeX/begingroup.js
@@ -0,0 +1,294 @@
+// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/begingroup.js
+ *
+ * Implements \begingroup and \endgroup commands that make local
+ * definitions possible and are removed when the \endgroup occurs.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2020 The MathJax Consortium
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+MathJax.Extension["TeX/begingroup"] = {
+ version: "2.7.9"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var TEX = MathJax.InputJax.TeX,
+ TEXDEF = TEX.Definitions;
+
+ /****************************************************/
+
+ //
+ // A namespace for localizing macros and environments
+ // (\begingroup and \endgroup create and destroy these)
+ //
+ var NSFRAME = MathJax.Object.Subclass({
+ macros: null, // the local macro definitions
+ environments: null, // the local environments
+ Init: function (macros,environments) {
+ this.macros = (macros || {});
+ this.environments = (environments || {});
+ },
+ //
+ // Find a macro or environment by name
+ //
+ Find: function (name,type) {if (this[type].hasOwnProperty(name)) {return this[type][name]}},
+ //
+ // Define or remove a macro or environment
+ //
+ Def: function (name,value,type) {this[type][name] = value},
+ Undef: function (name,type) {delete this[type][name]},
+ //
+ // Merge two namespaces (used when the equation namespace is combined with the root one)
+ //
+ Merge: function (frame) {
+ MathJax.Hub.Insert(this.macros,frame.macros);
+ MathJax.Hub.Insert(this.environments,frame.environments);
+ },
+ //
+ // Move global macros to the stack (globally) and remove from the frame
+ //
+ MergeGlobals: function (stack) {
+ var macros = this.macros;
+ for (var cs in macros) {if (macros.hasOwnProperty(cs) && macros[cs].global) {
+ stack.Def(cs,macros[cs],"macros",true);
+ delete macros[cs].global; delete macros[cs];
+ }}
+ },
+ //
+ // Clear the macro and environment lists
+ // (but not global macros unless "all" is true)
+ //
+ Clear: function (all) {
+ this.environments = {};
+ if (all) {this.macros = {}} else {
+ var macros = this.macros;
+ for (var cs in macros) {
+ if (macros.hasOwnProperty(cs) && !macros[cs].global) {delete macros[cs]}
+ }
+ }
+ return this;
+ }
+ });
+
+ /****************************************************/
+
+ //
+ // A Stack of namespace frames
+ //
+ var NSSTACK = TEX.nsStack = MathJax.Object.Subclass({
+ stack: null, // the namespace frames
+ top: 0, // the current top one (we don't pop for real until the equation completes)
+ isEqn: false, // true if this is the equation stack (not the global one)
+ //
+ // Set up the initial stack frame
+ //
+ Init: function (eqn) {
+ this.isEqn = eqn; this.stack = [];
+ if (!eqn) {this.Push(NSFRAME(TEXDEF.macros,TEXDEF.environment))}
+ else {this.Push(NSFRAME())}
+ },
+ //
+ // Define a macro or environment in the top frame
+ //
+ Def: function (name,value,type,global) {
+ var n = this.top-1;
+ if (global) {
+ //
+ // Define global macros in the base frame and remove that cs
+ // from all other frames. Mark the global ones in equations
+ // so they can be made global when merged with the root stack.
+ //
+ while (n > 0) {this.stack[n].Undef(name,type); n--}
+ if (!MathJax.Object.isArray(value)) {value = [value]}
+ if (this.isEqn) {value.global = true}
+ }
+ this.stack[n].Def(name,value,type);
+ },
+ //
+ // Push a new namespace frame on the stack
+ //
+ Push: function (frame) {
+ this.stack.push(frame);
+ this.top = this.stack.length;
+ },
+ //
+ // Pop the top stack frame
+ // (if it is the root, just keep track of the pop so we can
+ // reset it if the equation is reprocessed)
+ //
+ Pop: function () {
+ var top;
+ if (this.top > 1) {
+ top = this.stack[--this.top];
+ if (this.isEqn) {this.stack.pop()}
+ } else if (this.isEqn) {
+ this.Clear();
+ }
+ return top;
+ },
+ //
+ // Search the stack from top to bottom for the first
+ // definition of the given control sequence in the given type
+ //
+ Find: function (name,type) {
+ for (var i = this.top-1; i >= 0; i--) {
+ var def = this.stack[i].Find(name,type);
+ if (def) {return def}
+ }
+ return null;
+ },
+ //
+ // Combine the equation stack with the global one
+ // (The bottom frame of the equation goes with the top frame of the global one,
+ // and the remainder are pushed on the global stack, truncated to the
+ // position where items were poped from it.)
+ //
+ Merge: function (stack) {
+ stack.stack[0].MergeGlobals(this);
+ this.stack[this.top-1].Merge(stack.stack[0]);
+ var data = [this.top,this.stack.length-this.top].concat(stack.stack.slice(1));
+ this.stack.splice.apply(this.stack,data);
+ this.top = this.stack.length;
+ },
+ //
+ // Put back the temporarily poped items
+ //
+ Reset: function () {this.top = this.stack.length},
+ //
+ // Clear the stack and start with a blank frame
+ //
+ Clear: function (all) {
+ this.stack = [this.stack[0].Clear()];
+ this.top = this.stack.length;
+ }
+ },{
+ nsFrame: NSFRAME
+ });
+
+ /****************************************************/
+
+ //
+ // Define the new macros
+ //
+ TEXDEF.Add({
+ macros: {
+ begingroup: "BeginGroup",
+ endgroup: "EndGroup",
+ global: "Global",
+ gdef: ["Macro","\\global\\def"]
+ }
+ },null,true);
+
+ TEX.Parse.Augment({
+ //
+ // Implement \begingroup
+ //
+ BeginGroup: function (name) {
+ TEX.eqnStack.Push(NSFRAME());
+ },
+ //
+ // Implements \endgroup
+ //
+ EndGroup: function (name) {
+ //
+ // If the equation has pushed frames, pop one,
+ // Otherwise clear the equation stack and pop the top global one
+ //
+ if (TEX.eqnStack.top > 1) {
+ TEX.eqnStack.Pop();
+ } else if (TEX.rootStack.top === 1) {
+ TEX.Error(["ExtraEndMissingBegin","Extra %1 or missing \\begingroup",name]);
+ } else {
+ TEX.eqnStack.Clear();
+ TEX.rootStack.Pop();
+ }
+ },
+
+ //
+ // Replace the original routines with ones that looks through the
+ // equation and root stacks for the given name
+ //
+ csFindMacro: function (name) {
+ return (TEX.eqnStack.Find(name,"macros") || TEX.rootStack.Find(name,"macros"));
+ },
+ envFindName: function (name) {
+ return (TEX.eqnStack.Find(name,"environments") || TEX.rootStack.Find(name,"environments"));
+ },
+
+ //
+ // Modify the way macros and environments are defined
+ // to make them go into the equation namespace stack
+ //
+ setDef: function (name,value) {
+ value.isUser = true;
+ TEX.eqnStack.Def(name,value,"macros",this.stack.env.isGlobal);
+ delete this.stack.env.isGlobal;
+ },
+ setEnv: function (name,value) {
+ value.isUser = true;
+ TEX.eqnStack.Def(name,value,"environments")
+ },
+
+ //
+ // Implement \global (for \global\let, \global\def and \global\newcommand)
+ //
+ Global: function (name) {
+ var i = this.i; var cs = this.GetCSname(name); this.i = i;
+ if (cs !== "let" && cs !== "def" && cs !== "newcommand" &&
+ cs !== "DeclareMathOperator" && cs !== "Newextarrow") {
+ TEX.Error(["GlobalNotFollowedBy",
+ "%1 not followed by \\let, \\def, or \\newcommand",name]);
+ }
+ this.stack.env.isGlobal = true;
+ }
+ });
+
+ /****************************************************/
+
+ TEX.rootStack = NSSTACK(); // the global namespace stack
+ TEX.eqnStack = NSSTACK(true); // the equation stack
+
+ //
+ // Reset the global stack and clear the equation stack
+ // (this gets us back to the initial stack state as it was
+ // before the equation was first processed, in case the equation
+ // get restarted due to an autoloaded file)
+ //
+ TEX.prefilterHooks.Add(function () {TEX.rootStack.Reset(); TEX.eqnStack.Clear(true)});
+
+ //
+ // We only get here if there were no errors and the equation is fully
+ // processed (all restarts are complete). So we merge the equation
+ // stack into the global stack, thus making the changes from this
+ // equation permanent.
+ //
+ TEX.postfilterHooks.Add(function () {TEX.rootStack.Merge(TEX.eqnStack)});
+
+ /*********************************************************/
+
+ MathJax.Hub.Startup.signal.Post("TeX begingroup Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/begingroup.js");
+// @license-end