diff --git a/MarkDownEditor.Setup/Product.wxs b/MarkDownEditor.Setup/Product.wxs
index c92e90c..92198a5 100644
--- a/MarkDownEditor.Setup/Product.wxs
+++ b/MarkDownEditor.Setup/Product.wxs
@@ -2,8 +2,8 @@
-
-
+
+
@@ -12,9 +12,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -28,7 +41,7 @@
-
+
@@ -53,11 +66,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MarkDownEditor.sln b/MarkDownEditor.sln
index 7e21f4c..c59b7f9 100644
--- a/MarkDownEditor.sln
+++ b/MarkDownEditor.sln
@@ -1,12 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkDownEditor", "MarkDownEditor\MarkDownEditor.csproj", "{48932BB7-3CC3-4897-A466-BE91A9FA1E40}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8} = {B0F82DB9-F3EF-458E-8331-57563ABB84A8}
+ EndProjectSection
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MarkDownEditor.Setup", "MarkDownEditor.Setup\MarkDownEditor.Setup.wixproj", "{C80C4996-3D52-4236-9AFE-5F48997DC5B6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WkHtmlToPdfWrapper", "WkHtmlToPdfWrapper\WkHtmlToPdfWrapper.csproj", "{B0F82DB9-F3EF-458E-8331-57563ABB84A8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WkHtmlToImageWrapper", "WkHtmlToImageWrapper\WkHtmlToImageWrapper.csproj", "{D01A2A12-54DD-4B88-A46A-926B4D0154DE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -35,6 +42,30 @@ Global
{C80C4996-3D52-4236-9AFE-5F48997DC5B6}.Release|x64.ActiveCfg = Release|x86
{C80C4996-3D52-4236-9AFE-5F48997DC5B6}.Release|x86.ActiveCfg = Release|x86
{C80C4996-3D52-4236-9AFE-5F48997DC5B6}.Release|x86.Build.0 = Release|x86
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|x64.Build.0 = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Debug|x86.Build.0 = Debug|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|x64.ActiveCfg = Release|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|x64.Build.0 = Release|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|x86.ActiveCfg = Release|Any CPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}.Release|x86.Build.0 = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|x64.Build.0 = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Debug|x86.Build.0 = Debug|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|x64.ActiveCfg = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|x64.Build.0 = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|x86.ActiveCfg = Release|Any CPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MarkDownEditor/App.config b/MarkDownEditor/App.config
index 6f4aeab..2142bac 100644
--- a/MarkDownEditor/App.config
+++ b/MarkDownEditor/App.config
@@ -70,6 +70,9 @@
1
+
+ False
+
diff --git a/MarkDownEditor/MarkDownEditor.csproj b/MarkDownEditor/MarkDownEditor.csproj
index fbc9839..8bd3abb 100644
--- a/MarkDownEditor/MarkDownEditor.csproj
+++ b/MarkDownEditor/MarkDownEditor.csproj
@@ -290,6 +290,114 @@
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -334,6 +442,16 @@
false
+
+
+ {d01a2a12-54dd-4b88-a46a-926b4d0154de}
+ WkHtmlToImageWrapper
+
+
+ {b0f82db9-f3ef-458e-8331-57563abb84a8}
+ WkHtmlToPdfWrapper
+
+
diff --git a/MarkDownEditor/MathJax/MathJax.js b/MarkDownEditor/MathJax/MathJax.js
new file mode 100644
index 0000000..ff0a6ff
--- /dev/null
+++ b/MarkDownEditor/MathJax/MathJax.js
@@ -0,0 +1,3273 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax.js
+ *
+ * The main support code for the MathJax Hub, including the
+ * Ajax, Callback, Messaging, and Object-Oriented Programming
+ * libraries, as well as the base Jax classes, and startup
+ * processing code.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.
+ */
+
+
+//
+// Check if browser can support MathJax (no one fails this nowadays)
+//
+if (document.getElementById && document.childNodes && document.createElement) {
+//
+// Skip if MathJax is already loaded
+//
+if (!(window.MathJax && MathJax.Hub)) {
+
+//
+// Get author configuration from MathJax variable, if any
+//
+if (window.MathJax) {window.MathJax = {AuthorConfig: window.MathJax}}
+ else {window.MathJax = {}}
+
+// MathJax.isPacked = true; // This line is uncommented by the packer.
+
+MathJax.version = "2.6.1";
+MathJax.fileversion = "2.6.1";
+MathJax.cdnVersion = "2.6.1"; // specifies a revision to break caching
+MathJax.cdnFileVersions = {}; // can be used to specify revisions for individual files
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var PROTO = []; // a static object used to indicate when a prototype is being created
+ var OBJECT = function (def) {
+ var obj = def.constructor; if (!obj) {obj = function () {}}
+ for (var id in def) {if (id !== 'constructor' && def.hasOwnProperty(id)) {obj[id] = def[id]}}
+ return obj;
+ };
+ var CONSTRUCTOR = function () {
+ return function () {return arguments.callee.Init.call(this,arguments)};
+ };
+
+ BASE.Object = OBJECT({
+ constructor: CONSTRUCTOR(),
+
+ Subclass: function (def,classdef) {
+ var obj = CONSTRUCTOR();
+ obj.SUPER = this; obj.Init = this.Init;
+ obj.Subclass = this.Subclass; obj.Augment = this.Augment;
+ obj.protoFunction = this.protoFunction;
+ obj.can = this.can; obj.has = this.has; obj.isa = this.isa;
+ obj.prototype = new this(PROTO);
+ obj.prototype.constructor = obj; // the real constructor
+ obj.Augment(def,classdef);
+ return obj;
+ },
+
+ Init: function (args) {
+ var obj = this;
+ if (args.length === 1 && args[0] === PROTO) {return obj}
+ if (!(obj instanceof args.callee)) {obj = new args.callee(PROTO)}
+ return obj.Init.apply(obj,args) || obj;
+ },
+
+ Augment: function (def,classdef) {
+ var id;
+ if (def != null) {
+ for (id in def) {if (def.hasOwnProperty(id)) {this.protoFunction(id,def[id])}}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (def.toString !== this.prototype.toString && def.toString !== {}.toString)
+ {this.protoFunction('toString',def.toString)}
+ }
+ if (classdef != null) {
+ for (id in classdef) {if (classdef.hasOwnProperty(id)) {this[id] = classdef[id]}}
+ }
+ return this;
+ },
+
+ protoFunction: function (id,def) {
+ this.prototype[id] = def;
+ if (typeof def === "function") {def.SUPER = this.SUPER.prototype}
+ },
+
+ prototype: {
+ Init: function () {},
+ SUPER: function (fn) {return fn.callee.SUPER},
+ can: function (method) {return typeof(this[method]) === "function"},
+ has: function (property) {return typeof(this[property]) !== "undefined"},
+ isa: function (obj) {return (obj instanceof Object) && (this instanceof obj)}
+ },
+
+ can: function (method) {return this.prototype.can.call(this,method)},
+ has: function (property) {return this.prototype.has.call(this,property)},
+ isa: function (obj) {
+ var constructor = this;
+ while (constructor) {
+ if (constructor === obj) {return true} else {constructor = constructor.SUPER}
+ }
+ return false;
+ },
+
+
+ SimpleSUPER: OBJECT({
+ constructor: function (def) {return this.SimpleSUPER.define(def)},
+
+ define: function (src) {
+ var dst = {};
+ if (src != null) {
+ for (var id in src) {if (src.hasOwnProperty(id)) {dst[id] = this.wrap(id,src[id])}}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (src.toString !== this.prototype.toString && src.toString !== {}.toString)
+ {dst.toString = this.wrap('toString',src.toString)}
+ }
+ return dst;
+ },
+
+ wrap: function (id,f) {
+ if (typeof(f) !== 'function' || !f.toString().match(/\.\s*SUPER\s*\(/)) {return f}
+ var fn = function () {
+ this.SUPER = fn.SUPER[id];
+ try {var result = f.apply(this,arguments)} catch (err) {delete this.SUPER; throw err}
+ delete this.SUPER;
+ return result;
+ }
+ fn.toString = function () {return f.toString.apply(f,arguments)}
+ return fn;
+ }
+
+ })
+ });
+
+})("MathJax");
+
+/**********************************************************/
+
+/*
+ * Create a callback function from various forms of data:
+ *
+ * MathJax.Callback(fn) -- callback to a function
+ *
+ * MathJax.Callback([fn]) -- callback to function
+ * MathJax.Callback([fn,data...])
+ * -- callback to function with given data as arguments
+ * MathJax.Callback([object,fn])
+ * -- call fn with object as "this"
+ * MathJax.Callback([object,fn,data...])
+ * -- call fn with object as "this" and data as arguments
+ * MathJax.Callback(["method",object])
+ * -- call method of object wth object as "this"
+ * MathJax.Callback(["method",object,data...])
+ * -- as above, but with data as arguments to method
+ *
+ * MathJax.Callback({hook: fn, data: [...], object: this})
+ * -- give function, data, and object to act as "this" explicitly
+ *
+ * MathJax.Callback("code") -- callback that compiles and executes a string
+ *
+ * MathJax.Callback([...],i)
+ * -- use slice of array starting at i and interpret
+ * result as above. (Used for passing "arguments" array
+ * and trimming initial arguments, if any.)
+ */
+
+/*
+ * MathJax.Callback.After([...],cb1,cb2,...)
+ * -- make a callback that isn't called until all the other
+ * ones are called first. I.e., wait for a union of
+ * callbacks to occur before making the given callback.
+ */
+
+/*
+ * MathJax.Callback.Queue([callback,...])
+ * -- make a synchronized queue of commands that process
+ * sequentially, waiting for those that return uncalled
+ * callbacks.
+ */
+
+/*
+ * MathJax.Callback.Signal(name)
+ * -- finds or creates a names signal, to which listeners
+ * can be attached and are signaled by messages posted
+ * to the signal. Responses can be asynchronous.
+ */
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+ //
+ // Create a callback from an associative array
+ //
+ var CALLBACK = function (data) {
+ var cb = function () {return arguments.callee.execute.apply(arguments.callee,arguments)};
+ for (var id in CALLBACK.prototype) {
+ if (CALLBACK.prototype.hasOwnProperty(id)) {
+ if (typeof(data[id]) !== 'undefined') {cb[id] = data[id]}
+ else {cb[id] = CALLBACK.prototype[id]}
+ }
+ }
+ cb.toString = CALLBACK.prototype.toString;
+ return cb;
+ };
+ CALLBACK.prototype = {
+ isCallback: true,
+ hook: function () {},
+ data: [],
+ object: window,
+ execute: function () {
+ if (!this.called || this.autoReset) {
+ this.called = !this.autoReset;
+ return this.hook.apply(this.object,this.data.concat([].slice.call(arguments,0)));
+ }
+ },
+ reset: function () {delete this.called},
+ toString: function () {return this.hook.toString.apply(this.hook,arguments)}
+ };
+ var ISCALLBACK = function (f) {
+ return (typeof(f) === "function" && f.isCallback);
+ }
+
+ //
+ // Evaluate a string in global context
+ //
+ var EVAL = function (code) {return eval.call(window,code)}
+ var TESTEVAL = function () {
+ EVAL("var __TeSt_VaR__ = 1"); // check if it works in global context
+ if (window.__TeSt_VaR__) {
+ try { delete window.__TeSt_VaR__; } // NOTE IE9 throws when in IE7 mode
+ catch (error) { window.__TeSt_VaR__ = null; }
+ } else {
+ if (window.execScript) {
+ // IE
+ EVAL = function (code) {
+ BASE.__code = code;
+ code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
+ window.execScript(code);
+ var result = BASE.__result; delete BASE.__result; delete BASE.__code;
+ if (result instanceof Error) {throw result}
+ return result;
+ }
+ } else {
+ // Safari2
+ EVAL = function (code) {
+ BASE.__code = code;
+ code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
+ var head = (document.getElementsByTagName("head"))[0]; if (!head) {head = document.body}
+ var script = document.createElement("script");
+ script.appendChild(document.createTextNode(code));
+ head.appendChild(script); head.removeChild(script);
+ var result = BASE.__result; delete BASE.__result; delete BASE.__code;
+ if (result instanceof Error) {throw result}
+ return result;
+ }
+ }
+ }
+ TESTEVAL = null;
+ }
+
+ //
+ // Create a callback from various types of data
+ //
+ var USING = function (args,i) {
+ if (arguments.length > 1) {
+ if (arguments.length === 2 && !(typeof arguments[0] === 'function') &&
+ arguments[0] instanceof Object && typeof arguments[1] === 'number')
+ {args = [].slice.call(args,i)}
+ else {args = [].slice.call(arguments,0)}
+ }
+ if (args instanceof Array && args.length === 1) {args = args[0]}
+ if (typeof args === 'function') {
+ if (args.execute === CALLBACK.prototype.execute) {return args}
+ return CALLBACK({hook: args});
+ } else if (args instanceof Array) {
+ if (typeof(args[0]) === 'string' && args[1] instanceof Object &&
+ typeof args[1][args[0]] === 'function') {
+ return CALLBACK({hook: args[1][args[0]], object: args[1], data: args.slice(2)});
+ } else if (typeof args[0] === 'function') {
+ return CALLBACK({hook: args[0], data: args.slice(1)});
+ } else if (typeof args[1] === 'function') {
+ return CALLBACK({hook: args[1], object: args[0], data: args.slice(2)});
+ }
+ } else if (typeof(args) === 'string') {
+ if (TESTEVAL) TESTEVAL();
+ return CALLBACK({hook: EVAL, data: [args]});
+ } else if (args instanceof Object) {
+ return CALLBACK(args);
+ } else if (typeof(args) === 'undefined') {
+ return CALLBACK({});
+ }
+ throw Error("Can't make callback from given data");
+ };
+
+ //
+ // Wait for a given time to elapse and then perform the callback
+ //
+ var DELAY = function (time,callback) {
+ callback = USING(callback);
+ callback.timeout = setTimeout(callback,time);
+ return callback;
+ };
+
+ //
+ // Callback used by AFTER, QUEUE, and SIGNAL to check if calls have completed
+ //
+ var WAITFOR = function (callback,signal) {
+ callback = USING(callback);
+ if (!callback.called) {WAITSIGNAL(callback,signal); signal.pending++}
+ };
+ var WAITEXECUTE = function () {
+ var signals = this.signal; delete this.signal;
+ this.execute = this.oldExecute; delete this.oldExecute;
+ var result = this.execute.apply(this,arguments);
+ if (ISCALLBACK(result) && !result.called) {WAITSIGNAL(result,signals)} else {
+ for (var i = 0, m = signals.length; i < m; i++) {
+ signals[i].pending--;
+ if (signals[i].pending <= 0) {signals[i].call()}
+ }
+ }
+ };
+ var WAITSIGNAL = function (callback,signals) {
+ if (!(signals instanceof Array)) {signals = [signals]}
+ if (!callback.signal) {
+ callback.oldExecute = callback.execute;
+ callback.execute = WAITEXECUTE;
+ callback.signal = signals;
+ } else if (signals.length === 1) {callback.signal.push(signals[0])}
+ else {callback.signal = callback.signal.concat(signals)}
+ };
+
+ //
+ // Create a callback that is called when a collection of other callbacks have
+ // all been executed. If the callback gets called immediately (i.e., the
+ // others are all already called), check if it returns another callback
+ // and return that instead.
+ //
+ var AFTER = function (callback) {
+ callback = USING(callback);
+ callback.pending = 0;
+ for (var i = 1, m = arguments.length; i < m; i++)
+ {if (arguments[i]) {WAITFOR(arguments[i],callback)}}
+ if (callback.pending === 0) {
+ var result = callback();
+ if (ISCALLBACK(result)) {callback = result}
+ }
+ return callback;
+ };
+
+ //
+ // An array of prioritized hooks that are executed sequentially
+ // with a given set of data.
+ //
+ var HOOKS = MathJax.Object.Subclass({
+ //
+ // Initialize the array and the auto-reset status
+ //
+ Init: function (reset) {
+ this.hooks = [];
+ this.remove = []; // used when hooks are removed during execution of list
+ this.reset = reset;
+ this.running = false;
+ },
+ //
+ // Add a callback to the list, in priority order (default priority is 10)
+ //
+ Add: function (hook,priority) {
+ if (priority == null) {priority = 10}
+ if (!ISCALLBACK(hook)) {hook = USING(hook)}
+ hook.priority = priority;
+ var i = this.hooks.length;
+ while (i > 0 && priority < this.hooks[i-1].priority) {i--}
+ this.hooks.splice(i,0,hook);
+ return hook;
+ },
+ Remove: function (hook) {
+ for (var i = 0, m = this.hooks.length; i < m; i++) {
+ if (this.hooks[i] === hook) {
+ if (this.running) {this.remove.push(i)}
+ else {this.hooks.splice(i,1)}
+ return;
+ }
+ }
+ },
+ //
+ // Execute the list of callbacks, resetting them if requested.
+ // If any return callbacks, return a callback that will be
+ // executed when they all have completed.
+ // Remove any hooks that requested being removed during processing.
+ //
+ Execute: function () {
+ var callbacks = [{}];
+ this.running = true;
+ for (var i = 0, m = this.hooks.length; i < m; i++) {
+ if (this.reset) {this.hooks[i].reset()}
+ var result = this.hooks[i].apply(window,arguments);
+ if (ISCALLBACK(result) && !result.called) {callbacks.push(result)}
+ }
+ this.running = false;
+ if (this.remove.length) {this.RemovePending()}
+ if (callbacks.length === 1) {return null}
+ if (callbacks.length === 2) {return callbacks[1]}
+ return AFTER.apply({},callbacks);
+ },
+ //
+ // Remove hooks that asked to be removed during execution of list
+ //
+ RemovePending: function () {
+ this.remove = this.remove.sort();
+ for (var i = this.remove.length-1; i >= 0; i--) {this.hooks.splice(i,1)}
+ this.remove = [];
+ }
+
+ });
+
+ //
+ // Run an array of callbacks passing them the given data.
+ // (Legacy function, since this has been replaced by the HOOKS object).
+ //
+ var EXECUTEHOOKS = function (hooks,data,reset) {
+ if (!hooks) {return null}
+ if (!(hooks instanceof Array)) {hooks = [hooks]}
+ if (!(data instanceof Array)) {data = (data == null ? [] : [data])}
+ var handler = HOOKS(reset);
+ for (var i = 0, m = hooks.length; i < m; i++) {handler.Add(hooks[i])}
+ return handler.Execute.apply(handler,data);
+ };
+
+ //
+ // Command queue that performs commands in order, waiting when
+ // necessary for commands to complete asynchronousely
+ //
+ var QUEUE = BASE.Object.Subclass({
+ //
+ // Create the queue and push any commands that are specified
+ //
+ Init: function () {
+ this.pending = this.running = 0;
+ this.queue = [];
+ this.Push.apply(this,arguments);
+ },
+ //
+ // Add commands to the queue and run them. Adding a callback object
+ // (rather than a callback specification) queues a wait for that callback.
+ // Return the final callback for synchronization purposes.
+ //
+ Push: function () {
+ var callback;
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ callback = USING(arguments[i]);
+ if (callback === arguments[i] && !callback.called)
+ {callback = USING(["wait",this,callback])}
+ this.queue.push(callback);
+ }
+ if (!this.running && !this.pending) {this.Process()}
+ return callback;
+ },
+ //
+ // Process the command queue if we aren't waiting on another command
+ //
+ Process: function (queue) {
+ while (!this.running && !this.pending && this.queue.length) {
+ var callback = this.queue[0];
+ queue = this.queue.slice(1); this.queue = [];
+ this.Suspend(); var result = callback(); this.Resume();
+ if (queue.length) {this.queue = queue.concat(this.queue)}
+ if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
+ }
+ },
+ //
+ // Suspend/Resume command processing on this queue
+ //
+ Suspend: function () {this.running++},
+ Resume: function () {if (this.running) {this.running--}},
+ //
+ // Used by WAITFOR to restart the queue when an action completes
+ //
+ call: function () {this.Process.apply(this,arguments)},
+ wait: function (callback) {return callback}
+ });
+
+ //
+ // Create a named signal that listeners can attach to, to be signaled by
+ // postings made to the signal. Posts are queued if they occur while one
+ // is already in process.
+ //
+ var SIGNAL = QUEUE.Subclass({
+ Init: function (name) {
+ QUEUE.prototype.Init.call(this);
+ this.name = name;
+ this.posted = []; // the messages posted so far
+ this.listeners = HOOKS(true); // those with interest in this signal
+ this.posting = false;
+ this.callback = null;
+ },
+ //
+ // Post a message to the signal listeners, with callback for when complete
+ //
+ Post: function (message,callback,forget) {
+ callback = USING(callback);
+ if (this.posting || this.pending) {
+ this.Push(["Post",this,message,callback,forget]);
+ } else {
+ this.callback = callback; callback.reset();
+ if (!forget) {this.posted.push(message)}
+ this.Suspend(); this.posting = true;
+ var result = this.listeners.Execute(message);
+ if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
+ this.Resume(); this.posting = false;
+ if (!this.pending) {this.call()}
+ }
+ return callback;
+ },
+ //
+ // Clear the post history (so new listeners won't get old messages)
+ //
+ Clear: function (callback) {
+ callback = USING(callback);
+ if (this.posting || this.pending) {
+ callback = this.Push(["Clear",this,callback]);
+ } else {
+ this.posted = [];
+ callback();
+ }
+ return callback;
+ },
+ //
+ // Call the callback (all replies are in) and process the command queue
+ //
+ call: function () {this.callback(this); this.Process()},
+
+ //
+ // A listener calls this to register interest in the signal (so it will be called
+ // when posts occur). If ignorePast is true, it will not be sent the post history.
+ //
+ Interest: function (callback,ignorePast,priority) {
+ callback = USING(callback);
+ this.listeners.Add(callback,priority);
+ if (!ignorePast) {
+ for (var i = 0, m = this.posted.length; i < m; i++) {
+ callback.reset();
+ var result = callback(this.posted[i]);
+ if (ISCALLBACK(result) && i === this.posted.length-1) {WAITFOR(result,this)}
+ }
+ }
+ return callback;
+ },
+ //
+ // A listener calls this to remove itself from a signal
+ //
+ NoInterest: function (callback) {
+ this.listeners.Remove(callback);
+ },
+
+ //
+ // Hook a callback to a particular message on this signal
+ //
+ MessageHook: function (msg,callback,priority) {
+ callback = USING(callback);
+ if (!this.hooks) {this.hooks = {}; this.Interest(["ExecuteHooks",this])}
+ if (!this.hooks[msg]) {this.hooks[msg] = HOOKS(true)}
+ this.hooks[msg].Add(callback,priority);
+ for (var i = 0, m = this.posted.length; i < m; i++)
+ {if (this.posted[i] == msg) {callback.reset(); callback(this.posted[i])}}
+ callback.msg = msg; // keep track so we can remove it
+ return callback;
+ },
+ //
+ // Execute the message hooks for the given message
+ //
+ ExecuteHooks: function (msg) {
+ var type = ((msg instanceof Array) ? msg[0] : msg);
+ if (!this.hooks[type]) {return null}
+ return this.hooks[type].Execute(msg);
+ },
+ //
+ // Remove a hook safely
+ //
+ RemoveHook: function (hook) {
+ this.hooks[hook.msg].Remove(hook);
+ }
+
+ },{
+ signals: {}, // the named signals
+ find: function (name) {
+ if (!SIGNAL.signals[name]) {SIGNAL.signals[name] = new SIGNAL(name)}
+ return SIGNAL.signals[name];
+ }
+ });
+
+ //
+ // The main entry-points
+ //
+ BASE.Callback = BASE.CallBack = USING;
+ BASE.Callback.Delay = DELAY;
+ BASE.Callback.After = AFTER;
+ BASE.Callback.Queue = QUEUE;
+ BASE.Callback.Signal = SIGNAL.find;
+ BASE.Callback.Hooks = HOOKS;
+ BASE.Callback.ExecuteHooks = EXECUTEHOOKS;
+})("MathJax");
+
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var isSafari2 = (navigator.vendor === "Apple Computer, Inc." &&
+ typeof navigator.vendorSub === "undefined");
+ var sheets = 0; // used by Safari2
+
+ //
+ // Update sheets count and look up the head object
+ //
+ var HEAD = function (head) {
+ if (document.styleSheets && document.styleSheets.length > sheets)
+ {sheets = document.styleSheets.length}
+ if (!head) {
+ head = document.head || ((document.getElementsByTagName("head"))[0]);
+ if (!head) {head = document.body}
+ }
+ return head;
+ };
+
+ //
+ // Remove scripts that are completed so they don't clutter up the HEAD.
+ // This runs via setTimeout since IE7 can't remove the script while it is running.
+ //
+ var SCRIPTS = []; // stores scripts to be removed after a delay
+ var REMOVESCRIPTS = function () {
+ for (var i = 0, m = SCRIPTS.length; i < m; i++) {BASE.Ajax.head.removeChild(SCRIPTS[i])}
+ SCRIPTS = [];
+ };
+
+ var PATH = {};
+ PATH[BASENAME] = ""; // empty path gets the root URL
+
+ BASE.Ajax = {
+ loaded: {}, // files already loaded
+ loading: {}, // files currently in process of loading
+ loadHooks: {}, // hooks to call when files are loaded
+ timeout: 15*1000, // timeout for loading of files (15 seconds)
+ styleDelay: 1, // delay to use before styles are available
+ config: {
+ root: "", // URL of root directory to load from
+ path: PATH // paths to named URL's (e.g., [MathJax]/...)
+ },
+
+ STATUS: {
+ OK: 1, // file is loading or did load OK
+ ERROR: -1 // file timed out during load
+ },
+
+ //
+ // Return a complete URL to a file (replacing any root names)
+ //
+ fileURL: function (file) {
+ var match = file.match(/^\[([-._a-z0-9]+)\]/i);
+ if (match && match[1] in PATH)
+ {file = (PATH[match[1]]||this.config.root) + file.substr(match[1].length+2)}
+ return file;
+ },
+ //
+ // Replace root names if URL includes one
+ //
+ fileName: function (url) {
+ var root = this.config.root;
+ if (url.substr(0,root.length) === root) {url = "["+BASENAME+"]"+url.substr(root.length)}
+ else {
+ for (var id in PATH) {if (PATH.hasOwnProperty(id) && PATH[id]) {
+ if (url.substr(0,PATH[id].length) === PATH[id])
+ {url = "["+id+"]"+url.substr(PATH[id].length); break}
+ }}
+ }
+ return url;
+ },
+ //
+ // Cache-breaking revision number for file
+ //
+ fileRev: function (file) {
+ var rev = BASE.cdnFileVersions[name] || BASE.cdnVersion;
+ if (rev) {rev = "?rev="+rev}
+ return rev;
+ },
+ urlRev: function (file) {return this.fileURL(file)+this.fileRev(file)},
+
+ //
+ // Load a file if it hasn't been already.
+ // Make sure the file URL is "safe"?
+ //
+ Require: function (file,callback) {
+ callback = BASE.Callback(callback); var type;
+ if (file instanceof Object) {
+ for (var i in file)
+ {if (file.hasOwnProperty(i)) {type = i.toUpperCase(); file = file[i]}}
+ } else {type = file.split(/\./).pop().toUpperCase()}
+ file = this.fileURL(file);
+ // FIXME: check that URL is OK
+ if (this.loaded[file]) {
+ callback(this.loaded[file]);
+ } else {
+ var FILE = {}; FILE[type] = file;
+ this.Load(FILE,callback);
+ }
+ return callback;
+ },
+
+ //
+ // Load a file regardless of where it is and whether it has
+ // already been loaded.
+ //
+ Load: function (file,callback) {
+ callback = BASE.Callback(callback); var type;
+ if (file instanceof Object) {
+ for (var i in file)
+ {if (file.hasOwnProperty(i)) {type = i.toUpperCase(); file = file[i]}}
+ } else {type = file.split(/\./).pop().toUpperCase()}
+ file = this.fileURL(file);
+ if (this.loading[file]) {
+ this.addHook(file,callback);
+ } else {
+ this.head = HEAD(this.head);
+ if (this.loader[type]) {this.loader[type].call(this,file,callback)}
+ else {throw Error("Can't load files of type "+type)}
+ }
+ return callback;
+ },
+
+ //
+ // Register a load hook for a particular file (it will be called when
+ // loadComplete() is called for that file)
+ //
+ LoadHook: function (file,callback,priority) {
+ callback = BASE.Callback(callback);
+ if (file instanceof Object)
+ {for (var i in file) {if (file.hasOwnProperty(i)) {file = file[i]}}}
+ file = this.fileURL(file);
+ if (this.loaded[file]) {callback(this.loaded[file])}
+ else {this.addHook(file,callback,priority)}
+ return callback;
+ },
+ addHook: function (file,callback,priority) {
+ if (!this.loadHooks[file]) {this.loadHooks[file] = MathJax.Callback.Hooks()}
+ this.loadHooks[file].Add(callback,priority);
+ callback.file = file;
+ },
+ removeHook: function (hook) {
+ if (this.loadHooks[hook.file]) {
+ this.loadHooks[hook.file].Remove(hook);
+ if (!this.loadHooks[hook.file].hooks.length) {delete this.loadHooks[hook.file]}
+ }
+ },
+
+ //
+ // Used when files are combined in a preloading configuration file
+ //
+ Preloading: function () {
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ var file = this.fileURL(arguments[i]);
+ if (!this.loading[file]) {this.loading[file] = {preloaded: true}}
+ }
+ },
+
+ //
+ // Code used to load the various types of files
+ // (JS for JavaScript, CSS for style sheets)
+ //
+ loader: {
+ //
+ // Create a SCRIPT tag to load the file
+ //
+ JS: function (file,callback) {
+ var name = this.fileName(file);
+ var script = document.createElement("script");
+ var timeout = BASE.Callback(["loadTimeout",this,file]);
+ this.loading[file] = {
+ callback: callback,
+ timeout: setTimeout(timeout,this.timeout),
+ status: this.STATUS.OK,
+ script: script
+ };
+ //
+ // Add this to the structure above after it is created to prevent recursion
+ // when loading the initial localization file (before loading messsage is available)
+ //
+ this.loading[file].message = BASE.Message.File(name);
+ script.onerror = timeout; // doesn't work in IE and no apparent substitute
+ script.type = "text/javascript";
+ script.src = file+this.fileRev(name);
+ this.head.appendChild(script);
+ },
+ //
+ // Create a LINK tag to load the style sheet
+ //
+ CSS: function (file,callback) {
+ var name = this.fileName(file);
+ var link = document.createElement("link");
+ link.rel = "stylesheet"; link.type = "text/css";
+ link.href = file+this.fileRev(name);
+ this.loading[file] = {
+ callback: callback,
+ message: BASE.Message.File(name),
+ status: this.STATUS.OK
+ };
+ this.head.appendChild(link);
+ this.timer.create.call(this,[this.timer.file,file],link);
+ }
+ },
+
+ //
+ // Timing code for checking when style sheets are available.
+ //
+ timer: {
+ //
+ // Create the timing callback and start the timing loop.
+ // We use a delay because some browsers need it to allow the styles
+ // to be processed.
+ //
+ create: function (callback,node) {
+ callback = BASE.Callback(callback);
+ if (node.nodeName === "STYLE" && node.styleSheet &&
+ typeof(node.styleSheet.cssText) !== 'undefined') {
+ callback(this.STATUS.OK); // MSIE processes style immediately, but doesn't set its styleSheet!
+ } else if (window.chrome && node.nodeName === "LINK") {
+ callback(this.STATUS.OK); // Chrome doesn't give access to cssRules for stylesheet in
+ // a link node, so we can't detect when it is loaded.
+ } else if (isSafari2) {
+ this.timer.start(this,[this.timer.checkSafari2,sheets++,callback],this.styleDelay);
+ } else {
+ this.timer.start(this,[this.timer.checkLength,node,callback],this.styleDelay);
+ }
+ return callback;
+ },
+ //
+ // Start the timer for the given callback checker
+ //
+ start: function (AJAX,check,delay,timeout) {
+ check = BASE.Callback(check);
+ check.execute = this.execute; check.time = this.time;
+ check.STATUS = AJAX.STATUS; check.timeout = timeout || AJAX.timeout;
+ check.delay = check.total = delay || 0;
+ if (delay) {setTimeout(check,delay)} else {check()}
+ },
+ //
+ // Increment the time total, increase the delay
+ // and test if we are past the timeout time.
+ //
+ time: function (callback) {
+ this.total += this.delay;
+ this.delay = Math.floor(this.delay * 1.05 + 5);
+ if (this.total >= this.timeout) {callback(this.STATUS.ERROR); return 1}
+ return 0;
+ },
+ //
+ // For JS file loads, call the proper routine according to status
+ //
+ file: function (file,status) {
+ if (status < 0) {BASE.Ajax.loadTimeout(file)} else {BASE.Ajax.loadComplete(file)}
+ },
+ //
+ // Call the hook with the required data
+ //
+ execute: function () {this.hook.call(this.object,this,this.data[0],this.data[1])},
+ //
+ // Safari2 doesn't set the link's stylesheet, so we need to look in the
+ // document.styleSheets array for the new sheet when it is created
+ //
+ checkSafari2: function (check,length,callback) {
+ if (check.time(callback)) return;
+ if (document.styleSheets.length > length &&
+ document.styleSheets[length].cssRules &&
+ document.styleSheets[length].cssRules.length)
+ {callback(check.STATUS.OK)} else {setTimeout(check,check.delay)}
+ },
+ //
+ // Look for the stylesheets rules and check when they are defined
+ // and no longer of length zero. (This assumes there actually ARE
+ // some rules in the stylesheet.)
+ //
+ checkLength: function (check,node,callback) {
+ if (check.time(callback)) return;
+ var isStyle = 0; var sheet = (node.sheet || node.styleSheet);
+ try {if ((sheet.cssRules||sheet.rules||[]).length > 0) {isStyle = 1}} catch(err) {
+ if (err.message.match(/protected variable|restricted URI/)) {isStyle = 1}
+ else if (err.message.match(/Security error/)) {
+ // Firefox3 gives "Security error" for missing files, so
+ // can't distinguish that from OK files on remote servers.
+ // or OK files in different directory from local files.
+ isStyle = 1; // just say it is OK (can't really tell)
+ }
+ }
+ if (isStyle) {
+ // Opera 9.6 requires this setTimeout
+ setTimeout(BASE.Callback([callback,check.STATUS.OK]),0);
+ } else {
+ setTimeout(check,check.delay);
+ }
+ }
+ },
+
+ //
+ // JavaScript code must call this when they are completely initialized
+ // (this allows them to perform asynchronous actions before indicating
+ // that they are complete).
+ //
+ loadComplete: function (file) {
+ file = this.fileURL(file);
+ var loading = this.loading[file];
+ if (loading && !loading.preloaded) {
+ BASE.Message.Clear(loading.message);
+ clearTimeout(loading.timeout);
+ if (loading.script) {
+ if (SCRIPTS.length === 0) {setTimeout(REMOVESCRIPTS,0)}
+ SCRIPTS.push(loading.script);
+ }
+ this.loaded[file] = loading.status; delete this.loading[file];
+ this.addHook(file,loading.callback);
+ } else {
+ if (loading) {delete this.loading[file]}
+ this.loaded[file] = this.STATUS.OK;
+ loading = {status: this.STATUS.OK}
+ }
+ if (!this.loadHooks[file]) {return null}
+ return this.loadHooks[file].Execute(loading.status);
+ },
+
+ //
+ // If a file fails to load within the timeout period (or the onerror handler
+ // is called), this routine runs to signal the error condition.
+ //
+ loadTimeout: function (file) {
+ if (this.loading[file].timeout) {clearTimeout(this.loading[file].timeout)}
+ this.loading[file].status = this.STATUS.ERROR;
+ this.loadError(file);
+ this.loadComplete(file);
+ },
+
+ //
+ // The default error hook for file load failures
+ //
+ loadError: function (file) {
+ BASE.Message.Set(["LoadFailed","File failed to load: %1",file],null,2000);
+ BASE.Hub.signal.Post(["file load error",file]);
+ },
+
+ //
+ // Defines a style sheet from a hash of style declarations (key:value pairs
+ // where the key is the style selector and the value is a hash of CSS attributes
+ // and values).
+ //
+ Styles: function (styles,callback) {
+ var styleString = this.StyleString(styles);
+ if (styleString === "") {
+ callback = BASE.Callback(callback);
+ callback();
+ } else {
+ var style = document.createElement("style"); style.type = "text/css";
+ this.head = HEAD(this.head);
+ this.head.appendChild(style);
+ if (style.styleSheet && typeof(style.styleSheet.cssText) !== 'undefined') {
+ style.styleSheet.cssText = styleString;
+ } else {
+ style.appendChild(document.createTextNode(styleString));
+ }
+ callback = this.timer.create.call(this,callback,style);
+ }
+ return callback;
+ },
+
+ //
+ // Create a stylesheet string from a style declaration object
+ //
+ StyleString: function (styles) {
+ if (typeof(styles) === 'string') {return styles}
+ var string = "", id, style;
+ for (id in styles) {if (styles.hasOwnProperty(id)) {
+ if (typeof styles[id] === 'string') {
+ string += id + " {"+styles[id]+"}\n";
+ } else if (styles[id] instanceof Array) {
+ for (var i = 0; i < styles[id].length; i++) {
+ style = {}; style[id] = styles[id][i];
+ string += this.StyleString(style);
+ }
+ } else if (id.substr(0,6) === '@media') {
+ string += id + " {"+this.StyleString(styles[id])+"}\n";
+ } else if (styles[id] != null) {
+ style = [];
+ for (var name in styles[id]) {if (styles[id].hasOwnProperty(name)) {
+ if (styles[id][name] != null)
+ {style[style.length] = name + ': ' + styles[id][name]}
+ }}
+ string += id +" {"+style.join('; ')+"}\n";
+ }
+ }}
+ return string;
+ }
+ };
+
+})("MathJax");
+
+/**********************************************************/
+
+MathJax.HTML = {
+ //
+ // Create an HTML element with given attributes and content.
+ // The def parameter is an (optional) object containing key:value pairs
+ // of the attributes and their values, and contents is an (optional)
+ // array of strings to be inserted as text, or arrays of the form
+ // [type,def,contents] that describes an HTML element to be inserted
+ // into the current element. Thus the contents can describe a complete
+ // HTML snippet of arbitrary complexity. E.g.:
+ //
+ // MathJax.HTML.Element("span",{id:"mySpan",style{"font-style":"italic"}},[
+ // "(See the ",["a",{href:"http://www.mathjax.org"},["MathJax home page"]],
+ // " for more details.)"]);
+ //
+ Element: function (type,def,contents) {
+ var obj = document.createElement(type), id;
+ if (def) {
+ if (def.hasOwnProperty("style")) {
+ var style = def.style; def.style = {};
+ for (id in style) {if (style.hasOwnProperty(id))
+ {def.style[id.replace(/-([a-z])/g,this.ucMatch)] = style[id]}}
+ }
+ MathJax.Hub.Insert(obj,def);
+ for (id in def) {
+ if (id === "role" || id.substr(0,5) === "aria-") obj.setAttribute(id,def[id]);
+ }
+ }
+ if (contents) {
+ if (!(contents instanceof Array)) {contents = [contents]}
+ for (var i = 0, m = contents.length; i < m; i++) {
+ if (contents[i] instanceof Array) {
+ obj.appendChild(this.Element(contents[i][0],contents[i][1],contents[i][2]));
+ } else if (type === "script") { // IE throws an error if script is added as a text node
+ this.setScript(obj, contents[i]);
+ } else {
+ obj.appendChild(document.createTextNode(contents[i]));
+ }
+ }
+ }
+ return obj;
+ },
+ ucMatch: function (match,c) {return c.toUpperCase()},
+ addElement: function (span,type,def,contents) {return span.appendChild(this.Element(type,def,contents))},
+ TextNode: function (text) {return document.createTextNode(text)},
+ addText: function (span,text) {return span.appendChild(this.TextNode(text))},
+
+ //
+ // Set and get the text of a script
+ //
+ setScript: function (script,text) {
+ if (this.setScriptBug) {script.text = text} else {
+ while (script.firstChild) {script.removeChild(script.firstChild)}
+ this.addText(script,text);
+ }
+ },
+ getScript: function (script) {
+ var text = (script.text === "" ? script.innerHTML : script.text);
+ return text.replace(/^\s+/,"").replace(/\s+$/,"");
+ },
+
+ //
+ // Manage cookies
+ //
+ Cookie: {
+ prefix: "mjx",
+ expires: 365,
+
+ //
+ // Save an object as a named cookie
+ //
+ Set: function (name,def) {
+ var keys = [];
+ if (def) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {
+ keys.push(id+":"+def[id].toString().replace(/&/g,"&&"));
+ }}
+ }
+ var cookie = this.prefix+"."+name+"="+escape(keys.join('&;'));
+ if (this.expires) {
+ var time = new Date(); time.setDate(time.getDate() + this.expires);
+ cookie += '; expires='+time.toGMTString();
+ }
+ try {document.cookie = cookie+"; path=/"} catch (err) {} // ignore errors saving cookies
+ },
+
+ //
+ // Get the contents of a named cookie and incorporate
+ // it into the given object (or return a fresh one)
+ //
+ Get: function (name,obj) {
+ if (!obj) {obj = {}}
+ var pattern = new RegExp("(?:^|;\\s*)"+this.prefix+"\\."+name+"=([^;]*)(?:;|$)");
+ var match;
+ try {match = pattern.exec(document.cookie)} catch (err) {}; // ignore errors reading cookies
+ if (match && match[1] !== "") {
+ var keys = unescape(match[1]).split('&;');
+ for (var i = 0, m = keys.length; i < m; i++) {
+ match = keys[i].match(/([^:]+):(.*)/);
+ var value = match[2].replace(/&&/g,'&');
+ if (value === "true") {value = true} else if (value === "false") {value = false}
+ else if (value.match(/^-?(\d+(\.\d+)?|\.\d+)$/)) {value = parseFloat(value)}
+ obj[match[1]] = value;
+ }
+ }
+ return obj;
+ }
+ }
+
+};
+
+
+/**********************************************************/
+
+MathJax.Localization = {
+
+ locale: "en",
+ directory: "[MathJax]/localization",
+ strings: {
+ // Currently, this list is not modified by the MathJax-i18n script. You can
+ // run the following command in MathJax/unpacked/localization to update it:
+ //
+ // find . -name "*.js" | xargs grep menuTitle\: | grep -v qqq | sed 's/^\.\/\(.*\)\/.*\.js\: / "\1"\: \{/' | sed 's/,$/\},/' | sed 's/"English"/"English", isLoaded: true/' > tmp ; sort tmp > tmp2 ; sed '$ s/,$//' tmp2 ; rm tmp*
+ //
+ // This only takes languages with localization data so you must also add
+ // the languages that use a remap but are not translated at all.
+ //
+ "ast": {menuTitle: "asturianu"},
+ "bg": {menuTitle: "\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438"},
+ "bcc": {menuTitle: "\u0628\u0644\u0648\u0686\u06CC"},
+ "br": {menuTitle: "brezhoneg"},
+ "ca": {menuTitle: "catal\u00E0"},
+ "cdo": {menuTitle: "M\u00ECng-d\u0115\u0324ng-ng\u1E73\u0304"},
+ "cs": {menuTitle: "\u010De\u0161tina"},
+ "da": {menuTitle: "dansk"},
+ "de": {menuTitle: "Deutsch"},
+ "en": {menuTitle: "English", isLoaded: true},
+ "eo": {menuTitle: "Esperanto"},
+ "es": {menuTitle: "espa\u00F1ol"},
+ "fa": {menuTitle: "\u0641\u0627\u0631\u0633\u06CC"},
+ "fi": {menuTitle: "suomi"},
+ "fr": {menuTitle: "fran\u00E7ais"},
+ "gl": {menuTitle: "galego"},
+ "he": {menuTitle: "\u05E2\u05D1\u05E8\u05D9\u05EA"},
+ "ia": {menuTitle: "interlingua"},
+ "it": {menuTitle: "italiano"},
+ "ja": {menuTitle: "\u65E5\u672C\u8A9E"},
+ "kn": {menuTitle: "\u0C95\u0CA8\u0CCD\u0CA8\u0CA1"},
+ "ko": {menuTitle: "\uD55C\uAD6D\uC5B4"},
+ "lb": {menuTitle: "L\u00EBtzebuergesch"},
+ "lt": {menuTitle: "lietuvi\u0173"},
+ "mk": {menuTitle: "\u043C\u0430\u043A\u0435\u0434\u043E\u043D\u0441\u043A\u0438"},
+ "nl": {menuTitle: "Nederlands"},
+ "oc": {menuTitle: "occitan"},
+ "pl": {menuTitle: "polski"},
+ "pt": {menuTitle: "portugus\u00EA"},
+ "pt-br": {menuTitle: "portugu\u00EAs do Brasil"},
+ "ru": {menuTitle: "\u0440\u0443\u0441\u0441\u043A\u0438\u0439"},
+ "sco": {menuTitle: "Scots"},
+ "scn": {menuTitle: "sicilianu"},
+ "sl": {menuTitle: "sloven\u0161\u010Dina"},
+ "sv": {menuTitle: "svenska"},
+ "tr": {menuTitle: "T\u00FCrk\u00E7e"},
+ "uk": {menuTitle: "\u0443\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"},
+ "vi": {menuTitle: "Ti\u1EBFng Vi\u1EC7t"},
+ "zh-hans": {menuTitle: "\u4E2D\u6587\uFF08\u7B80\u4F53\uFF09"}
+ },
+
+ //
+ // The pattern for substitution escapes:
+ // %n or %{n} or %{plural:%n|option1|option1|...} or %c
+ //
+ pattern: /%(\d+|\{\d+\}|\{[a-z]+:\%\d+(?:\|(?:%\{\d+\}|%.|[^\}])*)+\}|.)/g,
+
+ SPLIT: ("axb".split(/(x)/).length === 3 ?
+ function (string,regex) {return string.split(regex)} :
+ //
+ // IE8 and below don't do split() correctly when the pattern includes
+ // parentheses (the split should include the matched exrepssions).
+ // So implement it by hand here.
+ //
+ function (string,regex) {
+ var result = [], match, last = 0;
+ regex.lastIndex = 0;
+ while ((match = regex.exec(string))) {
+ result.push(string.substr(last,match.index-last));
+ result.push.apply(result,match.slice(1));
+ last = match.index + match[0].length;
+ }
+ result.push(string.substr(last));
+ return result;
+ }),
+
+ _: function (id,phrase) {
+ if (phrase instanceof Array) {return this.processSnippet(id,phrase)}
+ return this.processString(this.lookupPhrase(id,phrase),[].slice.call(arguments,2));
+ },
+
+ processString: function (string,args,domain) {
+ //
+ // Process arguments for substitution
+ // If the argument is a snippet (and we are processing snippets) do so,
+ // Otherwise, if it is a number, convert it for the lacale
+ //
+ var i, m;
+ for (i = 0, m = args.length; i < m; i++) {
+ if (domain && args[i] instanceof Array) {args[i] = this.processSnippet(domain,args[i])}
+ }
+ //
+ // Split string at escapes and process them individually
+ //
+ var parts = this.SPLIT(string,this.pattern);
+ for (i = 1, m = parts.length; i < m; i += 2) {
+ var c = parts[i].charAt(0); // first char will be { or \d or a char to be kept literally
+ if (c >= "0" && c <= "9") { // %n
+ parts[i] = args[parts[i]-1];
+ if (typeof parts[i] === "number") parts[i] = this.number(parts[i]);
+ } else if (c === "{") { // %{n} or %{plural:%n|...}
+ c = parts[i].substr(1);
+ if (c >= "0" && c <= "9") { // %{n}
+ parts[i] = args[parts[i].substr(1,parts[i].length-2)-1];
+ if (typeof parts[i] === "number") parts[i] = this.number(parts[i]);
+ } else { // %{plural:%n|...}
+ var match = parts[i].match(/^\{([a-z]+):%(\d+)\|(.*)\}$/);
+ if (match) {
+ if (match[1] === "plural") {
+ var n = args[match[2]-1];
+ if (typeof n === "undefined") {
+ parts[i] = "???"; // argument doesn't exist
+ } else {
+ n = this.plural(n) - 1; // index of the form to use
+ var plurals = match[3].replace(/(^|[^%])(%%)*%\|/g,"$1$2%\uEFEF").split(/\|/); // the parts (replacing %| with a special character)
+ if (n >= 0 && n < plurals.length) {
+ parts[i] = this.processString(plurals[n].replace(/\uEFEF/g,"|"),args,domain);
+ } else {
+ parts[i] = "???"; // no string for this index
+ }
+ }
+ } else {parts[i] = "%"+parts[i]} // not "plural", put back the % and leave unchanged
+ }
+ }
+ }
+ if (parts[i] == null) {parts[i] = "???"}
+ }
+ //
+ // If we are not forming a snippet, return the completed string
+ //
+ if (!domain) {return parts.join("")}
+ //
+ // We need to return an HTML snippet, so buld it from the
+ // broken up string with inserted parts (that could be snippets)
+ //
+ var snippet = [], part = "";
+ for (i = 0; i < m; i++) {
+ part += parts[i]; i++; // add the string and move on to substitution result
+ if (i < m) {
+ if (parts[i] instanceof Array) { // substitution was a snippet
+ snippet.push(part); // add the accumulated string
+ snippet = snippet.concat(parts[i]); // concatenate the substution snippet
+ part = ""; // start accumulating a new string
+ } else { // substitution was a string
+ part += parts[i]; // add to accumulating string
+ }
+ }
+ }
+ if (part !== "") {snippet.push(part)} // add final string
+ return snippet;
+ },
+
+ processSnippet: function (domain,snippet) {
+ var result = []; // the new snippet
+ //
+ // Look through the original snippet for
+ // strings or snippets to translate
+ //
+ for (var i = 0, m = snippet.length; i < m; i++) {
+ if (snippet[i] instanceof Array) {
+ //
+ // This could be a sub-snippet:
+ // ["tag"] or ["tag",{properties}] or ["tag",{properties},snippet]
+ // Or it could be something to translate:
+ // [id,string,args] or [domain,snippet]
+ var data = snippet[i];
+ if (typeof data[1] === "string") { // [id,string,args]
+ var id = data[0]; if (!(id instanceof Array)) {id = [domain,id]}
+ var phrase = this.lookupPhrase(id,data[1]);
+ result = result.concat(this.processMarkdown(phrase,data.slice(2),domain));
+ } else if (data[1] instanceof Array) { // [domain,snippet]
+ result = result.concat(this.processSnippet.apply(this,data));
+ } else if (data.length >= 3) { // ["tag",{properties},snippet]
+ result.push([data[0],data[1],this.processSnippet(domain,data[2])]);
+ } else { // ["tag"] or ["tag",{properties}]
+ result.push(snippet[i]);
+ }
+ } else { // a string
+ result.push(snippet[i]);
+ }
+ }
+ return result;
+ },
+
+ markdownPattern: /(%.)|(\*{1,3})((?:%.|.)+?)\2|(`+)((?:%.|.)+?)\4|\[((?:%.|.)+?)\]\(([^\s\)]+)\)/,
+ // %c or *bold*, **italics**, ***bold-italics***, or `code`, or [link](url)
+
+ processMarkdown: function (phrase,args,domain) {
+ var result = [], data;
+ //
+ // Split the string by the Markdown pattern
+ // (the text blocks are separated by
+ // c,stars,star-text,backtics,code-text,link-text,URL).
+ // Start with teh first text string from the split.
+ //
+ var parts = phrase.split(this.markdownPattern);
+ var string = parts[0];
+ //
+ // Loop through the matches and process them
+ //
+ for (var i = 1, m = parts.length; i < m; i += 8) {
+ if (parts[i+1]) { // stars (for bold/italic)
+ //
+ // Select the tag to use by number of stars (three stars requires two tags)
+ //
+ data = this.processString(parts[i+2],args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = [["b","i","i"][parts[i+1].length-1],{},data]; // number of stars determines type
+ if (parts[i+1].length === 3) {data = ["b",{},data]} // bold-italic
+ } else if (parts[i+3]) { // backtics (for code)
+ //
+ // Remove one leading or trailing space, and process substitutions
+ // Make a tag
+ //
+ data = this.processString(parts[i+4].replace(/^\s/,"").replace(/\s$/,""),args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = ["code",{},data];
+ } else if (parts[i+5]) { // hyperlink
+ //
+ // Process the link text, and make an tag with the URL
+ //
+ data = this.processString(parts[i+5],args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = ["a",{href:this.processString(parts[i+6],args),target:"_blank"},data];
+ } else {
+ //
+ // Escaped character (%c) gets added into the string.
+ //
+ string += parts[i]; data = null;
+ }
+ //
+ // If there is a tag to insert,
+ // Add any pending string, then push the tag
+ //
+ if (data) {
+ result = this.concatString(result,string,args,domain);
+ result.push(data); string = "";
+ }
+ //
+ // Process the string that follows matches pattern
+ //
+ if (parts[i+7] !== "") {string += parts[i+7]}
+ };
+ //
+ // Add any pending string and return the resulting snippet
+ //
+ result = this.concatString(result,string,args,domain);
+ return result;
+ },
+ concatString: function (result,string,args,domain) {
+ if (string != "") {
+ //
+ // Process the substutions.
+ // If the result is not a snippet, turn it into one.
+ // Then concatenate the snippet to the current one
+ //
+ string = this.processString(string,args,domain);
+ if (!(string instanceof Array)) {string = [string]}
+ result = result.concat(string);
+ }
+ return result;
+ },
+
+ lookupPhrase: function (id,phrase,domain) {
+ //
+ // Get the domain and messageID
+ //
+ if (!domain) {domain = "_"}
+ if (id instanceof Array) {domain = (id[0] || "_"); id = (id[1] || "")}
+ //
+ // Check if the data is available and if not,
+ // load it and throw a restart error so the calling
+ // code can wait for the load and try again.
+ //
+ var load = this.loadDomain(domain);
+ if (load) {MathJax.Hub.RestartAfter(load)}
+ //
+ // Look up the message in the localization data
+ // (if not found, the original English is used)
+ //
+ var localeData = this.strings[this.locale];
+ if (localeData) {
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (domainData.strings && id in domainData.strings)
+ {phrase = domainData.strings[id]}
+ }
+ }
+ //
+ // return the translated phrase
+ //
+ return phrase;
+ },
+
+ //
+ // Load a langauge data file from the proper
+ // directory and file.
+ //
+ loadFile: function (file,data,callback) {
+ callback = MathJax.Callback(callback);
+ file = (data.file || file); // the data's file name or the default name
+ if (!file.match(/\.js$/)) {file += ".js"} // add .js if needed
+ //
+ // Add the directory if the file doesn't
+ // contain a full URL already.
+ //
+ if (!file.match(/^([a-z]+:|\[MathJax\])/)) {
+ var dir = (this.strings[this.locale].directory ||
+ this.directory + "/" + this.locale ||
+ "[MathJax]/localization/" + this.locale);
+ file = dir + "/" + file;
+ }
+ //
+ // Load the file and mark the data as loaded (even if it
+ // failed to load, so we don't continue to try to load it
+ // over and over).
+ //
+ var load = MathJax.Ajax.Require(file,function () {data.isLoaded = true; return callback()});
+ //
+ // Return the callback if needed, otherwise null.
+ //
+ return (load.called ? null : load);
+ },
+
+ //
+ // Check to see if the localization data are loaded
+ // for the given domain; if not, load the data file,
+ // and return a callback for the loading operation.
+ // Otherwise return null (data are loaded).
+ //
+ loadDomain: function (domain,callback) {
+ var load, localeData = this.strings[this.locale];
+ if (localeData) {
+ if (!localeData.isLoaded) {
+ load = this.loadFile(this.locale,localeData);
+ if (load) {
+ return MathJax.Callback.Queue(
+ load,["loadDomain",this,domain] // call again to load domain
+ ).Push(callback||{});
+ }
+ }
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (!domainData.isLoaded) {
+ load = this.loadFile(domain,domainData);
+ if (load) {return MathJax.Callback.Queue(load).Push(callback)}
+ }
+ }
+ }
+ // localization data are loaded, so just do the callback
+ return MathJax.Callback(callback)();
+ },
+
+ //
+ // Perform a function, properly handling
+ // restarts due to localization file loads.
+ //
+ // Note that this may return before the function
+ // has been called successfully, so you should
+ // consider fn as running asynchronously. (Callbacks
+ // can be used to synchronize it with other actions.)
+ //
+ Try: function (fn) {
+ fn = MathJax.Callback(fn); fn.autoReset = true;
+ try {fn()} catch (err) {
+ if (!err.restart) {throw err}
+ MathJax.Callback.After(["Try",this,fn],err.restart);
+ }
+ },
+
+ //
+ // Reset the current language
+ //
+ resetLocale: function(locale) {
+ // Selection algorithm:
+ // 1) Downcase locale name (e.g. "en-US" => "en-us")
+ // 2) Try a parent language (e.g. "en-us" => "en")
+ // 3) Try the fallback specified in the data (e.g. "pt" => "pt-br")
+ // 4) Otherwise don't change the locale.
+ if (!locale) return;
+ locale = locale.toLowerCase();
+ while (!this.strings[locale]) {
+ var dashPos = locale.lastIndexOf("-");
+ if (dashPos === -1) return;
+ locale = locale.substring(0, dashPos);
+ }
+ var remap = this.strings[locale].remap;
+ this.locale = remap ? remap : locale;
+ },
+
+ //
+ // Set the current language
+ //
+ setLocale: function(locale) {
+ this.resetLocale(locale);
+ if (MathJax.Menu) {this.loadDomain("MathMenu")}
+ },
+
+ //
+ // Add or update a language or domain
+ //
+ addTranslation: function (locale,domain,definition) {
+ var data = this.strings[locale], isNew = false;
+ if (!data) {data = this.strings[locale] = {}; isNew = true}
+ if (!data.domains) {data.domains = {}}
+ if (domain) {
+ if (!data.domains[domain]) {data.domains[domain] = {}}
+ data = data.domains[domain];
+ }
+ MathJax.Hub.Insert(data,definition);
+ if (isNew && MathJax.Menu.menu) {MathJax.Menu.CreateLocaleMenu()}
+ },
+
+ //
+ // Set CSS for an element based on font requirements
+ //
+ setCSS: function (div) {
+ var locale = this.strings[this.locale];
+ if (locale) {
+ if (locale.fontFamily) {div.style.fontFamily = locale.fontFamily}
+ if (locale.fontDirection) {
+ div.style.direction = locale.fontDirection;
+ if (locale.fontDirection === "rtl") {div.style.textAlign = "right"}
+ }
+ }
+ return div;
+ },
+
+ //
+ // Get the language's font family or direction
+ //
+ fontFamily: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontFamily : null);
+ },
+ fontDirection: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontDirection : null);
+ },
+
+ //
+ // Get the language's plural index for a number
+ //
+ plural: function (n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.plural) {return locale.plural(n)}
+ // default
+ if (n == 1) {return 1} // one
+ return 2; // other
+ },
+
+ //
+ // Convert a number to language-specific form
+ //
+ number: function(n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.number) {return locale.number(n)}
+ // default
+ return n;
+ }
+};
+
+
+/**********************************************************/
+
+MathJax.Message = {
+ ready: false, // used to tell when the styles are available
+ log: [{}], current: null,
+ textNodeBug: (navigator.vendor === "Apple Computer, Inc." &&
+ typeof navigator.vendorSub === "undefined") ||
+ (window.hasOwnProperty && window.hasOwnProperty("konqueror")), // Konqueror displays some gibberish with text.nodeValue = "..."
+
+ styles: {
+ "#MathJax_Message": {
+ position: "fixed", left: "1px", bottom: "2px",
+ 'background-color': "#E6E6E6", border: "1px solid #959595",
+ margin: "0px", padding: "2px 8px",
+ 'z-index': "102", color: "black", 'font-size': "80%",
+ width: "auto", 'white-space': "nowrap"
+ },
+
+ "#MathJax_MSIE_Frame": {
+ position: "absolute",
+ top:0, left: 0, width: "0px", 'z-index': 101,
+ border: "0px", margin: "0px", padding: "0px"
+ }
+ },
+
+ browsers: {
+ MSIE: function (browser) {
+ MathJax.Message.msieFixedPositionBug = ((document.documentMode||0) < 7);
+ if (MathJax.Message.msieFixedPositionBug)
+ {MathJax.Hub.config.styles["#MathJax_Message"].position = "absolute"}
+ MathJax.Message.quirks = (document.compatMode === "BackCompat");
+ },
+ Chrome: function (browser) {
+ MathJax.Hub.config.styles["#MathJax_Message"].bottom = "1.5em";
+ MathJax.Hub.config.styles["#MathJax_Message"].left = "1em";
+ }
+ },
+
+ Init: function (styles) {
+ if (styles) {this.ready = true}
+ if (!document.body || !this.ready) {return false}
+ //
+ // ASCIIMathML replaces the entire page with a copy of itself (@#!#%@!!)
+ // so check that this.div is still part of the page, otherwise look up
+ // the copy and use that.
+ //
+ if (this.div && this.div.parentNode == null) {
+ this.div = document.getElementById("MathJax_Message");
+ if (this.div) {this.text = this.div.firstChild}
+ }
+ if (!this.div) {
+ var frame = document.body;
+ if (this.msieFixedPositionBug && window.attachEvent) {
+ frame = this.frame = this.addDiv(document.body); frame.removeAttribute("id");
+ frame.style.position = "absolute";
+ frame.style.border = frame.style.margin = frame.style.padding = "0px";
+ frame.style.zIndex = "101"; frame.style.height = "0px";
+ frame = this.addDiv(frame);
+ frame.id = "MathJax_MSIE_Frame";
+ window.attachEvent("onscroll",this.MoveFrame);
+ window.attachEvent("onresize",this.MoveFrame);
+ this.MoveFrame();
+ }
+ this.div = this.addDiv(frame); this.div.style.display = "none";
+ this.text = this.div.appendChild(document.createTextNode(""));
+ }
+ return true;
+ },
+
+ addDiv: function (parent) {
+ var div = document.createElement("div");
+ div.id = "MathJax_Message";
+ if (parent.firstChild) {parent.insertBefore(div,parent.firstChild)}
+ else {parent.appendChild(div)}
+ return div;
+ },
+
+ MoveFrame: function () {
+ var body = (MathJax.Message.quirks ? document.body : document.documentElement);
+ var frame = MathJax.Message.frame;
+ frame.style.left = body.scrollLeft + 'px';
+ frame.style.top = body.scrollTop + 'px';
+ frame.style.width = body.clientWidth + 'px';
+ frame = frame.firstChild;
+ frame.style.height = body.clientHeight + 'px';
+ },
+
+ localize: function (message) {
+ return MathJax.Localization._(message,message);
+ },
+
+ filterText: function (text,n,id) {
+ if (MathJax.Hub.config.messageStyle === "simple") {
+ if (id === "LoadFile") {
+ if (!this.loading) {this.loading = this.localize("Loading") + " "}
+ text = this.loading; this.loading += ".";
+ } else if (id === "ProcessMath") {
+ if (!this.processing) {this.processing = this.localize("Processing") + " "}
+ text = this.processing; this.processing += ".";
+ } else if (id === "TypesetMath") {
+ if (!this.typesetting) {this.typesetting = this.localize("Typesetting") + " "}
+ text = this.typesetting; this.typesetting += ".";
+ }
+ }
+ return text;
+ },
+
+ Set: function (text,n,clearDelay) {
+ if (n == null) {n = this.log.length; this.log[n] = {}}
+ //
+ // Translate message if it is [id,message,arguments]
+ //
+ var id = "";
+ if (text instanceof Array) {
+ id = text[0]; if (id instanceof Array) {id = id[1]}
+ //
+ // Localization._() will throw a restart error if a localization file
+ // needs to be loaded, so trap that and redo the Set() call
+ // after it is loaded.
+ //
+ try {
+ text = MathJax.Localization._.apply(MathJax.Localization,text);
+ } catch (err) {
+ if (!err.restart) {throw err}
+ if (!err.restart.called) {
+ //
+ // Mark it so we can tell if the Clear() comes before the message is displayed
+ //
+ if (this.log[n].restarted == null) {this.log[n].restarted = 0}
+ this.log[n].restarted++; delete this.log[n].cleared;
+ MathJax.Callback.After(["Set",this,text,n,clearDelay],err.restart);
+ return n;
+ }
+ }
+ }
+ //
+ // Clear the timout timer.
+ //
+ if (this.timer) {clearTimeout(this.timer); delete this.timer}
+ //
+ // Save the message and filtered message.
+ //
+ this.log[n].text = text; this.log[n].filteredText = text = this.filterText(text,n,id);
+ //
+ // Hook the message into the message list so we can tell
+ // what message to put up when this one is removed.
+ //
+ if (typeof(this.log[n].next) === "undefined") {
+ this.log[n].next = this.current;
+ if (this.current != null) {this.log[this.current].prev = n}
+ this.current = n;
+ }
+ //
+ // Show the message if it is the currently active one.
+ //
+ if (this.current === n && MathJax.Hub.config.messageStyle !== "none") {
+ if (this.Init()) {
+ if (this.textNodeBug) {this.div.innerHTML = text} else {this.text.nodeValue = text}
+ this.div.style.display = "";
+ if (this.status) {window.status = ""; delete this.status}
+ } else {
+ window.status = text;
+ this.status = true;
+ }
+ }
+ //
+ // Check if the message was resetarted to load a localization file
+ // and if it has been cleared in the meanwhile.
+ //
+ if (this.log[n].restarted) {
+ if (this.log[n].cleared) {clearDelay = 0}
+ if (--this.log[n].restarted === 0) {delete this.log[n].cleared}
+ }
+ //
+ // Check if we need to clear the message automatically.
+ //
+ if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n]),clearDelay)}
+ else if (clearDelay == 0) {this.Clear(n,0)}
+ //
+ // Return the message number.
+ //
+ return n;
+ },
+
+ Clear: function (n,delay) {
+ //
+ // Detatch the message from the active list.
+ //
+ if (this.log[n].prev != null) {this.log[this.log[n].prev].next = this.log[n].next}
+ if (this.log[n].next != null) {this.log[this.log[n].next].prev = this.log[n].prev}
+ //
+ // If it is the current message, get the next one to show.
+ //
+ if (this.current === n) {
+ this.current = this.log[n].next;
+ if (this.text) {
+ if (this.div.parentNode == null) {this.Init()} // see ASCIIMathML comments above
+ if (this.current == null) {
+ //
+ // If there are no more messages, remove the message box.
+ //
+ if (this.timer) {clearTimeout(this.timer); delete this.timer}
+ if (delay == null) {delay = 600}
+ if (delay === 0) {this.Remove()}
+ else {this.timer = setTimeout(MathJax.Callback(["Remove",this]),delay)}
+ } else if (MathJax.Hub.config.messageStyle !== "none") {
+ //
+ // If there is an old message, put it in place
+ //
+ if (this.textNodeBug) {this.div.innerHTML = this.log[this.current].filteredText}
+ else {this.text.nodeValue = this.log[this.current].filteredText}
+ }
+ if (this.status) {window.status = ""; delete this.status}
+ } else if (this.status) {
+ window.status = (this.current == null ? "" : this.log[this.current].text);
+ }
+ }
+ //
+ // Clean up the log data no longer needed
+ //
+ delete this.log[n].next; delete this.log[n].prev;
+ delete this.log[n].filteredText;
+ //
+ // If this is a restarted localization message, mark that it has been cleared
+ // while waiting for the file to load.
+ //
+ if (this.log[n].restarted) {this.log[n].cleared = true}
+ },
+
+ Remove: function () {
+ // FIXME: do a fade out or something else interesting?
+ this.text.nodeValue = "";
+ this.div.style.display = "none";
+ },
+
+ File: function (file) {
+ return this.Set(["LoadFile","Loading %1",file],null,null);
+ },
+
+ Log: function () {
+ var strings = [];
+ for (var i = 1, m = this.log.length; i < m; i++) {strings[i] = this.log[i].text}
+ return strings.join("\n");
+ }
+
+};
+
+/**********************************************************/
+
+MathJax.Hub = {
+ config: {
+ root: "",
+ config: [], // list of configuration files to load
+ styleSheets: [], // list of CSS files to load
+ styles: { // styles to generate in-line
+ ".MathJax_Preview": {color: "#888"}
+ },
+ jax: [], // list of input and output jax to load
+ extensions: [], // list of extensions to load
+ preJax: null, // pattern to remove from before math script tag
+ postJax: null, // pattern to remove from after math script tag
+ displayAlign: 'center', // how to align displayed equations (left, center, right)
+ displayIndent: '0', // indentation for displayed equations (when not centered)
+ preRemoveClass: 'MathJax_Preview', // class of objects to remove preceeding math script
+ showProcessingMessages: true, // display "Processing math: nn%" messages or not
+ messageStyle: "normal", // set to "none" or "simple" (for "Loading..." and "Processing...")
+ delayStartupUntil: "none", // set to "onload" to delay setup until the onload handler runs
+ // set to "configured" to delay startup until MathJax.Hub.Configured() is called
+ // set to a Callback to wait for before continuing with the startup
+ skipStartupTypeset: false, // set to true to skip PreProcess and Process during startup
+ elements: [], // array of elements to process when none is given explicitly
+ positionToHash: true, // after initial typeset pass, position to #hash location?
+
+ showMathMenu: true, // attach math context menu to typeset math?
+ showMathMenuMSIE: true, // separtely determine if MSIE should have math menu
+ // (since the code for that is a bit delicate)
+
+ menuSettings: {
+ zoom: "None", // when to do MathZoom
+ CTRL: false, // require CTRL for MathZoom?
+ ALT: false, // require Alt or Option?
+ CMD: false, // require CMD?
+ Shift: false, // require Shift?
+ discoverable: false, // make math menu discoverable on hover?
+ zscale: "200%", // the scaling factor for MathZoom
+ renderer: null, // set when Jax are loaded
+ font: "Auto", // what font HTML-CSS should use
+ context: "MathJax", // or "Browser" for pass-through to browser menu
+ locale: null, // the language to use for messages
+ mpContext: false, // true means pass menu events to MathPlayer in IE
+ mpMouse: false, // true means pass mouse events to MathPlayer in IE
+ texHints: true, // include class names for TeXAtom elements
+ FastPreview: null, // use PreviewHTML output as preview?
+ assistiveMML: null, // include hidden MathML for screen readers?
+ inTabOrder: true, // set to false if math elements should be included in the tabindex
+ semantics: false // add semantics tag with original form in MathML output
+ },
+
+ errorSettings: {
+ // localized HTML snippet structure for message to use
+ message: ["[",["MathProcessingError","Math Processing Error"],"]"],
+ style: {color: "#CC0000", "font-style":"italic"} // style for message
+ },
+
+ ignoreMMLattributes: {} // attributes not to copy to HTML-CSS or SVG output
+ // from MathML input (in addition to the ones in MML.nocopyAttributes).
+ // An id set to true will be ignored, one set to false will
+ // be allowed (even if other criteria normally would prevent
+ // it from being copied); use false carefully!
+ },
+
+ preProcessors: MathJax.Callback.Hooks(true), // list of callbacks for preprocessing (initialized by extensions)
+ inputJax: {}, // mime-type mapped to input jax (by registration)
+ outputJax: {order:{}}, // mime-type mapped to output jax list (by registration)
+
+ processSectionDelay: 50, // pause between input and output phases of processing
+ processUpdateTime: 250, // time between screen updates when processing math (milliseconds)
+ processUpdateDelay: 10, // pause between screen updates to allow other processing (milliseconds)
+
+ signal: MathJax.Callback.Signal("Hub"), // Signal used for Hub events
+
+ Config: function (def) {
+ this.Insert(this.config,def);
+ if (this.config.Augment) {this.Augment(this.config.Augment)}
+ },
+ CombineConfig: function (name,def) {
+ var config = this.config, id, parent; name = name.split(/\./);
+ for (var i = 0, m = name.length; i < m; i++) {
+ id = name[i]; if (!config[id]) {config[id] = {}}
+ parent = config; config = config[id];
+ }
+ parent[id] = config = this.Insert(def,config);
+ return config;
+ },
+
+ Register: {
+ PreProcessor: function () {return MathJax.Hub.preProcessors.Add.apply(MathJax.Hub.preProcessors,arguments)},
+ MessageHook: function () {return MathJax.Hub.signal.MessageHook.apply(MathJax.Hub.signal,arguments)},
+ StartupHook: function () {return MathJax.Hub.Startup.signal.MessageHook.apply(MathJax.Hub.Startup.signal,arguments)},
+ LoadHook: function () {return MathJax.Ajax.LoadHook.apply(MathJax.Ajax,arguments)}
+ },
+ UnRegister: {
+ PreProcessor: function (hook) {MathJax.Hub.preProcessors.Remove(hook)},
+ MessageHook: function (hook) {MathJax.Hub.signal.RemoveHook(hook)},
+ StartupHook: function (hook) {MathJax.Hub.Startup.signal.RemoveHook(hook)},
+ LoadHook: function (hook) {MathJax.Ajax.removeHook(hook)}
+ },
+
+ getAllJax: function (element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxByType: function (type,element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
+ scripts[i].MathJax.elementJax.mimeType === type)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxByInputType: function (type,element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
+ scripts[i].type && scripts[i].type.replace(/ *;(.|\s)*/,"") === type)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxFor: function (element) {
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (element && element.MathJax) {return element.MathJax.elementJax}
+ if (this.isMathJaxNode(element)) {
+ if (!element.isMathJax) {element = element.firstChild} // for NativeMML output
+ while (element && !element.jaxID) {element = element.parentNode}
+ if (element) {return MathJax.OutputJax[element.jaxID].getJaxFromMath(element)}
+ }
+ return null;
+ },
+
+ isJax: function (element) {
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (this.isMathJaxNode(element)) {return 1}
+ if (element && (element.tagName||"").toLowerCase() === 'script') {
+ if (element.MathJax)
+ {return (element.MathJax.state === MathJax.ElementJax.STATE.PROCESSED ? 1 : -1)}
+ if (element.type && this.inputJax[element.type.replace(/ *;(.|\s)*/,"")]) {return -1}
+ }
+ return 0;
+ },
+ isMathJaxNode: function (element) {
+ return !!element && (element.isMathJax || (element.className||"") === "MathJax_MathML");
+ },
+
+ setRenderer: function (renderer,type) {
+ if (!renderer) return;
+ if (!MathJax.OutputJax[renderer]) {
+ this.config.menuSettings.renderer = "";
+ var file = "[MathJax]/jax/output/"+renderer+"/config.js";
+ return MathJax.Ajax.Require(file,["setRenderer",this,renderer,type]);
+ } else {
+ this.config.menuSettings.renderer = renderer;
+ if (type == null) {type = "jax/mml"}
+ var jax = this.outputJax;
+ if (jax[type] && jax[type].length) {
+ if (renderer !== jax[type][0].id) {
+ jax[type].unshift(MathJax.OutputJax[renderer]);
+ return this.signal.Post(["Renderer Selected",renderer]);
+ }
+ }
+ return null;
+ }
+ },
+
+ Queue: function () {
+ return this.queue.Push.apply(this.queue,arguments);
+ },
+
+ Typeset: function (element,callback) {
+ if (!MathJax.isReady) return null;
+ var ec = this.elementCallback(element,callback);
+ if (ec.count) {
+ var queue = MathJax.Callback.Queue(
+ ["PreProcess",this,ec.elements],
+ ["Process",this,ec.elements]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ PreProcess: function (element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var queue = MathJax.Callback.Queue();
+ if (ec.count) {
+ var elements = (ec.count === 1 ? [ec.elements] : ec.elements);
+ queue.Push(["Post",this.signal,["Begin PreProcess",ec.elements]]);
+ for (var i = 0, m = elements.length; i < m; i++) {
+ if (elements[i]) {queue.Push(["Execute",this.preProcessors,elements[i]])}
+ }
+ queue.Push(["Post",this.signal,["End PreProcess",ec.elements]]);
+ }
+ return queue.Push(ec.callback);
+ },
+
+ Process: function (element,callback) {return this.takeAction("Process",element,callback)},
+ Update: function (element,callback) {return this.takeAction("Update",element,callback)},
+ Reprocess: function (element,callback) {return this.takeAction("Reprocess",element,callback)},
+ Rerender: function (element,callback) {return this.takeAction("Rerender",element,callback)},
+
+ takeAction: function (action,element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var elements = ec.elements;
+ var queue = MathJax.Callback.Queue(["Clear",this.signal]);
+ var state = {
+ scripts: [], // filled in by prepareScripts
+ start: new Date().getTime(), // timer for processing messages
+ i: 0, j: 0, // current script, current jax
+ jax: {}, // scripts grouped by output jax
+ jaxIDs: [] // id's of jax used
+ };
+ if (ec.count) {
+ var delay = ["Delay",MathJax.Callback,this.processSectionDelay];
+ if (!delay[2]) {delay = {}}
+ queue.Push(
+ ["Post",this.signal,["Begin "+action,elements]],
+ ["Post",this.signal,["Begin Math",elements,action]],
+ ["prepareScripts",this,action,elements,state],
+ ["Post",this.signal,["Begin Math Input",elements,action]],
+ ["processInput",this,state],
+ ["Post",this.signal,["End Math Input",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"preProcess"],
+ delay,
+ ["Post",this.signal,["Begin Math Output",elements,action]],
+ ["processOutput",this,state],
+ ["Post",this.signal,["End Math Output",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"postProcess"],
+ delay,
+ ["Post",this.signal,["End Math",elements,action]],
+ ["Post",this.signal,["End "+action,elements]]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ scriptAction: {
+ Process: function (script) {},
+ Update: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax && jax.needsUpdate()) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ else {script.MathJax.state = jax.STATE.PROCESSED}
+ },
+ Reprocess: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ },
+ Rerender: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.OUTPUT}
+ }
+ },
+
+ prepareScripts: function (action,element,state) {
+ if (arguments.callee.disabled) return;
+ var scripts = this.elementScripts(element);
+ var STATE = MathJax.ElementJax.STATE;
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var script = scripts[i];
+ if (script.type && this.inputJax[script.type.replace(/ *;(.|\n)*/,"")]) {
+ if (script.MathJax) {
+ if (script.MathJax.elementJax && script.MathJax.elementJax.hover) {
+ MathJax.Extension.MathEvents.Hover.ClearHover(script.MathJax.elementJax);
+ }
+ if (script.MathJax.state !== STATE.PENDING) {this.scriptAction[action](script)}
+ }
+ if (!script.MathJax) {script.MathJax = {state: STATE.PENDING}}
+ if (script.MathJax.error) delete script.MathJax.error;
+ if (script.MathJax.state !== STATE.PROCESSED) {state.scripts.push(script)}
+ }
+ }
+ },
+
+ checkScriptSiblings: function (script) {
+ if (script.MathJax.checked) return;
+ var config = this.config, pre = script.previousSibling;
+ if (pre && pre.nodeName === "#text") {
+ var preJax,postJax, post = script.nextSibling;
+ if (post && post.nodeName !== "#text") {post = null}
+ if (config.preJax) {
+ if (typeof(config.preJax) === "string") {config.preJax = new RegExp(config.preJax+"$")}
+ preJax = pre.nodeValue.match(config.preJax);
+ }
+ if (config.postJax && post) {
+ if (typeof(config.postJax) === "string") {config.postJax = new RegExp("^"+config.postJax)}
+ postJax = post.nodeValue.match(config.postJax);
+ }
+ if (preJax && (!config.postJax || postJax)) {
+ pre.nodeValue = pre.nodeValue.replace
+ (config.preJax,(preJax.length > 1? preJax[1] : ""));
+ pre = null;
+ }
+ if (postJax && (!config.preJax || preJax)) {
+ post.nodeValue = post.nodeValue.replace
+ (config.postJax,(postJax.length > 1? postJax[1] : ""));
+ }
+ if (pre && !pre.nodeValue.match(/\S/)) {pre = pre.previousSibling}
+ }
+ if (config.preRemoveClass && pre && pre.className === config.preRemoveClass)
+ {script.MathJax.preview = pre}
+ script.MathJax.checked = 1;
+ },
+
+ processInput: function (state) {
+ var jax, STATE = MathJax.ElementJax.STATE;
+ var script, prev, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ script = state.scripts[state.i]; if (!script) {state.i++; continue}
+ //
+ // Remove previous error marker, if any
+ //
+ prev = script.previousSibling;
+ if (prev && prev.className === "MathJax_Error") {prev.parentNode.removeChild(prev)}
+ //
+ // Check if already processed or needs processing
+ //
+ if (!script.MathJax || script.MathJax.state === STATE.PROCESSED) {state.i++; continue};
+ if (!script.MathJax.elementJax || script.MathJax.state === STATE.UPDATE) {
+ this.checkScriptSiblings(script); // remove preJax/postJax etc.
+ var type = script.type.replace(/ *;(.|\s)*/,""); // the input jax type
+ var input = this.inputJax[type]; // the input jax itself
+ jax = input.Process(script,state); // run the input jax
+ if (typeof jax === 'function') { // if a callback was returned
+ if (jax.called) continue; // go back and call Process() again
+ this.RestartAfter(jax); // wait for the callback
+ }
+ jax = jax.Attach(script,input.id); // register the jax on the script
+ this.saveScript(jax,state,script,STATE); // add script to state
+ this.postInputHooks.Execute(jax,input.id,script); // run global jax filters
+ } else if (script.MathJax.state === STATE.OUTPUT) {
+ this.saveScript(script.MathJax.elementJax,state,script,STATE); // add script to state
+ }
+ //
+ // Go on to the next script, and check if we need to update the processing message
+ //
+ state.i++; var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(1))}
+ }
+ } catch (err) {return this.processError(err,state,"Input")}
+ //
+ // Put up final message, reset the state and return
+ //
+ if (state.scripts.length && this.config.showProcessingMessages)
+ {MathJax.Message.Set(["ProcessMath","Processing math: %1%%",100],0)}
+ state.start = new Date().getTime(); state.i = state.j = 0;
+ return null;
+ },
+ postInputHooks: MathJax.Callback.Hooks(true), // hooks to run after element jax is created
+ saveScript: function (jax,state,script,STATE) {
+ //
+ // Check that output jax exists
+ //
+ if (!this.outputJax[jax.mimeType]) {
+ script.MathJax.state = STATE.UPDATE;
+ throw Error("No output jax registered for "+jax.mimeType);
+ }
+ //
+ // Record the output jax
+ // and put this script in the queue for that jax
+ //
+ jax.outputJax = this.outputJax[jax.mimeType][0].id;
+ if (!state.jax[jax.outputJax]) {
+ if (state.jaxIDs.length === 0) {
+ // use original array until we know there are more (rather than two copies)
+ state.jax[jax.outputJax] = state.scripts;
+ } else {
+ if (state.jaxIDs.length === 1) // get the script so far for the existing jax
+ {state.jax[state.jaxIDs[0]] = state.scripts.slice(0,state.i)}
+ state.jax[jax.outputJax] = []; // start a new array for the new jax
+ }
+ state.jaxIDs.push(jax.outputJax); // save the ID of the jax
+ }
+ if (state.jaxIDs.length > 1) {state.jax[jax.outputJax].push(script)}
+ //
+ // Mark script as needing output
+ //
+ script.MathJax.state = STATE.OUTPUT;
+ },
+
+ //
+ // Pre- and post-process scripts by jax
+ // (to get scaling factors, hide/show output, and so on)
+ // Since this can cause the jax to load, we need to trap restarts
+ //
+ prepareOutput: function (state,method) {
+ while (state.j < state.jaxIDs.length) {
+ var id = state.jaxIDs[state.j], JAX = MathJax.OutputJax[id];
+ if (JAX[method]) {
+ try {
+ var result = JAX[method](state);
+ if (typeof result === 'function') {
+ if (result.called) continue; // go back and try again
+ this.RestartAfter(result);
+ }
+ } catch (err) {
+ if (!err.restart) {
+ MathJax.Message.Set(["PrepError","Error preparing %1 output (%2)",id,method],null,600);
+ MathJax.Hub.lastPrepError = err;
+ state.j++;
+ }
+ return MathJax.Callback.After(["prepareOutput",this,state,method],err.restart);
+ }
+ }
+ state.j++;
+ }
+ return null;
+ },
+
+ processOutput: function (state) {
+ var result, STATE = MathJax.ElementJax.STATE, script, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ //
+ // Check that there is an element jax
+ //
+ script = state.scripts[state.i];
+ if (!script || !script.MathJax || script.MathJax.error) {state.i++; continue}
+ var jax = script.MathJax.elementJax; if (!jax) {state.i++; continue}
+ //
+ // Call the output Jax's Process method (which will be its Translate()
+ // method once loaded). Mark it as complete and remove the preview unless
+ // the Process() call returns an explicit false value (in which case, it will
+ // handle this later during the postProcess phase, as HTML-CSS does).
+ //
+ result = MathJax.OutputJax[jax.outputJax].Process(script,state);
+ if (result !== false) {
+ script.MathJax.state = STATE.PROCESSED;
+ if (script.MathJax.preview) {script.MathJax.preview.innerHTML = ""}
+ //
+ // Signal that new math is available
+ //
+ this.signal.Post(["New Math",jax.inputID]); // FIXME: wait for this? (i.e., restart if returns uncalled callback)
+ }
+ //
+ // Go on to next math expression
+ //
+ state.i++;
+ //
+ // Update the processing message, if needed
+ //
+ var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(this.processUpdateDelay))}
+ }
+ } catch (err) {return this.processError(err,state,"Output")}
+ //
+ // Put up the typesetting-complete message
+ //
+ if (state.scripts.length && this.config.showProcessingMessages) {
+ MathJax.Message.Set(["TypesetMath","Typesetting math: %1%%",100],0);
+ MathJax.Message.Clear(0);
+ }
+ state.i = state.j = 0;
+ return null;
+ },
+
+ processMessage: function (state,type) {
+ var m = Math.floor(state.i/(state.scripts.length)*100);
+ var message = (type === "Output" ? ["TypesetMath","Typesetting math: %1%%"] :
+ ["ProcessMath","Processing math: %1%%"]);
+ if (this.config.showProcessingMessages) {MathJax.Message.Set(message.concat(m),0)}
+ },
+
+ processError: function (err,state,type) {
+ if (!err.restart) {
+ if (!this.config.errorSettings.message) {throw err}
+ this.formatError(state.scripts[state.i],err); state.i++;
+ }
+ this.processMessage(state,type);
+ return MathJax.Callback.After(["process"+type,this,state],err.restart);
+ },
+
+ formatError: function (script,err) {
+ var LOCALIZE = function (id,text,arg1,arg2) {return MathJax.Localization._(id,text,arg1,arg2)};
+ //
+ // Get the error message, URL, and line, and save it for
+ // reporting in the Show Math As Error menu
+ //
+ var message = LOCALIZE("ErrorMessage","Error: %1",err.message)+"\n";
+ if (err.sourceURL||err.fileName) message += "\n"+LOCALIZE("ErrorFile","file: %1",err.sourceURL||err.fileName);
+ if (err.line||err.lineNumber) message += "\n"+LOCALIZE("ErrorLine","line: %1",err.line||err.lineNumber);
+ message += "\n\n"+LOCALIZE("ErrorTips","Debugging tips: use %1, inspect %2 in the browser console","'unpacked/MathJax.js'","'MathJax.Hub.lastError'");
+ script.MathJax.error = MathJax.OutputJax.Error.Jax(message,script);
+ if (script.MathJax.elementJax)
+ script.MathJax.error.inputID = script.MathJax.elementJax.inputID;
+ //
+ // Create the [Math Processing Error] span
+ //
+ var errorSettings = this.config.errorSettings;
+ var errorText = LOCALIZE(errorSettings.messageId,errorSettings.message);
+ var error = MathJax.HTML.Element("span", {
+ className:"MathJax_Error", jaxID:"Error", isMathJax:true,
+ id: script.MathJax.error.inputID+"-Frame"
+ },[["span",null,errorText]]);
+ //
+ // Attach the menu events
+ //
+ MathJax.Ajax.Require("[MathJax]/extensions/MathEvents.js",function () {
+ var EVENT = MathJax.Extension.MathEvents.Event,
+ HUB = MathJax.Hub;
+ error.oncontextmenu = EVENT.Menu;
+ error.onmousedown = EVENT.Mousedown;
+ error.onkeydown = EVENT.Keydown;
+ error.tabIndex = HUB.getTabOrder(HUB.getJaxFor(script));
+ });
+ //
+ // Insert the error into the page and remove any preview
+ //
+ var node = document.getElementById(error.id);
+ if (node) node.parentNode.removeChild(node);
+ script.parentNode.insertBefore(error,script);
+ if (script.MathJax.preview) {script.MathJax.preview.innerHTML = ""}
+ //
+ // Save the error for debugging purposes
+ // Report the error as a signal
+ //
+ this.lastError = err;
+ this.signal.Post(["Math Processing Error",script,err]);
+ },
+
+ RestartAfter: function (callback) {
+ throw this.Insert(Error("restart"),{restart: MathJax.Callback(callback)});
+ },
+
+ elementCallback: function (element,callback) {
+ if (callback == null && (element instanceof Array || typeof element === 'function'))
+ {try {MathJax.Callback(element); callback = element; element = null} catch(e) {}}
+ if (element == null) {element = this.config.elements || []}
+ if (this.isHTMLCollection(element)) {element = this.HTMLCollection2Array(element)}
+ if (!(element instanceof Array)) {element = [element]}
+ element = [].concat(element); // make a copy so the original isn't changed
+ for (var i = 0, m = element.length; i < m; i++)
+ {if (typeof(element[i]) === 'string') {element[i] = document.getElementById(element[i])}}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element.length == 0) {element.push(document.body)}
+ if (!callback) {callback = {}}
+ return {
+ count: element.length,
+ elements: (element.length === 1 ? element[0] : element),
+ callback: callback
+ };
+ },
+
+ elementScripts: function (element) {
+ var scripts = [];
+ if (element instanceof Array || this.isHTMLCollection(element)) {
+ for (var i = 0, m = element.length; i < m; i++) {
+ var alreadyDone = 0;
+ for (var j = 0; j < i && !alreadyDone; j++)
+ {alreadyDone = element[j].contains(element[i])}
+ if (!alreadyDone) scripts.push.apply(scripts,this.elementScripts(element[i]));
+ }
+ return scripts;
+ }
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element == null) {element = document.body}
+ if (element.tagName != null && element.tagName.toLowerCase() === "script") {return [element]}
+ scripts = element.getElementsByTagName("script");
+ if (this.msieHTMLCollectionBug) {scripts = this.HTMLCollection2Array(scripts)}
+ return scripts;
+ },
+
+ //
+ // IE8 fails to check "obj instanceof HTMLCollection" for some values of obj.
+ //
+ isHTMLCollection: function (obj) {
+ return ("HTMLCollection" in window && typeof(obj) === "object" && obj instanceof HTMLCollection);
+ },
+ //
+ // IE8 doesn't deal with HTMLCollection as an array, so convert to array
+ //
+ HTMLCollection2Array: function (nodes) {
+ if (!this.msieHTMLCollectionBug) {return [].slice.call(nodes)}
+ var NODES = [];
+ for (var i = 0, m = nodes.length; i < m; i++) {NODES[i] = nodes[i]}
+ return NODES;
+ },
+
+ Insert: function (dst,src) {
+ for (var id in src) {if (src.hasOwnProperty(id)) {
+ // allow for concatenation of arrays?
+ if (typeof src[id] === 'object' && !(src[id] instanceof Array) &&
+ (typeof dst[id] === 'object' || typeof dst[id] === 'function')) {
+ this.Insert(dst[id],src[id]);
+ } else {
+ dst[id] = src[id];
+ }
+ }}
+ return dst;
+ },
+
+ getTabOrder: function(script) {
+ return this.config.menuSettings.inTabOrder ? 0 : -1;
+ },
+
+ // Old browsers (e.g. Internet Explorer <= 8) do not support trim().
+ SplitList: ("trim" in String.prototype ?
+ function (list) {return list.trim().split(/\s+/)} :
+ function (list) {return list.replace(/^\s+/,'').
+ replace(/\s+$/,'').split(/\s+/)})
+};
+MathJax.Hub.Insert(MathJax.Hub.config.styles,MathJax.Message.styles);
+MathJax.Hub.Insert(MathJax.Hub.config.styles,{".MathJax_Error":MathJax.Hub.config.errorSettings.style});
+
+//
+// Storage area for extensions and preprocessors
+//
+MathJax.Extension = {};
+
+//
+// Hub Startup code
+//
+MathJax.Hub.Configured = MathJax.Callback({}); // called when configuration is complete
+MathJax.Hub.Startup = {
+ script: "", // the startup script from the SCRIPT call that loads MathJax.js
+ queue: MathJax.Callback.Queue(), // Queue used for startup actions
+ signal: MathJax.Callback.Signal("Startup"), // Signal used for startup events
+ params: {},
+
+ //
+ // Load the configuration files
+ //
+ Config: function () {
+ this.queue.Push(["Post",this.signal,"Begin Config"]);
+ //
+ // If a locale is given as a parameter,
+ // set the locale and the default menu value for the locale
+ //
+ if (this.params.locale) {
+ MathJax.Localization.resetLocale(this.params.locale);
+ MathJax.Hub.config.menuSettings.locale = this.params.locale;
+ }
+ //
+ // Run the config files, if any are given in the parameter list
+ //
+ if (this.params.config) {
+ var files = this.params.config.split(/,/);
+ for (var i = 0, m = files.length; i < m; i++) {
+ if (!files[i].match(/\.js$/)) {files[i] += ".js"}
+ this.queue.Push(["Require",MathJax.Ajax,this.URL("config",files[i])]);
+ }
+ }
+ //
+ // Perform author configuration from in-line MathJax = {...}
+ //
+ this.queue.Push(["Config",MathJax.Hub,MathJax.AuthorConfig]);
+ //
+ // Run the deprecated configuration script, if any (ignoring return value)
+ // Wait for the startup delay signal
+ // Run the mathjax-config blocks
+ // Load the files in the configuration's config array
+ //
+ if (this.script.match(/\S/)) {this.queue.Push(this.script+";\n1;")}
+ this.queue.Push(
+ ["ConfigDelay",this],
+ ["ConfigBlocks",this],
+ [function (THIS) {return THIS.loadArray(MathJax.Hub.config.config,"config",null,true)},this],
+ ["Post",this.signal,"End Config"]
+ );
+ },
+ //
+ // Return the delay callback
+ //
+ ConfigDelay: function () {
+ var delay = this.params.delayStartupUntil || MathJax.Hub.config.delayStartupUntil;
+ if (delay === "onload") {return this.onload}
+ if (delay === "configured") {return MathJax.Hub.Configured}
+ return delay;
+ },
+ //
+ // Run the scripts of type=text/x-mathjax-config
+ //
+ ConfigBlocks: function () {
+ var scripts = document.getElementsByTagName("script");
+ var last = null, queue = MathJax.Callback.Queue();
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var type = String(scripts[i].type).replace(/ /g,"");
+ if (type.match(/^text\/x-mathjax-config(;.*)?$/) && !type.match(/;executed=true/)) {
+ scripts[i].type += ";executed=true";
+ last = queue.Push(scripts[i].innerHTML+";\n1;");
+ }
+ }
+ return last;
+ },
+
+ //
+ // Read cookie and set up menu defaults
+ // (set the locale according to the cookie)
+ // (adjust the jax to accommodate renderer preferences)
+ //
+ Cookie: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Cookie"],
+ ["Get",MathJax.HTML.Cookie,"menu",MathJax.Hub.config.menuSettings],
+ [function (config) {
+ var SETTINGS = config.menuSettings;
+ if (SETTINGS.locale) MathJax.Localization.resetLocale(SETTINGS.locale);
+ var renderer = config.menuSettings.renderer, jax = config.jax;
+ if (renderer) {
+ var name = "output/"+renderer; jax.sort();
+ for (var i = 0, m = jax.length; i < m; i++) {
+ if (jax[i].substr(0,7) === "output/") break;
+ }
+ if (i == m-1) {jax.pop()} else {
+ while (i < m) {if (jax[i] === name) {jax.splice(i,1); break}; i++}
+ }
+ jax.unshift(name);
+ }
+ if (SETTINGS.CHTMLpreview != null) {
+ if (SETTINGS.FastPreview == null) SETTINGS.FastPreview = SETTINGS.CHTMLpreview;
+ delete SETTINGS.CHTMLpreview;
+ }
+ if (SETTINGS.FastPreview && !MathJax.Extension["fast-preview"])
+ MathJax.Hub.config.extensions.push("fast-preview.js");
+ if (config.menuSettings.assistiveMML && !MathJax.Extension.AssistiveMML)
+ MathJax.Hub.config.extensions.push("AssistiveMML.js");
+ },MathJax.Hub.config],
+ ["Post",this.signal,"End Cookie"]
+ );
+ },
+ //
+ // Setup stylesheets and extra styles
+ //
+ Styles: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Styles"],
+ ["loadArray",this,MathJax.Hub.config.styleSheets,"config"],
+ ["Styles",MathJax.Ajax,MathJax.Hub.config.styles],
+ ["Post",this.signal,"End Styles"]
+ );
+ },
+ //
+ // Load the input and output jax
+ //
+ Jax: function () {
+ var config = MathJax.Hub.config, jax = MathJax.Hub.outputJax;
+ // Save the order of the output jax since they are loading asynchronously
+ for (var i = 0, m = config.jax.length, k = 0; i < m; i++) {
+ var name = config.jax[i].substr(7);
+ if (config.jax[i].substr(0,7) === "output/" && jax.order[name] == null)
+ {jax.order[name] = k; k++}
+ }
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Jax"],
+ ["loadArray",this,config.jax,"jax","config.js"],
+ ["Post",this.signal,"End Jax"]
+ );
+ },
+ //
+ // Load the extensions
+ //
+ Extensions: function () {
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Extensions"],
+ ["loadArray",this,MathJax.Hub.config.extensions,"extensions"],
+ ["Post",this.signal,"End Extensions"]
+ );
+ },
+
+ //
+ // Initialize the Message system
+ //
+ Message: function () {
+ MathJax.Message.Init(true);
+ },
+
+ //
+ // Set the math menu renderer, if it isn't already
+ // (this must come after the jax are loaded)
+ //
+ Menu: function () {
+ var menu = MathJax.Hub.config.menuSettings, jax = MathJax.Hub.outputJax, registered;
+ for (var id in jax) {if (jax.hasOwnProperty(id)) {
+ if (jax[id].length) {registered = jax[id]; break}
+ }}
+ if (registered && registered.length) {
+ if (menu.renderer && menu.renderer !== registered[0].id)
+ {registered.unshift(MathJax.OutputJax[menu.renderer])}
+ menu.renderer = registered[0].id;
+ }
+ },
+
+ //
+ // Set the location to the designated hash position
+ //
+ Hash: function () {
+ if (MathJax.Hub.config.positionToHash && document.location.hash &&
+ document.body && document.body.scrollIntoView) {
+ var name = document.location.hash.substr(1);
+ var target = document.getElementById(name);
+ if (!target) {
+ var a = document.getElementsByTagName("a");
+ for (var i = 0, m = a.length; i < m; i++)
+ {if (a[i].name === name) {target = a[i]; break}}
+ }
+ if (target) {
+ while (!target.scrollIntoView) {target = target.parentNode}
+ target = this.HashCheck(target);
+ if (target && target.scrollIntoView)
+ {setTimeout(function () {target.scrollIntoView(true)},1)}
+ }
+ }
+ },
+ HashCheck: function (target) {
+ var jax = MathJax.Hub.getJaxFor(target);
+ if (jax && MathJax.OutputJax[jax.outputJax].hashCheck)
+ {target = MathJax.OutputJax[jax.outputJax].hashCheck(target)}
+ return target;
+ },
+
+ //
+ // Load the Menu and Zoom code, if it hasn't already been loaded.
+ // This is called after the initial typeset, so should no longer be
+ // competing with other page loads, but will make these available
+ // if needed later on.
+ //
+ MenuZoom: function () {
+ if (MathJax.Hub.config.showMathMenu) {
+ if (!MathJax.Extension.MathMenu) {
+ setTimeout(
+ function () {
+ MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/MathMenu.js",{}],
+ ["loadDomain",MathJax.Localization,"MathMenu"]
+ )
+ },1000
+ );
+ } else {
+ setTimeout(
+ MathJax.Callback(["loadDomain",MathJax.Localization,"MathMenu"]),
+ 1000
+ );
+ }
+ if (!MathJax.Extension.MathZoom) {
+ setTimeout(
+ MathJax.Callback(["Require",MathJax.Ajax,"[MathJax]/extensions/MathZoom.js",{}]),
+ 2000
+ );
+ }
+ }
+ },
+
+ //
+ // Setup the onload callback
+ //
+ onLoad: function () {
+ var onload = this.onload =
+ MathJax.Callback(function () {MathJax.Hub.Startup.signal.Post("onLoad")});
+ if (document.body && document.readyState)
+ if (MathJax.Hub.Browser.isMSIE) {
+ // IE can change from loading to interactive before
+ // full page is ready, so go with complete (even though
+ // that means we may have to wait longer).
+ if (document.readyState === "complete") {return [onload]}
+ } else if (document.readyState !== "loading") {return [onload]}
+ if (window.addEventListener) {
+ window.addEventListener("load",onload,false);
+ if (!this.params.noDOMContentEvent)
+ {window.addEventListener("DOMContentLoaded",onload,false)}
+ }
+ else if (window.attachEvent) {window.attachEvent("onload",onload)}
+ else {window.onload = onload}
+ return onload;
+ },
+
+ //
+ // Perform the initial typesetting (or skip if configuration says to)
+ //
+ Typeset: function (element,callback) {
+ if (MathJax.Hub.config.skipStartupTypeset) {return function () {}}
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Typeset"],
+ ["Typeset",MathJax.Hub,element,callback],
+ ["Post",this.signal,"End Typeset"]
+ );
+ },
+
+ //
+ // Create a URL in the MathJax hierarchy
+ //
+ URL: function (dir,name) {
+ if (!name.match(/^([a-z]+:\/\/|\[|\/)/)) {name = "[MathJax]/"+dir+"/"+name}
+ return name;
+ },
+
+ //
+ // Load an array of files, waiting for all of them
+ // to be loaded before going on
+ //
+ loadArray: function (files,dir,name,synchronous) {
+ if (files) {
+ if (!(files instanceof Array)) {files = [files]}
+ if (files.length) {
+ var queue = MathJax.Callback.Queue(), callback = {}, file;
+ for (var i = 0, m = files.length; i < m; i++) {
+ file = this.URL(dir,files[i]);
+ if (name) {file += "/" + name}
+ if (synchronous) {queue.Push(["Require",MathJax.Ajax,file,callback])}
+ else {queue.Push(MathJax.Ajax.Require(file,callback))}
+ }
+ return queue.Push({}); // wait for everything to finish
+ }
+ }
+ return null;
+ }
+
+};
+
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME], ROOT = "["+BASENAME+"]";
+ var HUB = BASE.Hub, AJAX = BASE.Ajax, CALLBACK = BASE.Callback;
+
+ var JAX = MathJax.Object.Subclass({
+ JAXFILE: "jax.js",
+ require: null, // array of files to load before jax.js is complete
+ config: {},
+ //
+ // Make a subclass and return an instance of it.
+ // (FIXME: should we replace config with a copy of the constructor's
+ // config? Otherwise all subclasses share the same config structure.)
+ //
+ Init: function (def,cdef) {
+ if (arguments.length === 0) {return this}
+ return (this.constructor.Subclass(def,cdef))();
+ },
+ //
+ // Augment by merging with class definition (not replacing)
+ //
+ Augment: function (def,cdef) {
+ var cObject = this.constructor, ndef = {};
+ if (def != null) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {
+ if (typeof def[id] === "function")
+ {cObject.protoFunction(id,def[id])} else {ndef[id] = def[id]}
+ }}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (def.toString !== cObject.prototype.toString && def.toString !== {}.toString)
+ {cObject.protoFunction('toString',def.toString)}
+ }
+ HUB.Insert(cObject.prototype,ndef);
+ cObject.Augment(null,cdef);
+ return this;
+ },
+ Translate: function (script,state) {
+ throw Error(this.directory+"/"+this.JAXFILE+" failed to define the Translate() method");
+ },
+ Register: function (mimetype) {},
+ Config: function () {
+ this.config = HUB.CombineConfig(this.id,this.config);
+ if (this.config.Augment) {this.Augment(this.config.Augment)}
+ },
+ Startup: function () {},
+ loadComplete: function (file) {
+ if (file === "config.js") {
+ return AJAX.loadComplete(this.directory+"/"+file);
+ } else {
+ var queue = CALLBACK.Queue();
+ queue.Push(
+ HUB.Register.StartupHook("End Config",{}), // wait until config complete
+ ["Post",HUB.Startup.signal,this.id+" Jax Config"],
+ ["Config",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Require"],
+ // Config may set the required and extensions array,
+ // so use functions to delay making the reference until needed
+ [function (THIS) {return MathJax.Hub.Startup.loadArray(THIS.require,this.directory)},this],
+ [function (config,id) {return MathJax.Hub.Startup.loadArray(config.extensions,"extensions/"+id)},this.config||{},this.id],
+ ["Post",HUB.Startup.signal,this.id+" Jax Startup"],
+ ["Startup",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Ready"]
+ );
+ if (this.copyTranslate) {
+ queue.Push(
+ [function (THIS) {
+ THIS.preProcess = THIS.preTranslate;
+ THIS.Process = THIS.Translate;
+ THIS.postProcess = THIS.postTranslate;
+ },this.constructor.prototype]
+ );
+ }
+ return queue.Push(["loadComplete",AJAX,this.directory+"/"+file]);
+ }
+ }
+ },{
+ id: "Jax",
+ version: "2.6.0",
+ directory: ROOT+"/jax",
+ extensionDir: ROOT+"/extensions"
+ });
+
+ /***********************************/
+
+ BASE.InputJax = JAX.Subclass({
+ elementJax: "mml", // the element jax to load for this input jax
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"],
+ copyTranslate: true,
+ Process: function (script,state) {
+ var queue = CALLBACK.Queue(), file;
+ // Load any needed element jax
+ var jax = this.elementJax; if (!(jax instanceof Array)) {jax = [jax]}
+ for (var i = 0, m = jax.length; i < m; i++) {
+ file = BASE.ElementJax.directory+"/"+jax[i]+"/"+this.JAXFILE;
+ if (!this.require) {this.require = []}
+ else if (!(this.require instanceof Array)) {this.require = [this.require]};
+ this.require.push(file); // so Startup will wait for it to be loaded
+ queue.Push(AJAX.Require(file));
+ }
+ // Load the input jax
+ file = this.directory+"/"+this.JAXFILE;
+ var load = queue.Push(AJAX.Require(file));
+ if (!load.called) {
+ this.constructor.prototype.Process = function () {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ }
+ // Load the associated output jax
+ jax = HUB.outputJax["jax/"+jax[0]];
+ if (jax) {queue.Push(AJAX.Require(jax[0].directory+"/"+this.JAXFILE))}
+ return queue.Push({});
+ },
+ needsUpdate: function (jax) {
+ var script = jax.SourceElement();
+ return (jax.originalText !== BASE.HTML.getScript(script));
+ },
+ Register: function (mimetype) {
+ if (!HUB.inputJax) {HUB.inputJax = {}}
+ HUB.inputJax[mimetype] = this;
+ }
+ },{
+ id: "InputJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/input",
+ extensionDir: JAX.extensionDir
+ });
+
+ /***********************************/
+
+ BASE.OutputJax = JAX.Subclass({
+ copyTranslate: true,
+ preProcess: function (state) {
+ var load, file = this.directory+"/"+this.JAXFILE;
+ this.constructor.prototype.preProcess = function (state) {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ load = AJAX.Require(file);
+ return load;
+ },
+ Register: function (mimetype) {
+ var jax = HUB.outputJax;
+ if (!jax[mimetype]) {jax[mimetype] = []}
+ // If the output jax is earlier in the original configuration list, put it first here
+ if (jax[mimetype].length && (this.id === HUB.config.menuSettings.renderer ||
+ (jax.order[this.id]||0) < (jax.order[jax[mimetype][0].id]||0)))
+ {jax[mimetype].unshift(this)} else {jax[mimetype].push(this)}
+ // Make sure the element jax is loaded before Startup is called
+ if (!this.require) {this.require = []}
+ else if (!(this.require instanceof Array)) {this.require = [this.require]};
+ this.require.push(BASE.ElementJax.directory+"/"+(mimetype.split(/\//)[1])+"/"+this.JAXFILE);
+ },
+ Remove: function (jax) {}
+ },{
+ id: "OutputJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/output",
+ extensionDir: JAX.extensionDir,
+ fontDir: ROOT+(BASE.isPacked?"":"/..")+"/fonts",
+ imageDir: ROOT+(BASE.isPacked?"":"/..")+"/images"
+ });
+
+ /***********************************/
+
+ BASE.ElementJax = JAX.Subclass({
+ // make a subclass, not an instance
+ Init: function (def,cdef) {return this.constructor.Subclass(def,cdef)},
+
+ inputJax: null,
+ outputJax: null,
+ inputID: null,
+ originalText: "",
+ mimeType: "",
+ sourceMenuTitle: /*_(MathMenu)*/ ["MathMLcode","MathML Code"],
+
+ Text: function (text,callback) {
+ var script = this.SourceElement();
+ BASE.HTML.setScript(script,text);
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Update(script,callback);
+ },
+ Reprocess: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Reprocess(script,callback);
+ },
+ Update: function (callback) {return this.Rerender(callback)},
+ Rerender: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.OUTPUT;
+ return HUB.Process(script,callback);
+ },
+ Remove: function (keep) {
+ if (this.hover) {this.hover.clear(this)}
+ BASE.OutputJax[this.outputJax].Remove(this);
+ if (!keep) {
+ HUB.signal.Post(["Remove Math",this.inputID]); // wait for this to finish?
+ this.Detach();
+ }
+ },
+ needsUpdate: function () {
+ return BASE.InputJax[this.inputJax].needsUpdate(this);
+ },
+
+ SourceElement: function () {return document.getElementById(this.inputID)},
+
+ Attach: function (script,inputJax) {
+ var jax = script.MathJax.elementJax;
+ if (script.MathJax.state === this.STATE.UPDATE) {
+ jax.Clone(this);
+ } else {
+ jax = script.MathJax.elementJax = this;
+ if (script.id) {this.inputID = script.id}
+ else {script.id = this.inputID = BASE.ElementJax.GetID(); this.newID = 1}
+ }
+ jax.originalText = BASE.HTML.getScript(script);
+ jax.inputJax = inputJax;
+ if (jax.root) {jax.root.inputID = jax.inputID}
+ return jax;
+ },
+ Detach: function () {
+ var script = this.SourceElement(); if (!script) return;
+ try {delete script.MathJax} catch(err) {script.MathJax = null}
+ if (this.newID) {script.id = ""}
+ },
+ Clone: function (jax) {
+ var id;
+ for (id in this) {
+ if (!this.hasOwnProperty(id)) continue;
+ if (typeof(jax[id]) === 'undefined' && id !== 'newID') {delete this[id]}
+ }
+ for (id in jax) {
+ if (!jax.hasOwnProperty(id)) continue;
+ if (typeof(this[id]) === 'undefined' || (this[id] !== jax[id] && id !== 'inputID'))
+ {this[id] = jax[id]}
+ }
+ }
+ },{
+ id: "ElementJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/element",
+ extensionDir: JAX.extensionDir,
+ ID: 0, // jax counter (for IDs)
+ STATE: {
+ PENDING: 1, // script is identified as math but not yet processed
+ PROCESSED: 2, // script has been processed
+ UPDATE: 3, // elementJax should be updated
+ OUTPUT: 4 // output should be updated (input is OK)
+ },
+
+ GetID: function () {this.ID++; return "MathJax-Element-"+this.ID},
+ Subclass: function () {
+ var obj = JAX.Subclass.apply(this,arguments);
+ obj.loadComplete = this.prototype.loadComplete;
+ return obj;
+ }
+ });
+ BASE.ElementJax.prototype.STATE = BASE.ElementJax.STATE;
+
+ //
+ // Some "Fake" jax used to allow menu access for "Math Processing Error" messages
+ //
+ BASE.OutputJax.Error = {
+ id: "Error", version: "2.6.0", config: {}, errors: 0,
+ ContextMenu: function () {return BASE.Extension.MathEvents.Event.ContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ Mousedown: function () {return BASE.Extension.MathEvents.Event.AltContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ getJaxFromMath: function (math) {return (math.nextSibling.MathJax||{}).error},
+ Jax: function (text,script) {
+ var jax = MathJax.Hub.inputJax[script.type.replace(/ *;(.|\s)*/,"")];
+ this.errors++;
+ return {
+ inputJax: (jax||{id:"Error"}).id, // Use Error InputJax as fallback
+ outputJax: "Error",
+ inputID: "MathJax-Error-"+this.errors,
+ sourceMenuTitle: /*_(MathMenu)*/ ["ErrorMessage","Error Message"],
+ sourceMenuFormat: "Error",
+ originalText: MathJax.HTML.getScript(script),
+ errorText: text
+ }
+ }
+ };
+ BASE.InputJax.Error = {
+ id: "Error", version: "2.6.0", config: {},
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"]
+ };
+
+})("MathJax");
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var HUB = BASE.Hub; var STARTUP = HUB.Startup; var CONFIG = HUB.config;
+ var HEAD = document.head || (document.getElementsByTagName("head")[0]);
+ if (!HEAD) {HEAD = document.childNodes[0]};
+ var scripts = (document.documentElement || document).getElementsByTagName("script");
+ if (scripts.length === 0 && HEAD.namespaceURI)
+ scripts = document.getElementsByTagNameNS(HEAD.namespaceURI,"script");
+ var namePattern = new RegExp("(^|/)"+BASENAME+"\\.js(\\?.*)?$");
+ for (var i = scripts.length-1; i >= 0; i--) {
+ if ((scripts[i].src||"").match(namePattern)) {
+ STARTUP.script = scripts[i].innerHTML;
+ if (RegExp.$2) {
+ var params = RegExp.$2.substr(1).split(/\&/);
+ for (var j = 0, m = params.length; j < m; j++) {
+ var KV = params[j].match(/(.*)=(.*)/);
+ if (KV) {STARTUP.params[unescape(KV[1])] = unescape(KV[2])}
+ }
+ }
+ CONFIG.root = scripts[i].src.replace(/(^|\/)[^\/]*(\?.*)?$/,'')
+ // convert mathjax/latest to mathjax/x.y-latest so that all files are the same version
+ .replace(/^(https?:\/\/cdn.mathjax.org\/mathjax\/)(latest)/,"$1"+BASE.version.split(/\./).slice(0,2).join(".")+"-$2");
+ BASE.Ajax.config.root = CONFIG.root;
+ break;
+ }
+ }
+
+ var AGENT = navigator.userAgent;
+ var BROWSERS = {
+ isMac: (navigator.platform.substr(0,3) === "Mac"),
+ isPC: (navigator.platform.substr(0,3) === "Win"),
+ isMSIE: ("ActiveXObject" in window && "clipboardData" in window),
+ isEdge: ("MSGestureEvent" in window && "chrome" in window &&
+ window.chrome.loadTimes == null),
+ isFirefox: (!!AGENT.match(/Gecko\//) && !AGENT.match(/like Gecko/)),
+ isSafari: (!!AGENT.match(/ (Apple)?WebKit\//) && !AGENT.match(/ like iPhone /) &&
+ (!window.chrome || window.chrome.app == null)),
+ isChrome: ("chrome" in window && window.chrome.loadTimes != null),
+ isOpera: ("opera" in window && window.opera.version != null),
+ isKonqueror: ("konqueror" in window && navigator.vendor == "KDE"),
+ versionAtLeast: function (v) {
+ var bv = (this.version).split('.'); v = (new String(v)).split('.');
+ for (var i = 0, m = v.length; i < m; i++)
+ {if (bv[i] != v[i]) {return parseInt(bv[i]||"0") >= parseInt(v[i])}}
+ return true;
+ },
+ Select: function (choices) {
+ var browser = choices[HUB.Browser];
+ if (browser) {return browser(HUB.Browser)}
+ return null;
+ }
+ };
+
+ var xAGENT = AGENT
+ .replace(/^Mozilla\/(\d+\.)+\d+ /,"") // remove initial Mozilla, which is never right
+ .replace(/[a-z][-a-z0-9._: ]+\/\d+[^ ]*-[^ ]*\.([a-z][a-z])?\d+ /i,"") // remove linux version
+ .replace(/Gentoo |Ubuntu\/(\d+\.)*\d+ (\([^)]*\) )?/,""); // special case for these
+
+ HUB.Browser = HUB.Insert(HUB.Insert(new String("Unknown"),{version: "0.0"}),BROWSERS);
+ for (var browser in BROWSERS) {if (BROWSERS.hasOwnProperty(browser)) {
+ if (BROWSERS[browser] && browser.substr(0,2) === "is") {
+ browser = browser.slice(2);
+ if (browser === "Mac" || browser === "PC") continue;
+ HUB.Browser = HUB.Insert(new String(browser),BROWSERS);
+ var VERSION = new RegExp(
+ ".*(Version/| Trident/.*; rv:)((?:\\d+\\.)+\\d+)|" + // for Safari, Opera10, and IE11+
+ ".*("+browser+")"+(browser == "MSIE" ? " " : "/")+"((?:\\d+\\.)*\\d+)|"+ // for one of the main browsers
+ "(?:^|\\(| )([a-z][-a-z0-9._: ]+|(?:Apple)?WebKit)/((?:\\d+\\.)+\\d+)"); // for unrecognized browser
+ var MATCH = VERSION.exec(xAGENT) || ["","","","unknown","0.0"];
+ HUB.Browser.name = (MATCH[1] != "" ? browser : (MATCH[3] || MATCH[5]));
+ HUB.Browser.version = MATCH[2] || MATCH[4] || MATCH[6];
+ break;
+ }
+ }};
+
+ //
+ // Initial browser-specific info (e.g., touch up version or name, check for MathPlayer, etc.)
+ // Wrap in try/catch just in case of error (see issue #1155).
+ //
+ try {HUB.Browser.Select({
+ Safari: function (browser) {
+ var v = parseInt((String(browser.version).split("."))[0]);
+ if (v > 85) {browser.webkit = browser.version}
+ if (v >= 538) {browser.version = "8.0"}
+ else if (v >= 537) {browser.version = "7.0"}
+ else if (v >= 536) {browser.version = "6.0"}
+ else if (v >= 534) {browser.version = "5.1"}
+ else if (v >= 533) {browser.version = "5.0"}
+ else if (v >= 526) {browser.version = "4.0"}
+ else if (v >= 525) {browser.version = "3.1"}
+ else if (v > 500) {browser.version = "3.0"}
+ else if (v > 400) {browser.version = "2.0"}
+ else if (v > 85) {browser.version = "1.0"}
+ browser.webkit = (navigator.appVersion.match(/WebKit\/(\d+)\./))[1];
+ browser.isMobile = (navigator.appVersion.match(/Mobile/i) != null);
+ browser.noContextMenu = browser.isMobile;
+ },
+ Firefox: function (browser) {
+ if ((browser.version === "0.0" || AGENT.match(/Firefox/) == null) &&
+ navigator.product === "Gecko") {
+ var rv = AGENT.match(/[\/ ]rv:(\d+\.\d.*?)[\) ]/);
+ if (rv) {browser.version = rv[1]}
+ else {
+ var date = (navigator.buildID||navigator.productSub||"0").substr(0,8);
+ if (date >= "20111220") {browser.version = "9.0"}
+ else if (date >= "20111120") {browser.version = "8.0"}
+ else if (date >= "20110927") {browser.version = "7.0"}
+ else if (date >= "20110816") {browser.version = "6.0"}
+ else if (date >= "20110621") {browser.version = "5.0"}
+ else if (date >= "20110320") {browser.version = "4.0"}
+ else if (date >= "20100121") {browser.version = "3.6"}
+ else if (date >= "20090630") {browser.version = "3.5"}
+ else if (date >= "20080617") {browser.version = "3.0"}
+ else if (date >= "20061024") {browser.version = "2.0"}
+ }
+ }
+ browser.isMobile = (navigator.appVersion.match(/Android/i) != null ||
+ AGENT.match(/ Fennec\//) != null ||
+ AGENT.match(/Mobile/) != null);
+ },
+ Chrome: function (browser) {
+ browser.noContextMenu = browser.isMobile = !!navigator.userAgent.match(/ Mobile[ \/]/);
+ },
+ Opera: function (browser) {browser.version = opera.version()},
+ Edge: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ },
+ MSIE: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ browser.isIE9 = !!(document.documentMode && (window.performance || window.msPerformance));
+ MathJax.HTML.setScriptBug = !browser.isIE9 || document.documentMode < 9;
+ MathJax.Hub.msieHTMLCollectionBug = (document.documentMode < 9);
+ //
+ // MathPlayer doesn't function properly in IE10, and not at all in IE11,
+ // so don't even try to load it.
+ //
+ if (document.documentMode < 10 && !STARTUP.params.NoMathPlayer) {
+ try {
+ new ActiveXObject("MathPlayer.Factory.1");
+ browser.hasMathPlayer = true;
+ } catch (err) {}
+ try {
+ if (browser.hasMathPlayer) {
+ var mathplayer = document.createElement("object");
+ mathplayer.id = "mathplayer"; mathplayer.classid = "clsid:32F66A20-7614-11D4-BD11-00104BD3F987";
+ HEAD.appendChild(mathplayer);
+ document.namespaces.add("m","http://www.w3.org/1998/Math/MathML");
+ browser.mpNamespace = true;
+ if (document.readyState && (document.readyState === "loading" ||
+ document.readyState === "interactive")) {
+ document.write('');
+ browser.mpImported = true;
+ }
+ } else {
+ // Adding any namespace avoids a crash in IE9 in IE9-standards mode
+ // (any reference to document.namespaces before document.readyState is
+ // "complete" causes an "unspecified error" to be thrown)
+ document.namespaces.add("mjx_IE_fix","http://www.w3.org/1999/xlink");
+ }
+ } catch (err) {}
+ }
+ }
+ });} catch (err) {
+ console.error(err.message);
+ }
+ HUB.Browser.Select(MathJax.Message.browsers);
+
+ if (BASE.AuthorConfig && typeof BASE.AuthorConfig.AuthorInit === "function") {BASE.AuthorConfig.AuthorInit()}
+ HUB.queue = BASE.Callback.Queue();
+ HUB.queue.Push(
+ ["Post",STARTUP.signal,"Begin"],
+ ["Config",STARTUP],
+ ["Cookie",STARTUP],
+ ["Styles",STARTUP],
+ ["Message",STARTUP],
+ function () {
+ // Do Jax and Extensions in parallel, but wait for them all to complete
+ var queue = BASE.Callback.Queue(
+ STARTUP.Jax(),
+ STARTUP.Extensions()
+ );
+ return queue.Push({});
+ },
+ ["Menu",STARTUP],
+ STARTUP.onLoad(),
+ function () {MathJax.isReady = true}, // indicates that MathJax is ready to process math
+ ["Typeset",STARTUP],
+ ["Hash",STARTUP],
+ ["MenuZoom",STARTUP],
+ ["Post",STARTUP.signal,"End"]
+ );
+
+})("MathJax");
+
+}}
diff --git a/MarkDownEditor/MathJax/config/TEX_CHTML.js b/MarkDownEditor/MathJax/config/TEX_CHTML.js
new file mode 100644
index 0000000..e4fed61
--- /dev/null
+++ b/MarkDownEditor/MathJax/config/TEX_CHTML.js
@@ -0,0 +1,8 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+MathJax.Hub.Config({
+ extensions: ["tex2jax.js","MathEvents.js","MathZoom.js","MathMenu.js","TeX/noErrors.js","TeX/noUndefined.js","TeX/AMSmath.js","TeX/AMSsymbols.js","fast-preview.js"],
+ jax: ["input/TeX","output/PreviewHTML"]
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/config/TEX_CHTML.js");
diff --git a/MarkDownEditor/MathJax/extensions/MathEvents.js b/MarkDownEditor/MathJax/extensions/MathEvents.js
new file mode 100644
index 0000000..0c106d6
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/MathEvents.js
@@ -0,0 +1,619 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathEvents.js
+ *
+ * Implements the event handlers needed by the output jax to perform
+ * menu, hover, and other events.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2011-2015 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.
+ */
+
+(function (HUB,HTML,AJAX,CALLBACK,LOCALE,OUTPUT,INPUT) {
+ var VERSION = "2.6.0";
+
+ var EXTENSION = MathJax.Extension;
+ var ME = EXTENSION.MathEvents = {version: VERSION};
+
+ var SETTINGS = HUB.config.menuSettings;
+
+ var CONFIG = {
+ hover: 500, // time required to be considered a hover
+ frame: {
+ x: 3.5, y: 5, // frame padding and
+ bwidth: 1, // frame border width (in pixels)
+ bcolor: "#A6D", // frame border color
+ hwidth: "15px", // haze width
+ hcolor: "#83A" // haze color
+ },
+ button: {
+ x: -6, y: -3, // menu button offsets
+ wx: -2 // button offset for full-width equations
+ },
+ fadeinInc: .2, // increment for fade-in
+ fadeoutInc: .05, // increment for fade-out
+ fadeDelay: 50, // delay between fade-in or fade-out steps
+ fadeoutStart: 400, // delay before fade-out after mouseout
+ fadeoutDelay: 15*1000, // delay before automatic fade-out
+
+ styles: {
+ ".MathJax_Hover_Frame": {
+ "border-radius": ".25em", // Opera 10.5 and IE9
+ "-webkit-border-radius": ".25em", // Safari and Chrome
+ "-moz-border-radius": ".25em", // Firefox
+ "-khtml-border-radius": ".25em", // Konqueror
+
+ "box-shadow": "0px 0px 15px #83A", // Opera 10.5 and IE9
+ "-webkit-box-shadow": "0px 0px 15px #83A", // Safari and Chrome
+ "-moz-box-shadow": "0px 0px 15px #83A", // Forefox
+ "-khtml-box-shadow": "0px 0px 15px #83A", // Konqueror
+
+ border: "1px solid #A6D ! important",
+ display: "inline-block", position:"absolute"
+ },
+
+ ".MathJax_Menu_Button .MathJax_Hover_Arrow": {
+ position:"absolute",
+ cursor:"pointer",
+ display:"inline-block",
+ border:"2px solid #AAA",
+ "border-radius":"4px",
+ "-webkit-border-radius": "4px", // Safari and Chrome
+ "-moz-border-radius": "4px", // Firefox
+ "-khtml-border-radius": "4px", // Konqueror
+ "font-family":"'Courier New',Courier",
+ "font-size":"9px",
+ color:"#F0F0F0"
+ },
+ ".MathJax_Menu_Button .MathJax_Hover_Arrow span": {
+ display:"block",
+ "background-color":"#AAA",
+ border:"1px solid",
+ "border-radius":"3px",
+ "line-height":0,
+ padding:"4px"
+ },
+ ".MathJax_Hover_Arrow:hover": {
+ color:"white!important",
+ border:"2px solid #CCC!important"
+ },
+ ".MathJax_Hover_Arrow:hover span": {
+ "background-color":"#CCC!important"
+ }
+ }
+ };
+
+
+ //
+ // Common event-handling code
+ //
+ var EVENT = ME.Event = {
+
+ LEFTBUTTON: 0, // the event.button value for left button
+ RIGHTBUTTON: 2, // the event.button value for right button
+ MENUKEY: "altKey", // the event value for alternate context menu
+
+ /*************************************************************/
+ /*
+ * Enum element for key codes.
+ */
+ KEY: {
+ RETURN: 13,
+ ESCAPE: 27,
+ SPACE: 32,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40
+ },
+
+ Mousedown: function (event) {return EVENT.Handler(event,"Mousedown",this)},
+ Mouseup: function (event) {return EVENT.Handler(event,"Mouseup",this)},
+ Mousemove: function (event) {return EVENT.Handler(event,"Mousemove",this)},
+ Mouseover: function (event) {return EVENT.Handler(event,"Mouseover",this)},
+ Mouseout: function (event) {return EVENT.Handler(event,"Mouseout",this)},
+ Click: function (event) {return EVENT.Handler(event,"Click",this)},
+ DblClick: function (event) {return EVENT.Handler(event,"DblClick",this)},
+ Menu: function (event) {return EVENT.Handler(event,"ContextMenu",this)},
+
+ //
+ // Call the output jax's event handler or the zoom handler
+ //
+ Handler: function (event,type,math) {
+ if (AJAX.loadingMathMenu) {return EVENT.False(event)}
+ var jax = OUTPUT[math.jaxID];
+ if (!event) {event = window.event}
+ event.isContextMenu = (type === "ContextMenu");
+ if (jax[type]) {return jax[type](event,math)}
+ if (EXTENSION.MathZoom) {return EXTENSION.MathZoom.HandleEvent(event,type,math)}
+ },
+
+ //
+ // Try to cancel the event in every way we can
+ //
+ False: function (event) {
+ if (!event) {event = window.event}
+ if (event) {
+ if (event.preventDefault) {event.preventDefault()} else {event.returnValue = false}
+ if (event.stopPropagation) {event.stopPropagation()}
+ event.cancelBubble = true;
+ }
+ return false;
+ },
+
+ //
+ // Keydown event handler. Should only fire on Space key.
+ //
+ Keydown: function (event, math) {
+ if (!event) event = window.event;
+ if (event.keyCode === EVENT.KEY.SPACE) {
+ EVENT.ContextMenu(event, this);
+ };
+ },
+
+ //
+ // Load the contextual menu code, if needed, and post the menu
+ //
+ ContextMenu: function (event,math,force) {
+ //
+ // Check if we are showing menus
+ //
+ var JAX = OUTPUT[math.jaxID], jax = JAX.getJaxFromMath(math);
+ var show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ if (!show || (SETTINGS.context !== "MathJax" && !force)) return;
+
+ //
+ // Remove selections, remove hover fades
+ //
+ if (ME.msieEventBug) {event = window.event || event}
+ EVENT.ClearSelection(); HOVER.ClearHoverTimer();
+ if (jax.hover) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove); delete jax.hover.remove}
+ jax.hover.nofade = true;
+ }
+
+ //
+ // If the menu code is loaded,
+ // Check if localization needs loading;
+ // If not, post the menu, and return.
+ // Otherwise wait for the localization to load
+ // Otherwse load the menu code.
+ // Try again after the file is loaded.
+ //
+ var MENU = MathJax.Menu; var load, fn;
+ if (MENU) {
+ if (MENU.loadingDomain) {return EVENT.False(event)}
+ load = LOCALE.loadDomain("MathMenu");
+ if (!load) {
+ MENU.jax = jax;
+ var source = MENU.menu.Find("Show Math As").submenu;
+ source.items[0].name = jax.sourceMenuTitle;
+ source.items[0].format = (jax.sourceMenuFormat||"MathML");
+ source.items[1].name = INPUT[jax.inputJax].sourceMenuTitle;
+ source.items[5].disabled = !INPUT[jax.inputJax].annotationEncoding;
+
+ //
+ // Try and find each known annotation format and enable the menu
+ // items accordingly.
+ //
+ var annotations = source.items[2]; annotations.disabled = true;
+ var annotationItems = annotations.submenu.items;
+ annotationList = MathJax.Hub.Config.semanticsAnnotations;
+ for (var i = 0, m = annotationItems.length; i < m; i++) {
+ var name = annotationItems[i].name[1]
+ if (jax.root && jax.root.getAnnotation(name) !== null) {
+ annotations.disabled = false;
+ annotationItems[i].hidden = false;
+ } else {
+ annotationItems[i].hidden = true;
+ }
+ }
+
+ var MathPlayer = MENU.menu.Find("Math Settings","MathPlayer");
+ MathPlayer.hidden = !(jax.outputJax === "NativeMML" && HUB.Browser.hasMathPlayer);
+ return MENU.menu.Post(event);
+ }
+ MENU.loadingDomain = true;
+ fn = function () {delete MENU.loadingDomain};
+ } else {
+ if (AJAX.loadingMathMenu) {return EVENT.False(event)}
+ AJAX.loadingMathMenu = true;
+ load = AJAX.Require("[MathJax]/extensions/MathMenu.js");
+ fn = function () {
+ delete AJAX.loadingMathMenu;
+ if (!MathJax.Menu) {MathJax.Menu = {}}
+ }
+ }
+ var ev = {
+ pageX:event.pageX, pageY:event.pageY,
+ clientX:event.clientX, clientY:event.clientY
+ };
+ CALLBACK.Queue(
+ load, fn, // load the file and delete the marker when done
+ ["ContextMenu",EVENT,ev,math,force] // call this function again
+ );
+ return EVENT.False(event);
+ },
+
+ //
+ // Mousedown handler for alternate means of accessing menu
+ //
+ AltContextMenu: function (event,math) {
+ var JAX = OUTPUT[math.jaxID];
+ var show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ if (show) {
+ show = (JAX.config.showMathMenuMSIE != null ? JAX : HUB).config.showMathMenuMSIE;
+ if (SETTINGS.context === "MathJax" && !SETTINGS.mpContext && show) {
+ if (!ME.noContextMenuBug || event.button !== EVENT.RIGHTBUTTON) return;
+ } else {
+ if (!event[EVENT.MENUKEY] || event.button !== EVENT.LEFTBUTTON) return;
+ }
+ return JAX.ContextMenu(event,math,true);
+ }
+ },
+
+ ClearSelection: function () {
+ if (ME.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)}
+ if (document.selection) {setTimeout("document.selection.empty()",0)}
+ },
+
+ getBBox: function (span) {
+ span.appendChild(ME.topImg);
+ var h = ME.topImg.offsetTop, d = span.offsetHeight-h, w = span.offsetWidth;
+ span.removeChild(ME.topImg);
+ return {w:w, h:h, d:d};
+ }
+
+ };
+
+ //
+ // Handle hover "discoverability"
+ //
+ var HOVER = ME.Hover = {
+
+ //
+ // Check if we are moving from a non-MathJax element to a MathJax one
+ // and either start fading in again (if it is fading out) or start the
+ // timer for the hover
+ //
+ Mouseover: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && (HUB.isMathJaxNode(from) !== HUB.isMathJaxNode(to) ||
+ HUB.getJaxFor(from) !== HUB.getJaxFor(to))) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {HOVER.ReHover(jax)} else {HOVER.HoverTimer(jax,math)}
+ return EVENT.False(event);
+ }
+ }
+ },
+ //
+ // Check if we are moving from a MathJax element to a non-MathJax one
+ // and either start fading out, or clear the timer if we haven't
+ // hovered yet
+ //
+ Mouseout: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var from = event.fromElement || event.relatedTarget,
+ to = event.toElement || event.target;
+ if (from && to && (HUB.isMathJaxNode(from) !== HUB.isMathJaxNode(to) ||
+ HUB.getJaxFor(from) !== HUB.getJaxFor(to))) {
+ var jax = this.getJaxFromMath(math);
+ if (jax.hover) {HOVER.UnHover(jax)} else {HOVER.ClearHoverTimer()}
+ return EVENT.False(event);
+ }
+ }
+ },
+ //
+ // Restart hover timer if the mouse moves
+ //
+ Mousemove: function (event,math) {
+ if (SETTINGS.discoverable || SETTINGS.zoom === "Hover") {
+ var jax = this.getJaxFromMath(math); if (jax.hover) return;
+ if (HOVER.lastX == event.clientX && HOVER.lastY == event.clientY) return;
+ HOVER.lastX = event.clientX; HOVER.lastY = event.clientY;
+ HOVER.HoverTimer(jax,math);
+ return EVENT.False(event);
+ }
+ },
+
+ //
+ // Clear the old timer and start a new one
+ //
+ HoverTimer: function (jax,math) {
+ this.ClearHoverTimer();
+ this.hoverTimer = setTimeout(CALLBACK(["Hover",this,jax,math]),CONFIG.hover);
+ },
+ ClearHoverTimer: function () {
+ if (this.hoverTimer) {clearTimeout(this.hoverTimer); delete this.hoverTimer}
+ },
+
+ //
+ // Handle putting up the hover frame
+ //
+ Hover: function (jax,math) {
+ //
+ // Check if Zoom handles the hover event
+ //
+ if (EXTENSION.MathZoom && EXTENSION.MathZoom.Hover({},math)) return;
+ //
+ // Get the hover data
+ //
+ var JAX = OUTPUT[jax.outputJax],
+ span = JAX.getHoverSpan(jax,math),
+ bbox = JAX.getHoverBBox(jax,span,math),
+ show = (JAX.config.showMathMenu != null ? JAX : HUB).config.showMathMenu;
+ var dx = CONFIG.frame.x, dy = CONFIG.frame.y, dd = CONFIG.frame.bwidth; // frame size
+ if (ME.msieBorderWidthBug) {dd = 0}
+ jax.hover = {opacity:0, id:jax.inputID+"-Hover"};
+ //
+ // The frame and menu button
+ //
+ var frame = HTML.Element("span",{
+ id:jax.hover.id, isMathJax: true,
+ style:{display:"inline-block", width:0, height:0, position:"relative"}
+ },[["span",{
+ className:"MathJax_Hover_Frame", isMathJax: true,
+ style:{
+ display:"inline-block", position:"absolute",
+ top:this.Px(-bbox.h-dy-dd-(bbox.y||0)), left:this.Px(-dx-dd+(bbox.x||0)),
+ width:this.Px(bbox.w+2*dx), height:this.Px(bbox.h+bbox.d+2*dy),
+ opacity:0, filter:"alpha(opacity=0)"
+ }}
+ ]]
+ );
+ var button = HTML.Element("span",{
+ isMathJax: true, id:jax.hover.id+"Menu", className:"MathJax_Menu_Button",
+ style:{display:"inline-block", "z-index": 1, width:0, height:0, position:"relative"}
+ },[["span",{
+ className: "MathJax_Hover_Arrow", isMathJax: true, math: math,
+ onclick: this.HoverMenu, jax:JAX.id,
+ style: {
+ left:this.Px(bbox.w+dx+dd+(bbox.x||0)+CONFIG.button.x),
+ top:this.Px(-bbox.h-dy-dd-(bbox.y||0)-CONFIG.button.y),
+ opacity:0, filter:"alpha(opacity=0)"
+ }
+ },[["span",{isMathJax:true},"\u25BC"]]]]
+ );
+ if (bbox.width) {
+ frame.style.width = button.style.width = bbox.width;
+ frame.style.marginRight = button.style.marginRight = "-"+bbox.width;
+ frame.firstChild.style.width = bbox.width;
+ button.firstChild.style.left = "";
+ button.firstChild.style.right = this.Px(CONFIG.button.wx);
+ }
+ //
+ // Add the frame and button
+ //
+ span.parentNode.insertBefore(frame,span);
+ if (show) {span.parentNode.insertBefore(button,span)}
+ if (span.style) {span.style.position = "relative"} // so math is on top of hover frame
+ //
+ // Start the hover fade-in
+ //
+ this.ReHover(jax);
+ },
+ //
+ // Restart the hover fade in and fade-out timers
+ //
+ ReHover: function (jax) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ jax.hover.remove = setTimeout(CALLBACK(["UnHover",this,jax]),CONFIG.fadeoutDelay);
+ this.HoverFadeTimer(jax,CONFIG.fadeinInc);
+ },
+ //
+ // Start the fade-out
+ //
+ UnHover: function (jax) {
+ if (!jax.hover.nofade) {this.HoverFadeTimer(jax,-CONFIG.fadeoutInc,CONFIG.fadeoutStart)}
+ },
+ //
+ // Handle the fade-in and fade-out
+ //
+ HoverFade: function (jax) {
+ delete jax.hover.timer;
+ jax.hover.opacity = Math.max(0,Math.min(1,jax.hover.opacity + jax.hover.inc));
+ jax.hover.opacity = Math.floor(1000*jax.hover.opacity)/1000;
+ var frame = document.getElementById(jax.hover.id),
+ button = document.getElementById(jax.hover.id+"Menu");
+ frame.firstChild.style.opacity = jax.hover.opacity;
+ frame.firstChild.style.filter = "alpha(opacity="+Math.floor(100*jax.hover.opacity)+")";
+ if (button) {
+ button.firstChild.style.opacity = jax.hover.opacity;
+ button.firstChild.style.filter = frame.style.filter;
+ }
+ if (jax.hover.opacity === 1) {return}
+ if (jax.hover.opacity > 0) {this.HoverFadeTimer(jax,jax.hover.inc); return}
+ frame.parentNode.removeChild(frame);
+ if (button) {button.parentNode.removeChild(button)}
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ delete jax.hover;
+ },
+ //
+ // Set the fade to in or out (via inc) and start the timer, if needed
+ //
+ HoverFadeTimer: function (jax,inc,delay) {
+ jax.hover.inc = inc;
+ if (!jax.hover.timer) {
+ jax.hover.timer = setTimeout(CALLBACK(["HoverFade",this,jax]),(delay||CONFIG.fadeDelay));
+ }
+ },
+
+ //
+ // Handle a click on the menu button
+ //
+ HoverMenu: function (event) {
+ if (!event) {event = window.event}
+ return OUTPUT[this.jax].ContextMenu(event,this.math,true);
+ },
+
+ //
+ // Clear all hover timers
+ //
+ ClearHover: function (jax) {
+ if (jax.hover.remove) {clearTimeout(jax.hover.remove)}
+ if (jax.hover.timer) {clearTimeout(jax.hover.timer)}
+ HOVER.ClearHoverTimer();
+ delete jax.hover;
+ },
+
+ //
+ // Make a measurement in pixels
+ //
+ Px: function (m) {
+ if (Math.abs(m) < .006) {return "0px"}
+ return m.toFixed(2).replace(/\.?0+$/,"") + "px";
+ },
+
+ //
+ // Preload images so they show up with the menu
+ //
+ getImages: function () {
+ if (SETTINGS.discoverable) {
+ var menu = new Image();
+ menu.src = CONFIG.button.src;
+ }
+ }
+
+ };
+
+ //
+ // Handle touch events.
+ //
+ // Use double-tap-and-hold as a replacement for context menu event.
+ // Use double-tap as a replacement for double click.
+ //
+ var TOUCH = ME.Touch = {
+
+ last: 0, // time of last tap event
+ delay: 500, // delay time for double-click
+
+ //
+ // Check if this is a double-tap, and if so, start the timer
+ // for the double-tap and hold (to trigger the contextual menu)
+ //
+ start: function (event) {
+ var now = new Date().getTime();
+ var dblTap = (now - TOUCH.last < TOUCH.delay && TOUCH.up);
+ TOUCH.last = now; TOUCH.up = false;
+ if (dblTap) {
+ TOUCH.timeout = setTimeout(TOUCH.menu,TOUCH.delay,event,this);
+ event.preventDefault();
+ }
+ },
+
+ //
+ // Check if there is a timeout pending, i.e., we have a
+ // double-tap and were waiting to see if it is held long
+ // enough for the menu. Since we got the end before the
+ // timeout, it is a double-click, not a double-tap-and-hold.
+ // Prevent the default action and issue a double click.
+ //
+ end: function (event) {
+ var now = new Date().getTime();
+ TOUCH.up = (now - TOUCH.last < TOUCH.delay);
+ if (TOUCH.timeout) {
+ clearTimeout(TOUCH.timeout);
+ delete TOUCH.timeout; TOUCH.last = 0; TOUCH.up = false;
+ event.preventDefault();
+ return EVENT.Handler((event.touches[0]||event.touch),"DblClick",this);
+ }
+ },
+
+ //
+ // If the timeout passes without an end event, we issue
+ // the contextual menu event.
+ //
+ menu: function (event,math) {
+ delete TOUCH.timeout; TOUCH.last = 0; TOUCH.up = false;
+ return EVENT.Handler((event.touches[0]||event.touch),"ContextMenu",math);
+ }
+
+ };
+
+ /*
+ * //
+ * // Mobile screens are small, so use larger version of arrow
+ * //
+ * if (HUB.Browser.isMobile) {
+ * var arrow = CONFIG.styles[".MathJax_Hover_Arrow"];
+ * arrow.width = "25px"; arrow.height = "18px";
+ * CONFIG.button.x = -6;
+ * }
+ */
+
+ //
+ // Set up browser-specific values
+ //
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var mode = (document.documentMode || 0);
+ var isIE8 = browser.versionAtLeast("8.0");
+ ME.msieBorderWidthBug = (document.compatMode === "BackCompat"); // borders are inside offsetWidth/Height
+ ME.msieEventBug = browser.isIE9; // must get event from window even though event is passed
+ ME.msieAlignBug = (!isIE8 || mode < 8); // inline-block spans don't rest on baseline
+ if (mode < 9) {EVENT.LEFTBUTTON = 1} // IE < 9 has wrong event.button values
+ },
+ Safari: function (browser) {
+ ME.safariContextMenuBug = true; // selection can be started by contextmenu event
+ },
+ Opera: function (browser) {
+ ME.operaPositionBug = true; // position is wrong unless border is used
+ },
+ Konqueror: function (browser) {
+ ME.noContextMenuBug = true; // doesn't produce contextmenu event
+ }
+ });
+
+ //
+ // Used in measuring zoom and hover positions
+ //
+ ME.topImg = (ME.msieAlignBug ?
+ HTML.Element("img",{style:{width:0,height:0,position:"relative"},src:"about:blank"}) :
+ HTML.Element("span",{style:{width:0,height:0,display:"inline-block"}})
+ );
+ if (ME.operaPositionBug) {ME.topImg.style.border="1px solid"}
+
+ //
+ // Get configuration from user
+ //
+ ME.config = CONFIG = HUB.CombineConfig("MathEvents",CONFIG);
+ var SETFRAME = function () {
+ var haze = CONFIG.styles[".MathJax_Hover_Frame"];
+ haze.border = CONFIG.frame.bwidth+"px solid "+CONFIG.frame.bcolor+" ! important";
+ haze["box-shadow"] = haze["-webkit-box-shadow"] =
+ haze["-moz-box-shadow"] = haze["-khtml-box-shadow"] =
+ "0px 0px "+CONFIG.frame.hwidth+" "+CONFIG.frame.hcolor;
+ };
+
+ //
+ // Queue the events needed for startup
+ //
+ CALLBACK.Queue(
+ HUB.Register.StartupHook("End Config",{}), // wait until config is complete
+ [SETFRAME],
+ ["getImages",HOVER],
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathEvents Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathEvents.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.Callback,
+ MathJax.Localization,MathJax.OutputJax,MathJax.InputJax);
diff --git a/MarkDownEditor/MathJax/extensions/MathMenu.js b/MarkDownEditor/MathJax/extensions/MathMenu.js
new file mode 100644
index 0000000..34dbc40
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/MathMenu.js
@@ -0,0 +1,1657 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathMenu.js
+ *
+ * Implements a right-mouse (or CTRL-click) menu over mathematics
+ * elements that gives the user the ability to copy the source,
+ * change the math size, and zoom settings.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2015 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.
+ */
+
+(function (HUB,HTML,AJAX,CALLBACK,OUTPUT) {
+ var VERSION = "2.6.1";
+
+ var SIGNAL = MathJax.Callback.Signal("menu"); // signal for menu events
+
+ MathJax.Extension.MathMenu = {
+ version: VERSION,
+ signal: SIGNAL
+ };
+
+ var _ = function (id) {
+ return MathJax.Localization._.apply(
+ MathJax.Localization,
+ [["MathMenu",id]].concat([].slice.call(arguments,1))
+ );
+ };
+
+ var isPC = HUB.Browser.isPC, isMSIE = HUB.Browser.isMSIE, isIE9 = ((document.documentMode||0) > 8);
+ var ROUND = (isPC ? null : "5px");
+
+ var CONFIG = HUB.CombineConfig("MathMenu",{
+ delay: 150, // the delay for submenus
+
+ showRenderer: true, // show the "Math Renderer" menu?
+ showMathPlayer: true, // show the "MathPlayer" menu?
+ showFontMenu: false, // show the "Font Preference" menu?
+ showContext: false, // show the "Context Menu" menu?
+ showDiscoverable: false, // show the "Discoverable" menu?
+ showLocale: true, // show the "Locale" menu?
+ showLocaleURL: false, // show the "Load from URL" menu?
+
+ semanticsAnnotations: {
+ "TeX": ["TeX", "LaTeX", "application/x-tex"],
+ "StarMath": ["StarMath 5.0"],
+ "Maple": ["Maple"],
+ "ContentMathML": ["MathML-Content", "application/mathml-content+xml"],
+ "OpenMath": ["OpenMath"]
+ },
+
+ windowSettings: { // for source window
+ status: "no", toolbar: "no", locationbar: "no", menubar: "no",
+ directories: "no", personalbar: "no", resizable: "yes", scrollbars: "yes",
+ width: 400, height: 300,
+ left: Math.round((screen.width - 400)/2),
+ top: Math.round((screen.height - 300)/3)
+ },
+
+ styles: {
+ "#MathJax_About": {
+ position:"fixed", left:"50%", width:"auto", "text-align":"center",
+ border:"3px outset", padding:"1em 2em", "background-color":"#DDDDDD", color:"black",
+ cursor: "default", "font-family":"message-box", "font-size":"120%",
+ "font-style":"normal", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none", "z-index":201,
+
+ "border-radius": "15px", // Opera 10.5 and IE9
+ "-webkit-border-radius": "15px", // Safari and Chrome
+ "-moz-border-radius": "15px", // Firefox
+ "-khtml-border-radius": "15px", // Konqueror
+
+ "box-shadow":"0px 10px 20px #808080", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"0px 10px 20px #808080", // Safari 3 and Chrome
+ "-moz-box-shadow":"0px 10px 20px #808080", // Forefox 3.5
+ "-khtml-box-shadow":"0px 10px 20px #808080", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+ "#MathJax_About.MathJax_MousePost": {
+ outline:"none"
+ },
+
+ ".MathJax_Menu": {
+ position:"absolute", "background-color":"white", color:"black",
+ width:"auto", padding:(isPC ? "2px" : "5px 0px"),
+ border:"1px solid #CCCCCC", margin:0, cursor:"default",
+ font: "menu", "text-align":"left", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none", "z-index":201,
+
+ "border-radius": ROUND, // Opera 10.5 and IE9
+ "-webkit-border-radius": ROUND, // Safari and Chrome
+ "-moz-border-radius": ROUND, // Firefox
+ "-khtml-border-radius": ROUND, // Konqueror
+
+ "box-shadow":"0px 10px 20px #808080", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"0px 10px 20px #808080", // Safari 3 and Chrome
+ "-moz-box-shadow":"0px 10px 20px #808080", // Forefox 3.5
+ "-khtml-box-shadow":"0px 10px 20px #808080", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+
+ ".MathJax_MenuItem": {
+ padding: (isPC ? "2px 2em" : "1px 2em"),
+ background:"transparent"
+ },
+
+ ".MathJax_MenuArrow": {
+ position:"absolute", right:".5em", "padding-top":".25em", color:"#666666",
+ "font-family": (isMSIE ? "'Arial unicode MS'" : null), "font-size": ".75em"
+ },
+ ".MathJax_MenuActive .MathJax_MenuArrow": {color:"white"},
+ ".MathJax_MenuArrow.RTL": {left:".5em", right:"auto"},
+
+ ".MathJax_MenuCheck": {
+ position:"absolute", left:".7em",
+ "font-family": (isMSIE ? "'Arial unicode MS'" : null)
+ },
+ ".MathJax_MenuCheck.RTL": {right:".7em", left:"auto"},
+
+ ".MathJax_MenuRadioCheck": {
+ position:"absolute", left: (isPC ? "1em" : ".7em")
+ },
+ ".MathJax_MenuRadioCheck.RTL": {
+ right: (isPC ? "1em" : ".7em"), left:"auto"
+ },
+
+ ".MathJax_MenuLabel": {
+ padding: (isPC ? "2px 2em 4px 1.33em" : "1px 2em 3px 1.33em"),
+ "font-style":"italic"
+ },
+
+ ".MathJax_MenuRule": {
+ "border-top": (isPC ? "1px solid #CCCCCC" : "1px solid #DDDDDD"),
+ margin: (isPC ? "4px 1px 0px" : "4px 3px")
+ },
+
+ ".MathJax_MenuDisabled": {
+ color:"GrayText"
+ },
+ ".MathJax_MenuActive": {
+ "background-color": (isPC ? "Highlight" : "#606872"),
+ color: (isPC ? "HighlightText" : "white")
+ },
+
+ ".MathJax_MenuDisabled:focus, .MathJax_MenuLabel:focus": {
+ "background-color": "#E8E8E8"
+ },
+ ".MathJax_ContextMenu:focus": {
+ outline:"none"
+ },
+ ".MathJax_ContextMenu .MathJax_MenuItem:focus": {
+ outline:"none"
+ },
+
+ "#MathJax_AboutClose": {
+ top:".2em", right:".2em"
+ },
+ ".MathJax_Menu .MathJax_MenuClose": {
+ top:"-10px", left:"-10px"
+ },
+
+ ".MathJax_MenuClose": {
+ position:"absolute",
+ cursor:"pointer",
+ display:"inline-block",
+ border:"2px solid #AAA",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "font-family":"'Courier New',Courier",
+ "font-size":"24px",
+ color:"#F0F0F0"
+ },
+ ".MathJax_MenuClose span": {
+ display:"block", "background-color":"#AAA", border:"1.5px solid",
+ "border-radius":"18px",
+ "-webkit-border-radius": "18px", // Safari and Chrome
+ "-moz-border-radius": "18px", // Firefox
+ "-khtml-border-radius": "18px", // Konqueror
+ "line-height":0,
+ padding:"8px 0 6px" // may need to be browser-specific
+ },
+ ".MathJax_MenuClose:hover": {
+ color:"white!important",
+ border:"2px solid #CCC!important"
+ },
+ ".MathJax_MenuClose:hover span": {
+ "background-color":"#CCC!important"
+ },
+ ".MathJax_MenuClose:hover:focus": {
+ outline:"none"
+ }
+ }
+ });
+
+ var FALSE, HOVER, KEY;
+ HUB.Register.StartupHook("MathEvents Ready",function () {
+ FALSE = MathJax.Extension.MathEvents.Event.False;
+ HOVER = MathJax.Extension.MathEvents.Hover;
+ KEY = MathJax.Extension.MathEvents.Event.KEY;
+ });
+
+
+ /*************************************************************/
+ /*
+ * Abstract class of all keyboard navigatable objects.
+ */
+ var NAV = MathJax.Object.Subclass({
+ /*
+ * Moving in the list of items.
+ */
+ Keydown: function(event, menu) {
+ switch (event.keyCode) {
+ case KEY.ESCAPE:
+ this.Remove(event, menu);
+ break;
+ case KEY.RIGHT:
+ this.Right(event, menu);
+ break;
+ case KEY.LEFT:
+ this.Left(event, menu);
+ break;
+ case KEY.UP:
+ this.Up(event, menu);
+ break;
+ case KEY.DOWN:
+ this.Down(event, menu);
+ break;
+ case KEY.RETURN:
+ case KEY.SPACE:
+ this.Space(event, menu);
+ break;
+ default:
+ return;
+ break;
+ }
+ return FALSE(event);
+ },
+ Escape: function(event, menu) { },
+ Right: function(event, menu) { },
+ Left: function(event, menu) { },
+ Up: function(event, menu) { },
+ Down: function(event, menu) { },
+ Space: function(event, menu) { }
+ }, {});
+
+
+ /*************************************************************/
+ /*
+ * The main menu class
+ */
+ var MENU = MathJax.Menu = NAV.Subclass({
+ version: VERSION,
+ items: [],
+ posted: false,
+ title: null,
+ margin: 5,
+
+ Init: function (def) {this.items = [].slice.call(arguments,0)},
+ With: function (def) {if (def) {HUB.Insert(this,def)}; return this},
+
+ /*
+ * Display the menu
+ */
+ Post: function (event,parent,forceLTR) {
+ if (!event) {event = window.event||{}}
+ var div = document.getElementById("MathJax_MenuFrame");
+ if (!div) {
+ div = MENU.Background(this);
+ delete ITEM.lastItem; delete ITEM.lastMenu;
+ delete MENU.skipUp;
+ SIGNAL.Post(["post",MENU.jax]);
+ MENU.isRTL = (MathJax.Localization.fontDirection() === "rtl");
+ }
+ var menu = HTML.Element("div",{
+ onmouseup: MENU.Mouseup, ondblclick: FALSE,
+ ondragstart: FALSE, onselectstart: FALSE, oncontextmenu: FALSE,
+ menuItem: this, className: "MathJax_Menu", onkeydown: MENU.Keydown,
+ role: "menu"
+ });
+ if (event.type === "contextmenu" || event.type === "mouseover")
+ menu.className += " MathJax_ContextMenu";
+ if (!forceLTR) {MathJax.Localization.setCSS(menu)}
+
+ for (var i = 0, m = this.items.length; i < m; i++) {this.items[i].Create(menu)}
+ if (MENU.isMobile) {
+ HTML.addElement(menu,"span",{
+ className: "MathJax_MenuClose", menu: parent,
+ ontouchstart: MENU.Close, ontouchend: FALSE, onmousedown: MENU.Close, onmouseup: FALSE
+ },[["span",{},"\u00D7"]]);
+ }
+
+ div.appendChild(menu);
+ this.posted = true;
+ if (menu.offsetWidth) menu.style.width = (menu.offsetWidth+2) + "px";
+ var x = event.pageX, y = event.pageY;
+ if (!x && !y && "clientX" in event) {
+ x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+ }
+ if (!parent) {
+ var node = MENU.CurrentNode() || event.target;
+ if ((event.type === "keydown" || (!x && !y)) && node) {
+ var offsetX = window.pageXOffset || document.documentElement.scrollLeft;
+ var offsetY = window.pageYOffset || document.documentElement.scrollTop;
+ var rect = node.getBoundingClientRect();
+ x = (rect.right + rect.left) / 2 + offsetX;
+ y = (rect.bottom + rect.top) / 2 + offsetY;
+ }
+ if (x + menu.offsetWidth > document.body.offsetWidth - this.margin)
+ {x = document.body.offsetWidth - menu.offsetWidth - this.margin}
+ if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20}
+ MENU.skipUp = event.isContextMenu;
+ } else {
+ var side = "left", mw = parent.offsetWidth;
+ x = (MENU.isMobile ? 30 : mw - 2); y = 0;
+ while (parent && parent !== div) {
+ x += parent.offsetLeft; y += parent.offsetTop;
+ parent = parent.parentNode;
+ }
+ if (!MENU.isMobile) {
+ if ((MENU.isRTL && x - mw - menu.offsetWidth > this.margin) ||
+ (!MENU.isRTL && x + menu.offsetWidth > document.body.offsetWidth - this.margin))
+ {side = "right"; x = Math.max(this.margin,x - mw - menu.offsetWidth + 6)}
+ }
+ if (!isPC) {
+ // in case these ever get implemented
+ menu.style["borderRadiusTop"+side] = 0; // Opera 10.5
+ menu.style["WebkitBorderRadiusTop"+side] = 0; // Safari and Chrome
+ menu.style["MozBorderRadiusTop"+side] = 0; // Firefox
+ menu.style["KhtmlBorderRadiusTop"+side] = 0; // Konqueror
+ }
+ }
+
+ menu.style.left = x+"px"; menu.style.top = y+"px";
+ if (document.selection && document.selection.empty) {document.selection.empty()}
+
+ // Focusing while keeping the scroll position.
+ var oldX = window.pageXOffset || document.documentElement.scrollLeft;
+ var oldY = window.pageYOffset || document.documentElement.scrollTop;
+ MENU.Focus(menu);
+ if (event.type === "keydown") {
+ MENU.skipMouseoverFromKey = true;
+ setTimeout(function() {delete MENU.skipMouseoverFromKey;}, CONFIG.delay);
+ }
+ window.scrollTo(oldX, oldY);
+ return FALSE(event);
+ },
+
+ /*
+ * Remove the menu from the screen
+ */
+ Remove: function (event,menu) {
+ SIGNAL.Post(["unpost",MENU.jax]);
+ var div = document.getElementById("MathJax_MenuFrame");
+ if (div) {
+ div.parentNode.removeChild(div);
+ if (this.msieFixedPositionBug) {detachEvent("onresize",MENU.Resize)}
+ }
+ if (MENU.jax.hover) {
+ delete MENU.jax.hover.nofade;
+ HOVER.UnHover(MENU.jax);
+ }
+ MENU.Unfocus(menu);
+ if (event.type === "mousedown") MENU.CurrentNode().blur();
+ return FALSE(event);
+ },
+
+ /*
+ * Find an item in a menu (or submenu) by name (Find) or ID (FindID).
+ * A list of names or IDs means descend into submenus.
+ */
+ Find: function (name) {return this.FindN(1,name,[].slice.call(arguments,1))},
+ FindId: function (name) {return this.FindN(0,name,[].slice.call(arguments,1))},
+ FindN: function (n,name,names) {
+ for (var i = 0, m = this.items.length; i < m; i++) {
+ if (this.items[i].name[n] === name) {
+ if (names.length) {
+ if (!this.items[i].submenu) {return null}
+ return this.items[i].submenu.FindN(n,names[0],names.slice(1));
+ }
+ return this.items[i];
+ }
+ }
+ return null;
+ },
+
+ /*
+ * Find the index of a menu item (so we can insert before or after it)
+ */
+ IndexOf: function (name) {return this.IndexOfN(1,name)},
+ IndexOfId: function (name) {return this.IndexOfN(0,name)},
+ IndexOfN: function (n,name) {
+ for (var i = 0, m = this.items.length; i < m; i++)
+ {if (this.items[i].name[n] === name) {return i}}
+ return null;
+ },
+
+ Right: function(event, menu) {
+ MENU.Right(event, menu);
+ },
+ Left: function(event, menu) {
+ MENU.Left(event, menu);
+ },
+ Up: function(event, menu) {
+ var node = menu.lastChild;
+ node.menuItem.Activate(event, node);
+ },
+ Down: function(event, menu) {
+ var node = menu.firstChild;
+ node.menuItem.Activate(event, node);
+ },
+ Space: function(event, menu) {
+ this.Remove(event, menu);
+ }
+ },{
+
+ config: CONFIG,
+
+ Remove: function (event) {return MENU.Event(event,this,"Remove")},
+ Mouseover: function (event) {return MENU.Event(event,this,"Mouseover")},
+ Mouseout: function (event) {return MENU.Event(event,this,"Mouseout")},
+ Mousedown: function (event) {return MENU.Event(event,this,"Mousedown")},
+ Mouseup: function (event) {return MENU.Event(event,this,"Mouseup")},
+ Keydown: function (event) {return MENU.Event(event,this,"Keydown")},
+ /*
+ * Events for mobile devices.
+ */
+ Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")},
+ Touchend: function (event) {return MENU.Event(event,this,"Touchend")},
+ Close: function (event) {
+ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove"));
+ },
+ Event: function (event,menu,type,force) {
+ if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)}
+ if (MENU.skipMouseoverFromKey && type === "Mouseover") {
+ delete MENU.skipMouseoverFromKey;
+ return FALSE(event);
+ }
+ if (MENU.skipUp) {
+ if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)}
+ if (type === "Touchstart" ||
+ (type === "Mousedown" && !MENU.skipMousedown)) {delete MENU.skipUp}
+ }
+ if (!event) {event = window.event}
+ var item = menu.menuItem;
+ if (item && item[type]) {return item[type](event,menu)}
+ return null;
+ },
+ /*
+ * Style for the background DIV
+ */
+ BGSTYLE: {
+ position:"absolute", left:0, top:0, "z-index":200,
+ width:"100%", height:"100%", border:0, padding:0, margin:0
+ },
+
+ Background: function (menu) {
+ var div = HTML.addElement(document.body,"div",
+ {style:this.BGSTYLE, id:"MathJax_MenuFrame"},
+ [["div",{style: this.BGSTYLE, menuItem: menu, onmousedown: this.Remove}]]);
+ var bg = div.firstChild;
+ if (MENU.msieBackgroundBug) {
+ // MSIE doesn't allow transparent background to be hit boxes, so
+ // fake it using opacity with solid background color
+ bg.style.backgroundColor = "white"; bg.style.filter = "alpha(opacity=0)";
+ }
+ if (MENU.msieFixedPositionBug) {
+ // MSIE can't do fixed position, so use a full-sized background
+ // and an onresize handler to update it (stupid, but necessary)
+ div.width = div.height = 0; this.Resize();
+ attachEvent("onresize",this.Resize);
+ } else {
+ // otherwise, use a fixed position DIV to cover the viewport
+ bg.style.position = "fixed";
+ }
+ return div;
+ },
+ Resize: function () {setTimeout(MENU.SetWH,0)},
+ SetWH: function () {
+ var bg = document.getElementById("MathJax_MenuFrame");
+ if (bg) {
+ bg = bg.firstChild;
+ bg.style.width = bg.style.height = "1px"; // so scrollWidth/Height will be right below
+ bg.style.width = document.body.scrollWidth + "px";
+ bg.style.height = document.body.scrollHeight + "px";
+ }
+ },
+
+ /*************************************************************/
+ /*
+ * Keyboard navigation of menu.
+ */
+ posted: false, // Is a menu open?
+ active: null, // The focused in HTML node in the menu.
+
+ GetNode: function(jax) {
+ var node = document.getElementById(jax.inputID + "-Frame");
+ return node.isMathJax ? node : node.firstChild;
+ },
+ CurrentNode: function() {
+ return MENU.GetNode(MENU.jax);
+ },
+ AllNodes: function() {
+ var jaxs = MathJax.Hub.getAllJax();
+ var nodes = [];
+ for (var i = 0, jax; jax = jaxs[i]; i++) {
+ nodes.push(MENU.GetNode(jax));
+ }
+ return nodes;
+ },
+ ActiveNode: function() {
+ return MENU.active;
+ },
+ FocusNode: function(node) {
+ MENU.active = node;
+ node.focus();
+ },
+ //
+ // Focus is a global affair, since we only ever want a single focused item.
+ //
+ Focus: function(menu) {
+ !MENU.posted ? MENU.Activate(menu) : MENU.ActiveNode().tabIndex = -1;
+ menu.tabIndex = 0;
+ MENU.FocusNode(menu);
+ },
+ Activate: function(event, menu) {
+ MENU.UnsetTabIndex();
+ MENU.posted = true;
+ },
+ Unfocus: function() {
+ MENU.ActiveNode().tabIndex = -1;
+ MENU.SetTabIndex();
+ MENU.FocusNode(MENU.CurrentNode());
+ MENU.posted = false;
+ },
+ MoveHorizontal: function(event, menu, move) {
+ if (!event.shiftKey) return;
+ var jaxs = MENU.AllNodes();
+ var len = jaxs.length;
+ if (len === 0) return;
+ var next = jaxs[MENU.Mod(move(MENU.IndexOf(jaxs, MENU.CurrentNode())), len)];
+ if (next === MENU.CurrentNode()) return;
+ MENU.menu.Remove(event, menu);
+ MENU.jax = MathJax.Hub.getJaxFor(next);
+ MENU.FocusNode(next);
+ MENU.menu.Post(null);
+ },
+ Right: function(event, menu) {
+ MENU.MoveHorizontal(event, menu, function(x) {return x + 1;});
+ },
+ Left: function(event, menu) {
+ MENU.MoveHorizontal(event, menu, function(x) {return x - 1;});
+ },
+ UnsetTabIndex: function () {
+ var jaxs = MENU.AllNodes();
+ for (var j = 0, jax; jax = jaxs[j]; j++) {
+ if (jax.tabIndex > 0) {
+ jax.oldTabIndex = jax.tabIndex;
+ }
+ jax.tabIndex = -1;
+ }
+ },
+ SetTabIndex: function () {
+ var jaxs = MENU.AllNodes();
+ for (var j = 0, jax; jax = jaxs[j]; j++) {
+ if (jax.oldTabIndex !== undefined) {
+ jax.tabIndex = jax.oldTabIndex
+ delete jax.oldTabIndex;
+ } else {
+ jax.tabIndex = HUB.getTabOrder(jax);
+ }
+ }
+ },
+
+ //TODO: Move to utility class.
+ // Computes a mod n.
+ Mod: function(a, n) {
+ return ((a % n) + n) % n;
+ },
+ IndexOf: (Array.prototype.indexOf ?
+ function (A, item, start) {return A.indexOf(item, start);} :
+ function (A, item, start) {
+ for (var i = (start || 0), j = A.length; i < j; i++) {
+ if (item === A[i]) return i;
+ }
+ return -1;
+ }),
+
+ saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)},
+ getCookie: function () {this.cookie = HTML.Cookie.Get("menu")}
+
+ });
+
+ MathJax.Menu.NAV = NAV;
+
+ /*************************************************************/
+ /*
+ * Abstract class of menu items.
+ */
+ var ITEM = MENU.ITEM = NAV.Subclass({
+
+ name: "", // The menu item's label as [id,label] pair.
+ node: null, // The HTML node of the item.
+ menu: null, // The parent menu containing that item. HTML node.
+
+ Attributes: function(def) {
+ return HUB.Insert(
+ {onmouseup: MENU.Mouseup,
+ ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
+ ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
+ className: "MathJax_MenuItem", role: this.role,
+ menuItem: this},
+ def);
+ },
+
+ Create: function (menu) {
+ if (!this.hidden) {
+ var def = this.Attributes();
+ var label = this.Label(def,menu);
+ HTML.addElement(menu, "div", def, label);
+ }
+ },
+ Name: function () {return _(this.name[0],this.name[1])},
+
+ Mouseover: function (event,menu) {
+ if (menu.parentNode === MENU.ActiveNode().parentNode) {
+ this.Deactivate(MENU.ActiveNode());
+ }
+ this.Activate(event, menu);
+ },
+ Mouseout: function (event,menu) {
+ this.Deactivate(menu);
+ },
+ Mouseup: function (event,menu) {return this.Remove(event,menu)},
+
+
+ DeactivateSubmenus: function(menu) {
+ var menus = document.getElementById("MathJax_MenuFrame").childNodes,
+ items = ITEM.GetMenuNode(menu).childNodes;
+ for (var i = 0, m = items.length; i < m; i++) {
+ var item = items[i].menuItem;
+ // Deactivates submenu items.
+ if (item && item.submenu && item.submenu.posted &&
+ item !== menu.menuItem) {
+ item.Deactivate(items[i]);
+ }
+ }
+ this.RemoveSubmenus(menu, menus);
+ },
+ RemoveSubmenus: function(menu, menus) {
+ menus = menus || document.getElementById("MathJax_MenuFrame").childNodes;
+ var m = menus.length-1;
+ while (m >= 0 && ITEM.GetMenuNode(menu).menuItem !== menus[m].menuItem) {
+ menus[m].menuItem.posted = false;
+ menus[m].parentNode.removeChild(menus[m]);
+ m--;
+ }
+ },
+
+ Touchstart: function (event,menu) {return this.TouchEvent(event,menu,"Mousedown")},
+ Touchend: function (event,menu) {return this.TouchEvent(event,menu,"Mouseup")},
+ TouchEvent: function (event,menu,type) {
+ if (this !== ITEM.lastItem) {
+ if (ITEM.lastMenu) {MENU.Event(event,ITEM.lastMenu,"Mouseout")}
+ MENU.Event(event,menu,"Mouseover",true);
+ ITEM.lastItem = this; ITEM.lastMenu = menu;
+ }
+ if (this.nativeTouch) {return null}
+ MENU.Event(event,menu,type);
+ return false;
+ },
+
+ Remove: function (event,menu) {
+ menu = menu.parentNode.menuItem;
+ return menu.Remove(event,menu);
+ },
+
+ With: function (def) {if (def) {HUB.Insert(this,def)}; return this},
+
+ isRTL: function () {return MENU.isRTL},
+ rtlClass: function () {return (this.isRTL() ? " RTL" : "")}
+ }, {
+ GetMenuNode: function(item) {
+ return item.parentNode;
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * Abstract class of menu items that are focusable and perform some action
+ */
+ MENU.ENTRY = MENU.ITEM.Subclass({
+ role: "menuitem", // Aria role.
+
+ Attributes: function(def) {
+ def = HUB.Insert(
+ {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
+ onmousedown: MENU.Mousedown, onkeydown: MENU.Keydown,
+ "aria-disabled": !!this.disabled},
+ def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ if (this.disabled) {
+ def.className += " MathJax_MenuDisabled";
+ }
+ return def;
+ },
+ MoveVertical: function(event, item, move) {
+ var menuNode = ITEM.GetMenuNode(item);
+ var items = [];
+ for (var i = 0, allItems = menuNode.menuItem.items, it;
+ it = allItems[i]; i++) {
+ if (!it.hidden) {
+ items.push(it);
+ }
+ }
+ var index = MENU.IndexOf(items, this);
+ if (index === -1) return;
+ var len = items.length;
+ var children = menuNode.childNodes;
+ do {
+ index = MENU.Mod(move(index), len);
+ } while (items[index].hidden || !children[index].role ||
+ children[index].role === "separator");
+ this.Deactivate(item);
+ items[index].Activate(event, children[index]);
+ },
+ Up: function(event, item) {
+ this.MoveVertical(event, item, function(x) { return x - 1; });
+ },
+ Down: function(event, item) {
+ this.MoveVertical(event, item, function(x) { return x + 1; });
+ },
+ Right: function(event, item) {
+ this.MoveHorizontal(event, item, MENU.Right, !this.isRTL());
+ },
+ Left: function(event, item) {
+ this.MoveHorizontal(event, item, MENU.Left, this.isRTL());
+ },
+ MoveHorizontal: function(event, item, move, rtl) {
+ var menuNode = ITEM.GetMenuNode(item);
+ if (menuNode.menuItem === MENU.menu && event.shiftKey) {
+ move(event, item);
+ }
+ if (rtl) return;
+ if (menuNode.menuItem !== MENU.menu) {
+ this.Deactivate(item);
+ }
+ var parentNodes = menuNode.previousSibling.childNodes;
+ var length = parentNodes.length;
+ while (length--) {
+ var parent = parentNodes[length];
+ if (parent.menuItem.submenu &&
+ parent.menuItem.submenu === menuNode.menuItem) {
+ MENU.Focus(parent);
+ break;
+ }
+ }
+ this.RemoveSubmenus(item);
+ },
+ Space: function (event, menu) {
+ this.Mouseup(event, menu);
+ },
+
+ Activate: function (event, menu) {
+ this.Deactivate(menu);
+ if (!this.disabled) {
+ menu.className += " MathJax_MenuActive";
+ }
+ this.DeactivateSubmenus(menu);
+ MENU.Focus(menu);
+ },
+ Deactivate: function (menu) {
+ menu.className = menu.className.replace(/ MathJax_MenuActive/,"");
+ }
+
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that performs a command when selected
+ */
+ MENU.ITEM.COMMAND = MENU.ENTRY.Subclass({
+ action: function () {},
+
+ Init: function (name,action,def) {
+ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.action = action;
+ this.With(def);
+ },
+
+ Label: function (def,menu) {return [this.Name()]},
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ this.Remove(event,menu);
+ SIGNAL.Post(["command",this]);
+ this.action.call(this,event);
+ }
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that posts a submenu
+ */
+ MENU.ITEM.SUBMENU = MENU.ENTRY.Subclass({
+ submenu: null, // the submenu
+ marker: "\u25BA", // the submenu arrow
+ markerRTL: "\u25C4", // the submenu arrow for RTL
+
+ Attributes: function(def) {
+ def = HUB.Insert({"aria-haspopup": "true"}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,def) {
+ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair
+ this.name = name; var i = 1;
+ if (!(def instanceof MENU.ITEM)) {this.With(def), i++}
+ this.submenu = MENU.apply(MENU,[].slice.call(arguments,i));
+ },
+ Label: function (def,menu) {
+ this.submenu.posted = false;
+ return [this.Name()+" ",["span",{
+ className:"MathJax_MenuArrow" + this.rtlClass()
+ },[this.isRTL() ? this.markerRTL : this.marker]]];
+ },
+ Timer: function (event,menu) {
+ this.ClearTimer();
+ event = {type: event.type,
+ clientX: event.clientX, clientY: event.clientY}; // MSIE can't pass the event below
+ this.timer = setTimeout(CALLBACK(["Mouseup",this,event,menu]),CONFIG.delay);
+ },
+ ClearTimer: function() {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ },
+ Touchend: function (event,menu) {
+ var forceout = this.submenu.posted;
+ var result = this.SUPER(arguments).Touchend.apply(this,arguments);
+ if (forceout) {this.Deactivate(menu); delete ITEM.lastItem; delete ITEM.lastMenu}
+ return result;
+ },
+ Mouseout: function(event, menu) {
+ if (!this.submenu.posted) {
+ this.Deactivate(menu);
+ }
+ this.ClearTimer();
+ },
+ Mouseover: function(event, menu) {
+ this.Activate(event, menu);
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ if (!this.submenu.posted) {
+ this.ClearTimer();
+ this.submenu.Post(event, menu, this.ltr);
+ MENU.Focus(menu);
+ } else {
+ this.DeactivateSubmenus(menu);
+ }
+ }
+ return FALSE(event);
+ },
+ Activate: function (event, menu) {
+ if (!this.disabled) {
+ this.Deactivate(menu);
+ menu.className += " MathJax_MenuActive";
+ }
+ if (!this.submenu.posted) {
+ this.DeactivateSubmenus(menu);
+ if (!MENU.isMobile) {
+ this.Timer(event,menu);
+ }
+ }
+ MENU.Focus(menu);
+ },
+ MoveVertical: function(event, item, move) {
+ this.ClearTimer();
+ this.SUPER(arguments).MoveVertical.apply(this, arguments);
+ },
+ MoveHorizontal: function(event, menu, move, rtl) {
+ if (!rtl) {
+ this.SUPER(arguments).MoveHorizontal.apply(this, arguments);
+ return;
+ }
+ if (this.disabled) return;
+ if (!this.submenu.posted) {
+ this.Activate(event, menu);
+ return;
+ }
+ var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes;
+ if (submenuNodes.length > 0) {
+ this.submenu.items[0].Activate(event, submenuNodes[0]);
+ }
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is one of several radio buttons
+ */
+ MENU.ITEM.RADIO = MENU.ENTRY.Subclass({
+ variable: null, // the variable name
+ marker: (isPC ? "\u25CF" : "\u2713"), // the checkmark
+ role: "menuitemradio",
+
+ Attributes: function(def) {
+ var checked = CONFIG.settings[this.variable] === this.value ? "true" : "false";
+ def = HUB.Insert({"aria-checked": checked}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,variable,def) {
+ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.variable = variable; this.With(def);
+ if (this.value == null) {this.value = this.name[0]}
+ },
+ Label: function (def,menu) {
+ var span = {className:"MathJax_MenuRadioCheck" + this.rtlClass()};
+ if (CONFIG.settings[this.variable] !== this.value) {
+ span = {style:{display:"none"}};
+ }
+ return [["span",span,[this.marker]]," "+this.Name()];
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ var child = menu.parentNode.childNodes;
+ for (var i = 0, m = child.length; i < m; i++) {
+ var item = child[i].menuItem;
+ if (item && item.variable === this.variable) {
+ child[i].firstChild.style.display = "none";
+ }
+ }
+ menu.firstChild.display = "";
+ CONFIG.settings[this.variable] = this.value;
+ MENU.cookie[this.variable] = CONFIG.settings[this.variable]; MENU.saveCookie();
+ SIGNAL.Post(["radio button",this]);
+ }
+ this.Remove(event,menu);
+ if (this.action && !this.disabled) {this.action.call(MENU,this)}
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is checkable
+ */
+ MENU.ITEM.CHECKBOX = MENU.ENTRY.Subclass({
+ variable: null, // the variable name
+ marker: "\u2713", // the checkmark
+ role: "menuitemcheckbox",
+
+ Attributes: function(def) {
+ var checked = CONFIG.settings[this.variable] ? "true" : "false";
+ def = HUB.Insert({"aria-checked": checked}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Init: function (name,variable,def) {
+ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.variable = variable; this.With(def);
+ },
+ Label: function (def,menu) {
+ var span = {className:"MathJax_MenuCheck" + this.rtlClass()};
+ if (!CONFIG.settings[this.variable]) {span = {style:{display:"none"}}}
+ return [["span",span,[this.marker]]," "+this.Name()];
+ },
+ Mouseup: function (event,menu) {
+ if (!this.disabled) {
+ menu.firstChild.display = (CONFIG.settings[this.variable] ? "none" : "");
+ CONFIG.settings[this.variable] = !CONFIG.settings[this.variable];
+ MENU.cookie[this.variable] = CONFIG.settings[this.variable]; MENU.saveCookie();
+ SIGNAL.Post(["checkbox",this]);
+ }
+ this.Remove(event,menu);
+ if (this.action && !this.disabled) {this.action.call(MENU,this)}
+ return FALSE(event);
+ }
+ });
+
+ /*************************************************************/
+ /*
+ * A menu item that is a label
+ */
+ MENU.ITEM.LABEL = MENU.ENTRY.Subclass({
+ role: "menuitem", // Aria role.
+
+ Init: function (name,def) {
+ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair
+ this.name = name; this.With(def);
+ },
+ Label: function (def,menu) {
+ def.className += " MathJax_MenuLabel";
+ return [this.Name()];
+ },
+ Activate: function(event, menu) {
+ this.Deactivate(menu);
+ MENU.Focus(menu);
+ },
+ Mouseup: function (event,menu) { }
+ });
+
+ /*************************************************************/
+ /*
+ * A rule in a menu
+ */
+ MENU.ITEM.RULE = MENU.ITEM.Subclass({
+ role: "separator",
+
+ Attributes: function(def) {
+ def = HUB.Insert({"aria-orientation": "vertical"}, def);
+ def = this.SUPER(arguments).Attributes.call(this, def);
+ return def;
+ },
+ Label: function (def,menu) {
+ def.className += " MathJax_MenuRule";
+ return null;
+ }
+ });
+
+ /*************************************************************/
+ /*************************************************************/
+
+ /*
+ * Handle the ABOUT box
+ */
+ MENU.About = function (event) {
+ var font = MENU.About.GetFont();
+ var format = MENU.About.GetFormat();
+ var jax = ["MathJax.js v"+MathJax.fileversion,["br"]];
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]);
+ MENU.About.GetJax(jax,MathJax.InputJax,["InputJax","%1 Input Jax v%2"]);
+ MENU.About.GetJax(jax,MathJax.OutputJax,["OutputJax","%1 Output Jax v%2"]);
+ MENU.About.GetJax(jax,MathJax.ElementJax,["ElementJax","%1 Element Jax v%2"]);
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]);
+ MENU.About.GetJax(jax,MathJax.Extension,["Extension","%1 Extension v%2"],true);
+ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}],["center",{},[
+ HUB.Browser + " v"+HUB.Browser.version + (format ?
+ " \u2014 " + _(format.replace(/ /g,""),format) : "")
+ ]]);
+ MENU.About.div = MENU.Background(MENU.About);
+ var about = HTML.addElement(MENU.About.div,"div",{
+ id: "MathJax_About", tabIndex: 0, onkeydown: MENU.About.Keydown
+ },[
+ ["b",{style:{fontSize:"120%"}},["MathJax"]]," v"+MathJax.version,["br"],
+ _(font.replace(/ /g,""),"using "+font),["br"],["br"],
+ ["span",{style:{
+ display:"inline-block", "text-align":"left", "font-size":"80%",
+ "max-height":"20em", overflow:"auto",
+ "background-color":"#E4E4E4", padding:".4em .6em", border:"1px inset"
+ }, tabIndex: 0},jax],["br"],["br"],
+ ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]],
+ ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose",
+ onclick:MENU.About.Remove,
+ onkeydown: MENU.About.Keydown, tabIndex: 0, role: "button",
+ "aria-label": _("CloseAboutDialog","Close about MathJax dialog")},
+ [["span",{},"\u00D7"]]]
+ ]);
+ if (event.type === "mouseup") about.className += " MathJax_MousePost";
+ about.focus();
+ MathJax.Localization.setCSS(about);
+ var doc = (document.documentElement||{});
+ var H = window.innerHeight || doc.clientHeight || doc.scrollHeight || 0;
+ if (MENU.prototype.msieAboutBug) {
+ about.style.width = "20em"; about.style.position = "absolute";
+ about.style.left = Math.floor((document.documentElement.scrollWidth - about.offsetWidth)/2)+"px";
+ about.style.top = (Math.floor((H-about.offsetHeight)/3)+document.body.scrollTop)+"px";
+ } else {
+ about.style.marginLeft = Math.floor(-about.offsetWidth/2)+"px";
+ about.style.top = Math.floor((H-about.offsetHeight)/3)+"px";
+ }
+ };
+ MENU.About.Remove = function (event) {
+ if (MENU.About.div) {document.body.removeChild(MENU.About.div); delete MENU.About.div}
+ };
+ MENU.About.Keydown = function(event) {
+ if (event.keyCode === KEY.ESCAPE ||
+ (this.id === "MathJax_AboutClose" &&
+ (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) {
+ MENU.About.Remove(event);
+ MENU.CurrentNode().focus();
+ FALSE(event);
+ }
+ },
+ MENU.About.GetJax = function (jax,JAX,type,noTypeCheck) {
+ var info = [];
+ for (var id in JAX) {if (JAX.hasOwnProperty(id) && JAX[id]) {
+ if ((noTypeCheck && JAX[id].version) || (JAX[id].isa && JAX[id].isa(JAX)))
+ {info.push(_(type[0],type[1],(JAX[id].id||id),JAX[id].version))}
+ }}
+ info.sort();
+ for (var i = 0, m = info.length; i < m; i++) {jax.push(info[i],["br"])}
+ return jax;
+ };
+ MENU.About.GetFont = function () {
+ var jax = MathJax.Hub.outputJax["jax/mml"][0] || {};
+ var font = {
+ SVG: "web SVG",
+ CommonHTML: "web TeX",
+ "HTML-CSS": (jax.imgFonts ? "image" : (jax.webFonts ? "web" : "local")+" "+jax.fontInUse)
+ }[jax.id] || "generic";
+ return font + " fonts";
+ };
+ MENU.About.GetFormat = function () {
+ var jax = MathJax.Hub.outputJax["jax/mml"][0] || {};
+ if (jax.id !== "HTML-CSS"|| !jax.webFonts || jax.imgFonts) return;
+ return jax.allowWebFonts.replace(/otf/,"woff or otf") + " fonts";
+ };
+
+
+ /*
+ * Handle the MathJax HELP menu
+ */
+ MENU.Help = function (event) {
+ AJAX.Require("[MathJax]/extensions/HelpDialog.js",
+ function () {MathJax.Extension.Help.Dialog({type:event.type})});
+ };
+
+ /*
+ * Handle showing of element's source
+ */
+ MENU.ShowSource = function (event) {
+ if (!event) {event = window.event}
+ var EVENT = {screenX:event.screenX, screenY:event.screenY};
+ if (!MENU.jax) return;
+ if (this.format === "MathML") {
+ var MML = MathJax.ElementJax.mml;
+ if (MML && typeof(MML.mbase.prototype.toMathML) !== "undefined") {
+ // toMathML() can call MathJax.Hub.RestartAfter, so trap errors and check
+ try {MENU.ShowSource.Text(MENU.jax.root.toMathML("",MENU.jax),event)} catch (err) {
+ if (!err.restart) {throw err}
+ CALLBACK.After([this,MENU.ShowSource,EVENT],err.restart);
+ }
+ } else if (!AJAX.loadingToMathML) {
+ AJAX.loadingToMathML = true;
+ MENU.ShowSource.Window(event); // WeBKit needs to open window on click event
+ CALLBACK.Queue(
+ AJAX.Require("[MathJax]/extensions/toMathML.js"),
+ function () {
+ delete AJAX.loadingToMathML;
+ if (!MML.mbase.prototype.toMathML) {MML.mbase.prototype.toMathML = function () {}}
+ },
+ [this,MENU.ShowSource,EVENT] // call this function again
+ );
+ return;
+ }
+ } else if (this.format === "Error") {
+ MENU.ShowSource.Text(MENU.jax.errorText,event);
+ } else if (CONFIG.semanticsAnnotations[this.format]) {
+ var annotation = MENU.jax.root.getAnnotation(this.format);
+ if (annotation.data[0]) MENU.ShowSource.Text(annotation.data[0].toString());
+ } else {
+ if (MENU.jax.originalText == null) {
+ alert(_("NoOriginalForm","No original form available"));
+ return;
+ }
+ MENU.ShowSource.Text(MENU.jax.originalText,event);
+ }
+ };
+ MENU.ShowSource.Window = function (event) {
+ if (!MENU.ShowSource.w) {
+ var def = [], DEF = CONFIG.windowSettings;
+ for (var id in DEF) {if (DEF.hasOwnProperty(id)) {def.push(id+"="+DEF[id])}}
+ MENU.ShowSource.w = window.open("","_blank",def.join(","));
+ }
+ return MENU.ShowSource.w;
+ };
+ MENU.ShowSource.Text = function (text,event) {
+ var w = MENU.ShowSource.Window(event); delete MENU.ShowSource.w;
+ text = text.replace(/^\s*/,"").replace(/\s*$/,"");
+ text = text.replace(/&/g,"&").replace(//g,">");
+ var title = _("EqSource","MathJax Equation Source");
+ if (MENU.isMobile) {
+ w.document.open();
+ w.document.write(""+title+"");
+ w.document.write(""+text+"
");
+ w.document.write("
");
+ w.document.write("");
+ w.document.close();
+ } else {
+ w.document.open();
+ w.document.write(""+title+"");
+ w.document.write("");
+ w.document.write("");
+ w.document.close();
+ var table = w.document.body.firstChild;
+ setTimeout(function () {
+ var H = (w.outerHeight-w.innerHeight)||30, W = (w.outerWidth-w.innerWidth)||30, x, y;
+ W = Math.max(140,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25));
+ H = Math.max(40,Math.min(Math.floor(.5*screen.height),table.offsetHeight+H+25));
+ if (MENU.prototype.msieHeightBug) {H += 35}; // for title bar in XP
+ w.resizeTo(W,H);
+ var X; try {X = event.screenX} catch (e) {}; // IE8 throws an error accessing screenX
+ if (event && X != null) {
+ x = Math.max(0,Math.min(event.screenX-Math.floor(W/2), screen.width-W-20));
+ y = Math.max(0,Math.min(event.screenY-Math.floor(H/2), screen.height-H-20));
+ w.moveTo(x,y);
+ }
+ },50);
+ }
+ };
+
+ /*
+ * Handle rescaling all the math
+ */
+ MENU.Scale = function () {
+ var JAX = ["CommonHTML","HTML-CSS","SVG","NativeMML","PreviewHTML"], m = JAX.length,
+ SCALE = 100, i, jax;
+ for (i = 0; i < m; i++) {
+ jax = OUTPUT[JAX[i]];
+ if (jax) {SCALE = jax.config.scale; break}
+ }
+ var scale = prompt(_("ScaleMath","Scale all mathematics (compared to surrounding text) by"),SCALE+"%");
+ if (scale) {
+ if (scale.match(/^\s*\d+(\.\d*)?\s*%?\s*$/)) {
+ scale = parseFloat(scale);
+ if (scale) {
+ if (scale !== SCALE) {
+ for (i = 0; i < m; i++) {
+ jax = OUTPUT[JAX[i]];
+ if (jax) jax.config.scale = scale;
+ }
+ MENU.cookie.scale = HUB.config.scale = scale;
+ MENU.saveCookie();
+ HUB.Queue(["Rerender",HUB]);
+ }
+ } else {alert(_("NonZeroScale","The scale should not be zero"))}
+ } else {alert(_("PercentScale",
+ "The scale should be a percentage (e.g., 120%%)"))}
+ }
+ };
+
+ /*
+ * Handle loading the zoom code
+ */
+ MENU.Zoom = function () {
+ if (!MathJax.Extension.MathZoom) {AJAX.Require("[MathJax]/extensions/MathZoom.js")}
+ };
+
+ /*
+ * Handle changing the renderer
+ */
+ MENU.Renderer = function () {
+ var jax = HUB.outputJax["jax/mml"];
+ if (jax[0] !== CONFIG.settings.renderer) {
+ var BROWSER = HUB.Browser, message, MESSAGE = MENU.Renderer.Messages, warned;
+ //
+ // Check that the new renderer is appropriate for the browser
+ //
+ switch (CONFIG.settings.renderer) {
+ case "NativeMML":
+ if (!CONFIG.settings.warnedMML) {
+ if (BROWSER.isChrome && BROWSER.version.substr(0,3) !== "24.") {message = MESSAGE.MML.WebKit}
+ else if (BROWSER.isSafari && !BROWSER.versionAtLeast("5.0")) {message = MESSAGE.MML.WebKit}
+ else if (BROWSER.isMSIE) {if (!BROWSER.hasMathPlayer) {message = MESSAGE.MML.MSIE}}
+ else if (BROWSER.isEdge) {message = MESSAGE.MML.WebKit}
+ else {message = MESSAGE.MML[BROWSER]}
+ warned = "warnedMML";
+ }
+ break;
+
+ case "SVG":
+ if (!CONFIG.settings.warnedSVG) {
+ if (BROWSER.isMSIE && !isIE9) {message = MESSAGE.SVG.MSIE}
+ }
+ break;
+ }
+ if (message) {
+ message = _(message[0],message[1]);
+ message += "\n\n";
+ message += _("SwitchAnyway",
+ "Switch the renderer anyway?\n\n" +
+ "(Press OK to switch, CANCEL to continue with the current renderer)");
+ MENU.cookie.renderer = jax[0].id; MENU.saveCookie();
+ if (!confirm(message)) {
+ MENU.cookie.renderer = CONFIG.settings.renderer = HTML.Cookie.Get("menu").renderer;
+ MENU.saveCookie();
+ return;
+ }
+ if (warned) {MENU.cookie.warned = CONFIG.settings.warned = true}
+ MENU.cookie.renderer = CONFIG.settings.renderer; MENU.saveCookie();
+ }
+ HUB.Queue(
+ ["setRenderer",HUB,CONFIG.settings.renderer,"jax/mml"],
+ ["Rerender",HUB]
+ );
+ }
+ };
+ MENU.Renderer.Messages = {
+ MML: {
+ WebKit: ["WebkitNativeMMLWarning",
+ "Your browser doesn't seem to support MathML natively, " +
+ "so switching to MathML output may cause the mathematics " +
+ "on the page to become unreadable."],
+
+ MSIE: ["MSIENativeMMLWarning",
+ "Internet Explorer requires the MathPlayer plugin " +
+ "in order to process MathML output."],
+
+ Opera: ["OperaNativeMMLWarning",
+ "Opera's support for MathML is limited, so switching to " +
+ "MathML output may cause some expressions to render poorly."],
+
+ Safari: ["SafariNativeMMLWarning",
+ "Your browser's native MathML does not implement all the features " +
+ "used by MathJax, so some expressions may not render properly."],
+
+ Firefox: ["FirefoxNativeMMLWarning",
+ "Your browser's native MathML does not implement all the features " +
+ "used by MathJax, so some expressions may not render properly."]
+ },
+
+ SVG: {
+ MSIE: ["MSIESVGWarning",
+ "SVG is not implemented in Internet Explorer prior to " +
+ "IE9 or when it is emulating IE8 or below. " +
+ "Switching to SVG output will cause the mathematics to " +
+ "not display properly."]
+ }
+ };
+
+ /*
+ * Toggle assistive MML settings
+ */
+ MENU.AssistiveMML = function (item,restart) {
+ var AMML = MathJax.Extension.AssistiveMML;
+ if (!AMML) {
+ // Try to load the extension, but only try once.
+ if (!restart)
+ AJAX.Require("[MathJax]/extensions/AssistiveMML.js",["AssistiveMML",MENU,item,true]);
+ return;
+ }
+ MathJax.Hub.Queue([(CONFIG.settings.assistiveMML ? "Add" : "Remove")+"AssistiveMathML",AMML]);
+ };
+
+ /*
+ * Handle setting the HTMLCSS fonts
+ */
+ MENU.Font = function () {
+ var HTMLCSS = OUTPUT["HTML-CSS"]; if (!HTMLCSS) return;
+ document.location.reload();
+ };
+
+ /*
+ * Handle selection of locale and rerender the page
+ */
+ MENU.Locale = function () {
+ MathJax.Localization.setLocale(CONFIG.settings.locale);
+ MathJax.Hub.Queue(["Reprocess",MathJax.Hub]); // FIXME: Just reprocess error messages?
+ };
+ MENU.LoadLocale = function () {
+ var url = prompt(_("LoadURL","Load translation data from this URL:"));
+ if (url) {
+ if (!url.match(/\.js$/)) {
+ alert(_("BadURL",
+ "The URL should be for a javascript file that defines MathJax translation data. " +
+ "Javascript file names should end with '.js'"
+ ));
+ }
+ AJAX.Require(url,function (status) {
+ if (status != AJAX.STATUS.OK) {alert(_("BadData","Failed to load translation data from %1",url))}
+ });
+ }
+ };
+
+ /*
+ * Handle setting MathPlayer events
+ */
+ MENU.MPEvents = function (item) {
+ var discoverable = CONFIG.settings.discoverable,
+ MESSAGE = MENU.MPEvents.Messages;
+ if (!isIE9) {
+ if (CONFIG.settings.mpMouse && !confirm(_.apply(_,MESSAGE.IE8warning))) {
+ delete MENU.cookie.mpContext; delete CONFIG.settings.mpContext;
+ delete MENU.cookie.mpMouse; delete CONFIG.settings.mpMouse;
+ MENU.saveCookie();
+ return;
+ }
+ CONFIG.settings.mpContext = CONFIG.settings.mpMouse;
+ MENU.cookie.mpContext = MENU.cookie.mpMouse = CONFIG.settings.mpMouse;
+ MENU.saveCookie();
+ MathJax.Hub.Queue(["Rerender",MathJax.Hub])
+ } else if (!discoverable && item.name[1] === "Menu Events" && CONFIG.settings.mpContext) {
+ alert(_.apply(_,MESSAGE.IE9warning));
+ }
+ };
+
+ MENU.MPEvents.Messages = {
+ IE8warning: ["IE8warning",
+ "This will disable the MathJax menu and zoom features, " +
+ "but you can Alt-Click on an expression to obtain the MathJax " +
+ "menu instead.\n\nReally change the MathPlayer settings?"],
+
+ IE9warning: ["IE9warning",
+ "The MathJax contextual menu will be disabled, but you can " +
+ "Alt-Click on an expression to obtain the MathJax menu instead."]
+ };
+
+ /*************************************************************/
+ /*************************************************************/
+
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var quirks = (document.compatMode === "BackCompat");
+ var isIE8 = browser.versionAtLeast("8.0") && document.documentMode > 7;
+ MENU.Augment({
+ margin: 20,
+ msieBackgroundBug: ((document.documentMode||0) < 9),
+ msieFixedPositionBug: (quirks || !isIE8),
+ msieAboutBug: quirks,
+ msieHeightBug: ((document.documentMode||0) < 9)
+ // height of window doesn't include title bar in XP
+ });
+ if (isIE9) {
+ delete CONFIG.styles["#MathJax_About"].filter;
+ delete CONFIG.styles[".MathJax_Menu"].filter;
+ }
+ },
+ Firefox: function (browser) {
+ MENU.skipMouseover = browser.isMobile && browser.versionAtLeast("6.0");
+ MENU.skipMousedown = browser.isMobile;
+ }
+ });
+ MENU.isMobile = HUB.Browser.isMobile;
+ MENU.noContextMenu = HUB.Browser.noContextMenu;
+
+ /*************************************************************/
+
+ //
+ // Creates the locale menu from the list of locales in MathJax.Localization.strings
+ //
+ MENU.CreateLocaleMenu = function () {
+ if (!MENU.menu) return;
+ var menu = MENU.menu.Find("Language").submenu, items = menu.items;
+ //
+ // Get the names of the languages and sort them
+ //
+ var locales = [], LOCALE = MathJax.Localization.strings;
+ for (var id in LOCALE) {if (LOCALE.hasOwnProperty(id)) {locales.push(id)}}
+ locales = locales.sort(); menu.items = [];
+ //
+ // Add a menu item for each
+ //
+ for (var i = 0, m = locales.length; i < m; i++) {
+ var title = LOCALE[locales[i]].menuTitle;
+ if (title) {title += " ("+locales[i]+")"} else {title = locales[i]}
+ menu.items.push(ITEM.RADIO([locales[i],title],"locale",{action:MENU.Locale}));
+ }
+ //
+ // Add the rule and "Load from URL" items
+ //
+ menu.items.push(items[items.length-2],items[items.length-1]);
+ };
+
+ //
+ // Create the annotation menu from MathJax.Hub.config.semanticsAnnotations
+ //
+ MENU.CreateAnnotationMenu = function () {
+ if (!MENU.menu) return;
+ var menu = MENU.menu.Find("Show Math As","Annotation").submenu;
+ var annotations = CONFIG.semanticsAnnotations;
+ for (var a in annotations) {
+ if (annotations.hasOwnProperty(a)) {
+ menu.items.push(ITEM.COMMAND([a,a], MENU.ShowSource, {hidden: true, nativeTouch: true, format: a}));
+ }
+ }
+ };
+
+ /*************************************************************/
+
+ HUB.Register.StartupHook("End Config",function () {
+
+ /*
+ * Get the menu settings from the HUB (which includes the
+ * data from the cookie already), and add the format, if
+ * it wasn't set in the cookie.
+ */
+ CONFIG.settings = HUB.config.menuSettings;
+ if (typeof(CONFIG.settings.showRenderer) !== "undefined") {CONFIG.showRenderer = CONFIG.settings.showRenderer}
+ if (typeof(CONFIG.settings.showFontMenu) !== "undefined") {CONFIG.showFontMenu = CONFIG.settings.showFontMenu}
+ if (typeof(CONFIG.settings.showContext) !== "undefined") {CONFIG.showContext = CONFIG.settings.showContext}
+ MENU.getCookie();
+
+ /*
+ * The main menu
+ */
+ // Localization: items used as key, should be refactored.
+ MENU.menu = MENU(
+ ITEM.SUBMENU(["Show","Show Math As"],
+ ITEM.COMMAND(["MathMLcode","MathML Code"], MENU.ShowSource, {nativeTouch: true, format: "MathML"}),
+ ITEM.COMMAND(["Original","Original Form"], MENU.ShowSource, {nativeTouch: true}),
+ ITEM.SUBMENU(["Annotation","Annotation"], {disabled:true}),
+ ITEM.RULE(),
+ ITEM.CHECKBOX(["texHints","Show TeX hints in MathML"], "texHints"),
+ ITEM.CHECKBOX(["semantics","Add original form as annotation"], "semantics")
+ ),
+ ITEM.RULE(),
+ ITEM.SUBMENU(["Settings","Math Settings"],
+ ITEM.SUBMENU(["ZoomTrigger","Zoom Trigger"],
+ ITEM.RADIO(["Hover","Hover"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["Click","Click"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["DoubleClick","Double-Click"], "zoom", {action: MENU.Zoom}),
+ ITEM.RADIO(["NoZoom","No Zoom"], "zoom", {value: "None"}),
+ ITEM.RULE(),
+ ITEM.LABEL(["TriggerRequires","Trigger Requires:"]),
+ ITEM.CHECKBOX((HUB.Browser.isMac ? ["Option","Option"] : ["Alt","Alt"]), "ALT"),
+ ITEM.CHECKBOX(["Command","Command"], "CMD", {hidden: !HUB.Browser.isMac}),
+ ITEM.CHECKBOX(["Control","Control"], "CTRL", {hidden: HUB.Browser.isMac}),
+ ITEM.CHECKBOX(["Shift","Shift"], "Shift")
+ ),
+ ITEM.SUBMENU(["ZoomFactor","Zoom Factor"],
+ ITEM.RADIO("125%", "zscale"),
+ ITEM.RADIO("133%", "zscale"),
+ ITEM.RADIO("150%", "zscale"),
+ ITEM.RADIO("175%", "zscale"),
+ ITEM.RADIO("200%", "zscale"),
+ ITEM.RADIO("250%", "zscale"),
+ ITEM.RADIO("300%", "zscale"),
+ ITEM.RADIO("400%", "zscale")
+ ),
+ ITEM.RULE(),
+ ITEM.SUBMENU(["Renderer","Math Renderer"], {hidden:!CONFIG.showRenderer},
+ ITEM.RADIO(["HTML-CSS","HTML-CSS"], "renderer", {action: MENU.Renderer}),
+ ITEM.RADIO(["CommonHTML","Common HTML"], "renderer", {action: MENU.Renderer, value:"CommonHTML"}),
+ ITEM.RADIO(["PreviewHTML","Preview HTML"],"renderer", {action: MENU.Renderer, value:"PreviewHTML"}),
+ ITEM.RADIO(["MathML","MathML"], "renderer", {action: MENU.Renderer, value:"NativeMML"}),
+ ITEM.RADIO(["SVG","SVG"], "renderer", {action: MENU.Renderer}),
+ ITEM.RADIO(["PlainSource","Plain Source"],"renderer", {action: MENU.Renderer, value:"PlainSource"}),
+ ITEM.RULE(),
+ ITEM.CHECKBOX(["FastPreview","Fast Preview"], "FastPreview"),
+ ITEM.CHECKBOX(["AssistiveMML","Assistive MathML"], "assistiveMML", {action:MENU.AssistiveMML}),
+ ITEM.CHECKBOX(["InTabOrder","Include in Tab Order"], "inTabOrder")
+ ),
+ ITEM.SUBMENU("MathPlayer", {hidden:!HUB.Browser.isMSIE || !CONFIG.showMathPlayer,
+ disabled:!HUB.Browser.hasMathPlayer},
+ ITEM.LABEL(["MPHandles","Let MathPlayer Handle:"]),
+ ITEM.CHECKBOX(["MenuEvents","Menu Events"], "mpContext", {action: MENU.MPEvents, hidden:!isIE9}),
+ ITEM.CHECKBOX(["MouseEvents","Mouse Events"], "mpMouse", {action: MENU.MPEvents, hidden:!isIE9}),
+ ITEM.CHECKBOX(["MenuAndMouse","Mouse and Menu Events"], "mpMouse", {action: MENU.MPEvents, hidden:isIE9})
+ ),
+ ITEM.SUBMENU(["FontPrefs","Font Preference"], {hidden:!CONFIG.showFontMenu},
+ ITEM.LABEL(["ForHTMLCSS","For HTML-CSS:"]),
+ ITEM.RADIO(["Auto","Auto"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["TeXLocal","TeX (local)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["TeXWeb","TeX (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["TeXImage","TeX (image)"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["STIXLocal","STIX (local)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["STIXWeb","STIX (web)"], "font", {action: MENU.Font}),
+ ITEM.RULE(),
+ ITEM.RADIO(["AsanaMathWeb","Asana Math (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["GyrePagellaWeb","Gyre Pagella (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["GyreTermesWeb","Gyre Termes (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["LatinModernWeb","Latin Modern (web)"], "font", {action: MENU.Font}),
+ ITEM.RADIO(["NeoEulerWeb","Neo Euler (web)"], "font", {action: MENU.Font})
+ ),
+ ITEM.SUBMENU(["ContextMenu","Contextual Menu"], {hidden:!CONFIG.showContext},
+ ITEM.RADIO(["MathJax","MathJax"], "context"),
+ ITEM.RADIO(["Browser","Browser"], "context")
+ ),
+ ITEM.COMMAND(["Scale","Scale All Math ..."],MENU.Scale),
+ ITEM.RULE().With({hidden:!CONFIG.showDiscoverable, name:["","discover_rule"]}),
+ ITEM.CHECKBOX(["Discoverable","Highlight on Hover"], "discoverable", {hidden:!CONFIG.showDiscoverable})
+ ),
+ ITEM.SUBMENU(["Locale","Language"], {hidden:!CONFIG.showLocale, ltr:true},
+ ITEM.RADIO("en", "locale", {action: MENU.Locale}),
+ ITEM.RULE().With({hidden:!CONFIG.showLocaleURL, name:["","localURL_rule"]}),
+ ITEM.COMMAND(["LoadLocale","Load from URL ..."], MENU.LoadLocale, {hidden:!CONFIG.showLocaleURL})
+ ),
+ ITEM.RULE(),
+ ITEM.COMMAND(["About","About MathJax"],MENU.About),
+ ITEM.COMMAND(["Help","MathJax Help"],MENU.Help)
+ );
+
+ if (MENU.isMobile) {
+ (function () {
+ var settings = CONFIG.settings;
+ var trigger = MENU.menu.Find("Math Settings","Zoom Trigger").submenu;
+ trigger.items[0].disabled = trigger.items[1].disabled = true;
+ if (settings.zoom === "Hover" || settings.zoom == "Click") {settings.zoom = "None"}
+ trigger.items = trigger.items.slice(0,4);
+
+ if (navigator.appVersion.match(/[ (]Android[) ]/)) {
+ MENU.ITEM.SUBMENU.Augment({marker: "\u00BB"});
+ }
+ })();
+ }
+
+ MENU.CreateLocaleMenu();
+ MENU.CreateAnnotationMenu();
+ });
+
+ MENU.showRenderer = function (show) {
+ MENU.cookie.showRenderer = CONFIG.showRenderer = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Math Renderer").hidden = !show;
+ };
+ MENU.showMathPlayer = function (show) {
+ MENU.cookie.showMathPlayer = CONFIG.showMathPlayer = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","MathPlayer").hidden = !show;
+ };
+ MENU.showFontMenu = function (show) {
+ MENU.cookie.showFontMenu = CONFIG.showFontMenu = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Font Preference").hidden = !show;
+ };
+ MENU.showContext = function (show) {
+ MENU.cookie.showContext = CONFIG.showContext = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Contextual Menu").hidden = !show;
+ };
+ MENU.showDiscoverable = function (show) {
+ MENU.cookie.showDiscoverable = CONFIG.showDiscoverable = show; MENU.saveCookie();
+ MENU.menu.Find("Math Settings","Highlight on Hover").hidden = !show;
+ MENU.menu.Find("Math Settings","discover_rule").hidden = !show;
+ };
+ MENU.showLocale = function (show) {
+ MENU.cookie.showLocale = CONFIG.showLocale = show; MENU.saveCookie();
+ MENU.menu.Find("Language").hidden = !show;
+ };
+
+ MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () {
+ if (!MathJax.OutputJax["HTML-CSS"].config.imageFont)
+ {MENU.menu.Find("Math Settings","Font Preference","TeX (image)").disabled = true}
+ });
+
+ /*************************************************************/
+
+ CALLBACK.Queue(
+ HUB.Register.StartupHook("End Config",{}), // wait until config is complete
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathMenu Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.CallBack,MathJax.OutputJax);
diff --git a/MarkDownEditor/MathJax/extensions/MathZoom.js b/MarkDownEditor/MathJax/extensions/MathZoom.js
new file mode 100644
index 0000000..6f087f8
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/MathZoom.js
@@ -0,0 +1,366 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/MathZoom.js
+ *
+ * Implements the zoom feature for enlarging math expressions. It is
+ * loaded automatically when the Zoom menu selection changes from "None".
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2015 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.
+ */
+
+(function (HUB,HTML,AJAX,HTMLCSS,nMML) {
+ var VERSION = "2.6.0";
+
+ var CONFIG = HUB.CombineConfig("MathZoom",{
+ styles: {
+ //
+ // The styles for the MathZoom display box
+ //
+ "#MathJax_Zoom": {
+ position:"absolute", "background-color":"#F0F0F0", overflow:"auto",
+ display:"block", "z-index":301, padding:".5em", border:"1px solid black", margin:0,
+ "font-weight":"normal", "font-style":"normal",
+ "text-align":"left", "text-indent":0, "text-transform":"none",
+ "line-height":"normal", "letter-spacing":"normal", "word-spacing":"normal",
+ "word-wrap":"normal", "white-space":"nowrap", "float":"none",
+ "-webkit-box-sizing":"content-box", // Android ≤ 2.3, iOS ≤ 4
+ "-moz-box-sizing":"content-box", // Firefox ≤ 28
+ "box-sizing":"content-box", // Chrome, Firefox 29+, IE 8+, Opera, Safari 5.1
+ "box-shadow":"5px 5px 15px #AAAAAA", // Opera 10.5 and IE9
+ "-webkit-box-shadow":"5px 5px 15px #AAAAAA", // Safari 3 and Chrome
+ "-moz-box-shadow":"5px 5px 15px #AAAAAA", // Forefox 3.5
+ "-khtml-box-shadow":"5px 5px 15px #AAAAAA", // Konqueror
+ filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')" // IE
+ },
+
+ //
+ // The styles for the hidden overlay (should not need to be adjusted by the page author)
+ //
+ "#MathJax_ZoomOverlay": {
+ position:"absolute", left:0, top:0, "z-index":300, display:"inline-block",
+ width:"100%", height:"100%", border:0, padding:0, margin:0,
+ "background-color":"white", opacity:0, filter:"alpha(opacity=0)"
+ },
+
+ "#MathJax_ZoomFrame": {
+ position:"relative", display:"inline-block",
+ height:0, width:0
+ },
+
+ "#MathJax_ZoomEventTrap": {
+ position:"absolute", left:0, top:0, "z-index":302,
+ display:"inline-block", border:0, padding:0, margin:0,
+ "background-color":"white", opacity:0, filter:"alpha(opacity=0)"
+ }
+ }
+ });
+
+ var FALSE, HOVER, EVENT;
+ MathJax.Hub.Register.StartupHook("MathEvents Ready",function () {
+ EVENT = MathJax.Extension.MathEvents.Event;
+ FALSE = MathJax.Extension.MathEvents.Event.False;
+ HOVER = MathJax.Extension.MathEvents.Hover;
+ });
+
+ /*************************************************************/
+
+ var ZOOM = MathJax.Extension.MathZoom = {
+ version: VERSION,
+ settings: HUB.config.menuSettings,
+ scrollSize: 18, // width of scrool bars
+
+ //
+ // Process events passed from output jax
+ //
+ HandleEvent: function (event,type,math) {
+ if (ZOOM.settings.CTRL && !event.ctrlKey) return true;
+ if (ZOOM.settings.ALT && !event.altKey) return true;
+ if (ZOOM.settings.CMD && !event.metaKey) return true;
+ if (ZOOM.settings.Shift && !event.shiftKey) return true;
+ if (!ZOOM[type]) return true;
+ return ZOOM[type](event,math);
+ },
+
+ //
+ // Zoom on click
+ //
+ Click: function (event,math) {
+ if (this.settings.zoom === "Click") {return this.Zoom(event,math)}
+ },
+
+ //
+ // Zoom on double click
+ //
+ DblClick: function (event,math) {
+ if (this.settings.zoom === "Double-Click" || this.settings.zoom === "DoubleClick") {return this.Zoom(event,math)}
+ },
+
+ //
+ // Zoom on hover (called by MathEvents.Hover)
+ //
+ Hover: function (event,math) {
+ if (this.settings.zoom === "Hover") {this.Zoom(event,math); return true}
+ return false;
+ },
+
+
+ //
+ // Handle the actual zooming
+ //
+ Zoom: function (event,math) {
+ //
+ // Remove any other zoom and clear timers
+ //
+ this.Remove(); HOVER.ClearHoverTimer(); EVENT.ClearSelection();
+
+ //
+ // Find the jax
+ //
+ var JAX = MathJax.OutputJax[math.jaxID];
+ var jax = JAX.getJaxFromMath(math);
+ if (jax.hover) {HOVER.UnHover(jax)}
+
+ //
+ // Create the DOM elements for the zoom box
+ //
+ var container = this.findContainer(math);
+ var Mw = Math.floor(.85*container.clientWidth),
+ Mh = Math.max(document.body.clientHeight,document.documentElement.clientHeight);
+ if (this.getOverflow(container) !== "visible") {Mh = Math.min(container.clientHeight,Mh)}
+ Mh = Math.floor(.85*Mh);
+ var div = HTML.Element(
+ "span",{id:"MathJax_ZoomFrame"},[
+ ["span",{id:"MathJax_ZoomOverlay", onmousedown:this.Remove}],
+ ["span",{
+ id:"MathJax_Zoom", onclick:this.Remove,
+ style:{visibility:"hidden", fontSize:this.settings.zscale}
+ },[["span",{style:{display:"inline-block", "white-space":"nowrap"}}]]
+ ]]
+ );
+ var zoom = div.lastChild, span = zoom.firstChild, overlay = div.firstChild;
+ math.parentNode.insertBefore(div,math); math.parentNode.insertBefore(math,div); // put div after math
+ if (span.addEventListener) {span.addEventListener("mousedown",this.Remove,true)}
+ var eW = zoom.offsetWidth || zoom.clientWidth; Mw -= eW; Mh -= eW;
+ zoom.style.maxWidth = Mw+"px"; zoom.style.maxHeight = Mh+"px";
+
+ if (this.msieTrapEventBug) {
+ var trap = HTML.Element("span",{id:"MathJax_ZoomEventTrap", onmousedown:this.Remove});
+ div.insertBefore(trap,zoom);
+ }
+
+ //
+ // Display the zoomed math
+ //
+ if (this.msieZIndexBug) {
+ // MSIE doesn't do z-index properly, so move the div to the document.body,
+ // and use an image as a tracker for the usual position
+ var tracker = HTML.addElement(document.body,"img",{
+ src:"about:blank", id:"MathJax_ZoomTracker", width:0, height:0,
+ style:{width:0, height:0, position:"relative"}
+ });
+ div.style.position = "relative";
+ div.style.zIndex = CONFIG.styles["#MathJax_ZoomOverlay"]["z-index"];
+ div = tracker;
+ }
+
+ var bbox = JAX.Zoom(jax,span,math,Mw,Mh);
+
+ //
+ // Fix up size and position for browsers with bugs (IE)
+ //
+ if (this.msiePositionBug) {
+ if (this.msieSizeBug)
+ {zoom.style.height = bbox.zH+"px"; zoom.style.width = bbox.zW+"px"} // IE8 gets the dimensions completely wrong
+ if (zoom.offsetHeight > Mh) {zoom.style.height = Mh+"px"; zoom.style.width = (bbox.zW+this.scrollSize)+"px"} // IE doesn't do max-height?
+ if (zoom.offsetWidth > Mw) {zoom.style.width = Mw+"px"; zoom.style.height = (bbox.zH+this.scrollSize)+"px"}
+ }
+ if (this.operaPositionBug) {zoom.style.width = Math.min(Mw,bbox.zW)+"px"} // Opera gets width as 0?
+ if (zoom.offsetWidth > eW && zoom.offsetWidth-eW < Mw && zoom.offsetHeight-eW < Mh)
+ {zoom.style.overflow = "visible"} // don't show scroll bars if we don't need to
+ this.Position(zoom,bbox);
+ if (this.msieTrapEventBug) {
+ trap.style.height = zoom.clientHeight+"px"; trap.style.width = zoom.clientWidth+"px";
+ trap.style.left = (parseFloat(zoom.style.left)+zoom.clientLeft)+"px";
+ trap.style.top = (parseFloat(zoom.style.top)+zoom.clientTop)+"px";
+ }
+ zoom.style.visibility = "";
+
+ //
+ // Add event handlers
+ //
+ if (this.settings.zoom === "Hover") {overlay.onmouseover = this.Remove}
+ if (window.addEventListener) {addEventListener("resize",this.Resize,false)}
+ else if (window.attachEvent) {attachEvent("onresize",this.Resize)}
+ else {this.onresize = window.onresize; window.onresize = this.Resize}
+
+ //
+ // Let others know about the zoomed math
+ //
+ HUB.signal.Post(["math zoomed",jax]);
+
+ //
+ // Canel further actions
+ //
+ return FALSE(event);
+ },
+
+ //
+ // Set the position of the zoom box and overlay
+ //
+ Position: function (zoom,bbox) {
+ zoom.style.display = "none"; // avoids getting excessive width in Resize()
+ var XY = this.Resize(), x = XY.x, y = XY.y, W = bbox.mW;
+ zoom.style.display = "";
+ var dx = -W-Math.floor((zoom.offsetWidth-W)/2), dy = bbox.Y;
+ zoom.style.left = Math.max(dx,10-x)+"px"; zoom.style.top = Math.max(dy,10-y)+"px";
+ if (!ZOOM.msiePositionBug) {ZOOM.SetWH()} // refigure overlay width/height
+ },
+
+ //
+ // Handle resizing of overlay while zoom is displayed
+ //
+ Resize: function (event) {
+ if (ZOOM.onresize) {ZOOM.onresize(event)}
+ var div = document.getElementById("MathJax_ZoomFrame"),
+ overlay = document.getElementById("MathJax_ZoomOverlay");
+ var xy = ZOOM.getXY(div), obj = ZOOM.findContainer(div);
+ if (ZOOM.getOverflow(obj) !== "visible") {
+ overlay.scroll_parent = obj; // Save this for future reference.
+ var XY = ZOOM.getXY(obj); // Remove container position
+ xy.x -= XY.x; xy.y -= XY.y;
+ XY = ZOOM.getBorder(obj); // Remove container border
+ xy.x -= XY.x; xy.y -= XY.y;
+ }
+ overlay.style.left = (-xy.x)+"px"; overlay.style.top = (-xy.y)+"px";
+ if (ZOOM.msiePositionBug) {setTimeout(ZOOM.SetWH,0)} else {ZOOM.SetWH()}
+ return xy;
+ },
+ SetWH: function () {
+ var overlay = document.getElementById("MathJax_ZoomOverlay");
+ if (!overlay) return;
+ overlay.style.display = "none"; // so scrollWidth/Height will be right below
+ var doc = overlay.scroll_parent || document.documentElement || document.body;
+ overlay.style.width = doc.scrollWidth + "px";
+ overlay.style.height = Math.max(doc.clientHeight,doc.scrollHeight) + "px";
+ overlay.style.display = "";
+ },
+ findContainer: function (obj) {
+ obj = obj.parentNode;
+ while (obj.parentNode && obj !== document.body && ZOOM.getOverflow(obj) === "visible")
+ {obj = obj.parentNode}
+ return obj;
+ },
+ //
+ // Look up CSS properties (use getComputeStyle if available, or currentStyle if not)
+ //
+ getOverflow: (window.getComputedStyle ?
+ function (obj) {return getComputedStyle(obj).overflow} :
+ function (obj) {return (obj.currentStyle||{overflow:"visible"}).overflow}),
+ getBorder: function (obj) {
+ var size = {thin: 1, medium: 2, thick: 3};
+ var style = (window.getComputedStyle ? getComputedStyle(obj) :
+ (obj.currentStyle || {borderLeftWidth:0,borderTopWidth:0}));
+ var x = style.borderLeftWidth, y = style.borderTopWidth;
+ if (size[x]) {x = size[x]} else {x = parseInt(x)}
+ if (size[y]) {y = size[y]} else {y = parseInt(y)}
+ return {x:x, y:y};
+ },
+ //
+ // Get the position of an element on the page
+ //
+ getXY: function (div) {
+ var x = 0, y = 0, obj;
+ obj = div; while (obj.offsetParent) {x += obj.offsetLeft; obj = obj.offsetParent}
+ if (ZOOM.operaPositionBug) {div.style.border = "1px solid"} // to get vertical position right
+ obj = div; while (obj.offsetParent) {y += obj.offsetTop; obj = obj.offsetParent}
+ if (ZOOM.operaPositionBug) {div.style.border = ""}
+ return {x:x, y:y};
+ },
+
+ //
+ // Remove zoom display and event handlers
+ //
+ Remove: function (event) {
+ var div = document.getElementById("MathJax_ZoomFrame");
+ if (div) {
+ var JAX = MathJax.OutputJax[div.previousSibling.jaxID];
+ var jax = JAX.getJaxFromMath(div.previousSibling);
+ HUB.signal.Post(["math unzoomed",jax]);
+ div.parentNode.removeChild(div);
+ div = document.getElementById("MathJax_ZoomTracker");
+ if (div) {div.parentNode.removeChild(div)}
+ if (ZOOM.operaRefreshBug) {
+ // force a redisplay of the page
+ // (Opera doesn't refresh properly after the zoom is removed)
+ var overlay = HTML.addElement(document.body,"div",{
+ style:{position:"fixed", left:0, top:0, width:"100%", height:"100%",
+ backgroundColor:"white", opacity:0},
+ id: "MathJax_OperaDiv"
+ });
+ document.body.removeChild(overlay);
+ }
+ if (window.removeEventListener) {removeEventListener("resize",ZOOM.Resize,false)}
+ else if (window.detachEvent) {detachEvent("onresize",ZOOM.Resize)}
+ else {window.onresize = ZOOM.onresize; delete ZOOM.onresize}
+ }
+ return FALSE(event);
+ }
+
+ };
+
+
+ /*************************************************************/
+
+ HUB.Browser.Select({
+ MSIE: function (browser) {
+ var mode = (document.documentMode || 0);
+ var isIE9 = (mode >= 9);
+ ZOOM.msiePositionBug = !isIE9;
+ ZOOM.msieSizeBug = browser.versionAtLeast("7.0") &&
+ (!document.documentMode || mode === 7 || mode === 8);
+ ZOOM.msieZIndexBug = (mode <= 7);
+ ZOOM.msieInlineBlockAlignBug = (mode <= 7);
+ ZOOM.msieTrapEventBug = !window.addEventListener;
+ if (document.compatMode === "BackCompat") {ZOOM.scrollSize = 52} // don't know why this is so far off
+ if (isIE9) {delete CONFIG.styles["#MathJax_Zoom"].filter}
+ },
+
+ Opera: function (browser) {
+ ZOOM.operaPositionBug = true;
+ ZOOM.operaRefreshBug = true;
+ }
+ });
+
+ ZOOM.topImg = (ZOOM.msieInlineBlockAlignBug ?
+ HTML.Element("img",{style:{width:0,height:0,position:"relative"},src:"about:blank"}) :
+ HTML.Element("span",{style:{width:0,height:0,display:"inline-block"}})
+ );
+ if (ZOOM.operaPositionBug || ZOOM.msieTopBug) {ZOOM.topImg.style.border="1px solid"}
+
+ /*************************************************************/
+
+ MathJax.Callback.Queue(
+ ["StartupHook",MathJax.Hub.Register,"Begin Styles",{}],
+ ["Styles",AJAX,CONFIG.styles],
+ ["Post",HUB.Startup.signal,"MathZoom Ready"],
+ ["loadComplete",AJAX,"[MathJax]/extensions/MathZoom.js"]
+ );
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.OutputJax["HTML-CSS"],MathJax.OutputJax.NativeMML);
diff --git a/MarkDownEditor/MathJax/extensions/TeX/AMSmath.js b/MarkDownEditor/MathJax/extensions/TeX/AMSmath.js
new file mode 100644
index 0000000..c0fd6b1
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/TeX/AMSmath.js
@@ -0,0 +1,641 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/AMSmath.js
+ *
+ * Implements AMS math environments and macros.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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/AMSmath"] = {
+ version: "2.6.1",
+
+ number: 0, // current equation number
+ startNumber: 0, // current starting equation number (for when equation is restarted)
+ IDs: {}, // IDs used in previous equations
+ eqIDs: {}, // IDs used in this equation
+ labels: {}, // the set of labels
+ eqlabels: {}, // labels in the current equation
+ refs: [] // array of jax with unresolved references
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+
+ var MML = MathJax.ElementJax.mml,
+ TEX = MathJax.InputJax.TeX,
+ AMS = MathJax.Extension["TeX/AMSmath"];
+
+ var TEXDEF = TEX.Definitions,
+ STACKITEM = TEX.Stack.Item,
+ CONFIG = TEX.config.equationNumbers;
+
+ var COLS = function (W) {
+ var WW = [];
+ for (var i = 0, m = W.length; i < m; i++)
+ {WW[i] = TEX.Parse.prototype.Em(W[i])}
+ return WW.join(" ");
+ };
+
+ /******************************************************************************/
+
+ TEXDEF.Add({
+ mathchar0mo: {
+ iiiint: ['2A0C',{texClass: MML.TEXCLASS.OP}]
+ },
+
+ macros: {
+ mathring: ['Accent','2DA'], // or 0x30A
+
+ nobreakspace: 'Tilde',
+ negmedspace: ['Spacer',MML.LENGTH.NEGATIVEMEDIUMMATHSPACE],
+ negthickspace: ['Spacer',MML.LENGTH.NEGATIVETHICKMATHSPACE],
+
+// intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'],
+// iint: ['MultiIntegral','\\int\\intI'], // now in core TeX input jax
+// iiint: ['MultiIntegral','\\int\\intI\\intI'], // now in core TeX input jax
+// iiiint: ['MultiIntegral','\\int\\intI\\intI\\intI'], // now in mathchar0mo above
+ idotsint: ['MultiIntegral','\\int\\cdots\\int'],
+
+// dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}}',1],
+// ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}\\mathord{.}}',1],
+ dddot: ['Accent','20DB'],
+ ddddot: ['Accent','20DC'],
+
+ sideset: ['Macro','\\mathop{\\mathop{\\rlap{\\phantom{#3}}}\\nolimits#1\\!\\mathop{#3}\\nolimits#2}',3],
+
+ boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1],
+
+ tag: 'HandleTag',
+ notag: 'HandleNoTag',
+ label: 'HandleLabel',
+ ref: 'HandleRef',
+ eqref: ['HandleRef',true],
+
+ substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1],
+
+ injlim: ['NamedOp','inj lim'],
+ projlim: ['NamedOp','proj lim'],
+ varliminf: ['Macro','\\mathop{\\underline{\\mmlToken{mi}{lim}}}'],
+ varlimsup: ['Macro','\\mathop{\\overline{\\mmlToken{mi}{lim}}}'],
+ varinjlim: ['Macro','\\mathop{\\underrightarrow{\\mmlToken{mi}{lim}}}'],
+ varprojlim: ['Macro','\\mathop{\\underleftarrow{\\mmlToken{mi}{lim}}}'],
+
+ DeclareMathOperator: 'HandleDeclareOp',
+ operatorname: 'HandleOperatorName',
+ SkipLimits: 'SkipLimits',
+
+ genfrac: 'Genfrac',
+ frac: ['Genfrac',"","","",""],
+ tfrac: ['Genfrac',"","","",1],
+ dfrac: ['Genfrac',"","","",0],
+ binom: ['Genfrac',"(",")","0",""],
+ tbinom: ['Genfrac',"(",")","0",1],
+ dbinom: ['Genfrac',"(",")","0",0],
+
+ cfrac: 'CFrac',
+
+ shoveleft: ['HandleShove',MML.ALIGN.LEFT],
+ shoveright: ['HandleShove',MML.ALIGN.RIGHT],
+
+ xrightarrow: ['xArrow',0x2192,5,6],
+ xleftarrow: ['xArrow',0x2190,7,3]
+ },
+
+ environment: {
+ align: ['AMSarray',null,true,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])],
+ 'align*': ['AMSarray',null,false,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])],
+ multline: ['Multline',null,true],
+ 'multline*': ['Multline',null,false],
+ split: ['AMSarray',null,false,false,'rl',COLS([0])],
+ gather: ['AMSarray',null,true,true, 'c'],
+ 'gather*': ['AMSarray',null,false,true, 'c'],
+
+ alignat: ['AlignAt',null,true,true],
+ 'alignat*': ['AlignAt',null,false,true],
+ alignedat: ['AlignAt',null,false,false],
+
+ aligned: ['AlignedAMSArray',null,null,null,'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0]),".5em",'D'],
+ gathered: ['AlignedAMSArray',null,null,null,'c',null,".5em",'D'],
+
+ subarray: ['Array',null,null,null,null,COLS([0]),"0.1em",'S',1],
+ smallmatrix: ['Array',null,null,null,'c',COLS([1/3]),".2em",'S',1],
+
+ 'equation': ['EquationBegin','Equation',true],
+ 'equation*': ['EquationBegin','EquationStar',false],
+
+ eqnarray: ['AMSarray',null,true,true, 'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"],
+ 'eqnarray*': ['AMSarray',null,false,true,'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"]
+ },
+
+ delimiter: {
+ '\\lvert': ['2223',{texClass:MML.TEXCLASS.OPEN}],
+ '\\rvert': ['2223',{texClass:MML.TEXCLASS.CLOSE}],
+ '\\lVert': ['2225',{texClass:MML.TEXCLASS.OPEN}],
+ '\\rVert': ['2225',{texClass:MML.TEXCLASS.CLOSE}]
+ }
+ },null,true);
+
+
+ /******************************************************************************/
+
+ TEX.Parse.Augment({
+
+ /*
+ * Add the tag to the environment (to be added to the table row later)
+ */
+ HandleTag: function (name) {
+ var star = this.GetStar();
+ var arg = this.trimSpaces(this.GetArgument(name)), tag = arg;
+ if (!star) {arg = CONFIG.formatTag(arg)}
+ var global = this.stack.global; global.tagID = tag;
+ if (global.notags) {
+ TEX.Error(["CommandNotAllowedInEnv",
+ "%1 not allowed in %2 environment",
+ name,global.notags]
+ );
+ }
+ if (global.tag) {TEX.Error(["MultipleCommand","Multiple %1",name])}
+ global.tag = MML.mtd.apply(MML,this.InternalMath(arg)).With({id:CONFIG.formatID(tag)});
+ },
+ HandleNoTag: function (name) {
+ if (this.stack.global.tag) {delete this.stack.global.tag}
+ this.stack.global.notag = true; // prevent auto-tagging
+ },
+
+ /*
+ * Record a label name for a tag
+ */
+ HandleLabel: function (name) {
+ var global = this.stack.global, label = this.GetArgument(name);
+ if (label === "") return;
+ if (!AMS.refUpdate) {
+ if (global.label) {TEX.Error(["MultipleCommand","Multiple %1",name])}
+ global.label = label;
+ if (AMS.labels[label] || AMS.eqlabels[label])
+ {TEX.Error(["MultipleLabel","Label '%1' multiply defined",label])}
+ AMS.eqlabels[label] = {tag:"???", id:""}; // will be replaced by tag value later
+ }
+ },
+
+ /*
+ * Handle a label reference
+ */
+ HandleRef: function (name,eqref) {
+ var label = this.GetArgument(name);
+ var ref = AMS.labels[label] || AMS.eqlabels[label];
+ if (!ref) {ref = {tag:"???",id:""}; AMS.badref = !AMS.refUpdate}
+ var tag = ref.tag; if (eqref) {tag = CONFIG.formatTag(tag)}
+ this.Push(MML.mrow.apply(MML,this.InternalMath(tag)).With({
+ href:CONFIG.formatURL(ref.id), "class":"MathJax_ref"
+ }));
+ },
+
+ /*
+ * Handle \DeclareMathOperator
+ */
+ HandleDeclareOp: function (name) {
+ var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits");
+ var cs = this.trimSpaces(this.GetArgument(name));
+ if (cs.charAt(0) == "\\") {cs = cs.substr(1)}
+ var op = this.GetArgument(name);
+ op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}');
+ TEX.Definitions.macros[cs] = ['Macro','\\mathop{\\rm '+op+'}'+limits];
+ },
+
+ HandleOperatorName: function (name) {
+ var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits");
+ var op = this.trimSpaces(this.GetArgument(name));
+ op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}');
+ this.string = '\\mathop{\\rm '+op+'}'+limits+" "+this.string.slice(this.i);
+ this.i = 0;
+ },
+
+ SkipLimits: function (name) {
+ var c = this.GetNext(), i = this.i;
+ if (c === "\\" && ++this.i && this.GetCS() !== "limits") this.i = i;
+ },
+
+ /*
+ * Record presence of \shoveleft and \shoveright
+ */
+ HandleShove: function (name,shove) {
+ var top = this.stack.Top();
+ if (top.type !== "multline" || top.data.length) {
+ TEX.Error(["CommandAtTheBeginingOfLine",
+ "%1 must come at the beginning of the line",name]);
+ }
+ top.data.shove = shove;
+ },
+
+ /*
+ * Handle \cfrac
+ */
+ CFrac: function (name) {
+ var lr = this.trimSpaces(this.GetBrackets(name,"")),
+ num = this.GetArgument(name),
+ den = this.GetArgument(name);
+ var frac = MML.mfrac(TEX.Parse('\\strut\\textstyle{'+num+'}',this.stack.env).mml(),
+ TEX.Parse('\\strut\\textstyle{'+den+'}',this.stack.env).mml());
+ lr = ({l:MML.ALIGN.LEFT, r:MML.ALIGN.RIGHT,"":""})[lr];
+ if (lr == null)
+ {TEX.Error(["IllegalAlign","Illegal alignment specified in %1",name])}
+ if (lr) {frac.numalign = frac.denomalign = lr}
+ this.Push(frac);
+ },
+
+ /*
+ * Implement AMS generalized fraction
+ */
+ Genfrac: function (name,left,right,thick,style) {
+ if (left == null) {left = this.GetDelimiterArg(name)}
+ if (right == null) {right = this.GetDelimiterArg(name)}
+ if (thick == null) {thick = this.GetArgument(name)}
+ if (style == null) {style = this.trimSpaces(this.GetArgument(name))}
+ var num = this.ParseArg(name);
+ var den = this.ParseArg(name);
+ var frac = MML.mfrac(num,den);
+ if (thick !== "") {frac.linethickness = thick}
+ if (left || right) {frac = TEX.fixedFence(left,frac.With({texWithDelims:true}),right)}
+ if (style !== "") {
+ var STYLE = (["D","T","S","SS"])[style];
+ if (STYLE == null)
+ {TEX.Error(["BadMathStyleFor","Bad math style for %1",name])}
+ frac = MML.mstyle(frac);
+ if (STYLE === "D") {frac.displaystyle = true; frac.scriptlevel = 0}
+ else {frac.displaystyle = false; frac.scriptlevel = style - 1}
+ }
+ this.Push(frac);
+ },
+
+ /*
+ * Implements multline environment (mostly handled through STACKITEM below)
+ */
+ Multline: function (begin,numbered) {
+ this.Push(begin); this.checkEqnEnv();
+ return STACKITEM.multline(numbered,this.stack).With({
+ arraydef: {
+ displaystyle: true,
+ rowspacing: ".5em",
+ width: TEX.config.MultLineWidth, columnwidth:"100%",
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent
+ }
+ });
+ },
+
+ /*
+ * Handle AMS aligned environments
+ */
+ AMSarray: function (begin,numbered,taggable,align,spacing) {
+ this.Push(begin); if (taggable) {this.checkEqnEnv()}
+ align = align.replace(/[^clr]/g,'').split('').join(' ');
+ align = align.replace(/l/g,'left').replace(/r/g,'right').replace(/c/g,'center');
+ return STACKITEM.AMSarray(begin.name,numbered,taggable,this.stack).With({
+ arraydef: {
+ displaystyle: true,
+ rowspacing: ".5em",
+ columnalign: align,
+ columnspacing: (spacing||"1em"),
+ rowspacing: "3pt",
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent
+ }
+ });
+ },
+
+ AlignedAMSArray: function (begin) {
+ var align = this.GetBrackets("\\begin{"+begin.name+"}");
+ return this.setArrayAlign(this.AMSarray.apply(this,arguments),align);
+ },
+
+ /*
+ * Handle alignat environments
+ */
+ AlignAt: function (begin,numbered,taggable) {
+ var n, valign, align = "", spacing = [];
+ if (!taggable) {valign = this.GetBrackets("\\begin{"+begin.name+"}")}
+ n = this.GetArgument("\\begin{"+begin.name+"}");
+ if (n.match(/[^0-9]/)) {
+ TEX.Error(["PositiveIntegerArg","Argument to %1 must me a positive integer",
+ "\\begin{"+begin.name+"}"]);
+ }
+ while (n > 0) {align += "rl"; spacing.push("0em 0em"); n--}
+ spacing = spacing.join(" ");
+ if (taggable) {return this.AMSarray(begin,numbered,taggable,align,spacing)}
+ var array = this.AMSarray(begin,numbered,taggable,align,spacing);
+ return this.setArrayAlign(array,valign);
+ },
+
+ /*
+ * Handle equation environment
+ */
+ EquationBegin: function (begin,force) {
+ this.checkEqnEnv();
+ this.stack.global.forcetag = (force && CONFIG.autoNumber !== "none");
+ return begin;
+ },
+ EquationStar: function (begin,row) {
+ this.stack.global.tagged = true; // prevent automatic tagging
+ return row;
+ },
+
+ /*
+ * Check for bad nesting of equation environments
+ */
+ checkEqnEnv: function () {
+ if (this.stack.global.eqnenv)
+ {TEX.Error(["ErroneousNestingEq","Erroneous nesting of equation structures"])}
+ this.stack.global.eqnenv = true;
+ },
+
+ /*
+ * Handle multiple integrals (make a mathop if followed by limits)
+ */
+ MultiIntegral: function (name,integral) {
+ var next = this.GetNext();
+ if (next === "\\") {
+ var i = this.i; next = this.GetArgument(name); this.i = i;
+ if (next === "\\limits") {
+ if (name === "\\idotsint") {integral = "\\!\\!\\mathop{\\,\\,"+integral+"}"}
+ else {integral = "\\!\\!\\!\\mathop{\\,\\,\\,"+integral+"}"}
+ }
+ }
+ this.string = integral + " " + this.string.slice(this.i);
+ this.i = 0;
+ },
+
+ /*
+ * Handle stretchable arrows
+ */
+ xArrow: function (name,chr,l,r) {
+ var def = {width: "+"+(l+r)+"mu", lspace: l+"mu"};
+ var bot = this.GetBrackets(name),
+ top = this.ParseArg(name);
+ var arrow = MML.mo(MML.chars(String.fromCharCode(chr))).With({
+ stretchy: true, texClass: MML.TEXCLASS.REL
+ });
+ var mml = MML.munderover(arrow);
+ mml.SetData(mml.over,MML.mpadded(top).With(def).With({voffset:".15em"}));
+ if (bot) {
+ bot = TEX.Parse(bot,this.stack.env).mml()
+ mml.SetData(mml.under,MML.mpadded(bot).With(def).With({voffset:"-.24em"}));
+ }
+ this.Push(mml.With({subsupOK:true}));
+ },
+
+ /*
+ * Get a delimiter or empty argument
+ */
+ GetDelimiterArg: function (name) {
+ var c = this.trimSpaces(this.GetArgument(name));
+ if (c == "") return null;
+ if (c in TEXDEF.delimiter) return c;
+ TEX.Error(["MissingOrUnrecognizedDelim","Missing or unrecognized delimiter for %1",name]);
+ },
+
+ /*
+ * Get a star following a control sequence name, if any
+ */
+ GetStar: function () {
+ var star = (this.GetNext() === "*");
+ if (star) {this.i++}
+ return star;
+ }
+
+ });
+
+ /******************************************************************************/
+
+ STACKITEM.Augment({
+ /*
+ * Increment equation number and form tag mtd element
+ */
+ autoTag: function () {
+ var global = this.global;
+ if (!global.notag) {
+ AMS.number++; global.tagID = CONFIG.formatNumber(AMS.number.toString());
+ var mml = TEX.Parse("\\text{"+CONFIG.formatTag(global.tagID)+"}",{}).mml();
+ global.tag = MML.mtd(mml).With({id:CONFIG.formatID(global.tagID)});
+ }
+ },
+
+ /*
+ * Get the tag and record the label, if any
+ */
+ getTag: function () {
+ var global = this.global, tag = global.tag; global.tagged = true;
+ if (global.label) {
+ if (CONFIG.useLabelIds) {tag.id = CONFIG.formatID(global.label)}
+ AMS.eqlabels[global.label] = {tag:global.tagID, id:tag.id};
+ }
+ //
+ // Check for repeated ID's (either in the document or as
+ // a previous tag) and find a unique related one. (#240)
+ //
+ if (document.getElementById(tag.id) || AMS.IDs[tag.id] || AMS.eqIDs[tag.id]) {
+ var i = 0, ID;
+ do {i++; ID = tag.id+"_"+i}
+ while (document.getElementById(ID) || AMS.IDs[ID] || AMS.eqIDs[ID]);
+ tag.id = ID; if (global.label) {AMS.eqlabels[global.label].id = ID}
+ }
+ AMS.eqIDs[tag.id] = 1;
+ this.clearTag();
+ return tag;
+ },
+ clearTag: function () {
+ var global = this.global;
+ delete global.tag; delete global.tagID; delete global.label;
+ },
+
+ /*
+ * If the initial child, skipping any initial space or
+ * empty braces (TeXAtom with child being an empty inferred row),
+ * is an , preceed it by an empty to force the to
+ * be infix.
+ */
+ fixInitialMO: function (data) {
+ for (var i = 0, m = data.length; i < m; i++) {
+ if (data[i] && (data[i].type !== "mspace" &&
+ (data[i].type !== "texatom" || (data[i].data[0] && data[i].data[0].data.length)))) {
+ if (data[i].isEmbellished()) data.unshift(MML.mi());
+ break;
+ }
+ }
+ }
+ });
+
+ /*
+ * Implement multline environment via a STACKITEM
+ */
+ STACKITEM.multline = STACKITEM.array.Subclass({
+ type: "multline",
+ Init: function (numbered,stack) {
+ this.SUPER(arguments).Init.apply(this);
+ this.numbered = (numbered && CONFIG.autoNumber !== "none");
+ this.save = {notag: stack.global.notag};
+ stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments
+ },
+ EndEntry: function () {
+ if (this.table.length) {this.fixInitialMO(this.data)}
+ var mtd = MML.mtd.apply(MML,this.data);
+ if (this.data.shove) {mtd.columnalign = this.data.shove}
+ this.row.push(mtd);
+ this.data = [];
+ },
+ EndRow: function () {
+ if (this.row.length != 1) {
+ TEX.Error(["MultlineRowsOneCol",
+ "The rows within the %1 environment must have exactly one column",
+ "multline"]);
+ }
+ this.table.push(this.row); this.row = [];
+ },
+ EndTable: function () {
+ this.SUPER(arguments).EndTable.call(this);
+ if (this.table.length) {
+ var m = this.table.length-1, i, label = -1;
+ if (!this.table[0][0].columnalign) {this.table[0][0].columnalign = MML.ALIGN.LEFT}
+ if (!this.table[m][0].columnalign) {this.table[m][0].columnalign = MML.ALIGN.RIGHT}
+ if (!this.global.tag && this.numbered) {this.autoTag()}
+ if (this.global.tag && !this.global.notags) {
+ label = (this.arraydef.side === "left" ? 0 : this.table.length - 1);
+ this.table[label] = [this.getTag()].concat(this.table[label]);
+ }
+ for (i = 0, m = this.table.length; i < m; i++) {
+ var mtr = (i === label ? MML.mlabeledtr : MML.mtr);
+ this.table[i] = mtr.apply(MML,this.table[i]);
+ }
+ }
+ this.global.notag = this.save.notag;
+ }
+ });
+
+ /*
+ * Save data about numbering and taging equations, and add
+ * tags at the ends of rows.
+ */
+ STACKITEM.AMSarray = STACKITEM.array.Subclass({
+ type: "AMSarray",
+ Init: function (name,numbered,taggable,stack) {
+ this.SUPER(arguments).Init.apply(this);
+ this.numbered = (numbered && CONFIG.autoNumber !== "none");
+ this.save = {notags: stack.global.notags, notag: stack.global.notag};
+ stack.global.notags = (taggable ? null : name);
+ stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments
+ },
+ EndEntry: function () {
+ if (this.row.length) {this.fixInitialMO(this.data)}
+ this.row.push(MML.mtd.apply(MML,this.data));
+ this.data = [];
+ },
+ EndRow: function () {
+ var mtr = MML.mtr;
+ if (!this.global.tag && this.numbered) {this.autoTag()}
+ if (this.global.tag && !this.global.notags) {
+ this.row = [this.getTag()].concat(this.row);
+ mtr = MML.mlabeledtr;
+ } else {this.clearTag()}
+ if (this.numbered) {delete this.global.notag}
+ this.table.push(mtr.apply(MML,this.row)); this.row = [];
+ },
+ EndTable: function () {
+ this.SUPER(arguments).EndTable.call(this);
+ this.global.notags = this.save.notags;
+ this.global.notag = this.save.notag;
+ }
+ });
+
+ //
+ // Look for \tag on a formula and make an mtable to include it
+ //
+ STACKITEM.start.Augment({
+ oldCheckItem: STACKITEM.start.prototype.checkItem,
+ checkItem: function (item) {
+ if (item.type === "stop") {
+ var mml = this.mmlData(), global = this.global;
+ if (AMS.display && !global.tag && !global.tagged && !global.isInner &&
+ (CONFIG.autoNumber === "all" || global.forcetag)) {this.autoTag()}
+ if (global.tag) {
+ var row = [this.getTag(),MML.mtd(mml)];
+ var def = {
+ side: TEX.config.TagSide,
+ minlabelspacing: TEX.config.TagIndent,
+ displaystyle: "inherit" // replaced by TeX input jax Translate() function with actual value
+ };
+ mml = MML.mtable(MML.mlabeledtr.apply(MML,row)).With(def);
+ }
+ return STACKITEM.mml(mml);
+ }
+ return this.oldCheckItem.call(this,item);
+ }
+ });
+
+ /******************************************************************************/
+
+ /*
+ * Add pre- and post-filters to handle the equation number maintainance.
+ */
+ TEX.prefilterHooks.Add(function (data) {
+ AMS.display = data.display;
+ AMS.number = AMS.startNumber; // reset equation numbers (in case the equation restarted)
+ AMS.eqlabels = AMS.eqIDs = {}; AMS.badref = false;
+ if (AMS.refUpdate) {AMS.number = data.script.MathJax.startNumber}
+ });
+ TEX.postfilterHooks.Add(function (data) {
+ data.script.MathJax.startNumber = AMS.startNumber;
+ AMS.startNumber = AMS.number; // equation numbers for next equation
+ MathJax.Hub.Insert(AMS.IDs,AMS.eqIDs); // save IDs from this equation
+ MathJax.Hub.Insert(AMS.labels,AMS.eqlabels); // save labels from this equation
+ if (AMS.badref && !data.math.texError) {AMS.refs.push(data.script)} // reprocess later
+ },100);
+
+ MathJax.Hub.Register.MessageHook("Begin Math Input",function () {
+ AMS.refs = []; // array of jax with bad references
+ AMS.refUpdate = false;
+ });
+ MathJax.Hub.Register.MessageHook("End Math Input",function (message) {
+ if (AMS.refs.length) {
+ AMS.refUpdate = true;
+ for (var i = 0, m = AMS.refs.length; i < m; i++)
+ {AMS.refs[i].MathJax.state = MathJax.ElementJax.STATE.UPDATE}
+ return MathJax.Hub.processInput({
+ scripts:AMS.refs,
+ start: new Date().getTime(),
+ i:0, j:0, jax:{}, jaxIDs:[]
+ });
+ }
+ return null;
+ });
+
+ //
+ // Clear the equation numbers and labels
+ //
+ TEX.resetEquationNumbers = function (n,keepLabels) {
+ AMS.startNumber = (n || 0);
+ if (!keepLabels) {AMS.labels = AMS.IDs = {}}
+ }
+
+ /******************************************************************************/
+
+ MathJax.Hub.Startup.signal.Post("TeX AMSmath Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSmath.js");
diff --git a/MarkDownEditor/MathJax/extensions/TeX/AMSsymbols.js b/MarkDownEditor/MathJax/extensions/TeX/AMSsymbols.js
new file mode 100644
index 0000000..50e7d59
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/TeX/AMSsymbols.js
@@ -0,0 +1,349 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/AMSsymbols.js
+ *
+ * Implements macros for accessing the AMS symbol fonts.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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/AMSsymbols"] = {
+ version: "2.6.0"
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml,
+ TEXDEF = MathJax.InputJax.TeX.Definitions;
+
+ TEXDEF.Add({
+
+ mathchar0mi: {
+ // Lowercase Greek letters
+ digamma: '03DD',
+ varkappa: '03F0',
+
+ // Uppercase Greek letters
+ varGamma: ['0393',{mathvariant: MML.VARIANT.ITALIC}],
+ varDelta: ['0394',{mathvariant: MML.VARIANT.ITALIC}],
+ varTheta: ['0398',{mathvariant: MML.VARIANT.ITALIC}],
+ varLambda: ['039B',{mathvariant: MML.VARIANT.ITALIC}],
+ varXi: ['039E',{mathvariant: MML.VARIANT.ITALIC}],
+ varPi: ['03A0',{mathvariant: MML.VARIANT.ITALIC}],
+ varSigma: ['03A3',{mathvariant: MML.VARIANT.ITALIC}],
+ varUpsilon: ['03A5',{mathvariant: MML.VARIANT.ITALIC}],
+ varPhi: ['03A6',{mathvariant: MML.VARIANT.ITALIC}],
+ varPsi: ['03A8',{mathvariant: MML.VARIANT.ITALIC}],
+ varOmega: ['03A9',{mathvariant: MML.VARIANT.ITALIC}],
+
+ // Hebrew letters
+ beth: '2136',
+ gimel: '2137',
+ daleth: '2138',
+
+ // Miscellaneous symbols
+// hbar: '0127', // in TeX/jax.js
+ backprime: ['2035',{variantForm: true}],
+ hslash: '210F',
+ varnothing: ['2205',{variantForm: true}],
+ blacktriangle: '25B4',
+ triangledown: ['25BD',{variantForm: true}],
+ blacktriangledown: '25BE',
+ square: '25FB',
+ Box: '25FB',
+ blacksquare: '25FC',
+ lozenge: '25CA',
+ Diamond: '25CA',
+ blacklozenge: '29EB',
+ circledS: ['24C8',{mathvariant: MML.VARIANT.NORMAL}],
+ bigstar: '2605',
+// angle: '2220', // in TeX/jax.js
+ sphericalangle: '2222',
+ measuredangle: '2221',
+ nexists: '2204',
+ complement: '2201',
+ mho: '2127',
+ eth: ['00F0',{mathvariant: MML.VARIANT.NORMAL}],
+ Finv: '2132',
+ diagup: '2571',
+ Game: '2141',
+ diagdown: '2572',
+ Bbbk: ['006B',{mathvariant: MML.VARIANT.DOUBLESTRUCK}],
+
+ yen: '00A5',
+ circledR: '00AE',
+ checkmark: '2713',
+ maltese: '2720'
+ },
+
+ mathchar0mo: {
+ // Binary operators
+ dotplus: '2214',
+ ltimes: '22C9',
+ smallsetminus: '2216',
+ rtimes: '22CA',
+ Cap: '22D2',
+ doublecap: '22D2',
+ leftthreetimes: '22CB',
+ Cup: '22D3',
+ doublecup: '22D3',
+ rightthreetimes: '22CC',
+ barwedge: '22BC',
+ curlywedge: '22CF',
+ veebar: '22BB',
+ curlyvee: '22CE',
+ doublebarwedge: '2A5E',
+ boxminus: '229F',
+ circleddash: '229D',
+ boxtimes: '22A0',
+ circledast: '229B',
+ boxdot: '22A1',
+ circledcirc: '229A',
+ boxplus: '229E',
+ centerdot: ['22C5',{variantForm: true}],
+ divideontimes: '22C7',
+ intercal: '22BA',
+
+ // Binary relations
+ leqq: '2266',
+ geqq: '2267',
+ leqslant: '2A7D',
+ geqslant: '2A7E',
+ eqslantless: '2A95',
+ eqslantgtr: '2A96',
+ lesssim: '2272',
+ gtrsim: '2273',
+ lessapprox: '2A85',
+ gtrapprox: '2A86',
+ approxeq: '224A',
+ lessdot: '22D6',
+ gtrdot: '22D7',
+ lll: '22D8',
+ llless: '22D8',
+ ggg: '22D9',
+ gggtr: '22D9',
+ lessgtr: '2276',
+ gtrless: '2277',
+ lesseqgtr: '22DA',
+ gtreqless: '22DB',
+ lesseqqgtr: '2A8B',
+ gtreqqless: '2A8C',
+ doteqdot: '2251',
+ Doteq: '2251',
+ eqcirc: '2256',
+ risingdotseq: '2253',
+ circeq: '2257',
+ fallingdotseq: '2252',
+ triangleq: '225C',
+ backsim: '223D',
+ thicksim: ['223C',{variantForm: true}],
+ backsimeq: '22CD',
+ thickapprox: ['2248',{variantForm: true}],
+ subseteqq: '2AC5',
+ supseteqq: '2AC6',
+ Subset: '22D0',
+ Supset: '22D1',
+ sqsubset: '228F',
+ sqsupset: '2290',
+ preccurlyeq: '227C',
+ succcurlyeq: '227D',
+ curlyeqprec: '22DE',
+ curlyeqsucc: '22DF',
+ precsim: '227E',
+ succsim: '227F',
+ precapprox: '2AB7',
+ succapprox: '2AB8',
+ vartriangleleft: '22B2',
+ lhd: '22B2',
+ vartriangleright: '22B3',
+ rhd: '22B3',
+ trianglelefteq: '22B4',
+ unlhd: '22B4',
+ trianglerighteq: '22B5',
+ unrhd: '22B5',
+ vDash: '22A8',
+ Vdash: '22A9',
+ Vvdash: '22AA',
+ smallsmile: ['2323',{variantForm: true}],
+ shortmid: ['2223',{variantForm: true}],
+ smallfrown: ['2322',{variantForm: true}],
+ shortparallel: ['2225',{variantForm: true}],
+ bumpeq: '224F',
+ between: '226C',
+ Bumpeq: '224E',
+ pitchfork: '22D4',
+ varpropto: '221D',
+ backepsilon: '220D',
+ blacktriangleleft: '25C2',
+ blacktriangleright: '25B8',
+ therefore: '2234',
+ because: '2235',
+ eqsim: '2242',
+ vartriangle: ['25B3',{variantForm: true}],
+ Join: '22C8',
+
+ // Negated relations
+ nless: '226E',
+ ngtr: '226F',
+ nleq: '2270',
+ ngeq: '2271',
+ nleqslant: ['2A87',{variantForm: true}],
+ ngeqslant: ['2A88',{variantForm: true}],
+ nleqq: ['2270',{variantForm: true}],
+ ngeqq: ['2271',{variantForm: true}],
+ lneq: '2A87',
+ gneq: '2A88',
+ lneqq: '2268',
+ gneqq: '2269',
+ lvertneqq: ['2268',{variantForm: true}],
+ gvertneqq: ['2269',{variantForm: true}],
+ lnsim: '22E6',
+ gnsim: '22E7',
+ lnapprox: '2A89',
+ gnapprox: '2A8A',
+ nprec: '2280',
+ nsucc: '2281',
+ npreceq: ['22E0',{variantForm: true}],
+ nsucceq: ['22E1',{variantForm: true}],
+ precneqq: '2AB5',
+ succneqq: '2AB6',
+ precnsim: '22E8',
+ succnsim: '22E9',
+ precnapprox: '2AB9',
+ succnapprox: '2ABA',
+ nsim: '2241',
+ ncong: '2246',
+ nshortmid: ['2224',{variantForm: true}],
+ nshortparallel: ['2226',{variantForm: true}],
+ nmid: '2224',
+ nparallel: '2226',
+ nvdash: '22AC',
+ nvDash: '22AD',
+ nVdash: '22AE',
+ nVDash: '22AF',
+ ntriangleleft: '22EA',
+ ntriangleright: '22EB',
+ ntrianglelefteq: '22EC',
+ ntrianglerighteq: '22ED',
+ nsubseteq: '2288',
+ nsupseteq: '2289',
+ nsubseteqq: ['2288',{variantForm: true}],
+ nsupseteqq: ['2289',{variantForm: true}],
+ subsetneq: '228A',
+ supsetneq: '228B',
+ varsubsetneq: ['228A',{variantForm: true}],
+ varsupsetneq: ['228B',{variantForm: true}],
+ subsetneqq: '2ACB',
+ supsetneqq: '2ACC',
+ varsubsetneqq: ['2ACB',{variantForm: true}],
+ varsupsetneqq: ['2ACC',{variantForm: true}],
+
+
+ // Arrows
+ leftleftarrows: '21C7',
+ rightrightarrows: '21C9',
+ leftrightarrows: '21C6',
+ rightleftarrows: '21C4',
+ Lleftarrow: '21DA',
+ Rrightarrow: '21DB',
+ twoheadleftarrow: '219E',
+ twoheadrightarrow: '21A0',
+ leftarrowtail: '21A2',
+ rightarrowtail: '21A3',
+ looparrowleft: '21AB',
+ looparrowright: '21AC',
+ leftrightharpoons: '21CB',
+ rightleftharpoons: ['21CC',{variantForm: true}],
+ curvearrowleft: '21B6',
+ curvearrowright: '21B7',
+ circlearrowleft: '21BA',
+ circlearrowright: '21BB',
+ Lsh: '21B0',
+ Rsh: '21B1',
+ upuparrows: '21C8',
+ downdownarrows: '21CA',
+ upharpoonleft: '21BF',
+ upharpoonright: '21BE',
+ downharpoonleft: '21C3',
+ restriction: '21BE',
+ multimap: '22B8',
+ downharpoonright: '21C2',
+ leftrightsquigarrow: '21AD',
+ rightsquigarrow: '21DD',
+ leadsto: '21DD',
+ dashrightarrow: '21E2',
+ dashleftarrow: '21E0',
+
+ // Negated arrows
+ nleftarrow: '219A',
+ nrightarrow: '219B',
+ nLeftarrow: '21CD',
+ nRightarrow: '21CF',
+ nleftrightarrow: '21AE',
+ nLeftrightarrow: '21CE'
+ },
+
+ delimiter: {
+ // corners
+ "\\ulcorner": '231C',
+ "\\urcorner": '231D',
+ "\\llcorner": '231E',
+ "\\lrcorner": '231F'
+ },
+
+ macros: {
+ implies: ['Macro','\\;\\Longrightarrow\\;'],
+ impliedby: ['Macro','\\;\\Longleftarrow\\;']
+ }
+
+ },null,true);
+
+ var REL = MML.mo.OPTYPES.REL;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u2322': REL, // smallfrown
+ '\u2323': REL, // smallsmile
+ '\u25B3': REL, // vartriangle
+ '\uE006': REL, // nshortmid
+ '\uE007': REL, // nshortparallel
+ '\uE00C': REL, // lvertneqq
+ '\uE00D': REL, // gvertneqq
+ '\uE00E': REL, // ngeqq
+ '\uE00F': REL, // ngeqslant
+ '\uE010': REL, // nleqslant
+ '\uE011': REL, // nleqq
+ '\uE016': REL, // nsubseteqq
+ '\uE017': REL, // varsubsetneqq
+ '\uE018': REL, // nsupseteqq
+ '\uE019': REL, // varsupsetneqq
+ '\uE01A': REL, // varsubsetneq
+ '\uE01B': REL, // varsupsetneq
+ '\uE04B': REL, // npreceq
+ '\uE04F': REL // nsucceq
+ }
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX AMSsymbols Ready");
+
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSsymbols.js");
diff --git a/MarkDownEditor/MathJax/extensions/TeX/noErrors.js b/MarkDownEditor/MathJax/extensions/TeX/noErrors.js
new file mode 100644
index 0000000..2d71ab3
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/TeX/noErrors.js
@@ -0,0 +1,405 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/noErrors.js
+ *
+ * Prevents the TeX error messages from being displayed and shows the
+ * original TeX code instead. You can configure whether the dollar signs
+ * are shown or not for in-line math, and whether to put all the TeX on
+ * one line or use multiple-lines.
+ *
+ * To configure this extension, use
+ *
+ * MathJax.Hub.Config({
+ * TeX: {
+ * noErrors: {
+ * inlineDelimiters: ["",""], // or ["$","$"] or ["\\(","\\)"]
+ * multiLine: true, // false for TeX on all one line
+ * style: {
+ * "font-size": "90%",
+ * "text-align": "left",
+ * "color": "black",
+ * "padding": "1px 3px",
+ * "border": "1px solid"
+ * // add any additional CSS styles that you want
+ * // (be sure there is no extra comma at the end of the last item)
+ * }
+ * }
+ * }
+ * });
+ *
+ * Display-style math is always shown in multi-line format, and without
+ * delimiters, as it will already be set off in its own centered
+ * paragraph, like standard display mathematics.
+ *
+ * The default settings place the invalid TeX in a multi-line box with a
+ * black border. If you want it to look as though the TeX is just part of
+ * the paragraph, use
+ *
+ * MathJax.Hub.Config({
+ * TeX: {
+ * noErrors: {
+ * inlineDelimiters: ["$","$"], // or ["",""] or ["\\(","\\)"]
+ * multiLine: false,
+ * style: {
+ * "font-size": "normal",
+ * "border": ""
+ * }
+ * }
+ * }
+ * });
+ *
+ * You may also wish to set the font family, as the default is "serif"
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.
+ */
+
+(function (HUB,HTML) {
+ var VERSION = "2.6.0";
+
+ var CONFIG = HUB.CombineConfig("TeX.noErrors",{
+ disabled: false, // set to true to return to original error messages
+ multiLine: true,
+ inlineDelimiters: ["",""], // or use ["$","$"] or ["\\(","\\)"]
+ style: {
+ "font-size": "90%",
+ "text-align": "left",
+ "color": "black",
+ "padding": "1px 3px",
+ "border": "1px solid"
+ }
+ });
+
+ var NBSP = "\u00A0";
+
+ //
+ // The configuration defaults, augmented by the user settings
+ //
+ MathJax.Extension["TeX/noErrors"] = {
+ version: VERSION,
+ config: CONFIG
+ };
+
+ HUB.Register.StartupHook("TeX Jax Ready",function () {
+ var FORMAT = MathJax.InputJax.TeX.formatError;
+
+ MathJax.InputJax.TeX.Augment({
+ //
+ // Make error messages be the original TeX code
+ // Mark them as errors and multi-line or not, and for
+ // multi-line TeX, make spaces non-breakable (to get formatting right)
+ //
+ formatError: function (err,math,displaystyle,script) {
+ if (CONFIG.disabled) {return FORMAT.apply(this,arguments)}
+ var message = err.message.replace(/\n.*/,"");
+ HUB.signal.Post(["TeX Jax - parse error",message,math,displaystyle,script]);
+ var delim = CONFIG.inlineDelimiters;
+ var multiLine = (displaystyle || CONFIG.multiLine);
+ if (!displaystyle) {math = delim[0] + math + delim[1]}
+ if (multiLine) {math = math.replace(/ /g,NBSP)} else {math = math.replace(/\n/g," ")}
+ return MathJax.ElementJax.mml.merror(math).With({isError:true, multiLine: multiLine});
+ }
+ });
+ });
+
+ /*******************************************************************
+ *
+ * Fix HTML-CSS output
+ */
+
+ HUB.Register.StartupHook("HTML-CSS Jax Config",function () {
+ HUB.Config({
+ "HTML-CSS": {
+ styles: {
+ ".MathJax .noError": HUB.Insert({
+ "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "")
+ },CONFIG.style)
+ }
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("HTML-CSS Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml;
+ var HTMLCSS = MathJax.OutputJax["HTML-CSS"];
+
+ var MATH = MML.math.prototype.toHTML,
+ MERROR = MML.merror.prototype.toHTML;
+
+ //
+ // Override math toHTML routine so that error messages
+ // don't have the clipping and other unneeded overhead
+ //
+ MML.math.Augment({
+ toHTML: function (span,node) {
+ var data = this.data[0];
+ if (data && data.data[0] && data.data[0].isError) {
+ span.style.fontSize = "";
+ span = this.HTMLcreateSpan(span);
+ span.bbox = data.data[0].toHTML(span).bbox;
+ } else {
+ span = MATH.apply(this,arguments);
+ }
+ return span;
+ }
+ });
+
+ //
+ // Override merror toHTML routine so that it puts out the
+ // TeX code in an inline-block with line breaks as in the original
+ //
+ MML.merror.Augment({
+ toHTML: function (span) {
+ if (!this.isError) {return MERROR.apply(this,arguments)}
+ span = this.HTMLcreateSpan(span); span.className = "noError"
+ if (this.multiLine) {span.style.display = "inline-block"}
+ var text = this.data[0].data[0].data.join("").split(/\n/);
+ for (var i = 0, m = text.length; i < m; i++) {
+ HTMLCSS.addText(span,text[i]);
+ if (i !== m-1) {HTMLCSS.addElement(span,"br",{isMathJax:true})}
+ }
+ var HD = HTMLCSS.getHD(span.parentNode), W = HTMLCSS.getW(span.parentNode);
+ if (m > 1) {
+ var H = (HD.h + HD.d)/2, x = HTMLCSS.TeX.x_height/2;
+ span.parentNode.style.verticalAlign = HTMLCSS.Em(HD.d+(x-H));
+ HD.h = x + H; HD.d = H - x;
+ }
+ span.bbox = {h: HD.h, d: HD.d, w: W, lw: 0, rw: W};
+ return span;
+ }
+ });
+
+ });
+
+ /*******************************************************************
+ *
+ * Fix SVG output
+ */
+
+ HUB.Register.StartupHook("SVG Jax Config",function () {
+ HUB.Config({
+ "SVG": {
+ styles: {
+ ".MathJax_SVG .noError": HUB.Insert({
+ "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "")
+ },CONFIG.style)
+ }
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("SVG Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml;
+
+ var MATH = MML.math.prototype.toSVG,
+ MERROR = MML.merror.prototype.toSVG;
+
+ //
+ // Override math toSVG routine so that error messages
+ // don't have the clipping and other unneeded overhead
+ //
+ MML.math.Augment({
+ toSVG: function (span,node) {
+ var data = this.data[0];
+ if (data && data.data[0] && data.data[0].isError)
+ {span = data.data[0].toSVG(span)} else {span = MATH.apply(this,arguments)}
+ return span;
+ }
+ });
+
+ //
+ // Override merror toSVG routine so that it puts out the
+ // TeX code in an inline-block with line breaks as in the original
+ //
+ MML.merror.Augment({
+ toSVG: function (span) {
+ if (!this.isError || this.Parent().type !== "math") {return MERROR.apply(this,arguments)}
+ span = HTML.addElement(span,"span",{className: "noError", isMathJax:true});
+ if (this.multiLine) {span.style.display = "inline-block"}
+ var text = this.data[0].data[0].data.join("").split(/\n/);
+ for (var i = 0, m = text.length; i < m; i++) {
+ HTML.addText(span,text[i]);
+ if (i !== m-1) {HTML.addElement(span,"br",{isMathJax:true})}
+ }
+ if (m > 1) {
+ var H = span.offsetHeight/2;
+ span.style.verticalAlign = (-H+(H/m))+"px";
+ }
+ return span;
+ }
+ });
+
+ });
+
+ /*******************************************************************
+ *
+ * Fix NativeMML output
+ */
+
+ HUB.Register.StartupHook("NativeMML Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml;
+ var CONFIG = MathJax.Extension["TeX/noErrors"].config;
+
+ var MATH = MML.math.prototype.toNativeMML,
+ MERROR = MML.merror.prototype.toNativeMML;
+
+ //
+ // Override math toNativeMML routine so that error messages
+ // don't get placed inside math tags.
+ //
+ MML.math.Augment({
+ toNativeMML: function (span) {
+ var data = this.data[0];
+ if (data && data.data[0] && data.data[0].isError)
+ {span = data.data[0].toNativeMML(span)} else {span = MATH.apply(this,arguments)}
+ return span;
+ }
+ });
+
+ //
+ // Override merror toNativeMML routine so that it puts out the
+ // TeX code in an inline-block with line breaks as in the original
+ //
+ MML.merror.Augment({
+ toNativeMML: function (span) {
+ if (!this.isError) {return MERROR.apply(this,arguments)}
+ span = span.appendChild(document.createElement("span"));
+ var text = this.data[0].data[0].data.join("").split(/\n/);
+ for (var i = 0, m = text.length; i < m; i++) {
+ span.appendChild(document.createTextNode(text[i]));
+ if (i !== m-1) {span.appendChild(document.createElement("br"))}
+ }
+ if (this.multiLine) {
+ span.style.display = "inline-block";
+ if (m > 1) {span.style.verticalAlign = "middle"}
+ }
+ for (var id in CONFIG.style) {if (CONFIG.style.hasOwnProperty(id)) {
+ var ID = id.replace(/-./g,function (c) {return c.charAt(1).toUpperCase()});
+ span.style[ID] = CONFIG.style[id];
+ }}
+ return span;
+ }
+ });
+
+ });
+
+ /*******************************************************************
+ *
+ * Fix PreviewHTML output
+ */
+
+ HUB.Register.StartupHook("PreviewHTML Jax Config",function () {
+ HUB.Config({
+ PreviewHTML: {
+ styles: {
+ ".MathJax_PHTML .noError": HUB.Insert({
+ "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "")
+ },CONFIG.style)
+ }
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("PreviewHTML Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml;
+ var HTML = MathJax.HTML;
+
+ var MERROR = MML.merror.prototype.toPreviewHTML;
+
+ //
+ // Override merror toPreviewHTML routine so that it puts out the
+ // TeX code in an inline-block with line breaks as in the original
+ //
+ MML.merror.Augment({
+ toPreviewHTML: function (span) {
+ if (!this.isError) return MERROR.apply(this,arguments);
+ span = this.PHTMLcreateSpan(span); span.className = "noError"
+ if (this.multiLine) span.style.display = "inline-block";
+ var text = this.data[0].data[0].data.join("").split(/\n/);
+ for (var i = 0, m = text.length; i < m; i++) {
+ HTML.addText(span,text[i]);
+ if (i !== m-1) {HTML.addElement(span,"br",{isMathJax:true})}
+ }
+ return span;
+ }
+ });
+
+ });
+
+ /*******************************************************************
+ *
+ * Fix CommonHTML output
+ */
+
+ HUB.Register.StartupHook("CommonHTML Jax Config",function () {
+ HUB.Config({
+ CommonHTML: {
+ styles: {
+ ".mjx-chtml .mjx-noError": HUB.Insert({
+ "line-height": 1.2,
+ "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "")
+ },CONFIG.style)
+ }
+ }
+ });
+ });
+
+ HUB.Register.StartupHook("CommonHTML Jax Ready",function () {
+ var MML = MathJax.ElementJax.mml;
+ var CHTML = MathJax.OutputJax.CommonHTML;
+ var HTML = MathJax.HTML;
+
+ var MERROR = MML.merror.prototype.toCommonHTML;
+
+ //
+ // Override merror toCommonHTML routine so that it puts out the
+ // TeX code in an inline-block with line breaks as in the original
+ //
+ MML.merror.Augment({
+ toCommonHTML: function (node) {
+ if (!this.isError) return MERROR.apply(this,arguments);
+ node = CHTML.addElement(node,"mjx-noError");
+ var text = this.data[0].data[0].data.join("").split(/\n/);
+ for (var i = 0, m = text.length; i < m; i++) {
+ HTML.addText(node,text[i]);
+ if (i !== m-1) {CHTML.addElement(node,"br",{isMathJax:true})}
+ }
+ var bbox = this.CHTML = CHTML.BBOX.zero();
+ bbox.w = (node.offsetWidth)/CHTML.em;
+ if (m > 1) {
+ var H2 = 1.2*m/2;
+ bbox.h = H2+.25; bbox.d = H2-.25;
+ node.style.verticalAlign = CHTML.Em(.45-H2);
+ } else {
+ bbox.h = 1; bbox.d = .2 + 2/CHTML.em;
+ }
+ return node;
+ }
+ });
+
+ });
+
+ /*******************************************************************/
+
+ HUB.Startup.signal.Post("TeX noErrors Ready");
+
+})(MathJax.Hub,MathJax.HTML);
+
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/noErrors.js");
diff --git a/MarkDownEditor/MathJax/extensions/TeX/noUndefined.js b/MarkDownEditor/MathJax/extensions/TeX/noUndefined.js
new file mode 100644
index 0000000..5021154
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/TeX/noUndefined.js
@@ -0,0 +1,72 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/TeX/noUndefined.js
+ *
+ * This causes undefined control sequences to be shown as their macro
+ * names rather than producing an error message. So $X_{\xxx}$ would
+ * display as an X with a subscript consiting of the text "\xxx".
+ *
+ * To configure this extension, use for example
+ *
+ * MathJax.Hub.Config({
+ * TeX: {
+ * noUndefined: {
+ * attributes: {
+ * mathcolor: "red",
+ * mathbackground: "#FFEEEE",
+ * mathsize: "90%"
+ * }
+ * }
+ * }
+ * });
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2010-2015 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.
+ */
+
+//
+// The configuration defaults, augmented by the user settings
+//
+MathJax.Extension["TeX/noUndefined"] = {
+ version: "2.6.0",
+ config: MathJax.Hub.CombineConfig("TeX.noUndefined",{
+ disabled: false, // set to true to return to original error messages
+ attributes: {
+ mathcolor: "red"
+ }
+ })
+};
+
+MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
+ var CONFIG = MathJax.Extension["TeX/noUndefined"].config;
+ var MML = MathJax.ElementJax.mml;
+ var UNDEFINED = MathJax.InputJax.TeX.Parse.prototype.csUndefined;
+
+ MathJax.InputJax.TeX.Parse.Augment({
+ csUndefined: function (name) {
+ if (CONFIG.disabled) {return UNDEFINED.apply(this,arguments)}
+ MathJax.Hub.signal.Post(["TeX Jax - undefined control sequence",name]);
+ this.Push(MML.mtext(name).With(CONFIG.attributes));
+ }
+ });
+
+ MathJax.Hub.Startup.signal.Post("TeX noUndefined Ready");
+});
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/noUndefined.js");
diff --git a/MarkDownEditor/MathJax/extensions/fast-preview.js b/MarkDownEditor/MathJax/extensions/fast-preview.js
new file mode 100644
index 0000000..73f3ee4
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/fast-preview.js
@@ -0,0 +1,155 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/fast-preview.js
+ *
+ * Implements a fast preview using the PreviewHTML output jax
+ * and then a slower update to the more accurate HTML-CSS output
+ * (or whatever the user has selected).
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2014-2015 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.
+ */
+
+(function (HUB,HTML,BROWSER) {
+
+ var SETTINGS = HUB.config.menuSettings;
+ var JAX = MathJax.OutputJax;
+ var msieColorBug = BROWSER.isMSIE && (document.documentMode||0) < 8;
+
+ var FastPreview = MathJax.Extension["fast-preview"] = {
+ version: "2.6.0",
+ enabled: true,
+
+ //
+ // Configuration for the chunking of the main output
+ // after the previews have been created, and other configuration.
+ //
+ config: HUB.CombineConfig("fast-preview",{
+ Chunks: {EqnChunk: 10000, EqnChunkFactor: 1, EqnChunkDelay: 0},
+ color: "inherit!important",
+ updateTime: 30, updateDelay: 6,
+ messageStyle: "none",
+ disabled: BROWSER.isMSIE && !BROWSER.versionAtLeast("8.0")
+ }),
+
+ //
+ // Ajust the chunking of the output jax
+ //
+ Config: function () {
+ if (HUB.config["CHTML-preview"])
+ MathJax.Hub.Config({"fast-preview": HUB.config["CHTML-preview"]});
+ var update, delay, style, done, saved;
+ var config = this.config;
+
+ if (!config.disabled && SETTINGS.FastPreview == null)
+ HUB.Config({menuSettings:{FastPreview:true}});
+ if (SETTINGS.FastPreview) {
+ MathJax.Ajax.Styles({".MathJax_Preview .MJXf-math":{color:config.color}});
+ HUB.Config({"HTML-CSS": config.Chunks, CommonHTML: config.Chunks, SVG: config.Chunks});
+ }
+ HUB.Register.MessageHook("Begin Math Output",function () {
+ if (!done && FastPreview.Active()) {
+ update = HUB.processUpdateTime; delay = HUB.processUpdateDelay;
+ style = HUB.config.messageStyle;
+ HUB.processUpdateTime = config.updateTime;
+ HUB.processUpdateDelay = config.updateDelay;
+ HUB.Config({messageStyle: config.messageStyle});
+ MathJax.Message.Clear(0,0);
+ saved = true;
+ }
+ });
+ HUB.Register.MessageHook("End Math Output",function () {
+ if (!done && saved) {
+ HUB.processUpdateTime = update;
+ HUB.processUpdateDelay = delay;
+ HUB.Config({messageStyle: style});
+ done = true;
+ }
+ });
+ },
+
+ //
+ // Allow page to override user settings (for things like editor previews)
+ //
+ Disable: function () {this.enabled = false},
+ Enable: function () {this.enabled = true},
+
+ Active: function () {
+ return SETTINGS.FastPreview && this.enabled &&
+ !(JAX[SETTINGS.renderer]||{}).noFastPreview;
+ },
+
+ //
+ // Insert a preview span, if there isn't one already,
+ // and call the PreviewHTML output jax to create the preview
+ //
+ Preview: function (data) {
+ if (!this.Active()) return;
+ var preview = data.script.MathJax.preview || data.script.previousSibling;
+ if (!preview || preview.className !== MathJax.Hub.config.preRemoveClass) {
+ preview = HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass});
+ data.script.parentNode.insertBefore(preview,data.script);
+ data.script.MathJax.preview = preview;
+ }
+ preview.innerHTML = "";
+ preview.style.color = (msieColorBug ? "black" : "inherit");
+ return this.postFilter(preview,data);
+ },
+ postFilter: function (preview,data) {
+ //
+ // Load the PreviewHTML jax if it is not already loaded
+ //
+ if (!data.math.root.toPreviewHTML) {
+ var queue = MathJax.Callback.Queue();
+ queue.Push(
+ ["Require",MathJax.Ajax,"[MathJax]/jax/output/PreviewHTML/config.js"],
+ ["Require",MathJax.Ajax,"[MathJax]/jax/output/PreviewHTML/jax.js"]
+ );
+ HUB.RestartAfter(queue.Push({}));
+ }
+ data.math.root.toPreviewHTML(preview);
+ },
+
+ //
+ // Hook into the input jax postFilter to create the previews as
+ // the input jax are processed.
+ //
+ Register: function (name) {
+ HUB.Register.StartupHook(name+" Jax Require",function () {
+ var jax = MathJax.InputJax[name];
+ jax.postfilterHooks.Add(["Preview",MathJax.Extension["fast-preview"]],50);
+ });
+ }
+ }
+
+ //
+ // Hook into each input jax
+ //
+ FastPreview.Register("TeX");
+ FastPreview.Register("MathML");
+ FastPreview.Register("AsciiMath");
+
+ HUB.Register.StartupHook("End Config",["Config",FastPreview]);
+
+ HUB.Startup.signal.Post("fast-preview Ready");
+
+})(MathJax.Hub,MathJax.HTML,MathJax.Hub.Browser);
+
+MathJax.Ajax.loadComplete("[MathJax]/extensions/fast-preview.js");
+
diff --git a/MarkDownEditor/MathJax/extensions/tex2jax.js b/MarkDownEditor/MathJax/extensions/tex2jax.js
new file mode 100644
index 0000000..2623881
--- /dev/null
+++ b/MarkDownEditor/MathJax/extensions/tex2jax.js
@@ -0,0 +1,309 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/extensions/tex2jax.js
+ *
+ * Implements the TeX to Jax preprocessor that locates TeX code
+ * within the text of a document and replaces it with SCRIPT tags
+ * for processing by MathJax.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.tex2jax = {
+ version: "2.6.0",
+ config: {
+ inlineMath: [ // The start/stop pairs for in-line math
+// ['$','$'], // (comment out any you don't want, or add your own, but
+ ['\\(','\\)'] // be sure that you don't have an extra comma at the end)
+ ],
+
+ displayMath: [ // The start/stop pairs for display math
+ ['$$','$$'], // (comment out any you don't want, or add your own, but
+ ['\\[','\\]'] // be sure that you don't have an extra comma at the end)
+ ],
+
+ balanceBraces: true, // determines whether tex2jax requires braces to be
+ // balanced within math delimiters (allows for nested
+ // dollar signs). Set to false to get pre-v2.0 compatibility.
+
+ skipTags: ["script","noscript","style","textarea","pre","code","annotation","annotation-xml"],
+ // The names of the tags whose contents will not be
+ // scanned for math delimiters
+
+ ignoreClass: "tex2jax_ignore", // the class name of elements whose contents should
+ // NOT be processed by tex2jax. Note that this
+ // is a regular expression, so be sure to quote any
+ // regexp special characters
+
+ processClass: "tex2jax_process", // the class name of elements whose contents SHOULD
+ // be processed when they appear inside ones that
+ // are ignored. Note that this is a regular expression,
+ // so be sure to quote any regexp special characters
+
+ processEscapes: false, // set to true to allow \$ to produce a dollar without
+ // starting in-line math mode
+
+ processEnvironments: true, // set to true to process \begin{xxx}...\end{xxx} outside
+ // of math mode, false to prevent that
+
+ processRefs: true, // set to true to process \ref{...} outside of math mode
+
+
+ preview: "TeX" // set to "none" to not insert MathJax_Preview spans
+ // or set to an array specifying an HTML snippet
+ // to use the same preview for every equation.
+
+ },
+
+ PreProcess: function (element) {
+ if (!this.configured) {
+ this.config = MathJax.Hub.CombineConfig("tex2jax",this.config);
+ if (this.config.Augment) {MathJax.Hub.Insert(this,this.config.Augment)}
+ if (typeof(this.config.previewTeX) !== "undefined" && !this.config.previewTeX)
+ {this.config.preview = "none"} // backward compatibility for previewTeX parameter
+ this.configured = true;
+ }
+ if (typeof(element) === "string") {element = document.getElementById(element)}
+ if (!element) {element = document.body}
+ if (this.createPatterns()) {this.scanElement(element,element.nextSibling)}
+ },
+
+ createPatterns: function () {
+ var starts = [], parts = [], i, m, config = this.config;
+ this.match = {};
+ for (i = 0, m = config.inlineMath.length; i < m; i++) {
+ starts.push(this.patternQuote(config.inlineMath[i][0]));
+ this.match[config.inlineMath[i][0]] = {
+ mode: "",
+ end: config.inlineMath[i][1],
+ pattern: this.endPattern(config.inlineMath[i][1])
+ };
+ }
+ for (i = 0, m = config.displayMath.length; i < m; i++) {
+ starts.push(this.patternQuote(config.displayMath[i][0]));
+ this.match[config.displayMath[i][0]] = {
+ mode: "; mode=display",
+ end: config.displayMath[i][1],
+ pattern: this.endPattern(config.displayMath[i][1])
+ };
+ }
+ if (starts.length) {parts.push(starts.sort(this.sortLength).join("|"))}
+ if (config.processEnvironments) {parts.push("\\\\begin\\{([^}]*)\\}")}
+ if (config.processEscapes) {parts.push("\\\\*\\\\\\\$")}
+ if (config.processRefs) {parts.push("\\\\(eq)?ref\\{[^}]*\\}")}
+ this.start = new RegExp(parts.join("|"),"g");
+ this.skipTags = new RegExp("^("+config.skipTags.join("|")+")$","i");
+ var ignore = [];
+ if (MathJax.Hub.config.preRemoveClass) {ignore.push(MathJax.Hub.config.preRemoveClass)};
+ if (config.ignoreClass) {ignore.push(config.ignoreClass)}
+ this.ignoreClass = (ignore.length ? new RegExp("(^| )("+ignore.join("|")+")( |$)") : /^$/);
+ this.processClass = new RegExp("(^| )("+config.processClass+")( |$)");
+ return (parts.length > 0);
+ },
+
+ patternQuote: function (s) {return s.replace(/([\^$(){}+*?\-|\[\]\:\\])/g,'\\$1')},
+
+ endPattern: function (end) {
+ return new RegExp(this.patternQuote(end)+"|\\\\.|[{}]","g");
+ },
+
+ sortLength: function (a,b) {
+ if (a.length !== b.length) {return b.length - a.length}
+ return (a == b ? 0 : (a < b ? -1 : 1));
+ },
+
+ scanElement: function (element,stop,ignore) {
+ var cname, tname, ignoreChild, process;
+ while (element && element != stop) {
+ if (element.nodeName.toLowerCase() === '#text') {
+ if (!ignore) {element = this.scanText(element)}
+ } else {
+ cname = (typeof(element.className) === "undefined" ? "" : element.className);
+ tname = (typeof(element.tagName) === "undefined" ? "" : element.tagName);
+ if (typeof(cname) !== "string") {cname = String(cname)} // jsxgraph uses non-string class names!
+ process = this.processClass.exec(cname);
+ if (element.firstChild && !cname.match(/(^| )MathJax/) &&
+ (process || !this.skipTags.exec(tname))) {
+ ignoreChild = (ignore || this.ignoreClass.exec(cname)) && !process;
+ this.scanElement(element.firstChild,stop,ignoreChild);
+ }
+ }
+ if (element) {element = element.nextSibling}
+ }
+ },
+
+ scanText: function (element) {
+ if (element.nodeValue.replace(/\s+/,'') == '') {return element}
+ var match, prev;
+ this.search = {start: true};
+ this.pattern = this.start;
+ while (element) {
+ this.pattern.lastIndex = 0;
+ while (element && element.nodeName.toLowerCase() === '#text' &&
+ (match = this.pattern.exec(element.nodeValue))) {
+ if (this.search.start) {element = this.startMatch(match,element)}
+ else {element = this.endMatch(match,element)}
+ }
+ if (this.search.matched) {element = this.encloseMath(element)}
+ if (element) {
+ do {prev = element; element = element.nextSibling}
+ while (element && (element.nodeName.toLowerCase() === 'br' ||
+ element.nodeName.toLowerCase() === '#comment'));
+ if (!element || element.nodeName !== '#text')
+ {return (this.search.close ? this.prevEndMatch() : prev)}
+ }
+ }
+ return element;
+ },
+
+ startMatch: function (match,element) {
+ var delim = this.match[match[0]];
+ if (delim != null) { // a start delimiter
+ this.search = {
+ end: delim.end, mode: delim.mode, pcount: 0,
+ open: element, olen: match[0].length, opos: this.pattern.lastIndex - match[0].length
+ };
+ this.switchPattern(delim.pattern);
+ } else if (match[0].substr(0,6) === "\\begin") { // \begin{...}
+ this.search = {
+ end: "\\end{"+match[1]+"}", mode: "; mode=display", pcount: 0,
+ open: element, olen: 0, opos: this.pattern.lastIndex - match[0].length,
+ isBeginEnd: true
+ };
+ this.switchPattern(this.endPattern(this.search.end));
+ } else if (match[0].substr(0,4) === "\\ref" || match[0].substr(0,6) === "\\eqref") {
+ this.search = {
+ mode: "", end: "", open: element, pcount: 0,
+ olen: 0, opos: this.pattern.lastIndex - match[0].length
+ }
+ return this.endMatch([""],element);
+ } else { // escaped dollar signs
+ // put $ in a span so it doesn't get processed again
+ // split off backslashes so they don't get removed later
+ var slashes = match[0].substr(0,match[0].length-1), n, span;
+ if (slashes.length % 2 === 0) {span = [slashes.replace(/\\\\/g,"\\")]; n = 1}
+ else {span = [slashes.substr(1).replace(/\\\\/g,"\\"),"$"]; n = 0}
+ span = MathJax.HTML.Element("span",null,span);
+ var text = MathJax.HTML.TextNode(element.nodeValue.substr(0,match.index));
+ element.nodeValue = element.nodeValue.substr(match.index + match[0].length - n);
+ element.parentNode.insertBefore(span,element);
+ element.parentNode.insertBefore(text,span);
+ this.pattern.lastIndex = n;
+ }
+ return element;
+ },
+
+ endMatch: function (match,element) {
+ var search = this.search;
+ if (match[0] == search.end) {
+ if (!search.close || search.pcount === 0) {
+ search.close = element;
+ search.cpos = this.pattern.lastIndex;
+ search.clen = (search.isBeginEnd ? 0 : match[0].length);
+ }
+ if (search.pcount === 0) {
+ search.matched = true;
+ element = this.encloseMath(element);
+ this.switchPattern(this.start);
+ }
+ }
+ else if (match[0] === "{") {search.pcount++}
+ else if (match[0] === "}" && search.pcount) {search.pcount--}
+ return element;
+ },
+ prevEndMatch: function () {
+ this.search.matched = true;
+ var element = this.encloseMath(this.search.close);
+ this.switchPattern(this.start);
+ return element;
+ },
+
+ switchPattern: function (pattern) {
+ pattern.lastIndex = this.pattern.lastIndex;
+ this.pattern = pattern;
+ this.search.start = (pattern === this.start);
+ },
+
+ encloseMath: function (element) {
+ var search = this.search, close = search.close, CLOSE, math;
+ if (search.cpos === close.length) {close = close.nextSibling}
+ else {close = close.splitText(search.cpos)}
+ if (!close) {CLOSE = close = MathJax.HTML.addText(search.close.parentNode,"")}
+ search.close = close;
+ math = (search.opos ? search.open.splitText(search.opos) : search.open);
+ while (math.nextSibling && math.nextSibling !== close) {
+ if (math.nextSibling.nodeValue !== null) {
+ if (math.nextSibling.nodeName === "#comment") {
+ math.nodeValue += math.nextSibling.nodeValue.replace(/^\[CDATA\[((.|\n|\r)*)\]\]$/,"$1");
+ } else {
+ math.nodeValue += math.nextSibling.nodeValue;
+ }
+ } else if (this.msieNewlineBug) {
+ math.nodeValue += (math.nextSibling.nodeName.toLowerCase() === "br" ? "\n" : " ");
+ } else {
+ math.nodeValue += " ";
+ }
+ math.parentNode.removeChild(math.nextSibling);
+ }
+ var TeX = math.nodeValue.substr(search.olen,math.nodeValue.length-search.olen-search.clen);
+ math.parentNode.removeChild(math);
+ if (this.config.preview !== "none") {this.createPreview(search.mode,TeX)}
+ math = this.createMathTag(search.mode,TeX);
+ this.search = {}; this.pattern.lastIndex = 0;
+ if (CLOSE) {CLOSE.parentNode.removeChild(CLOSE)}
+ return math;
+ },
+
+ insertNode: function (node) {
+ var search = this.search;
+ search.close.parentNode.insertBefore(node,search.close);
+ },
+
+ createPreview: function (mode,tex) {
+ var preview = this.config.preview;
+ if (preview === "none") return;
+ if (preview === "TeX") {preview = [this.filterPreview(tex)]}
+ if (preview) {
+ preview = MathJax.HTML.Element("span",{className:MathJax.Hub.config.preRemoveClass},preview);
+ this.insertNode(preview);
+ }
+ },
+
+ createMathTag: function (mode,tex) {
+ var script = document.createElement("script");
+ script.type = "math/tex" + mode;
+ MathJax.HTML.setScript(script,tex);
+ this.insertNode(script);
+ return script;
+ },
+
+ filterPreview: function (tex) {return tex},
+
+ msieNewlineBug: (MathJax.Hub.Browser.isMSIE && document.documentMode < 9)
+
+};
+
+// We register the preprocessors with the following priorities:
+// - mml2jax.js: 5
+// - jsMath2jax.js: 8
+// - asciimath2jax.js, tex2jax.js: 10 (default)
+// See issues 18 and 484 and the other *2jax.js files.
+MathJax.Hub.Register.PreProcessor(["PreProcess",MathJax.Extension.tex2jax]);
+MathJax.Ajax.loadComplete("[MathJax]/extensions/tex2jax.js");
diff --git a/MarkDownEditor/MathJax/jax/element/mml/jax.js b/MarkDownEditor/MathJax/jax/element/mml/jax.js
new file mode 100644
index 0000000..e5e5562
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/jax.js
@@ -0,0 +1,1817 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/jax/element/mml/jax.js
+ *
+ * Implements the MML ElementJax that holds the internal represetation
+ * of the mathematics on the page. Various InputJax will produce this
+ * format, and the OutputJax will display it in various formats.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.ElementJax.mml = MathJax.ElementJax({
+ mimeType: "jax/mml"
+},{
+ id: "mml",
+ version: "2.6.0",
+ directory: MathJax.ElementJax.directory + "/mml",
+ extensionDir: MathJax.ElementJax.extensionDir + "/mml",
+ optableDir: MathJax.ElementJax.directory + "/mml/optable"
+});
+
+MathJax.ElementJax.mml.Augment({
+ Init: function () {
+ if (arguments.length === 1 && arguments[0].type === "math") {this.root = arguments[0]}
+ else {this.root = MathJax.ElementJax.mml.math.apply(this,arguments)}
+ if (this.root.attr && this.root.attr.mode) {
+ if (!this.root.display && this.root.attr.mode === "display") {
+ this.root.display = "block";
+ this.root.attrNames.push("display");
+ }
+ delete this.root.attr.mode;
+ for (var i = 0, m = this.root.attrNames.length; i < m; i++) {
+ if (this.root.attrNames[i] === "mode") {this.root.attrNames.splice(i,1); break}
+ }
+ }
+ }
+},{
+ INHERIT: "_inherit_",
+ AUTO: "_auto_",
+ SIZE: {
+ INFINITY: "infinity",
+ SMALL: "small",
+ NORMAL: "normal",
+ BIG: "big"
+ },
+ COLOR: {
+ TRANSPARENT: "transparent"
+ },
+ VARIANT: {
+ NORMAL: "normal",
+ BOLD: "bold",
+ ITALIC: "italic",
+ BOLDITALIC: "bold-italic",
+ DOUBLESTRUCK: "double-struck",
+ FRAKTUR: "fraktur",
+ BOLDFRAKTUR: "bold-fraktur",
+ SCRIPT: "script",
+ BOLDSCRIPT: "bold-script",
+ SANSSERIF: "sans-serif",
+ BOLDSANSSERIF: "bold-sans-serif",
+ SANSSERIFITALIC: "sans-serif-italic",
+ SANSSERIFBOLDITALIC: "sans-serif-bold-italic",
+ MONOSPACE: "monospace",
+ INITIAL: "inital",
+ TAILED: "tailed",
+ LOOPED: "looped",
+ STRETCHED: "stretched",
+ CALIGRAPHIC: "-tex-caligraphic",
+ OLDSTYLE: "-tex-oldstyle"
+ },
+ FORM: {
+ PREFIX: "prefix",
+ INFIX: "infix",
+ POSTFIX: "postfix"
+ },
+ LINEBREAK: {
+ AUTO: "auto",
+ NEWLINE: "newline",
+ NOBREAK: "nobreak",
+ GOODBREAK: "goodbreak",
+ BADBREAK: "badbreak"
+ },
+ LINEBREAKSTYLE: {
+ BEFORE: "before",
+ AFTER: "after",
+ DUPLICATE: "duplicate",
+ INFIXLINBREAKSTYLE: "infixlinebreakstyle"
+ },
+ INDENTALIGN: {
+ LEFT: "left",
+ CENTER: "center",
+ RIGHT: "right",
+ AUTO: "auto",
+ ID: "id",
+ INDENTALIGN: "indentalign"
+ },
+ INDENTSHIFT: {
+ INDENTSHIFT: "indentshift"
+ },
+ LINETHICKNESS: {
+ THIN: "thin",
+ MEDIUM: "medium",
+ THICK: "thick"
+ },
+ NOTATION: {
+ LONGDIV: "longdiv",
+ ACTUARIAL: "actuarial",
+ RADICAL: "radical",
+ BOX: "box",
+ ROUNDEDBOX: "roundedbox",
+ CIRCLE: "circle",
+ LEFT: "left",
+ RIGHT: "right",
+ TOP: "top",
+ BOTTOM: "bottom",
+ UPDIAGONALSTRIKE: "updiagonalstrike",
+ DOWNDIAGONALSTRIKE: "downdiagonalstrike",
+ UPDIAGONALARROW: "updiagonalarrow",
+ VERTICALSTRIKE: "verticalstrike",
+ HORIZONTALSTRIKE: "horizontalstrike",
+ PHASORANGLE: "phasorangle",
+ MADRUWB: "madruwb"
+ },
+ ALIGN: {
+ TOP: "top",
+ BOTTOM: "bottom",
+ CENTER: "center",
+ BASELINE: "baseline",
+ AXIS: "axis",
+ LEFT: "left",
+ RIGHT: "right"
+ },
+ LINES: {
+ NONE: "none",
+ SOLID: "solid",
+ DASHED: "dashed"
+ },
+ SIDE: {
+ LEFT: "left",
+ RIGHT: "right",
+ LEFTOVERLAP: "leftoverlap",
+ RIGHTOVERLAP: "rightoverlap"
+ },
+ WIDTH: {
+ AUTO: "auto",
+ FIT: "fit"
+ },
+ ACTIONTYPE: {
+ TOGGLE: "toggle",
+ STATUSLINE: "statusline",
+ TOOLTIP: "tooltip",
+ INPUT: "input"
+ },
+ LENGTH: {
+ VERYVERYTHINMATHSPACE: "veryverythinmathspace",
+ VERYTHINMATHSPACE: "verythinmathspace",
+ THINMATHSPACE: "thinmathspace",
+ MEDIUMMATHSPACE: "mediummathspace",
+ THICKMATHSPACE: "thickmathspace",
+ VERYTHICKMATHSPACE: "verythickmathspace",
+ VERYVERYTHICKMATHSPACE: "veryverythickmathspace",
+ NEGATIVEVERYVERYTHINMATHSPACE: "negativeveryverythinmathspace",
+ NEGATIVEVERYTHINMATHSPACE: "negativeverythinmathspace",
+ NEGATIVETHINMATHSPACE: "negativethinmathspace",
+ NEGATIVEMEDIUMMATHSPACE: "negativemediummathspace",
+ NEGATIVETHICKMATHSPACE: "negativethickmathspace",
+ NEGATIVEVERYTHICKMATHSPACE: "negativeverythickmathspace",
+ NEGATIVEVERYVERYTHICKMATHSPACE: "negativeveryverythickmathspace"
+ },
+ OVERFLOW: {
+ LINBREAK: "linebreak",
+ SCROLL: "scroll",
+ ELIDE: "elide",
+ TRUNCATE: "truncate",
+ SCALE: "scale"
+ },
+ UNIT: {
+ EM: "em",
+ EX: "ex",
+ PX: "px",
+ IN: "in",
+ CM: "cm",
+ MM: "mm",
+ PT: "pt",
+ PC: "pc"
+ },
+ TEXCLASS: {
+ ORD: 0,
+ OP: 1,
+ BIN: 2,
+ REL: 3,
+ OPEN: 4,
+ CLOSE: 5,
+ PUNCT: 6,
+ INNER: 7,
+ VCENTER: 8,
+ NONE: -1
+ },
+ TEXCLASSNAMES: ["ORD", "OP", "BIN", "REL", "OPEN", "CLOSE", "PUNCT", "INNER", "VCENTER"],
+ skipAttributes: {
+ texClass:true, useHeight:true, texprimestyle:true
+ },
+ copyAttributes: {
+ displaystyle:1, scriptlevel:1, open:1, close:1, form:1,
+ actiontype: 1,
+ fontfamily:true, fontsize:true, fontweight:true, fontstyle:true,
+ color:true, background:true,
+ id:true, "class":1, href:true, style:true
+ },
+ copyAttributeNames: [
+ "displaystyle", "scriptlevel", "open", "close", "form", // force these to be copied
+ "actiontype",
+ "fontfamily", "fontsize", "fontweight", "fontstyle",
+ "color", "background",
+ "id", "class", "href", "style"
+ ],
+ nocopyAttributes: {
+ fontfamily: true, fontsize: true, fontweight: true, fontstyle: true,
+ color: true, background: true,
+ id: true, 'class': true, href: true, style: true,
+ xmlns: true
+ },
+ Error: function (message,def) {
+ var mml = this.merror(message),
+ dir = MathJax.Localization.fontDirection(),
+ font = MathJax.Localization.fontFamily();
+ if (def) {mml = mml.With(def)}
+ if (dir || font) {
+ mml = this.mstyle(mml);
+ if (dir) {mml.dir = dir}
+ if (font) {mml.style.fontFamily = "font-family: "+font}
+ }
+ return mml;
+ }
+});
+
+(function (MML) {
+
+ MML.mbase = MathJax.Object.Subclass({
+ type: "base", isToken: false,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT
+ },
+ noInherit: {},
+ noInheritAttribute: {
+ texClass: true
+ },
+ getRemoved: {},
+ linebreakContainer: false,
+
+ Init: function () {
+ this.data = [];
+ if (this.inferRow && !(arguments.length === 1 && arguments[0].inferred))
+ {this.Append(MML.mrow().With({inferred: true, notParent: true}))}
+ this.Append.apply(this,arguments);
+ },
+ With: function (def) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {this[id] = def[id]}}
+ return this;
+ },
+ Append: function () {
+ if (this.inferRow && this.data.length) {
+ this.data[0].Append.apply(this.data[0],arguments);
+ } else {
+ for (var i = 0, m = arguments.length; i < m; i++)
+ {this.SetData(this.data.length,arguments[i])}
+ }
+ },
+ SetData: function (i,item) {
+ if (item != null) {
+ if (!(item instanceof MML.mbase))
+ {item = (this.isToken || this.isChars ? MML.chars(item) : MML.mtext(item))}
+ item.parent = this;
+ item.setInherit(this.inheritFromMe ? this : this.inherit);
+ }
+ this.data[i] = item;
+ },
+ Parent: function () {
+ var parent = this.parent;
+ while (parent && parent.notParent) {parent = parent.parent}
+ return parent;
+ },
+ Get: function (name,nodefault,noself) {
+ if (!noself) {
+ if (this[name] != null) {return this[name]}
+ if (this.attr && this.attr[name] != null) {return this.attr[name]}
+ }
+ // FIXME: should cache these values and get from cache
+ // (clear cache when appended to a new object?)
+ var parent = this.Parent();
+ if (parent && parent["adjustChild_"+name] != null) {
+ return (parent["adjustChild_"+name])(this.childPosition(),nodefault);
+ }
+ var obj = this.inherit; var root = obj;
+ while (obj) {
+ var value = obj[name]; if (value == null && obj.attr) {value = obj.attr[name]}
+ if (obj.removedStyles && obj.getRemoved[name] && value == null) value = obj.removedStyles[obj.getRemoved[name]];
+ if (value != null && obj.noInheritAttribute && !obj.noInheritAttribute[name]) {
+ var noInherit = obj.noInherit[this.type];
+ if (!(noInherit && noInherit[name])) {return value}
+ }
+ root = obj; obj = obj.inherit;
+ }
+ if (!nodefault) {
+ if (this.defaults[name] === MML.AUTO) {return this.autoDefault(name)}
+ if (this.defaults[name] !== MML.INHERIT && this.defaults[name] != null)
+ {return this.defaults[name]}
+ if (root) {return root.defaults[name]}
+ }
+ return null;
+ },
+ hasValue: function (name) {return (this.Get(name,true) != null)},
+ getValues: function () {
+ var values = {};
+ for (var i = 0, m = arguments.length; i < m; i++)
+ {values[arguments[i]] = this.Get(arguments[i])}
+ return values;
+ },
+ adjustChild_scriptlevel: function (i,nodef) {return this.Get("scriptlevel",nodef)}, // always inherit from parent
+ adjustChild_displaystyle: function (i,nodef) {return this.Get("displaystyle",nodef)}, // always inherit from parent
+ adjustChild_texprimestyle: function (i,nodef) {return this.Get("texprimestyle",nodef)}, // always inherit from parent
+ childPosition: function () {
+ var child = this, parent = child.parent;
+ while (parent.notParent) {child = parent; parent = child.parent}
+ for (var i = 0, m = parent.data.length; i < m; i++) {if (parent.data[i] === child) {return i}}
+ return null;
+ },
+ setInherit: function (obj) {
+ if (obj !== this.inherit && this.inherit == null) {
+ this.inherit = obj;
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i] && this.data[i].setInherit) {this.data[i].setInherit(obj)}
+ }
+ }
+ },
+ setTeXclass: function (prev) {
+ this.getPrevClass(prev);
+ return (typeof(this.texClass) !== "undefined" ? this : prev);
+ },
+ getPrevClass: function (prev) {
+ if (prev) {
+ this.prevClass = prev.Get("texClass");
+ this.prevLevel = prev.Get("scriptlevel");
+ }
+ },
+ updateTeXclass: function (core) {
+ if (core) {
+ this.prevClass = core.prevClass; delete core.prevClass;
+ this.prevLevel = core.prevLevel; delete core.prevLevel;
+ this.texClass = core.Get("texClass");
+ }
+ },
+ texSpacing: function () {
+ var prev = (this.prevClass != null ? this.prevClass : MML.TEXCLASS.NONE);
+ var tex = (this.Get("texClass") || MML.TEXCLASS.ORD);
+ if (prev === MML.TEXCLASS.NONE || tex === MML.TEXCLASS.NONE) {return ""}
+ if (prev === MML.TEXCLASS.VCENTER) {prev = MML.TEXCLASS.ORD}
+ if (tex === MML.TEXCLASS.VCENTER) {tex = MML.TEXCLASS.ORD}
+ var space = this.TEXSPACE[prev][tex];
+ if (this.prevLevel > 0 && this.Get("scriptlevel") > 0 && space >= 0) {return ""}
+ return this.TEXSPACELENGTH[Math.abs(space)];
+ },
+ TEXSPACELENGTH:[
+ "",
+ MML.LENGTH.THINMATHSPACE,
+ MML.LENGTH.MEDIUMMATHSPACE,
+ MML.LENGTH.THICKMATHSPACE
+ ],
+ // See TeXBook Chapter 18 (p. 170)
+ TEXSPACE: [
+ [ 0,-1, 2, 3, 0, 0, 0, 1], // ORD
+ [-1,-1, 0, 3, 0, 0, 0, 1], // OP
+ [ 2, 2, 0, 0, 2, 0, 0, 2], // BIN
+ [ 3, 3, 0, 0, 3, 0, 0, 3], // REL
+ [ 0, 0, 0, 0, 0, 0, 0, 0], // OPEN
+ [ 0,-1, 2, 3, 0, 0, 0, 1], // CLOSE
+ [ 1, 1, 0, 1, 1, 1, 1, 1], // PUNCT
+ [ 1,-1, 2, 3, 1, 0, 1, 1] // INNER
+ ],
+ autoDefault: function (name) {return ""},
+ isSpacelike: function () {return false},
+ isEmbellished: function () {return false},
+ Core: function () {return this},
+ CoreMO: function () {return this},
+ childIndex: function(child) {
+ if (child == null) return;
+ for (var i = 0, m = this.data.length; i < m; i++) if (child === this.data[i]) return i;
+ },
+ CoreIndex: function () {
+ return (this.inferRow ? this.data[0]||this : this).childIndex(this.Core());
+ },
+ hasNewline: function () {
+ if (this.isEmbellished()) {return this.CoreMO().hasNewline()}
+ if (this.isToken || this.linebreakContainer) {return false}
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i] && this.data[i].hasNewline()) {return true}
+ }
+ return false;
+ },
+ array: function () {if (this.inferred) {return this.data} else {return [this]}},
+ toString: function () {return this.type+"("+this.data.join(",")+")"},
+ getAnnotation: function () {return null}
+ },{
+ childrenSpacelike: function () {
+ for (var i = 0, m = this.data.length; i < m; i++)
+ {if (!this.data[i].isSpacelike()) {return false}}
+ return true;
+ },
+ childEmbellished: function () {
+ return (this.data[0] && this.data[0].isEmbellished());
+ },
+ childCore: function () {return (this.inferRow && this.data[0] ? this.data[0].Core() : this.data[0])},
+ childCoreMO: function () {return (this.data[0] ? this.data[0].CoreMO() : null)},
+ setChildTeXclass: function (prev) {
+ if (this.data[0]) {
+ prev = this.data[0].setTeXclass(prev);
+ this.updateTeXclass(this.data[0]);
+ }
+ return prev;
+ },
+ setBaseTeXclasses: function (prev) {
+ this.getPrevClass(prev); this.texClass = null;
+ if (this.data[0]) {
+ if (this.isEmbellished() || this.data[0].isa(MML.mi)) {
+ prev = this.data[0].setTeXclass(prev);
+ this.updateTeXclass(this.Core());
+ } else {this.data[0].setTeXclass(); prev = this}
+ } else {prev = this}
+ for (var i = 1, m = this.data.length; i < m; i++)
+ {if (this.data[i]) {this.data[i].setTeXclass()}}
+ return prev;
+ },
+ setSeparateTeXclasses: function (prev) {
+ this.getPrevClass(prev);
+ for (var i = 0, m = this.data.length; i < m; i++)
+ {if (this.data[i]) {this.data[i].setTeXclass()}}
+ if (this.isEmbellished()) {this.updateTeXclass(this.Core())}
+ return this;
+ }
+ });
+
+ MML.mi = MML.mbase.Subclass({
+ type: "mi", isToken: true,
+ texClass: MML.TEXCLASS.ORD,
+ defaults: {
+ mathvariant: MML.AUTO,
+ mathsize: MML.INHERIT,
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT
+ },
+ autoDefault: function (name) {
+ if (name === "mathvariant") {
+ var mi = (this.data[0]||"").toString();
+ return (mi.length === 1 ||
+ (mi.length === 2 && mi.charCodeAt(0) >= 0xD800 && mi.charCodeAt(0) < 0xDC00) ?
+ MML.VARIANT.ITALIC : MML.VARIANT.NORMAL);
+ }
+ return "";
+ },
+ setTeXclass: function (prev) {
+ this.getPrevClass(prev);
+ var name = this.data.join("");
+ if (name.length > 1 && name.match(/^[a-z][a-z0-9]*$/i) &&
+ this.texClass === MML.TEXCLASS.ORD) {
+ this.texClass = MML.TEXCLASS.OP;
+ this.autoOP = true;
+ }
+ return this;
+ }
+ });
+
+ MML.mn = MML.mbase.Subclass({
+ type: "mn", isToken: true,
+ texClass: MML.TEXCLASS.ORD,
+ defaults: {
+ mathvariant: MML.INHERIT,
+ mathsize: MML.INHERIT,
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT
+ }
+ });
+
+ MML.mo = MML.mbase.Subclass({
+ type: "mo", isToken: true,
+ defaults: {
+ mathvariant: MML.INHERIT,
+ mathsize: MML.INHERIT,
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT,
+ form: MML.AUTO,
+ fence: MML.AUTO,
+ separator: MML.AUTO,
+ lspace: MML.AUTO,
+ rspace: MML.AUTO,
+ stretchy: MML.AUTO,
+ symmetric: MML.AUTO,
+ maxsize: MML.AUTO,
+ minsize: MML.AUTO,
+ largeop: MML.AUTO,
+ movablelimits: MML.AUTO,
+ accent: MML.AUTO,
+ linebreak: MML.LINEBREAK.AUTO,
+ lineleading: MML.INHERIT,
+ linebreakstyle: MML.AUTO,
+ linebreakmultchar: MML.INHERIT,
+ indentalign: MML.INHERIT,
+ indentshift: MML.INHERIT,
+ indenttarget: MML.INHERIT,
+ indentalignfirst: MML.INHERIT,
+ indentshiftfirst: MML.INHERIT,
+ indentalignlast: MML.INHERIT,
+ indentshiftlast: MML.INHERIT,
+ texClass: MML.AUTO
+ },
+ defaultDef: {
+ form: MML.FORM.INFIX,
+ fence: false,
+ separator: false,
+ lspace: MML.LENGTH.THICKMATHSPACE,
+ rspace: MML.LENGTH.THICKMATHSPACE,
+ stretchy: false,
+ symmetric: false,
+ maxsize: MML.SIZE.INFINITY,
+ minsize: '0em', //'1em',
+ largeop: false,
+ movablelimits: false,
+ accent: false,
+ linebreak: MML.LINEBREAK.AUTO,
+ lineleading: "1ex",
+ linebreakstyle: "before",
+ indentalign: MML.INDENTALIGN.AUTO,
+ indentshift: "0",
+ indenttarget: "",
+ indentalignfirst: MML.INDENTALIGN.INDENTALIGN,
+ indentshiftfirst: MML.INDENTSHIFT.INDENTSHIFT,
+ indentalignlast: MML.INDENTALIGN.INDENTALIGN,
+ indentshiftlast: MML.INDENTSHIFT.INDENTSHIFT,
+ texClass: MML.TEXCLASS.REL // for MML, but TeX sets ORD explicitly
+ },
+ SPACE_ATTR: {lspace: 0x01, rspace: 0x02, form: 0x04},
+ useMMLspacing: 0x07,
+ autoDefault: function (name,nodefault) {
+ var def = this.def;
+ if (!def) {
+ if (name === "form") {this.useMMLspacing &= ~this.SPACE_ATTR.form; return this.getForm()}
+ var mo = this.data.join("");
+ var forms = [this.Get("form"),MML.FORM.INFIX,MML.FORM.POSTFIX,MML.FORM.PREFIX];
+ for (var i = 0, m = forms.length; i < m; i++) {
+ var data = this.OPTABLE[forms[i]][mo];
+ if (data) {def = this.makeDef(data); break}
+ }
+ if (!def) {def = this.CheckRange(mo)}
+ if (!def && nodefault) {def = {}} else {
+ if (!def) {def = MathJax.Hub.Insert({},this.defaultDef)}
+ if (this.parent) {this.def = def} else {def = MathJax.Hub.Insert({},def)}
+ def.form = forms[0];
+ }
+ }
+ this.useMMLspacing &= ~(this.SPACE_ATTR[name] || 0);
+ if (def[name] != null) {return def[name]}
+ else if (!nodefault) {return this.defaultDef[name]}
+ return "";
+ },
+ CheckRange: function (mo) {
+ var n = mo.charCodeAt(0);
+ if (n >= 0xD800 && n < 0xDC00) {n = (((n-0xD800)<<10)+(mo.charCodeAt(1)-0xDC00))+0x10000}
+ for (var i = 0, m = this.RANGES.length; i < m && this.RANGES[i][0] <= n; i++) {
+ if (n <= this.RANGES[i][1]) {
+ if (this.RANGES[i][3]) {
+ var file = MML.optableDir+"/"+this.RANGES[i][3]+".js";
+ this.RANGES[i][3] = null;
+ MathJax.Hub.RestartAfter(MathJax.Ajax.Require(file));
+ }
+ var data = MML.TEXCLASSNAMES[this.RANGES[i][2]];
+ data = this.OPTABLE.infix[mo] = MML.mo.OPTYPES[data === "BIN" ? "BIN3" : data];
+ return this.makeDef(data);
+ }
+ }
+ return null;
+ },
+ makeDef: function (data) {
+ if (data[2] == null) {data[2] = this.defaultDef.texClass}
+ if (!data[3]) {data[3] = {}}
+ var def = MathJax.Hub.Insert({},data[3]);
+ def.lspace = this.SPACE[data[0]]; def.rspace = this.SPACE[data[1]];
+ def.texClass = data[2];
+ if (def.texClass === MML.TEXCLASS.REL &&
+ (this.movablelimits || this.data.join("").match(/^[a-z]+$/i)))
+ {def.texClass = MML.TEXCLASS.OP} // mark named operators as OP
+ return def;
+ },
+ getForm: function () {
+ var core = this, parent = this.parent, Parent = this.Parent();
+ while (Parent && Parent.isEmbellished())
+ {core = parent; parent = Parent.parent; Parent = Parent.Parent()}
+ if (parent && parent.type === "mrow" && parent.NonSpaceLength() !== 1) {
+ if (parent.FirstNonSpace() === core) {return MML.FORM.PREFIX}
+ if (parent.LastNonSpace() === core) {return MML.FORM.POSTFIX}
+ }
+ return MML.FORM.INFIX;
+ },
+ isEmbellished: function () {return true},
+ hasNewline: function () {return (this.Get("linebreak") === MML.LINEBREAK.NEWLINE)},
+ CoreParent: function () {
+ var parent = this;
+ while (parent && parent.isEmbellished() &&
+ parent.CoreMO() === this && !parent.isa(MML.math)) {parent = parent.Parent()}
+ return parent;
+ },
+ CoreText: function (parent) {
+ if (!parent) {return ""}
+ if (parent.isEmbellished()) {return parent.CoreMO().data.join("")}
+ while ((((parent.isa(MML.mrow) || parent.isa(MML.TeXAtom) ||
+ parent.isa(MML.mstyle) || parent.isa(MML.mphantom)) &&
+ parent.data.length === 1) || parent.isa(MML.munderover)) &&
+ parent.data[0]) {parent = parent.data[0]}
+ if (!parent.isToken) {return ""} else {return parent.data.join("")}
+ },
+ remapChars: {
+ '*':"\u2217",
+ '"':"\u2033",
+ "\u00B0":"\u2218",
+ "\u00B2":"2",
+ "\u00B3":"3",
+ "\u00B4":"\u2032",
+ "\u00B9":"1"
+ },
+ remap: function (text,map) {
+ text = text.replace(/-/g,"\u2212");
+ if (map) {
+ text = text.replace(/'/g,"\u2032").replace(/`/g,"\u2035");
+ if (text.length === 1) {text = map[text]||text}
+ }
+ return text;
+ },
+ setTeXclass: function (prev) {
+ var values = this.getValues("form","lspace","rspace","fence"); // sets useMMLspacing
+ if (this.useMMLspacing) {this.texClass = MML.TEXCLASS.NONE; return this}
+ if (values.fence && !this.texClass) {
+ if (values.form === MML.FORM.PREFIX) {this.texClass = MML.TEXCLASS.OPEN}
+ if (values.form === MML.FORM.POSTFIX) {this.texClass = MML.TEXCLASS.CLOSE}
+ }
+ this.texClass = this.Get("texClass");
+ if (this.data.join("") === "\u2061") {
+ // force previous node to be texClass OP, and skip this node
+ if (prev) {prev.texClass = MML.TEXCLASS.OP; prev.fnOP = true}
+ this.texClass = this.prevClass = MML.TEXCLASS.NONE;
+ return prev;
+ }
+ return this.adjustTeXclass(prev);
+ },
+ adjustTeXclass: function (prev) {
+ if (this.texClass === MML.TEXCLASS.NONE) {return prev}
+ if (prev) {
+ if (prev.autoOP && (this.texClass === MML.TEXCLASS.BIN ||
+ this.texClass === MML.TEXCLASS.REL))
+ {prev.texClass = MML.TEXCLASS.ORD}
+ this.prevClass = prev.texClass || MML.TEXCLASS.ORD;
+ this.prevLevel = prev.Get("scriptlevel")
+ } else {this.prevClass = MML.TEXCLASS.NONE}
+ if (this.texClass === MML.TEXCLASS.BIN &&
+ (this.prevClass === MML.TEXCLASS.NONE ||
+ this.prevClass === MML.TEXCLASS.BIN ||
+ this.prevClass === MML.TEXCLASS.OP ||
+ this.prevClass === MML.TEXCLASS.REL ||
+ this.prevClass === MML.TEXCLASS.OPEN ||
+ this.prevClass === MML.TEXCLASS.PUNCT)) {
+ this.texClass = MML.TEXCLASS.ORD;
+ } else if (this.prevClass === MML.TEXCLASS.BIN &&
+ (this.texClass === MML.TEXCLASS.REL ||
+ this.texClass === MML.TEXCLASS.CLOSE ||
+ this.texClass === MML.TEXCLASS.PUNCT)) {
+ prev.texClass = this.prevClass = MML.TEXCLASS.ORD;
+ } else if (this.texClass === MML.TEXCLASS.BIN) {
+ //
+ // Check if node is the last one in its container since the rule
+ // above only takes effect if there is a node that follows.
+ //
+ var child = this, parent = this.parent;
+ while (parent && parent.parent && parent.isEmbellished() &&
+ (parent.data.length === 1 ||
+ (parent.type !== "mrow" && parent.Core() === child))) // handles msubsup and munderover
+ {child = parent; parent = parent.parent}
+ if (parent.data[parent.data.length-1] === child) this.texClass = MML.TEXCLASS.ORD;
+ }
+ return this;
+ }
+ });
+
+ MML.mtext = MML.mbase.Subclass({
+ type: "mtext", isToken: true,
+ isSpacelike: function () {return true},
+ texClass: MML.TEXCLASS.ORD,
+ defaults: {
+ mathvariant: MML.INHERIT,
+ mathsize: MML.INHERIT,
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT
+ }
+ });
+
+ MML.mspace = MML.mbase.Subclass({
+ type: "mspace", isToken: true,
+ isSpacelike: function () {return true},
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ width: "0em",
+ height: "0ex",
+ depth: "0ex",
+ linebreak: MML.LINEBREAK.AUTO
+ },
+ hasDimAttr: function () {
+ return (this.hasValue("width") || this.hasValue("height") ||
+ this.hasValue("depth"));
+ },
+ hasNewline: function () {
+ // The MathML spec says that the linebreak attribute should be ignored
+ // if any dimensional attribute is set.
+ return (!this.hasDimAttr() &&
+ this.Get("linebreak") === MML.LINEBREAK.NEWLINE);
+ }
+ });
+
+ MML.ms = MML.mbase.Subclass({
+ type: "ms", isToken: true,
+ texClass: MML.TEXCLASS.ORD,
+ defaults: {
+ mathvariant: MML.INHERIT,
+ mathsize: MML.INHERIT,
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT,
+ lquote: '"',
+ rquote: '"'
+ }
+ });
+
+ MML.mglyph = MML.mbase.Subclass({
+ type: "mglyph", isToken: true,
+ texClass: MML.TEXCLASS.ORD,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ alt: "",
+ src: "",
+ width: MML.AUTO,
+ height: MML.AUTO,
+ valign: "0em"
+ }
+ });
+
+ MML.mrow = MML.mbase.Subclass({
+ type: "mrow",
+ isSpacelike: MML.mbase.childrenSpacelike,
+ inferred: false, notParent: false,
+ isEmbellished: function () {
+ var isEmbellished = false;
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ if (this.data[i] == null) continue;
+ if (this.data[i].isEmbellished()) {
+ if (isEmbellished) {return false}
+ isEmbellished = true; this.core = i;
+ } else if (!this.data[i].isSpacelike()) {return false}
+ }
+ return isEmbellished;
+ },
+ NonSpaceLength: function () {
+ var n = 0;
+ for (var i = 0, m = this.data.length; i < m; i++)
+ {if (this.data[i] && !this.data[i].isSpacelike()) {n++}}
+ return n;
+ },
+ FirstNonSpace: function () {
+ for (var i = 0, m = this.data.length; i < m; i++)
+ {if (this.data[i] && !this.data[i].isSpacelike()) {return this.data[i]}}
+ return null;
+ },
+ LastNonSpace: function () {
+ for (var i = this.data.length-1; i >= 0; i--)
+ {if (this.data[0] && !this.data[i].isSpacelike()) {return this.data[i]}}
+ return null;
+ },
+ Core: function () {
+ if (!(this.isEmbellished()) || typeof(this.core) === "undefined") {return this}
+ return this.data[this.core];
+ },
+ CoreMO: function () {
+ if (!(this.isEmbellished()) || typeof(this.core) === "undefined") {return this}
+ return this.data[this.core].CoreMO();
+ },
+ toString: function () {
+ if (this.inferred) {return '[' + this.data.join(',') + ']'}
+ return this.SUPER(arguments).toString.call(this);
+ },
+ setTeXclass: function (prev) {
+ var i, m = this.data.length;
+ if ((this.open || this.close) && (!prev || !prev.fnOP)) {
+ //
+ // came from \left...\right
+ // so treat as subexpression (tex class INNER)
+ //
+ this.getPrevClass(prev); prev = null;
+ for (i = 0; i < m; i++)
+ {if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}}
+ if (!this.hasOwnProperty("texClass")) this.texClass = MML.TEXCLASS.INNER;
+ return this;
+ } else {
+ //
+ // Normal , so treat as
+ // thorugh mrow is not there
+ //
+ for (i = 0; i < m; i++)
+ {if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}}
+ if (this.data[0]) {this.updateTeXclass(this.data[0])}
+ return prev;
+ }
+ },
+ getAnnotation: function (name) {
+ if (this.data.length != 1) return null;
+ return this.data[0].getAnnotation(name);
+ }
+ });
+
+ MML.mfrac = MML.mbase.Subclass({
+ type: "mfrac", num: 0, den: 1,
+ linebreakContainer: true,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ linethickness: MML.LINETHICKNESS.MEDIUM,
+ numalign: MML.ALIGN.CENTER,
+ denomalign: MML.ALIGN.CENTER,
+ bevelled: false
+ },
+ adjustChild_displaystyle: function (n) {return false},
+ adjustChild_scriptlevel: function (n) {
+ var level = this.Get("scriptlevel");
+ if (!this.Get("displaystyle") || level > 0) {level++}
+ return level;
+ },
+ adjustChild_texprimestyle: function (n) {
+ if (n == this.den) {return true}
+ return this.Get("texprimestyle");
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.msqrt = MML.mbase.Subclass({
+ type: "msqrt",
+ inferRow: true,
+ linebreakContainer: true,
+ texClass: MML.TEXCLASS.ORD,
+ setTeXclass: MML.mbase.setSeparateTeXclasses,
+ adjustChild_texprimestyle: function (n) {return true}
+ });
+
+ MML.mroot = MML.mbase.Subclass({
+ type: "mroot",
+ linebreakContainer: true,
+ texClass: MML.TEXCLASS.ORD,
+ adjustChild_displaystyle: function (n) {
+ if (n === 1) {return false}
+ return this.Get("displaystyle");
+ },
+ adjustChild_scriptlevel: function (n) {
+ var level = this.Get("scriptlevel");
+ if (n === 1) {level += 2}
+ return level;
+ },
+ adjustChild_texprimestyle: function (n) {
+ if (n === 0) {return true};
+ return this.Get("texprimestyle");
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.mstyle = MML.mbase.Subclass({
+ type: "mstyle",
+ isSpacelike: MML.mbase.childrenSpacelike,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ inferRow: true,
+ defaults: {
+ scriptlevel: MML.INHERIT,
+ displaystyle: MML.INHERIT,
+ scriptsizemultiplier: Math.sqrt(1/2),
+ scriptminsize: "8pt",
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ dir: MML.INHERIT,
+ infixlinebreakstyle: MML.LINEBREAKSTYLE.BEFORE,
+ decimalseparator: "."
+ },
+ adjustChild_scriptlevel: function (n) {
+ var level = this.scriptlevel;
+ if (level == null) {
+ level = this.Get("scriptlevel");
+ } else if (String(level).match(/^ *[-+]/)) {
+ var LEVEL = this.Get("scriptlevel",null,true);
+ level = LEVEL + parseInt(level);
+ }
+ return level;
+ },
+ inheritFromMe: true,
+ noInherit: {
+ mpadded: {width: true, height: true, depth: true, lspace: true, voffset: true},
+ mtable: {width: true, height: true, depth: true, align: true}
+ },
+ getRemoved: {fontfamily:"fontFamily", fontweight:"fontWeight", fontstyle:"fontStyle", fontsize:"fontSize"},
+ setTeXclass: MML.mbase.setChildTeXclass
+ });
+
+ MML.merror = MML.mbase.Subclass({
+ type: "merror",
+ inferRow: true,
+ linebreakContainer: true,
+ texClass: MML.TEXCLASS.ORD
+ });
+
+ MML.mpadded = MML.mbase.Subclass({
+ type: "mpadded",
+ inferRow: true,
+ isSpacelike: MML.mbase.childrenSpacelike,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ width: "",
+ height: "",
+ depth: "",
+ lspace: 0,
+ voffset: 0
+ },
+ setTeXclass: MML.mbase.setChildTeXclass
+ });
+
+ MML.mphantom = MML.mbase.Subclass({
+ type: "mphantom",
+ texClass: MML.TEXCLASS.ORD,
+ inferRow: true,
+ isSpacelike: MML.mbase.childrenSpacelike,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ setTeXclass: MML.mbase.setChildTeXclass
+ });
+
+ MML.mfenced = MML.mbase.Subclass({
+ type: "mfenced",
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ open: '(',
+ close: ')',
+ separators: ','
+ },
+ addFakeNodes: function () {
+ var values = this.getValues("open","close","separators");
+ values.open = values.open.replace(/[ \t\n\r]/g,"");
+ values.close = values.close.replace(/[ \t\n\r]/g,"");
+ values.separators = values.separators.replace(/[ \t\n\r]/g,"");
+ //
+ // Create a fake node for the open item
+ //
+ if (values.open !== "") {
+ this.SetData("open",MML.mo(values.open).With({
+ fence:true, form:MML.FORM.PREFIX, texClass:MML.TEXCLASS.OPEN
+ }));
+ //
+ // Clear flag for using MML spacing even though form is specified
+ //
+ this.data.open.useMMLspacing = 0;
+ }
+ //
+ // Create fake nodes for the separators
+ //
+ if (values.separators !== "") {
+ while (values.separators.length < this.data.length)
+ {values.separators += values.separators.charAt(values.separators.length-1)}
+ for (var i = 1, m = this.data.length; i < m; i++) {
+ if (this.data[i]) {
+ this.SetData("sep"+i,MML.mo(values.separators.charAt(i-1)).With({separator:true}))
+ this.data["sep"+i].useMMLspacing = 0;
+ }
+ }
+ }
+ //
+ // Create fake node for the close item
+ //
+ if (values.close !== "") {
+ this.SetData("close",MML.mo(values.close).With({
+ fence:true, form:MML.FORM.POSTFIX, texClass:MML.TEXCLASS.CLOSE
+ }));
+ //
+ // Clear flag for using MML spacing even though form is specified
+ //
+ this.data.close.useMMLspacing = 0;
+ }
+ },
+ texClass: MML.TEXCLASS.OPEN,
+ setTeXclass: function (prev) {
+ this.addFakeNodes();
+ this.getPrevClass(prev);
+ if (this.data.open) {prev = this.data.open.setTeXclass(prev)}
+ if (this.data[0]) {prev = this.data[0].setTeXclass(prev)}
+ for (var i = 1, m = this.data.length; i < m; i++) {
+ if (this.data["sep"+i]) {prev = this.data["sep"+i].setTeXclass(prev)}
+ if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}
+ }
+ if (this.data.close) {prev = this.data.close.setTeXclass(prev)}
+ this.updateTeXclass(this.data.open);
+ this.texClass = MML.TEXCLASS.INNER;
+ return prev;
+ }
+ });
+
+ MML.menclose = MML.mbase.Subclass({
+ type: "menclose",
+ inferRow: true,
+ linebreakContainer: true,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ notation: MML.NOTATION.LONGDIV,
+ texClass: MML.TEXCLASS.ORD
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.msubsup = MML.mbase.Subclass({
+ type: "msubsup", base: 0, sub: 1, sup: 2,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ subscriptshift: "",
+ superscriptshift: "",
+ texClass: MML.AUTO
+ },
+ autoDefault: function (name) {
+ if (name === "texClass")
+ {return (this.isEmbellished() ? this.CoreMO().Get(name) : MML.TEXCLASS.ORD)}
+ return 0;
+ },
+ adjustChild_displaystyle: function (n) {
+ if (n > 0) {return false}
+ return this.Get("displaystyle");
+ },
+ adjustChild_scriptlevel: function (n) {
+ var level = this.Get("scriptlevel");
+ if (n > 0) {level++}
+ return level;
+ },
+ adjustChild_texprimestyle: function (n) {
+ if (n === this.sub) {return true}
+ return this.Get("texprimestyle");
+ },
+ setTeXclass: MML.mbase.setBaseTeXclasses
+ });
+
+ MML.msub = MML.msubsup.Subclass({type: "msub"});
+ MML.msup = MML.msubsup.Subclass({type: "msup", sub:2, sup:1});
+ MML.mmultiscripts = MML.msubsup.Subclass({
+ type: "mmultiscripts",
+ adjustChild_texprimestyle: function (n) {
+ if (n % 2 === 1) {return true}
+ return this.Get("texprimestyle");
+ }
+ });
+ MML.mprescripts = MML.mbase.Subclass({type: "mprescripts"});
+ MML.none = MML.mbase.Subclass({type: "none"});
+
+ MML.munderover = MML.mbase.Subclass({
+ type: "munderover",
+ base: 0, under: 1, over: 2, sub: 1, sup: 2,
+ ACCENTS: ["", "accentunder", "accent"],
+ linebreakContainer: true,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ accent: MML.AUTO,
+ accentunder: MML.AUTO,
+ align: MML.ALIGN.CENTER,
+ texClass: MML.AUTO,
+ subscriptshift: "", // when converted to msubsup by moveablelimits
+ superscriptshift: "" // when converted to msubsup by moveablelimits
+ },
+ autoDefault: function (name) {
+ if (name === "texClass")
+ {return (this.isEmbellished() ? this.CoreMO().Get(name) : MML.TEXCLASS.ORD)}
+ if (name === "accent" && this.data[this.over]) {return this.data[this.over].CoreMO().Get("accent")}
+ if (name === "accentunder" && this.data[this.under]) {return this.data[this.under].CoreMO().Get("accent")}
+ return false;
+ },
+ adjustChild_displaystyle: function (n) {
+ if (n > 0) {return false}
+ return this.Get("displaystyle");
+ },
+ adjustChild_scriptlevel: function (n) {
+ var level = this.Get("scriptlevel");
+ var force = (this.data[this.base] && !this.Get("displaystyle") &&
+ this.data[this.base].CoreMO().Get("movablelimits"));
+ if (n == this.under && (force || !this.Get("accentunder"))) {level++}
+ if (n == this.over && (force || !this.Get("accent"))) {level++}
+ return level;
+ },
+ adjustChild_texprimestyle: function (n) {
+ if (n === this.base && this.data[this.over]) {return true}
+ return this.Get("texprimestyle");
+ },
+ setTeXclass: MML.mbase.setBaseTeXclasses
+ });
+
+ MML.munder = MML.munderover.Subclass({type: "munder"});
+ MML.mover = MML.munderover.Subclass({
+ type: "mover", over: 1, under: 2, sup: 1, sub: 2,
+ ACCENTS: ["", "accent", "accentunder"]
+ });
+
+ MML.mtable = MML.mbase.Subclass({
+ type: "mtable",
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ align: MML.ALIGN.AXIS,
+ rowalign: MML.ALIGN.BASELINE,
+ columnalign: MML.ALIGN.CENTER,
+ groupalign: "{left}",
+ alignmentscope: true,
+ columnwidth: MML.WIDTH.AUTO,
+ width: MML.WIDTH.AUTO,
+ rowspacing: "1ex",
+ columnspacing: ".8em",
+ rowlines: MML.LINES.NONE,
+ columnlines: MML.LINES.NONE,
+ frame: MML.LINES.NONE,
+ framespacing: "0.4em 0.5ex",
+ equalrows: false,
+ equalcolumns: false,
+ displaystyle: false,
+ side: MML.SIDE.RIGHT,
+ minlabelspacing: "0.8em",
+ texClass: MML.TEXCLASS.ORD,
+ useHeight: 1
+ },
+ adjustChild_displaystyle: function () {
+ return (this.displaystyle != null ? this.displaystyle : this.defaults.displaystyle);
+ },
+ inheritFromMe: true,
+ noInherit: {
+ mover: {align: true},
+ munder: {align: true},
+ munderover: {align: true},
+ mtable: {
+ align: true, rowalign: true, columnalign: true, groupalign: true,
+ alignmentscope: true, columnwidth: true, width: true, rowspacing: true,
+ columnspacing: true, rowlines: true, columnlines: true, frame: true,
+ framespacing: true, equalrows: true, equalcolumns: true, displaystyle: true,
+ side: true, minlabelspacing: true, texClass: true, useHeight: 1
+ }
+ },
+ linebreakContainer: true,
+ Append: function () {
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ if (!((arguments[i] instanceof MML.mtr) ||
+ (arguments[i] instanceof MML.mlabeledtr))) {arguments[i] = MML.mtr(arguments[i])}
+ }
+ this.SUPER(arguments).Append.apply(this,arguments);
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.mtr = MML.mbase.Subclass({
+ type: "mtr",
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ rowalign: MML.INHERIT,
+ columnalign: MML.INHERIT,
+ groupalign: MML.INHERIT
+ },
+ inheritFromMe: true,
+ noInherit: {
+ mrow: {rowalign: true, columnalign: true, groupalign: true},
+ mtable: {rowalign: true, columnalign: true, groupalign: true}
+ },
+ linebreakContainer: true,
+ Append: function () {
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ if (!(arguments[i] instanceof MML.mtd)) {arguments[i] = MML.mtd(arguments[i])}
+ }
+ this.SUPER(arguments).Append.apply(this,arguments);
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.mtd = MML.mbase.Subclass({
+ type: "mtd",
+ inferRow: true,
+ linebreakContainer: true,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ rowspan: 1,
+ columnspan: 1,
+ rowalign: MML.INHERIT,
+ columnalign: MML.INHERIT,
+ groupalign: MML.INHERIT
+ },
+ setTeXclass: MML.mbase.setSeparateTeXclasses
+ });
+
+ MML.maligngroup = MML.mbase.Subclass({
+ type: "maligngroup",
+ isSpacelike: function () {return true},
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ groupalign: MML.INHERIT
+ },
+ inheritFromMe: true,
+ noInherit: {
+ mrow: {groupalign: true},
+ mtable: {groupalign: true}
+ }
+ });
+
+ MML.malignmark = MML.mbase.Subclass({
+ type: "malignmark",
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ edge: MML.SIDE.LEFT
+ },
+ isSpacelike: function () {return true}
+ });
+
+ MML.mlabeledtr = MML.mtr.Subclass({
+ type: "mlabeledtr"
+ });
+
+ MML.maction = MML.mbase.Subclass({
+ type: "maction",
+ defaults: {
+ mathbackground: MML.INHERIT,
+ mathcolor: MML.INHERIT,
+ actiontype: MML.ACTIONTYPE.TOGGLE,
+ selection: 1
+ },
+ selected: function () {return this.data[this.Get("selection")-1] || MML.NULL},
+ isEmbellished: function () {return this.selected().isEmbellished()},
+ isSpacelike: function () {return this.selected().isSpacelike()},
+ Core: function () {return this.selected().Core()},
+ CoreMO: function () {return this.selected().CoreMO()},
+ setTeXclass: function (prev) {
+ if (this.Get("actiontype") === MML.ACTIONTYPE.TOOLTIP && this.data[1]) {
+ // Make sure tooltip has proper spacing when typeset (see issue #412)
+ this.data[1].setTeXclass();
+ }
+ var selected = this.selected();
+ prev = selected.setTeXclass(prev);
+ this.updateTeXclass(selected);
+ return prev;
+ }
+ });
+
+ MML.semantics = MML.mbase.Subclass({
+ type: "semantics", notParent: true,
+ isEmbellished: MML.mbase.childEmbellished,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ defaults: {
+ definitionURL: null,
+ encoding: null
+ },
+ setTeXclass: MML.mbase.setChildTeXclass,
+ getAnnotation: function (name) {
+ var encodingList = MathJax.Hub.config.MathMenu.semanticsAnnotations[name];
+ if (encodingList) {
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ var encoding = this.data[i].Get("encoding");
+ if (encoding) {
+ for (var j = 0, n = encodingList.length; j < n; j++) {
+ if (encodingList[j] === encoding) return this.data[i];
+ }
+ }
+ }
+ }
+ return null;
+ }
+ });
+ MML.annotation = MML.mbase.Subclass({
+ type: "annotation", isChars: true,
+ linebreakContainer: true,
+ defaults: {
+ definitionURL: null,
+ encoding: null,
+ cd: "mathmlkeys",
+ name: "",
+ src: null
+ }
+ });
+ MML["annotation-xml"] = MML.mbase.Subclass({
+ type: "annotation-xml",
+ linebreakContainer: true,
+ defaults: {
+ definitionURL: null,
+ encoding: null,
+ cd: "mathmlkeys",
+ name: "",
+ src: null
+ }
+ });
+
+ MML.math = MML.mstyle.Subclass({
+ type: "math",
+ defaults: {
+ mathvariant: MML.VARIANT.NORMAL,
+ mathsize: MML.SIZE.NORMAL,
+ mathcolor: "", // should be "black", but allow it to inherit from surrounding text
+ mathbackground: MML.COLOR.TRANSPARENT,
+ dir: "ltr",
+ scriptlevel: 0,
+ displaystyle: MML.AUTO,
+ display: "inline",
+ maxwidth: "",
+ overflow: MML.OVERFLOW.LINEBREAK,
+ altimg: "",
+ 'altimg-width': "",
+ 'altimg-height': "",
+ 'altimg-valign': "",
+ alttext: "",
+ cdgroup: "",
+ scriptsizemultiplier: Math.sqrt(1/2),
+ scriptminsize: "8px", // should be 8pt, but that's too big
+ infixlinebreakstyle: MML.LINEBREAKSTYLE.BEFORE,
+ lineleading: "1ex",
+ indentshift: "auto", // use user configuration
+ indentalign: MML.INDENTALIGN.AUTO,
+ indentalignfirst: MML.INDENTALIGN.INDENTALIGN,
+ indentshiftfirst: MML.INDENTSHIFT.INDENTSHIFT,
+ indentalignlast: MML.INDENTALIGN.INDENTALIGN,
+ indentshiftlast: MML.INDENTSHIFT.INDENTSHIFT,
+ decimalseparator: ".",
+ texprimestyle: false // is it in TeX's C' style?
+ },
+ autoDefault: function (name) {
+ if (name === "displaystyle") {return this.Get("display") === "block"}
+ return "";
+ },
+ linebreakContainer: true,
+ setTeXclass: MML.mbase.setChildTeXclass,
+ getAnnotation: function (name) {
+ if (this.data.length != 1) return null;
+ return this.data[0].getAnnotation(name);
+ }
+ });
+
+ MML.chars = MML.mbase.Subclass({
+ type: "chars",
+ Append: function () {this.data.push.apply(this.data,arguments)},
+ value: function () {return this.data.join("")},
+ toString: function () {return this.data.join("")}
+ });
+
+ MML.entity = MML.mbase.Subclass({
+ type: "entity",
+ Append: function () {this.data.push.apply(this.data,arguments)},
+ value: function () {
+ if (this.data[0].substr(0,2) === "#x") {return parseInt(this.data[0].substr(2),16)}
+ else if (this.data[0].substr(0,1) === "#") {return parseInt(this.data[0].substr(1))}
+ else {return 0} // FIXME: look up named entities from table
+ },
+ toString: function () {
+ var n = this.value();
+ if (n <= 0xFFFF) {return String.fromCharCode(n)}
+ n -= 0x10000;
+ return String.fromCharCode((n>>10)+0xD800)
+ + String.fromCharCode((n&0x3FF)+0xDC00);
+ }
+ });
+
+ MML.xml = MML.mbase.Subclass({
+ type: "xml",
+ Init: function () {
+ this.div = document.createElement("div");
+ return this.SUPER(arguments).Init.apply(this,arguments);
+ },
+ Append: function () {
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ var node = this.Import(arguments[i]);
+ this.data.push(node);
+ this.div.appendChild(node);
+ }
+ },
+ Import: function (node) {
+ if (document.importNode) {return document.importNode(node,true)}
+ //
+ // IE < 9 doesn't have importNode, so fake it.
+ //
+ var nNode, i, m;
+ if (node.nodeType === 1) { // ELEMENT_NODE
+ nNode = document.createElement(node.nodeName);
+ for (i = 0, m = node.attributes.length; i < m; i++) {
+ var attribute = node.attributes[i];
+ if (attribute.specified && attribute.nodeValue != null && attribute.nodeValue != '')
+ {nNode.setAttribute(attribute.nodeName,attribute.nodeValue)}
+ if (attribute.nodeName === "style") {nNode.style.cssText = attribute.nodeValue}
+ }
+ if (node.className) {nNode.className = node.className}
+ } else if (node.nodeType === 3 || node.nodeType === 4) { // TEXT_NODE or CDATA_SECTION_NODE
+ nNode = document.createTextNode(node.nodeValue);
+ } else if (node.nodeType === 8) { // COMMENT_NODE
+ nNode = document.createComment(node.nodeValue);
+ } else {
+ return document.createTextNode('');
+ }
+ for (i = 0, m = node.childNodes.length; i < m; i++)
+ {nNode.appendChild(this.Import(node.childNodes[i]))}
+ return nNode;
+ },
+ value: function () {return this.div},
+ toString: function () {return this.div.innerHTML}
+ });
+
+ MML.TeXAtom = MML.mbase.Subclass({
+ type: "texatom",
+ inferRow: true, notParent: true,
+ texClass: MML.TEXCLASS.ORD,
+ Core: MML.mbase.childCore,
+ CoreMO: MML.mbase.childCoreMO,
+ isEmbellished: MML.mbase.childEmbellished,
+ setTeXclass: function (prev) {
+ this.data[0].setTeXclass();
+ return this.adjustTeXclass(prev);
+ },
+ adjustTeXclass: MML.mo.prototype.adjustTeXclass
+ });
+
+ MML.NULL = MML.mbase().With({type:"null"});
+
+ var TEXCLASS = MML.TEXCLASS;
+
+ var MO = {
+ ORD: [0,0,TEXCLASS.ORD],
+ ORD11: [1,1,TEXCLASS.ORD],
+ ORD21: [2,1,TEXCLASS.ORD],
+ ORD02: [0,2,TEXCLASS.ORD],
+ ORD55: [5,5,TEXCLASS.ORD],
+ OP: [1,2,TEXCLASS.OP,{largeop: true, movablelimits: true, symmetric: true}],
+ OPFIXED: [1,2,TEXCLASS.OP,{largeop: true, movablelimits: true}],
+ INTEGRAL: [0,1,TEXCLASS.OP,{largeop: true, symmetric: true}],
+ INTEGRAL2: [1,2,TEXCLASS.OP,{largeop: true, symmetric: true}],
+ BIN3: [3,3,TEXCLASS.BIN],
+ BIN4: [4,4,TEXCLASS.BIN],
+ BIN01: [0,1,TEXCLASS.BIN],
+ BIN5: [5,5,TEXCLASS.BIN],
+ TALLBIN: [4,4,TEXCLASS.BIN,{stretchy: true}],
+ BINOP: [4,4,TEXCLASS.BIN,{largeop: true, movablelimits: true}],
+ REL: [5,5,TEXCLASS.REL],
+ REL1: [1,1,TEXCLASS.REL,{stretchy: true}],
+ REL4: [4,4,TEXCLASS.REL],
+ RELSTRETCH: [5,5,TEXCLASS.REL,{stretchy: true}],
+ RELACCENT: [5,5,TEXCLASS.REL,{accent: true}],
+ WIDEREL: [5,5,TEXCLASS.REL,{accent: true, stretchy: true}],
+ OPEN: [0,0,TEXCLASS.OPEN,{fence: true, stretchy: true, symmetric: true}],
+ CLOSE: [0,0,TEXCLASS.CLOSE,{fence: true, stretchy: true, symmetric: true}],
+ INNER: [0,0,TEXCLASS.INNER],
+ PUNCT: [0,3,TEXCLASS.PUNCT],
+ ACCENT: [0,0,TEXCLASS.ORD,{accent: true}],
+ WIDEACCENT: [0,0,TEXCLASS.ORD,{accent: true, stretchy: true}]
+ };
+
+ MML.mo.Augment({
+ SPACE: [
+ '0em',
+ '0.1111em',
+ '0.1667em',
+ '0.2222em',
+ '0.2667em',
+ '0.3333em'
+ ],
+ RANGES: [
+ [0x20,0x7F,TEXCLASS.REL,"BasicLatin"],
+ [0xA0,0xFF,TEXCLASS.ORD,"Latin1Supplement"],
+ [0x100,0x17F,TEXCLASS.ORD],
+ [0x180,0x24F,TEXCLASS.ORD],
+ [0x2B0,0x2FF,TEXCLASS.ORD,"SpacingModLetters"],
+ [0x300,0x36F,TEXCLASS.ORD,"CombDiacritMarks"],
+ [0x370,0x3FF,TEXCLASS.ORD,"GreekAndCoptic"],
+ [0x1E00,0x1EFF,TEXCLASS.ORD],
+ [0x2000,0x206F,TEXCLASS.PUNCT,"GeneralPunctuation"],
+ [0x2070,0x209F,TEXCLASS.ORD],
+ [0x20A0,0x20CF,TEXCLASS.ORD],
+ [0x20D0,0x20FF,TEXCLASS.ORD,"CombDiactForSymbols"],
+ [0x2100,0x214F,TEXCLASS.ORD,"LetterlikeSymbols"],
+ [0x2150,0x218F,TEXCLASS.ORD],
+ [0x2190,0x21FF,TEXCLASS.REL,"Arrows"],
+ [0x2200,0x22FF,TEXCLASS.BIN,"MathOperators"],
+ [0x2300,0x23FF,TEXCLASS.ORD,"MiscTechnical"],
+ [0x2460,0x24FF,TEXCLASS.ORD],
+ [0x2500,0x259F,TEXCLASS.ORD],
+ [0x25A0,0x25FF,TEXCLASS.ORD,"GeometricShapes"],
+ [0x2700,0x27BF,TEXCLASS.ORD,"Dingbats"],
+ [0x27C0,0x27EF,TEXCLASS.ORD,"MiscMathSymbolsA"],
+ [0x27F0,0x27FF,TEXCLASS.REL,"SupplementalArrowsA"],
+ [0x2900,0x297F,TEXCLASS.REL,"SupplementalArrowsB"],
+ [0x2980,0x29FF,TEXCLASS.ORD,"MiscMathSymbolsB"],
+ [0x2A00,0x2AFF,TEXCLASS.BIN,"SuppMathOperators"],
+ [0x2B00,0x2BFF,TEXCLASS.ORD,"MiscSymbolsAndArrows"],
+ [0x1D400,0x1D7FF,TEXCLASS.ORD]
+ ],
+ OPTABLE: {
+ prefix: {
+ '\u2200': MO.ORD21, // for all
+ '\u2202': MO.ORD21, // partial differential
+ '\u2203': MO.ORD21, // there exists
+ '\u2207': MO.ORD21, // nabla
+ '\u220F': MO.OP, // n-ary product
+ '\u2210': MO.OP, // n-ary coproduct
+ '\u2211': MO.OP, // n-ary summation
+ '\u2212': MO.BIN01, // minus sign
+ '\u2213': MO.BIN01, // minus-or-plus sign
+ '\u221A': [1,1,TEXCLASS.ORD,{stretchy: true}], // square root
+ '\u2220': MO.ORD, // angle
+ '\u222B': MO.INTEGRAL, // integral
+ '\u222E': MO.INTEGRAL, // contour integral
+ '\u22C0': MO.OP, // n-ary logical and
+ '\u22C1': MO.OP, // n-ary logical or
+ '\u22C2': MO.OP, // n-ary intersection
+ '\u22C3': MO.OP, // n-ary union
+ '\u2308': MO.OPEN, // left ceiling
+ '\u230A': MO.OPEN, // left floor
+ '\u27E8': MO.OPEN, // mathematical left angle bracket
+ '\u27EE': MO.OPEN, // mathematical left flattened parenthesis
+ '\u2A00': MO.OP, // n-ary circled dot operator
+ '\u2A01': MO.OP, // n-ary circled plus operator
+ '\u2A02': MO.OP, // n-ary circled times operator
+ '\u2A04': MO.OP, // n-ary union operator with plus
+ '\u2A06': MO.OP, // n-ary square union operator
+ '\u00AC': MO.ORD21, // not sign
+ '\u00B1': MO.BIN01, // plus-minus sign
+ '(': MO.OPEN, // left parenthesis
+ '+': MO.BIN01, // plus sign
+ '-': MO.BIN01, // hyphen-minus
+ '[': MO.OPEN, // left square bracket
+ '{': MO.OPEN, // left curly bracket
+ '|': MO.OPEN // vertical line
+ },
+ postfix: {
+ '!': [1,0,TEXCLASS.CLOSE], // exclamation mark
+ '&': MO.ORD, // ampersand
+ '\u2032': MO.ORD02, // prime
+ '\u203E': MO.WIDEACCENT, // overline
+ '\u2309': MO.CLOSE, // right ceiling
+ '\u230B': MO.CLOSE, // right floor
+ '\u23DE': MO.WIDEACCENT, // top curly bracket
+ '\u23DF': MO.WIDEACCENT, // bottom curly bracket
+ '\u266D': MO.ORD02, // music flat sign
+ '\u266E': MO.ORD02, // music natural sign
+ '\u266F': MO.ORD02, // music sharp sign
+ '\u27E9': MO.CLOSE, // mathematical right angle bracket
+ '\u27EF': MO.CLOSE, // mathematical right flattened parenthesis
+ '\u02C6': MO.WIDEACCENT, // modifier letter circumflex accent
+ '\u02C7': MO.WIDEACCENT, // caron
+ '\u02C9': MO.WIDEACCENT, // modifier letter macron
+ '\u02CA': MO.ACCENT, // modifier letter acute accent
+ '\u02CB': MO.ACCENT, // modifier letter grave accent
+ '\u02D8': MO.ACCENT, // breve
+ '\u02D9': MO.ACCENT, // dot above
+ '\u02DC': MO.WIDEACCENT, // small tilde
+ '\u0302': MO.WIDEACCENT, // combining circumflex accent
+ '\u00A8': MO.ACCENT, // diaeresis
+ '\u00AF': MO.WIDEACCENT, // macron
+ ')': MO.CLOSE, // right parenthesis
+ ']': MO.CLOSE, // right square bracket
+ '^': MO.WIDEACCENT, // circumflex accent
+ '_': MO.WIDEACCENT, // low line
+ '`': MO.ACCENT, // grave accent
+ '|': MO.CLOSE, // vertical line
+ '}': MO.CLOSE, // right curly bracket
+ '~': MO.WIDEACCENT // tilde
+ },
+ infix: {
+ '': MO.ORD, // empty
+ '%': [3,3,TEXCLASS.ORD], // percent sign
+ '\u2022': MO.BIN4, // bullet
+ '\u2026': MO.INNER, // horizontal ellipsis
+ '\u2044': MO.TALLBIN, // fraction slash
+ '\u2061': MO.ORD, // function application
+ '\u2062': MO.ORD, // invisible times
+ '\u2063': [0,0,TEXCLASS.ORD,{linebreakstyle:"after", separator: true}], // invisible separator
+ '\u2064': MO.ORD, // invisible plus
+ '\u2190': MO.WIDEREL, // leftwards arrow
+ '\u2191': MO.RELSTRETCH, // upwards arrow
+ '\u2192': MO.WIDEREL, // rightwards arrow
+ '\u2193': MO.RELSTRETCH, // downwards arrow
+ '\u2194': MO.WIDEREL, // left right arrow
+ '\u2195': MO.RELSTRETCH, // up down arrow
+ '\u2196': MO.RELSTRETCH, // north west arrow
+ '\u2197': MO.RELSTRETCH, // north east arrow
+ '\u2198': MO.RELSTRETCH, // south east arrow
+ '\u2199': MO.RELSTRETCH, // south west arrow
+ '\u21A6': MO.WIDEREL, // rightwards arrow from bar
+ '\u21A9': MO.WIDEREL, // leftwards arrow with hook
+ '\u21AA': MO.WIDEREL, // rightwards arrow with hook
+ '\u21BC': MO.WIDEREL, // leftwards harpoon with barb upwards
+ '\u21BD': MO.WIDEREL, // leftwards harpoon with barb downwards
+ '\u21C0': MO.WIDEREL, // rightwards harpoon with barb upwards
+ '\u21C1': MO.WIDEREL, // rightwards harpoon with barb downwards
+ '\u21CC': MO.WIDEREL, // rightwards harpoon over leftwards harpoon
+ '\u21D0': MO.WIDEREL, // leftwards double arrow
+ '\u21D1': MO.RELSTRETCH, // upwards double arrow
+ '\u21D2': MO.WIDEREL, // rightwards double arrow
+ '\u21D3': MO.RELSTRETCH, // downwards double arrow
+ '\u21D4': MO.WIDEREL, // left right double arrow
+ '\u21D5': MO.RELSTRETCH, // up down double arrow
+ '\u2208': MO.REL, // element of
+ '\u2209': MO.REL, // not an element of
+ '\u220B': MO.REL, // contains as member
+ '\u2212': MO.BIN4, // minus sign
+ '\u2213': MO.BIN4, // minus-or-plus sign
+ '\u2215': MO.TALLBIN, // division slash
+ '\u2216': MO.BIN4, // set minus
+ '\u2217': MO.BIN4, // asterisk operator
+ '\u2218': MO.BIN4, // ring operator
+ '\u2219': MO.BIN4, // bullet operator
+ '\u221D': MO.REL, // proportional to
+ '\u2223': MO.REL, // divides
+ '\u2225': MO.REL, // parallel to
+ '\u2227': MO.BIN4, // logical and
+ '\u2228': MO.BIN4, // logical or
+ '\u2229': MO.BIN4, // intersection
+ '\u222A': MO.BIN4, // union
+ '\u223C': MO.REL, // tilde operator
+ '\u2240': MO.BIN4, // wreath product
+ '\u2243': MO.REL, // asymptotically equal to
+ '\u2245': MO.REL, // approximately equal to
+ '\u2248': MO.REL, // almost equal to
+ '\u224D': MO.REL, // equivalent to
+ '\u2250': MO.REL, // approaches the limit
+ '\u2260': MO.REL, // not equal to
+ '\u2261': MO.REL, // identical to
+ '\u2264': MO.REL, // less-than or equal to
+ '\u2265': MO.REL, // greater-than or equal to
+ '\u226A': MO.REL, // much less-than
+ '\u226B': MO.REL, // much greater-than
+ '\u227A': MO.REL, // precedes
+ '\u227B': MO.REL, // succeeds
+ '\u2282': MO.REL, // subset of
+ '\u2283': MO.REL, // superset of
+ '\u2286': MO.REL, // subset of or equal to
+ '\u2287': MO.REL, // superset of or equal to
+ '\u228E': MO.BIN4, // multiset union
+ '\u2291': MO.REL, // square image of or equal to
+ '\u2292': MO.REL, // square original of or equal to
+ '\u2293': MO.BIN4, // square cap
+ '\u2294': MO.BIN4, // square cup
+ '\u2295': MO.BIN4, // circled plus
+ '\u2296': MO.BIN4, // circled minus
+ '\u2297': MO.BIN4, // circled times
+ '\u2298': MO.BIN4, // circled division slash
+ '\u2299': MO.BIN4, // circled dot operator
+ '\u22A2': MO.REL, // right tack
+ '\u22A3': MO.REL, // left tack
+ '\u22A4': MO.ORD55, // down tack
+ '\u22A5': MO.REL, // up tack
+ '\u22A8': MO.REL, // true
+ '\u22C4': MO.BIN4, // diamond operator
+ '\u22C5': MO.BIN4, // dot operator
+ '\u22C6': MO.BIN4, // star operator
+ '\u22C8': MO.REL, // bowtie
+ '\u22EE': MO.ORD55, // vertical ellipsis
+ '\u22EF': MO.INNER, // midline horizontal ellipsis
+ '\u22F1': [5,5,TEXCLASS.INNER], // down right diagonal ellipsis
+ '\u25B3': MO.BIN4, // white up-pointing triangle
+ '\u25B5': MO.BIN4, // white up-pointing small triangle
+ '\u25B9': MO.BIN4, // white right-pointing small triangle
+ '\u25BD': MO.BIN4, // white down-pointing triangle
+ '\u25BF': MO.BIN4, // white down-pointing small triangle
+ '\u25C3': MO.BIN4, // white left-pointing small triangle
+ '\u2758': MO.REL, // light vertical bar
+ '\u27F5': MO.WIDEREL, // long leftwards arrow
+ '\u27F6': MO.WIDEREL, // long rightwards arrow
+ '\u27F7': MO.WIDEREL, // long left right arrow
+ '\u27F8': MO.WIDEREL, // long leftwards double arrow
+ '\u27F9': MO.WIDEREL, // long rightwards double arrow
+ '\u27FA': MO.WIDEREL, // long left right double arrow
+ '\u27FC': MO.WIDEREL, // long rightwards arrow from bar
+ '\u2A2F': MO.BIN4, // vector or cross product
+ '\u2A3F': MO.BIN4, // amalgamation or coproduct
+ '\u2AAF': MO.REL, // precedes above single-line equals sign
+ '\u2AB0': MO.REL, // succeeds above single-line equals sign
+ '\u00B1': MO.BIN4, // plus-minus sign
+ '\u00B7': MO.BIN4, // middle dot
+ '\u00D7': MO.BIN4, // multiplication sign
+ '\u00F7': MO.BIN4, // division sign
+ '*': MO.BIN3, // asterisk
+ '+': MO.BIN4, // plus sign
+ ',': [0,3,TEXCLASS.PUNCT,{linebreakstyle:"after", separator: true}], // comma
+ '-': MO.BIN4, // hyphen-minus
+ '.': [3,3,TEXCLASS.ORD], // full stop
+ '/': MO.ORD11, // solidus
+ ':': [1,2,TEXCLASS.REL], // colon
+ ';': [0,3,TEXCLASS.PUNCT,{linebreakstyle:"after", separator: true}], // semicolon
+ '<': MO.REL, // less-than sign
+ '=': MO.REL, // equals sign
+ '>': MO.REL, // greater-than sign
+ '?': [1,1,TEXCLASS.CLOSE], // question mark
+ '\\': MO.ORD, // reverse solidus
+ '^': MO.ORD11, // circumflex accent
+ '_': MO.ORD11, // low line
+ '|': [2,2,TEXCLASS.ORD,{fence: true, stretchy: true, symmetric: true}], // vertical line
+ '#': MO.ORD, // #
+ '$': MO.ORD, // $
+ '\u002E': [0,3,TEXCLASS.PUNCT,{separator: true}], // \ldotp
+ '\u02B9': MO.ORD, // prime
+ '\u0300': MO.ACCENT, // \grave
+ '\u0301': MO.ACCENT, // \acute
+ '\u0303': MO.WIDEACCENT, // \tilde
+ '\u0304': MO.ACCENT, // \bar
+ '\u0306': MO.ACCENT, // \breve
+ '\u0307': MO.ACCENT, // \dot
+ '\u0308': MO.ACCENT, // \ddot
+ '\u030C': MO.ACCENT, // \check
+ '\u0332': MO.WIDEACCENT, // horizontal line
+ '\u0338': MO.REL4, // \not
+ '\u2015': [0,0,TEXCLASS.ORD,{stretchy: true}], // horizontal line
+ '\u2017': [0,0,TEXCLASS.ORD,{stretchy: true}], // horizontal line
+ '\u2020': MO.BIN3, // \dagger
+ '\u2021': MO.BIN3, // \ddagger
+ '\u20D7': MO.ACCENT, // \vec
+ '\u2111': MO.ORD, // \Im
+ '\u2113': MO.ORD, // \ell
+ '\u2118': MO.ORD, // \wp
+ '\u211C': MO.ORD, // \Re
+ '\u2205': MO.ORD, // \emptyset
+ '\u221E': MO.ORD, // \infty
+ '\u2305': MO.BIN3, // barwedge
+ '\u2306': MO.BIN3, // doublebarwedge
+ '\u2322': MO.REL4, // \frown
+ '\u2323': MO.REL4, // \smile
+ '\u2329': MO.OPEN, // langle
+ '\u232A': MO.CLOSE, // rangle
+ '\u23AA': MO.ORD, // \bracevert
+ '\u23AF': [0,0,TEXCLASS.ORD,{stretchy: true}], // \underline
+ '\u23B0': MO.OPEN, // \lmoustache
+ '\u23B1': MO.CLOSE, // \rmoustache
+ '\u2500': MO.ORD, // horizontal line
+ '\u25EF': MO.BIN3, // \bigcirc
+ '\u2660': MO.ORD, // \spadesuit
+ '\u2661': MO.ORD, // \heartsuit
+ '\u2662': MO.ORD, // \diamondsuit
+ '\u2663': MO.ORD, // \clubsuit
+ '\u3008': MO.OPEN, // langle
+ '\u3009': MO.CLOSE, // rangle
+ '\uFE37': MO.WIDEACCENT, // horizontal brace down
+ '\uFE38': MO.WIDEACCENT // horizontal brace up
+ }
+ }
+ },{
+ OPTYPES: MO
+ });
+
+ //
+ // These are not in the W3C table, but FF works this way,
+ // and it makes sense, so add it here
+ //
+ var OPTABLE = MML.mo.prototype.OPTABLE;
+ OPTABLE.infix["^"] = MO.WIDEREL;
+ OPTABLE.infix["_"] = MO.WIDEREL;
+ OPTABLE.prefix["\u2223"] = MO.OPEN;
+ OPTABLE.prefix["\u2225"] = MO.OPEN;
+ OPTABLE.postfix["\u2223"] = MO.CLOSE;
+ OPTABLE.postfix["\u2225"] = MO.CLOSE;
+
+})(MathJax.ElementJax.mml);
+
+MathJax.ElementJax.mml.loadComplete("jax.js");
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/Arrows.js b/MarkDownEditor/MathJax/jax/element/mml/optable/Arrows.js
new file mode 100644
index 0000000..bf0e353
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/Arrows.js
@@ -0,0 +1,122 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/Arrows.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u219A': MO.RELACCENT, // leftwards arrow with stroke
+ '\u219B': MO.RELACCENT, // rightwards arrow with stroke
+ '\u219C': MO.WIDEREL, // leftwards wave arrow
+ '\u219D': MO.WIDEREL, // rightwards wave arrow
+ '\u219E': MO.WIDEREL, // leftwards two headed arrow
+ '\u219F': MO.WIDEREL, // upwards two headed arrow
+ '\u21A0': MO.WIDEREL, // rightwards two headed arrow
+ '\u21A1': MO.RELSTRETCH, // downwards two headed arrow
+ '\u21A2': MO.WIDEREL, // leftwards arrow with tail
+ '\u21A3': MO.WIDEREL, // rightwards arrow with tail
+ '\u21A4': MO.WIDEREL, // leftwards arrow from bar
+ '\u21A5': MO.RELSTRETCH, // upwards arrow from bar
+ '\u21A7': MO.RELSTRETCH, // downwards arrow from bar
+ '\u21A8': MO.RELSTRETCH, // up down arrow with base
+ '\u21AB': MO.WIDEREL, // leftwards arrow with loop
+ '\u21AC': MO.WIDEREL, // rightwards arrow with loop
+ '\u21AD': MO.WIDEREL, // left right wave arrow
+ '\u21AE': MO.RELACCENT, // left right arrow with stroke
+ '\u21AF': MO.RELSTRETCH, // downwards zigzag arrow
+ '\u21B0': MO.RELSTRETCH, // upwards arrow with tip leftwards
+ '\u21B1': MO.RELSTRETCH, // upwards arrow with tip rightwards
+ '\u21B2': MO.RELSTRETCH, // downwards arrow with tip leftwards
+ '\u21B3': MO.RELSTRETCH, // downwards arrow with tip rightwards
+ '\u21B4': MO.RELSTRETCH, // rightwards arrow with corner downwards
+ '\u21B5': MO.RELSTRETCH, // downwards arrow with corner leftwards
+ '\u21B6': MO.RELACCENT, // anticlockwise top semicircle arrow
+ '\u21B7': MO.RELACCENT, // clockwise top semicircle arrow
+ '\u21B8': MO.REL, // north west arrow to long bar
+ '\u21B9': MO.WIDEREL, // leftwards arrow to bar over rightwards arrow to bar
+ '\u21BA': MO.REL, // anticlockwise open circle arrow
+ '\u21BB': MO.REL, // clockwise open circle arrow
+ '\u21BE': MO.RELSTRETCH, // upwards harpoon with barb rightwards
+ '\u21BF': MO.RELSTRETCH, // upwards harpoon with barb leftwards
+ '\u21C2': MO.RELSTRETCH, // downwards harpoon with barb rightwards
+ '\u21C3': MO.RELSTRETCH, // downwards harpoon with barb leftwards
+ '\u21C4': MO.WIDEREL, // rightwards arrow over leftwards arrow
+ '\u21C5': MO.RELSTRETCH, // upwards arrow leftwards of downwards arrow
+ '\u21C6': MO.WIDEREL, // leftwards arrow over rightwards arrow
+ '\u21C7': MO.WIDEREL, // leftwards paired arrows
+ '\u21C8': MO.RELSTRETCH, // upwards paired arrows
+ '\u21C9': MO.WIDEREL, // rightwards paired arrows
+ '\u21CA': MO.RELSTRETCH, // downwards paired arrows
+ '\u21CB': MO.WIDEREL, // leftwards harpoon over rightwards harpoon
+ '\u21CD': MO.RELACCENT, // leftwards double arrow with stroke
+ '\u21CE': MO.RELACCENT, // left right double arrow with stroke
+ '\u21CF': MO.RELACCENT, // rightwards double arrow with stroke
+ '\u21D6': MO.RELSTRETCH, // north west double arrow
+ '\u21D7': MO.RELSTRETCH, // north east double arrow
+ '\u21D8': MO.RELSTRETCH, // south east double arrow
+ '\u21D9': MO.RELSTRETCH, // south west double arrow
+ '\u21DA': MO.WIDEREL, // leftwards triple arrow
+ '\u21DB': MO.WIDEREL, // rightwards triple arrow
+ '\u21DC': MO.WIDEREL, // leftwards squiggle arrow
+ '\u21DD': MO.WIDEREL, // rightwards squiggle arrow
+ '\u21DE': MO.REL, // upwards arrow with double stroke
+ '\u21DF': MO.REL, // downwards arrow with double stroke
+ '\u21E0': MO.WIDEREL, // leftwards dashed arrow
+ '\u21E1': MO.RELSTRETCH, // upwards dashed arrow
+ '\u21E2': MO.WIDEREL, // rightwards dashed arrow
+ '\u21E3': MO.RELSTRETCH, // downwards dashed arrow
+ '\u21E4': MO.WIDEREL, // leftwards arrow to bar
+ '\u21E5': MO.WIDEREL, // rightwards arrow to bar
+ '\u21E6': MO.WIDEREL, // leftwards white arrow
+ '\u21E7': MO.RELSTRETCH, // upwards white arrow
+ '\u21E8': MO.WIDEREL, // rightwards white arrow
+ '\u21E9': MO.RELSTRETCH, // downwards white arrow
+ '\u21EA': MO.RELSTRETCH, // upwards white arrow from bar
+ '\u21EB': MO.RELSTRETCH, // upwards white arrow on pedestal
+ '\u21EC': MO.RELSTRETCH, // upwards white arrow on pedestal with horizontal bar
+ '\u21ED': MO.RELSTRETCH, // upwards white arrow on pedestal with vertical bar
+ '\u21EE': MO.RELSTRETCH, // upwards white double arrow
+ '\u21EF': MO.RELSTRETCH, // upwards white double arrow on pedestal
+ '\u21F0': MO.WIDEREL, // rightwards white arrow from wall
+ '\u21F1': MO.REL, // north west arrow to corner
+ '\u21F2': MO.REL, // south east arrow to corner
+ '\u21F3': MO.RELSTRETCH, // up down white arrow
+ '\u21F4': MO.RELACCENT, // right arrow with small circle
+ '\u21F5': MO.RELSTRETCH, // downwards arrow leftwards of upwards arrow
+ '\u21F6': MO.WIDEREL, // three rightwards arrows
+ '\u21F7': MO.RELACCENT, // leftwards arrow with vertical stroke
+ '\u21F8': MO.RELACCENT, // rightwards arrow with vertical stroke
+ '\u21F9': MO.RELACCENT, // left right arrow with vertical stroke
+ '\u21FA': MO.RELACCENT, // leftwards arrow with double vertical stroke
+ '\u21FB': MO.RELACCENT, // rightwards arrow with double vertical stroke
+ '\u21FC': MO.RELACCENT, // left right arrow with double vertical stroke
+ '\u21FD': MO.WIDEREL, // leftwards open-headed arrow
+ '\u21FE': MO.WIDEREL, // rightwards open-headed arrow
+ '\u21FF': MO.WIDEREL // left right open-headed arrow
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/Arrows.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/BasicLatin.js b/MarkDownEditor/MathJax/jax/element/mml/optable/BasicLatin.js
new file mode 100644
index 0000000..f69468f
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/BasicLatin.js
@@ -0,0 +1,65 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/BasicLatin.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '||': [0,0,TEXCLASS.BIN,{fence: true, stretchy: true, symmetric: true}], // multiple character operator: ||
+ '|||': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true, symmetric: true}] // multiple character operator: |||
+ },
+ postfix: {
+ '!!': [1,0,TEXCLASS.BIN], // multiple character operator: !!
+ '\'': MO.ACCENT, // apostrophe
+ '++': [0,0,TEXCLASS.BIN], // multiple character operator: ++
+ '--': [0,0,TEXCLASS.BIN], // multiple character operator: --
+ '..': [0,0,TEXCLASS.BIN], // multiple character operator: ..
+ '...': MO.ORD, // multiple character operator: ...
+ '||': [0,0,TEXCLASS.BIN,{fence: true, stretchy: true, symmetric: true}], // multiple character operator: ||
+ '|||': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true, symmetric: true}] // multiple character operator: |||
+ },
+ infix: {
+ '!=': MO.BIN4, // multiple character operator: !=
+ '&&': MO.BIN4, // multiple character operator: &&
+ '**': [1,1,TEXCLASS.BIN], // multiple character operator: **
+ '*=': MO.BIN4, // multiple character operator: *=
+ '+=': MO.BIN4, // multiple character operator: +=
+ '-=': MO.BIN4, // multiple character operator: -=
+ '->': MO.BIN5, // multiple character operator: ->
+ '//': [1,1,TEXCLASS.BIN], // multiple character operator: //
+ '/=': MO.BIN4, // multiple character operator: /=
+ ':=': MO.BIN4, // multiple character operator: :=
+ '<=': MO.BIN5, // multiple character operator: <=
+ '<>': [1,1,TEXCLASS.BIN], // multiple character operator: <>
+ '==': MO.BIN4, // multiple character operator: ==
+ '>=': MO.BIN5, // multiple character operator: >=
+ '@': MO.ORD11, // commercial at
+ '||': [2,2,TEXCLASS.BIN,{fence: true, stretchy: true, symmetric: true}], // multiple character operator: ||
+ '|||': [2,2,TEXCLASS.ORD,{fence: true, stretchy: true, symmetric: true}] // multiple character operator: |||
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/BasicLatin.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiacritMarks.js b/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiacritMarks.js
new file mode 100644
index 0000000..4f705c6
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiacritMarks.js
@@ -0,0 +1,35 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/CombDiacritMarks.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ postfix: {
+ '\u0311': MO.ACCENT // combining inverted breve
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/CombDiacritMarks.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiactForSymbols.js b/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiactForSymbols.js
new file mode 100644
index 0000000..bcebec2
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/CombDiactForSymbols.js
@@ -0,0 +1,36 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/CombDiactForSymbols.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ postfix: {
+ '\u20DB': MO.ACCENT, // combining three dots above
+ '\u20DC': MO.ACCENT // combining four dots above
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/CombDiactForSymbols.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/Dingbats.js b/MarkDownEditor/MathJax/jax/element/mml/optable/Dingbats.js
new file mode 100644
index 0000000..ed89722
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/Dingbats.js
@@ -0,0 +1,38 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/Dingbats.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2772': MO.OPEN // light left tortoise shell bracket ornament
+ },
+ postfix: {
+ '\u2773': MO.CLOSE // light right tortoise shell bracket ornament
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/Dingbats.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/GeneralPunctuation.js b/MarkDownEditor/MathJax/jax/element/mml/optable/GeneralPunctuation.js
new file mode 100644
index 0000000..544ea64
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/GeneralPunctuation.js
@@ -0,0 +1,42 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/GeneralPunctuation.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2016': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true}], // double vertical line
+ '\u2018': [0,0,TEXCLASS.OPEN,{fence: true}], // left single quotation mark
+ '\u201C': [0,0,TEXCLASS.OPEN,{fence: true}] // left double quotation mark
+ },
+ postfix: {
+ '\u2016': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true}], // double vertical line
+ '\u2019': [0,0,TEXCLASS.CLOSE,{fence: true}], // right single quotation mark
+ '\u201D': [0,0,TEXCLASS.CLOSE,{fence: true}] // right double quotation mark
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/GeneralPunctuation.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/GeometricShapes.js b/MarkDownEditor/MathJax/jax/element/mml/optable/GeometricShapes.js
new file mode 100644
index 0000000..d94705e
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/GeometricShapes.js
@@ -0,0 +1,66 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/GeometricShapes.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u25A0': MO.BIN3, // black square
+ '\u25A1': MO.BIN3, // white square
+ '\u25AA': MO.BIN3, // black small square
+ '\u25AB': MO.BIN3, // white small square
+ '\u25AD': MO.BIN3, // white rectangle
+ '\u25AE': MO.BIN3, // black vertical rectangle
+ '\u25AF': MO.BIN3, // white vertical rectangle
+ '\u25B0': MO.BIN3, // black parallelogram
+ '\u25B1': MO.BIN3, // white parallelogram
+ '\u25B2': MO.BIN4, // black up-pointing triangle
+ '\u25B4': MO.BIN4, // black up-pointing small triangle
+ '\u25B6': MO.BIN4, // black right-pointing triangle
+ '\u25B7': MO.BIN4, // white right-pointing triangle
+ '\u25B8': MO.BIN4, // black right-pointing small triangle
+ '\u25BC': MO.BIN4, // black down-pointing triangle
+ '\u25BE': MO.BIN4, // black down-pointing small triangle
+ '\u25C0': MO.BIN4, // black left-pointing triangle
+ '\u25C1': MO.BIN4, // white left-pointing triangle
+ '\u25C2': MO.BIN4, // black left-pointing small triangle
+ '\u25C4': MO.BIN4, // black left-pointing pointer
+ '\u25C5': MO.BIN4, // white left-pointing pointer
+ '\u25C6': MO.BIN4, // black diamond
+ '\u25C7': MO.BIN4, // white diamond
+ '\u25C8': MO.BIN4, // white diamond containing black small diamond
+ '\u25C9': MO.BIN4, // fisheye
+ '\u25CC': MO.BIN4, // dotted circle
+ '\u25CD': MO.BIN4, // circle with vertical fill
+ '\u25CE': MO.BIN4, // bullseye
+ '\u25CF': MO.BIN4, // black circle
+ '\u25D6': MO.BIN4, // left half black circle
+ '\u25D7': MO.BIN4, // right half black circle
+ '\u25E6': MO.BIN4 // white bullet
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/GeometricShapes.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/GreekAndCoptic.js b/MarkDownEditor/MathJax/jax/element/mml/optable/GreekAndCoptic.js
new file mode 100644
index 0000000..a5c3890
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/GreekAndCoptic.js
@@ -0,0 +1,35 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/GreekAndCoptic.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u03F6': MO.REL // greek reversed lunate epsilon symbol
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/GreekAndCoptic.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/Latin1Supplement.js b/MarkDownEditor/MathJax/jax/element/mml/optable/Latin1Supplement.js
new file mode 100644
index 0000000..834491c
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/Latin1Supplement.js
@@ -0,0 +1,37 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/Latin1Supplement.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ postfix: {
+ '\u00B0': MO.ORD, // degree sign
+ '\u00B4': MO.ACCENT, // acute accent
+ '\u00B8': MO.ACCENT // cedilla
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/Latin1Supplement.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/LetterlikeSymbols.js b/MarkDownEditor/MathJax/jax/element/mml/optable/LetterlikeSymbols.js
new file mode 100644
index 0000000..65c3535
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/LetterlikeSymbols.js
@@ -0,0 +1,36 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/LetterlikeSymbols.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2145': MO.ORD21, // double-struck italic capital d
+ '\u2146': [2,0,TEXCLASS.ORD] // double-struck italic small d
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/LetterlikeSymbols.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/MathOperators.js b/MarkDownEditor/MathJax/jax/element/mml/optable/MathOperators.js
new file mode 100644
index 0000000..6ade894
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/MathOperators.js
@@ -0,0 +1,228 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/MathOperators.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2204': MO.ORD21, // there does not exist
+ '\u221B': MO.ORD11, // cube root
+ '\u221C': MO.ORD11, // fourth root
+ '\u2221': MO.ORD, // measured angle
+ '\u2222': MO.ORD, // spherical angle
+ '\u222C': MO.INTEGRAL, // double integral
+ '\u222D': MO.INTEGRAL, // triple integral
+ '\u222F': MO.INTEGRAL, // surface integral
+ '\u2230': MO.INTEGRAL, // volume integral
+ '\u2231': MO.INTEGRAL, // clockwise integral
+ '\u2232': MO.INTEGRAL, // clockwise contour integral
+ '\u2233': MO.INTEGRAL // anticlockwise contour integral
+ },
+ infix: {
+ '\u2201': [1,2,TEXCLASS.ORD], // complement
+ '\u2206': MO.BIN3, // increment
+ '\u220A': MO.REL, // small element of
+ '\u220C': MO.REL, // does not contain as member
+ '\u220D': MO.REL, // small contains as member
+ '\u220E': MO.BIN3, // end of proof
+ '\u2214': MO.BIN4, // dot plus
+ '\u221F': MO.REL, // right angle
+ '\u2224': MO.REL, // does not divide
+ '\u2226': MO.REL, // not parallel to
+ '\u2234': MO.REL, // therefore
+ '\u2235': MO.REL, // because
+ '\u2236': MO.REL, // ratio
+ '\u2237': MO.REL, // proportion
+ '\u2238': MO.BIN4, // dot minus
+ '\u2239': MO.REL, // excess
+ '\u223A': MO.BIN4, // geometric proportion
+ '\u223B': MO.REL, // homothetic
+ '\u223D': MO.REL, // reversed tilde
+ '\u223D\u0331': MO.BIN3, // reversed tilde with underline
+ '\u223E': MO.REL, // inverted lazy s
+ '\u223F': MO.BIN3, // sine wave
+ '\u2241': MO.REL, // not tilde
+ '\u2242': MO.REL, // minus tilde
+ '\u2242\u0338': MO.REL, // minus tilde with slash
+ '\u2244': MO.REL, // not asymptotically equal to
+ '\u2246': MO.REL, // approximately but not actually equal to
+ '\u2247': MO.REL, // neither approximately nor actually equal to
+ '\u2249': MO.REL, // not almost equal to
+ '\u224A': MO.REL, // almost equal or equal to
+ '\u224B': MO.REL, // triple tilde
+ '\u224C': MO.REL, // all equal to
+ '\u224E': MO.REL, // geometrically equivalent to
+ '\u224E\u0338': MO.REL, // geometrically equivalent to with slash
+ '\u224F': MO.REL, // difference between
+ '\u224F\u0338': MO.REL, // difference between with slash
+ '\u2251': MO.REL, // geometrically equal to
+ '\u2252': MO.REL, // approximately equal to or the image of
+ '\u2253': MO.REL, // image of or approximately equal to
+ '\u2254': MO.REL, // colon equals
+ '\u2255': MO.REL, // equals colon
+ '\u2256': MO.REL, // ring in equal to
+ '\u2257': MO.REL, // ring equal to
+ '\u2258': MO.REL, // corresponds to
+ '\u2259': MO.REL, // estimates
+ '\u225A': MO.REL, // equiangular to
+ '\u225C': MO.REL, // delta equal to
+ '\u225D': MO.REL, // equal to by definition
+ '\u225E': MO.REL, // measured by
+ '\u225F': MO.REL, // questioned equal to
+ '\u2262': MO.REL, // not identical to
+ '\u2263': MO.REL, // strictly equivalent to
+ '\u2266': MO.REL, // less-than over equal to
+ '\u2266\u0338': MO.REL, // less-than over equal to with slash
+ '\u2267': MO.REL, // greater-than over equal to
+ '\u2268': MO.REL, // less-than but not equal to
+ '\u2269': MO.REL, // greater-than but not equal to
+ '\u226A\u0338': MO.REL, // much less than with slash
+ '\u226B\u0338': MO.REL, // much greater than with slash
+ '\u226C': MO.REL, // between
+ '\u226D': MO.REL, // not equivalent to
+ '\u226E': MO.REL, // not less-than
+ '\u226F': MO.REL, // not greater-than
+ '\u2270': MO.REL, // neither less-than nor equal to
+ '\u2271': MO.REL, // neither greater-than nor equal to
+ '\u2272': MO.REL, // less-than or equivalent to
+ '\u2273': MO.REL, // greater-than or equivalent to
+ '\u2274': MO.REL, // neither less-than nor equivalent to
+ '\u2275': MO.REL, // neither greater-than nor equivalent to
+ '\u2276': MO.REL, // less-than or greater-than
+ '\u2277': MO.REL, // greater-than or less-than
+ '\u2278': MO.REL, // neither less-than nor greater-than
+ '\u2279': MO.REL, // neither greater-than nor less-than
+ '\u227C': MO.REL, // precedes or equal to
+ '\u227D': MO.REL, // succeeds or equal to
+ '\u227E': MO.REL, // precedes or equivalent to
+ '\u227F': MO.REL, // succeeds or equivalent to
+ '\u227F\u0338': MO.REL, // succeeds or equivalent to with slash
+ '\u2280': MO.REL, // does not precede
+ '\u2281': MO.REL, // does not succeed
+ '\u2282\u20D2': MO.REL, // subset of with vertical line
+ '\u2283\u20D2': MO.REL, // superset of with vertical line
+ '\u2284': MO.REL, // not a subset of
+ '\u2285': MO.REL, // not a superset of
+ '\u2288': MO.REL, // neither a subset of nor equal to
+ '\u2289': MO.REL, // neither a superset of nor equal to
+ '\u228A': MO.REL, // subset of with not equal to
+ '\u228B': MO.REL, // superset of with not equal to
+ '\u228C': MO.BIN4, // multiset
+ '\u228D': MO.BIN4, // multiset multiplication
+ '\u228F': MO.REL, // square image of
+ '\u228F\u0338': MO.REL, // square image of with slash
+ '\u2290': MO.REL, // square original of
+ '\u2290\u0338': MO.REL, // square original of with slash
+ '\u229A': MO.BIN4, // circled ring operator
+ '\u229B': MO.BIN4, // circled asterisk operator
+ '\u229C': MO.BIN4, // circled equals
+ '\u229D': MO.BIN4, // circled dash
+ '\u229E': MO.BIN4, // squared plus
+ '\u229F': MO.BIN4, // squared minus
+ '\u22A0': MO.BIN4, // squared times
+ '\u22A1': MO.BIN4, // squared dot operator
+ '\u22A6': MO.REL, // assertion
+ '\u22A7': MO.REL, // models
+ '\u22A9': MO.REL, // forces
+ '\u22AA': MO.REL, // triple vertical bar right turnstile
+ '\u22AB': MO.REL, // double vertical bar double right turnstile
+ '\u22AC': MO.REL, // does not prove
+ '\u22AD': MO.REL, // not true
+ '\u22AE': MO.REL, // does not force
+ '\u22AF': MO.REL, // negated double vertical bar double right turnstile
+ '\u22B0': MO.REL, // precedes under relation
+ '\u22B1': MO.REL, // succeeds under relation
+ '\u22B2': MO.REL, // normal subgroup of
+ '\u22B3': MO.REL, // contains as normal subgroup
+ '\u22B4': MO.REL, // normal subgroup of or equal to
+ '\u22B5': MO.REL, // contains as normal subgroup or equal to
+ '\u22B6': MO.REL, // original of
+ '\u22B7': MO.REL, // image of
+ '\u22B8': MO.REL, // multimap
+ '\u22B9': MO.REL, // hermitian conjugate matrix
+ '\u22BA': MO.BIN4, // intercalate
+ '\u22BB': MO.BIN4, // xor
+ '\u22BC': MO.BIN4, // nand
+ '\u22BD': MO.BIN4, // nor
+ '\u22BE': MO.BIN3, // right angle with arc
+ '\u22BF': MO.BIN3, // right triangle
+ '\u22C7': MO.BIN4, // division times
+ '\u22C9': MO.BIN4, // left normal factor semidirect product
+ '\u22CA': MO.BIN4, // right normal factor semidirect product
+ '\u22CB': MO.BIN4, // left semidirect product
+ '\u22CC': MO.BIN4, // right semidirect product
+ '\u22CD': MO.REL, // reversed tilde equals
+ '\u22CE': MO.BIN4, // curly logical or
+ '\u22CF': MO.BIN4, // curly logical and
+ '\u22D0': MO.REL, // double subset
+ '\u22D1': MO.REL, // double superset
+ '\u22D2': MO.BIN4, // double intersection
+ '\u22D3': MO.BIN4, // double union
+ '\u22D4': MO.REL, // pitchfork
+ '\u22D5': MO.REL, // equal and parallel to
+ '\u22D6': MO.REL, // less-than with dot
+ '\u22D7': MO.REL, // greater-than with dot
+ '\u22D8': MO.REL, // very much less-than
+ '\u22D9': MO.REL, // very much greater-than
+ '\u22DA': MO.REL, // less-than equal to or greater-than
+ '\u22DB': MO.REL, // greater-than equal to or less-than
+ '\u22DC': MO.REL, // equal to or less-than
+ '\u22DD': MO.REL, // equal to or greater-than
+ '\u22DE': MO.REL, // equal to or precedes
+ '\u22DF': MO.REL, // equal to or succeeds
+ '\u22E0': MO.REL, // does not precede or equal
+ '\u22E1': MO.REL, // does not succeed or equal
+ '\u22E2': MO.REL, // not square image of or equal to
+ '\u22E3': MO.REL, // not square original of or equal to
+ '\u22E4': MO.REL, // square image of or not equal to
+ '\u22E5': MO.REL, // square original of or not equal to
+ '\u22E6': MO.REL, // less-than but not equivalent to
+ '\u22E7': MO.REL, // greater-than but not equivalent to
+ '\u22E8': MO.REL, // precedes but not equivalent to
+ '\u22E9': MO.REL, // succeeds but not equivalent to
+ '\u22EA': MO.REL, // not normal subgroup of
+ '\u22EB': MO.REL, // does not contain as normal subgroup
+ '\u22EC': MO.REL, // not normal subgroup of or equal to
+ '\u22ED': MO.REL, // does not contain as normal subgroup or equal
+ '\u22F0': MO.REL, // up right diagonal ellipsis
+ '\u22F2': MO.REL, // element of with long horizontal stroke
+ '\u22F3': MO.REL, // element of with vertical bar at end of horizontal stroke
+ '\u22F4': MO.REL, // small element of with vertical bar at end of horizontal stroke
+ '\u22F5': MO.REL, // element of with dot above
+ '\u22F6': MO.REL, // element of with overbar
+ '\u22F7': MO.REL, // small element of with overbar
+ '\u22F8': MO.REL, // element of with underbar
+ '\u22F9': MO.REL, // element of with two horizontal strokes
+ '\u22FA': MO.REL, // contains with long horizontal stroke
+ '\u22FB': MO.REL, // contains with vertical bar at end of horizontal stroke
+ '\u22FC': MO.REL, // small contains with vertical bar at end of horizontal stroke
+ '\u22FD': MO.REL, // contains with overbar
+ '\u22FE': MO.REL, // small contains with overbar
+ '\u22FF': MO.REL // z notation bag membership
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/MathOperators.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsA.js b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsA.js
new file mode 100644
index 0000000..ee0f854
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsA.js
@@ -0,0 +1,42 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/MiscMathSymbolsA.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u27E6': MO.OPEN, // mathematical left white square bracket
+ '\u27EA': MO.OPEN, // mathematical left double angle bracket
+ '\u27EC': MO.OPEN // mathematical left white tortoise shell bracket
+ },
+ postfix: {
+ '\u27E7': MO.CLOSE, // mathematical right white square bracket
+ '\u27EB': MO.CLOSE, // mathematical right double angle bracket
+ '\u27ED': MO.CLOSE // mathematical right white tortoise shell bracket
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/MiscMathSymbolsA.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsB.js b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsB.js
new file mode 100644
index 0000000..ab0ede7
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscMathSymbolsB.js
@@ -0,0 +1,168 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/MiscMathSymbolsB.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2980': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true}], // triple vertical bar delimiter
+ '\u2983': MO.OPEN, // left white curly bracket
+ '\u2985': MO.OPEN, // left white parenthesis
+ '\u2987': MO.OPEN, // z notation left image bracket
+ '\u2989': MO.OPEN, // z notation left binding bracket
+ '\u298B': MO.OPEN, // left square bracket with underbar
+ '\u298D': MO.OPEN, // left square bracket with tick in top corner
+ '\u298F': MO.OPEN, // left square bracket with tick in bottom corner
+ '\u2991': MO.OPEN, // left angle bracket with dot
+ '\u2993': MO.OPEN, // left arc less-than bracket
+ '\u2995': MO.OPEN, // double left arc greater-than bracket
+ '\u2997': MO.OPEN, // left black tortoise shell bracket
+ '\u29FC': MO.OPEN // left-pointing curved angle bracket
+ },
+ postfix: {
+ '\u2980': [0,0,TEXCLASS.ORD,{fence: true, stretchy: true}], // triple vertical bar delimiter
+ '\u2984': MO.CLOSE, // right white curly bracket
+ '\u2986': MO.CLOSE, // right white parenthesis
+ '\u2988': MO.CLOSE, // z notation right image bracket
+ '\u298A': MO.CLOSE, // z notation right binding bracket
+ '\u298C': MO.CLOSE, // right square bracket with underbar
+ '\u298E': MO.CLOSE, // right square bracket with tick in bottom corner
+ '\u2990': MO.CLOSE, // right square bracket with tick in top corner
+ '\u2992': MO.CLOSE, // right angle bracket with dot
+ '\u2994': MO.CLOSE, // right arc greater-than bracket
+ '\u2996': MO.CLOSE, // double right arc less-than bracket
+ '\u2998': MO.CLOSE, // right black tortoise shell bracket
+ '\u29FD': MO.CLOSE // right-pointing curved angle bracket
+ },
+ infix: {
+ '\u2981': MO.BIN3, // z notation spot
+ '\u2982': MO.BIN3, // z notation type colon
+ '\u2999': MO.BIN3, // dotted fence
+ '\u299A': MO.BIN3, // vertical zigzag line
+ '\u299B': MO.BIN3, // measured angle opening left
+ '\u299C': MO.BIN3, // right angle variant with square
+ '\u299D': MO.BIN3, // measured right angle with dot
+ '\u299E': MO.BIN3, // angle with s inside
+ '\u299F': MO.BIN3, // acute angle
+ '\u29A0': MO.BIN3, // spherical angle opening left
+ '\u29A1': MO.BIN3, // spherical angle opening up
+ '\u29A2': MO.BIN3, // turned angle
+ '\u29A3': MO.BIN3, // reversed angle
+ '\u29A4': MO.BIN3, // angle with underbar
+ '\u29A5': MO.BIN3, // reversed angle with underbar
+ '\u29A6': MO.BIN3, // oblique angle opening up
+ '\u29A7': MO.BIN3, // oblique angle opening down
+ '\u29A8': MO.BIN3, // measured angle with open arm ending in arrow pointing up and right
+ '\u29A9': MO.BIN3, // measured angle with open arm ending in arrow pointing up and left
+ '\u29AA': MO.BIN3, // measured angle with open arm ending in arrow pointing down and right
+ '\u29AB': MO.BIN3, // measured angle with open arm ending in arrow pointing down and left
+ '\u29AC': MO.BIN3, // measured angle with open arm ending in arrow pointing right and up
+ '\u29AD': MO.BIN3, // measured angle with open arm ending in arrow pointing left and up
+ '\u29AE': MO.BIN3, // measured angle with open arm ending in arrow pointing right and down
+ '\u29AF': MO.BIN3, // measured angle with open arm ending in arrow pointing left and down
+ '\u29B0': MO.BIN3, // reversed empty set
+ '\u29B1': MO.BIN3, // empty set with overbar
+ '\u29B2': MO.BIN3, // empty set with small circle above
+ '\u29B3': MO.BIN3, // empty set with right arrow above
+ '\u29B4': MO.BIN3, // empty set with left arrow above
+ '\u29B5': MO.BIN3, // circle with horizontal bar
+ '\u29B6': MO.BIN4, // circled vertical bar
+ '\u29B7': MO.BIN4, // circled parallel
+ '\u29B8': MO.BIN4, // circled reverse solidus
+ '\u29B9': MO.BIN4, // circled perpendicular
+ '\u29BA': MO.BIN4, // circle divided by horizontal bar and top half divided by vertical bar
+ '\u29BB': MO.BIN4, // circle with superimposed x
+ '\u29BC': MO.BIN4, // circled anticlockwise-rotated division sign
+ '\u29BD': MO.BIN4, // up arrow through circle
+ '\u29BE': MO.BIN4, // circled white bullet
+ '\u29BF': MO.BIN4, // circled bullet
+ '\u29C0': MO.REL, // circled less-than
+ '\u29C1': MO.REL, // circled greater-than
+ '\u29C2': MO.BIN3, // circle with small circle to the right
+ '\u29C3': MO.BIN3, // circle with two horizontal strokes to the right
+ '\u29C4': MO.BIN4, // squared rising diagonal slash
+ '\u29C5': MO.BIN4, // squared falling diagonal slash
+ '\u29C6': MO.BIN4, // squared asterisk
+ '\u29C7': MO.BIN4, // squared small circle
+ '\u29C8': MO.BIN4, // squared square
+ '\u29C9': MO.BIN3, // two joined squares
+ '\u29CA': MO.BIN3, // triangle with dot above
+ '\u29CB': MO.BIN3, // triangle with underbar
+ '\u29CC': MO.BIN3, // s in triangle
+ '\u29CD': MO.BIN3, // triangle with serifs at bottom
+ '\u29CE': MO.REL, // right triangle above left triangle
+ '\u29CF': MO.REL, // left triangle beside vertical bar
+ '\u29CF\u0338': MO.REL, // left triangle beside vertical bar with slash
+ '\u29D0': MO.REL, // vertical bar beside right triangle
+ '\u29D0\u0338': MO.REL, // vertical bar beside right triangle with slash
+ '\u29D1': MO.REL, // bowtie with left half black
+ '\u29D2': MO.REL, // bowtie with right half black
+ '\u29D3': MO.REL, // black bowtie
+ '\u29D4': MO.REL, // times with left half black
+ '\u29D5': MO.REL, // times with right half black
+ '\u29D6': MO.BIN4, // white hourglass
+ '\u29D7': MO.BIN4, // black hourglass
+ '\u29D8': MO.BIN3, // left wiggly fence
+ '\u29D9': MO.BIN3, // right wiggly fence
+ '\u29DB': MO.BIN3, // right double wiggly fence
+ '\u29DC': MO.BIN3, // incomplete infinity
+ '\u29DD': MO.BIN3, // tie over infinity
+ '\u29DE': MO.REL, // infinity negated with vertical bar
+ '\u29DF': MO.BIN3, // double-ended multimap
+ '\u29E0': MO.BIN3, // square with contoured outline
+ '\u29E1': MO.REL, // increases as
+ '\u29E2': MO.BIN4, // shuffle product
+ '\u29E3': MO.REL, // equals sign and slanted parallel
+ '\u29E4': MO.REL, // equals sign and slanted parallel with tilde above
+ '\u29E5': MO.REL, // identical to and slanted parallel
+ '\u29E6': MO.REL, // gleich stark
+ '\u29E7': MO.BIN3, // thermodynamic
+ '\u29E8': MO.BIN3, // down-pointing triangle with left half black
+ '\u29E9': MO.BIN3, // down-pointing triangle with right half black
+ '\u29EA': MO.BIN3, // black diamond with down arrow
+ '\u29EB': MO.BIN3, // black lozenge
+ '\u29EC': MO.BIN3, // white circle with down arrow
+ '\u29ED': MO.BIN3, // black circle with down arrow
+ '\u29EE': MO.BIN3, // error-barred white square
+ '\u29EF': MO.BIN3, // error-barred black square
+ '\u29F0': MO.BIN3, // error-barred white diamond
+ '\u29F1': MO.BIN3, // error-barred black diamond
+ '\u29F2': MO.BIN3, // error-barred white circle
+ '\u29F3': MO.BIN3, // error-barred black circle
+ '\u29F4': MO.REL, // rule-delayed
+ '\u29F5': MO.BIN4, // reverse solidus operator
+ '\u29F6': MO.BIN4, // solidus with overbar
+ '\u29F7': MO.BIN4, // reverse solidus with horizontal stroke
+ '\u29F8': MO.BIN3, // big solidus
+ '\u29F9': MO.BIN3, // big reverse solidus
+ '\u29FA': MO.BIN3, // double plus
+ '\u29FB': MO.BIN3, // triple plus
+ '\u29FE': MO.BIN4, // tiny
+ '\u29FF': MO.BIN4 // miny
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/MiscMathSymbolsB.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/MiscSymbolsAndArrows.js b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscSymbolsAndArrows.js
new file mode 100644
index 0000000..723ac61
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscSymbolsAndArrows.js
@@ -0,0 +1,36 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/MiscSymbolsAndArrows.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u2B45': MO.RELSTRETCH, // leftwards quadruple arrow
+ '\u2B46': MO.RELSTRETCH // rightwards quadruple arrow
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/MiscSymbolsAndArrows.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/MiscTechnical.js b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscTechnical.js
new file mode 100644
index 0000000..ad478a1
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/MiscTechnical.js
@@ -0,0 +1,40 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/MiscTechnical.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ postfix: {
+ '\u23B4': MO.WIDEACCENT, // top square bracket
+ '\u23B5': MO.WIDEACCENT, // bottom square bracket
+ '\u23DC': MO.WIDEACCENT, // top parenthesis
+ '\u23DD': MO.WIDEACCENT, // bottom parenthesis
+ '\u23E0': MO.WIDEACCENT, // top tortoise shell bracket
+ '\u23E1': MO.WIDEACCENT // bottom tortoise shell bracket
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/MiscTechnical.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/SpacingModLetters.js b/MarkDownEditor/MathJax/jax/element/mml/optable/SpacingModLetters.js
new file mode 100644
index 0000000..75c925f
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/SpacingModLetters.js
@@ -0,0 +1,38 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/SpacingModLetters.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ postfix: {
+ '\u02CD': MO.WIDEACCENT, // modifier letter low macron
+ '\u02DA': MO.ACCENT, // ring above
+ '\u02DD': MO.ACCENT, // double acute accent
+ '\u02F7': MO.WIDEACCENT // modifier letter low tilde
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/SpacingModLetters.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/SuppMathOperators.js b/MarkDownEditor/MathJax/jax/element/mml/optable/SuppMathOperators.js
new file mode 100644
index 0000000..ff2afac
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/SuppMathOperators.js
@@ -0,0 +1,289 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/SuppMathOperators.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ prefix: {
+ '\u2A03': MO.OP, // n-ary union operator with dot
+ '\u2A05': MO.OP, // n-ary square intersection operator
+ '\u2A07': MO.OP, // two logical and operator
+ '\u2A08': MO.OP, // two logical or operator
+ '\u2A09': MO.OP, // n-ary times operator
+ '\u2A0A': MO.OP, // modulo two sum
+ '\u2A0B': MO.INTEGRAL2, // summation with integral
+ '\u2A0C': MO.INTEGRAL, // quadruple integral operator
+ '\u2A0D': MO.INTEGRAL2, // finite part integral
+ '\u2A0E': MO.INTEGRAL2, // integral with double stroke
+ '\u2A0F': MO.INTEGRAL2, // integral average with slash
+ '\u2A10': MO.OP, // circulation function
+ '\u2A11': MO.OP, // anticlockwise integration
+ '\u2A12': MO.OP, // line integration with rectangular path around pole
+ '\u2A13': MO.OP, // line integration with semicircular path around pole
+ '\u2A14': MO.OP, // line integration not including the pole
+ '\u2A15': MO.INTEGRAL2, // integral around a point operator
+ '\u2A16': MO.INTEGRAL2, // quaternion integral operator
+ '\u2A17': MO.INTEGRAL2, // integral with leftwards arrow with hook
+ '\u2A18': MO.INTEGRAL2, // integral with times sign
+ '\u2A19': MO.INTEGRAL2, // integral with intersection
+ '\u2A1A': MO.INTEGRAL2, // integral with union
+ '\u2A1B': MO.INTEGRAL2, // integral with overbar
+ '\u2A1C': MO.INTEGRAL2, // integral with underbar
+ '\u2AFC': MO.OP, // large triple vertical bar operator
+ '\u2AFF': MO.OP // n-ary white vertical bar
+ },
+ infix: {
+ '\u2A1D': MO.BIN3, // join
+ '\u2A1E': MO.BIN3, // large left triangle operator
+ '\u2A1F': MO.BIN3, // z notation schema composition
+ '\u2A20': MO.BIN3, // z notation schema piping
+ '\u2A21': MO.BIN3, // z notation schema projection
+ '\u2A22': MO.BIN4, // plus sign with small circle above
+ '\u2A23': MO.BIN4, // plus sign with circumflex accent above
+ '\u2A24': MO.BIN4, // plus sign with tilde above
+ '\u2A25': MO.BIN4, // plus sign with dot below
+ '\u2A26': MO.BIN4, // plus sign with tilde below
+ '\u2A27': MO.BIN4, // plus sign with subscript two
+ '\u2A28': MO.BIN4, // plus sign with black triangle
+ '\u2A29': MO.BIN4, // minus sign with comma above
+ '\u2A2A': MO.BIN4, // minus sign with dot below
+ '\u2A2B': MO.BIN4, // minus sign with falling dots
+ '\u2A2C': MO.BIN4, // minus sign with rising dots
+ '\u2A2D': MO.BIN4, // plus sign in left half circle
+ '\u2A2E': MO.BIN4, // plus sign in right half circle
+ '\u2A30': MO.BIN4, // multiplication sign with dot above
+ '\u2A31': MO.BIN4, // multiplication sign with underbar
+ '\u2A32': MO.BIN4, // semidirect product with bottom closed
+ '\u2A33': MO.BIN4, // smash product
+ '\u2A34': MO.BIN4, // multiplication sign in left half circle
+ '\u2A35': MO.BIN4, // multiplication sign in right half circle
+ '\u2A36': MO.BIN4, // circled multiplication sign with circumflex accent
+ '\u2A37': MO.BIN4, // multiplication sign in double circle
+ '\u2A38': MO.BIN4, // circled division sign
+ '\u2A39': MO.BIN4, // plus sign in triangle
+ '\u2A3A': MO.BIN4, // minus sign in triangle
+ '\u2A3B': MO.BIN4, // multiplication sign in triangle
+ '\u2A3C': MO.BIN4, // interior product
+ '\u2A3D': MO.BIN4, // righthand interior product
+ '\u2A3E': MO.BIN4, // z notation relational composition
+ '\u2A40': MO.BIN4, // intersection with dot
+ '\u2A41': MO.BIN4, // union with minus sign
+ '\u2A42': MO.BIN4, // union with overbar
+ '\u2A43': MO.BIN4, // intersection with overbar
+ '\u2A44': MO.BIN4, // intersection with logical and
+ '\u2A45': MO.BIN4, // union with logical or
+ '\u2A46': MO.BIN4, // union above intersection
+ '\u2A47': MO.BIN4, // intersection above union
+ '\u2A48': MO.BIN4, // union above bar above intersection
+ '\u2A49': MO.BIN4, // intersection above bar above union
+ '\u2A4A': MO.BIN4, // union beside and joined with union
+ '\u2A4B': MO.BIN4, // intersection beside and joined with intersection
+ '\u2A4C': MO.BIN4, // closed union with serifs
+ '\u2A4D': MO.BIN4, // closed intersection with serifs
+ '\u2A4E': MO.BIN4, // double square intersection
+ '\u2A4F': MO.BIN4, // double square union
+ '\u2A50': MO.BIN4, // closed union with serifs and smash product
+ '\u2A51': MO.BIN4, // logical and with dot above
+ '\u2A52': MO.BIN4, // logical or with dot above
+ '\u2A53': MO.BIN4, // double logical and
+ '\u2A54': MO.BIN4, // double logical or
+ '\u2A55': MO.BIN4, // two intersecting logical and
+ '\u2A56': MO.BIN4, // two intersecting logical or
+ '\u2A57': MO.BIN4, // sloping large or
+ '\u2A58': MO.BIN4, // sloping large and
+ '\u2A59': MO.REL, // logical or overlapping logical and
+ '\u2A5A': MO.BIN4, // logical and with middle stem
+ '\u2A5B': MO.BIN4, // logical or with middle stem
+ '\u2A5C': MO.BIN4, // logical and with horizontal dash
+ '\u2A5D': MO.BIN4, // logical or with horizontal dash
+ '\u2A5E': MO.BIN4, // logical and with double overbar
+ '\u2A5F': MO.BIN4, // logical and with underbar
+ '\u2A60': MO.BIN4, // logical and with double underbar
+ '\u2A61': MO.BIN4, // small vee with underbar
+ '\u2A62': MO.BIN4, // logical or with double overbar
+ '\u2A63': MO.BIN4, // logical or with double underbar
+ '\u2A64': MO.BIN4, // z notation domain antirestriction
+ '\u2A65': MO.BIN4, // z notation range antirestriction
+ '\u2A66': MO.REL, // equals sign with dot below
+ '\u2A67': MO.REL, // identical with dot above
+ '\u2A68': MO.REL, // triple horizontal bar with double vertical stroke
+ '\u2A69': MO.REL, // triple horizontal bar with triple vertical stroke
+ '\u2A6A': MO.REL, // tilde operator with dot above
+ '\u2A6B': MO.REL, // tilde operator with rising dots
+ '\u2A6C': MO.REL, // similar minus similar
+ '\u2A6D': MO.REL, // congruent with dot above
+ '\u2A6E': MO.REL, // equals with asterisk
+ '\u2A6F': MO.REL, // almost equal to with circumflex accent
+ '\u2A70': MO.REL, // approximately equal or equal to
+ '\u2A71': MO.BIN4, // equals sign above plus sign
+ '\u2A72': MO.BIN4, // plus sign above equals sign
+ '\u2A73': MO.REL, // equals sign above tilde operator
+ '\u2A74': MO.REL, // double colon equal
+ '\u2A75': MO.REL, // two consecutive equals signs
+ '\u2A76': MO.REL, // three consecutive equals signs
+ '\u2A77': MO.REL, // equals sign with two dots above and two dots below
+ '\u2A78': MO.REL, // equivalent with four dots above
+ '\u2A79': MO.REL, // less-than with circle inside
+ '\u2A7A': MO.REL, // greater-than with circle inside
+ '\u2A7B': MO.REL, // less-than with question mark above
+ '\u2A7C': MO.REL, // greater-than with question mark above
+ '\u2A7D': MO.REL, // less-than or slanted equal to
+ '\u2A7D\u0338': MO.REL, // less-than or slanted equal to with slash
+ '\u2A7E': MO.REL, // greater-than or slanted equal to
+ '\u2A7E\u0338': MO.REL, // greater-than or slanted equal to with slash
+ '\u2A7F': MO.REL, // less-than or slanted equal to with dot inside
+ '\u2A80': MO.REL, // greater-than or slanted equal to with dot inside
+ '\u2A81': MO.REL, // less-than or slanted equal to with dot above
+ '\u2A82': MO.REL, // greater-than or slanted equal to with dot above
+ '\u2A83': MO.REL, // less-than or slanted equal to with dot above right
+ '\u2A84': MO.REL, // greater-than or slanted equal to with dot above left
+ '\u2A85': MO.REL, // less-than or approximate
+ '\u2A86': MO.REL, // greater-than or approximate
+ '\u2A87': MO.REL, // less-than and single-line not equal to
+ '\u2A88': MO.REL, // greater-than and single-line not equal to
+ '\u2A89': MO.REL, // less-than and not approximate
+ '\u2A8A': MO.REL, // greater-than and not approximate
+ '\u2A8B': MO.REL, // less-than above double-line equal above greater-than
+ '\u2A8C': MO.REL, // greater-than above double-line equal above less-than
+ '\u2A8D': MO.REL, // less-than above similar or equal
+ '\u2A8E': MO.REL, // greater-than above similar or equal
+ '\u2A8F': MO.REL, // less-than above similar above greater-than
+ '\u2A90': MO.REL, // greater-than above similar above less-than
+ '\u2A91': MO.REL, // less-than above greater-than above double-line equal
+ '\u2A92': MO.REL, // greater-than above less-than above double-line equal
+ '\u2A93': MO.REL, // less-than above slanted equal above greater-than above slanted equal
+ '\u2A94': MO.REL, // greater-than above slanted equal above less-than above slanted equal
+ '\u2A95': MO.REL, // slanted equal to or less-than
+ '\u2A96': MO.REL, // slanted equal to or greater-than
+ '\u2A97': MO.REL, // slanted equal to or less-than with dot inside
+ '\u2A98': MO.REL, // slanted equal to or greater-than with dot inside
+ '\u2A99': MO.REL, // double-line equal to or less-than
+ '\u2A9A': MO.REL, // double-line equal to or greater-than
+ '\u2A9B': MO.REL, // double-line slanted equal to or less-than
+ '\u2A9C': MO.REL, // double-line slanted equal to or greater-than
+ '\u2A9D': MO.REL, // similar or less-than
+ '\u2A9E': MO.REL, // similar or greater-than
+ '\u2A9F': MO.REL, // similar above less-than above equals sign
+ '\u2AA0': MO.REL, // similar above greater-than above equals sign
+ '\u2AA1': MO.REL, // double nested less-than
+ '\u2AA1\u0338': MO.REL, // double nested less-than with slash
+ '\u2AA2': MO.REL, // double nested greater-than
+ '\u2AA2\u0338': MO.REL, // double nested greater-than with slash
+ '\u2AA3': MO.REL, // double nested less-than with underbar
+ '\u2AA4': MO.REL, // greater-than overlapping less-than
+ '\u2AA5': MO.REL, // greater-than beside less-than
+ '\u2AA6': MO.REL, // less-than closed by curve
+ '\u2AA7': MO.REL, // greater-than closed by curve
+ '\u2AA8': MO.REL, // less-than closed by curve above slanted equal
+ '\u2AA9': MO.REL, // greater-than closed by curve above slanted equal
+ '\u2AAA': MO.REL, // smaller than
+ '\u2AAB': MO.REL, // larger than
+ '\u2AAC': MO.REL, // smaller than or equal to
+ '\u2AAD': MO.REL, // larger than or equal to
+ '\u2AAE': MO.REL, // equals sign with bumpy above
+ '\u2AAF\u0338': MO.REL, // precedes above single-line equals sign with slash
+ '\u2AB0\u0338': MO.REL, // succeeds above single-line equals sign with slash
+ '\u2AB1': MO.REL, // precedes above single-line not equal to
+ '\u2AB2': MO.REL, // succeeds above single-line not equal to
+ '\u2AB3': MO.REL, // precedes above equals sign
+ '\u2AB4': MO.REL, // succeeds above equals sign
+ '\u2AB5': MO.REL, // precedes above not equal to
+ '\u2AB6': MO.REL, // succeeds above not equal to
+ '\u2AB7': MO.REL, // precedes above almost equal to
+ '\u2AB8': MO.REL, // succeeds above almost equal to
+ '\u2AB9': MO.REL, // precedes above not almost equal to
+ '\u2ABA': MO.REL, // succeeds above not almost equal to
+ '\u2ABB': MO.REL, // double precedes
+ '\u2ABC': MO.REL, // double succeeds
+ '\u2ABD': MO.REL, // subset with dot
+ '\u2ABE': MO.REL, // superset with dot
+ '\u2ABF': MO.REL, // subset with plus sign below
+ '\u2AC0': MO.REL, // superset with plus sign below
+ '\u2AC1': MO.REL, // subset with multiplication sign below
+ '\u2AC2': MO.REL, // superset with multiplication sign below
+ '\u2AC3': MO.REL, // subset of or equal to with dot above
+ '\u2AC4': MO.REL, // superset of or equal to with dot above
+ '\u2AC5': MO.REL, // subset of above equals sign
+ '\u2AC6': MO.REL, // superset of above equals sign
+ '\u2AC7': MO.REL, // subset of above tilde operator
+ '\u2AC8': MO.REL, // superset of above tilde operator
+ '\u2AC9': MO.REL, // subset of above almost equal to
+ '\u2ACA': MO.REL, // superset of above almost equal to
+ '\u2ACB': MO.REL, // subset of above not equal to
+ '\u2ACC': MO.REL, // superset of above not equal to
+ '\u2ACD': MO.REL, // square left open box operator
+ '\u2ACE': MO.REL, // square right open box operator
+ '\u2ACF': MO.REL, // closed subset
+ '\u2AD0': MO.REL, // closed superset
+ '\u2AD1': MO.REL, // closed subset or equal to
+ '\u2AD2': MO.REL, // closed superset or equal to
+ '\u2AD3': MO.REL, // subset above superset
+ '\u2AD4': MO.REL, // superset above subset
+ '\u2AD5': MO.REL, // subset above subset
+ '\u2AD6': MO.REL, // superset above superset
+ '\u2AD7': MO.REL, // superset beside subset
+ '\u2AD8': MO.REL, // superset beside and joined by dash with subset
+ '\u2AD9': MO.REL, // element of opening downwards
+ '\u2ADA': MO.REL, // pitchfork with tee top
+ '\u2ADB': MO.REL, // transversal intersection
+ '\u2ADC': MO.REL, // forking
+ '\u2ADD': MO.REL, // nonforking
+ '\u2ADE': MO.REL, // short left tack
+ '\u2ADF': MO.REL, // short down tack
+ '\u2AE0': MO.REL, // short up tack
+ '\u2AE1': MO.REL, // perpendicular with s
+ '\u2AE2': MO.REL, // vertical bar triple right turnstile
+ '\u2AE3': MO.REL, // double vertical bar left turnstile
+ '\u2AE4': MO.REL, // vertical bar double left turnstile
+ '\u2AE5': MO.REL, // double vertical bar double left turnstile
+ '\u2AE6': MO.REL, // long dash from left member of double vertical
+ '\u2AE7': MO.REL, // short down tack with overbar
+ '\u2AE8': MO.REL, // short up tack with underbar
+ '\u2AE9': MO.REL, // short up tack above short down tack
+ '\u2AEA': MO.REL, // double down tack
+ '\u2AEB': MO.REL, // double up tack
+ '\u2AEC': MO.REL, // double stroke not sign
+ '\u2AED': MO.REL, // reversed double stroke not sign
+ '\u2AEE': MO.REL, // does not divide with reversed negation slash
+ '\u2AEF': MO.REL, // vertical line with circle above
+ '\u2AF0': MO.REL, // vertical line with circle below
+ '\u2AF1': MO.REL, // down tack with circle below
+ '\u2AF2': MO.REL, // parallel with horizontal stroke
+ '\u2AF3': MO.REL, // parallel with tilde operator
+ '\u2AF4': MO.BIN4, // triple vertical bar binary relation
+ '\u2AF5': MO.BIN4, // triple vertical bar with horizontal stroke
+ '\u2AF6': MO.BIN4, // triple colon operator
+ '\u2AF7': MO.REL, // triple nested less-than
+ '\u2AF8': MO.REL, // triple nested greater-than
+ '\u2AF9': MO.REL, // double-line slanted less-than or equal to
+ '\u2AFA': MO.REL, // double-line slanted greater-than or equal to
+ '\u2AFB': MO.BIN4, // triple solidus binary relation
+ '\u2AFD': MO.BIN4, // double solidus operator
+ '\u2AFE': MO.BIN3 // white vertical bar
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/SuppMathOperators.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsA.js b/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsA.js
new file mode 100644
index 0000000..47a853b
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsA.js
@@ -0,0 +1,40 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/SupplementalArrowsA.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u27F0': MO.RELSTRETCH, // upwards quadruple arrow
+ '\u27F1': MO.RELSTRETCH, // downwards quadruple arrow
+ '\u27FB': MO.WIDEREL, // long leftwards arrow from bar
+ '\u27FD': MO.WIDEREL, // long leftwards double arrow from bar
+ '\u27FE': MO.WIDEREL, // long rightwards double arrow from bar
+ '\u27FF': MO.WIDEREL // long rightwards squiggle arrow
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/SupplementalArrowsA.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsB.js b/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsB.js
new file mode 100644
index 0000000..a3ddf0a
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/element/mml/optable/SupplementalArrowsB.js
@@ -0,0 +1,162 @@
+/*************************************************************
+ *
+ * MathJax/jax/output/HTML-CSS/optable/SupplementalArrowsB.js
+ *
+ * Copyright (c) 2010-2015 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.
+ *
+ */
+
+(function (MML) {
+ var MO = MML.mo.OPTYPES;
+ var TEXCLASS = MML.TEXCLASS;
+
+ MathJax.Hub.Insert(MML.mo.prototype,{
+ OPTABLE: {
+ infix: {
+ '\u2900': MO.RELACCENT, // rightwards two-headed arrow with vertical stroke
+ '\u2901': MO.RELACCENT, // rightwards two-headed arrow with double vertical stroke
+ '\u2902': MO.RELACCENT, // leftwards double arrow with vertical stroke
+ '\u2903': MO.RELACCENT, // rightwards double arrow with vertical stroke
+ '\u2904': MO.RELACCENT, // left right double arrow with vertical stroke
+ '\u2905': MO.RELACCENT, // rightwards two-headed arrow from bar
+ '\u2906': MO.RELACCENT, // leftwards double arrow from bar
+ '\u2907': MO.RELACCENT, // rightwards double arrow from bar
+ '\u2908': MO.REL, // downwards arrow with horizontal stroke
+ '\u2909': MO.REL, // upwards arrow with horizontal stroke
+ '\u290A': MO.RELSTRETCH, // upwards triple arrow
+ '\u290B': MO.RELSTRETCH, // downwards triple arrow
+ '\u290C': MO.WIDEREL, // leftwards double dash arrow
+ '\u290D': MO.WIDEREL, // rightwards double dash arrow
+ '\u290E': MO.WIDEREL, // leftwards triple dash arrow
+ '\u290F': MO.WIDEREL, // rightwards triple dash arrow
+ '\u2910': MO.WIDEREL, // rightwards two-headed triple dash arrow
+ '\u2911': MO.RELACCENT, // rightwards arrow with dotted stem
+ '\u2912': MO.RELSTRETCH, // upwards arrow to bar
+ '\u2913': MO.RELSTRETCH, // downwards arrow to bar
+ '\u2914': MO.RELACCENT, // rightwards arrow with tail with vertical stroke
+ '\u2915': MO.RELACCENT, // rightwards arrow with tail with double vertical stroke
+ '\u2916': MO.RELACCENT, // rightwards two-headed arrow with tail
+ '\u2917': MO.RELACCENT, // rightwards two-headed arrow with tail with vertical stroke
+ '\u2918': MO.RELACCENT, // rightwards two-headed arrow with tail with double vertical stroke
+ '\u2919': MO.RELACCENT, // leftwards arrow-tail
+ '\u291A': MO.RELACCENT, // rightwards arrow-tail
+ '\u291B': MO.RELACCENT, // leftwards double arrow-tail
+ '\u291C': MO.RELACCENT, // rightwards double arrow-tail
+ '\u291D': MO.RELACCENT, // leftwards arrow to black diamond
+ '\u291E': MO.RELACCENT, // rightwards arrow to black diamond
+ '\u291F': MO.RELACCENT, // leftwards arrow from bar to black diamond
+ '\u2920': MO.RELACCENT, // rightwards arrow from bar to black diamond
+ '\u2921': MO.RELSTRETCH, // north west and south east arrow
+ '\u2922': MO.RELSTRETCH, // north east and south west arrow
+ '\u2923': MO.REL, // north west arrow with hook
+ '\u2924': MO.REL, // north east arrow with hook
+ '\u2925': MO.REL, // south east arrow with hook
+ '\u2926': MO.REL, // south west arrow with hook
+ '\u2927': MO.REL, // north west arrow and north east arrow
+ '\u2928': MO.REL, // north east arrow and south east arrow
+ '\u2929': MO.REL, // south east arrow and south west arrow
+ '\u292A': MO.REL, // south west arrow and north west arrow
+ '\u292B': MO.REL, // rising diagonal crossing falling diagonal
+ '\u292C': MO.REL, // falling diagonal crossing rising diagonal
+ '\u292D': MO.REL, // south east arrow crossing north east arrow
+ '\u292E': MO.REL, // north east arrow crossing south east arrow
+ '\u292F': MO.REL, // falling diagonal crossing north east arrow
+ '\u2930': MO.REL, // rising diagonal crossing south east arrow
+ '\u2931': MO.REL, // north east arrow crossing north west arrow
+ '\u2932': MO.REL, // north west arrow crossing north east arrow
+ '\u2933': MO.RELACCENT, // wave arrow pointing directly right
+ '\u2934': MO.REL, // arrow pointing rightwards then curving upwards
+ '\u2935': MO.REL, // arrow pointing rightwards then curving downwards
+ '\u2936': MO.REL, // arrow pointing downwards then curving leftwards
+ '\u2937': MO.REL, // arrow pointing downwards then curving rightwards
+ '\u2938': MO.REL, // right-side arc clockwise arrow
+ '\u2939': MO.REL, // left-side arc anticlockwise arrow
+ '\u293A': MO.RELACCENT, // top arc anticlockwise arrow
+ '\u293B': MO.RELACCENT, // bottom arc anticlockwise arrow
+ '\u293C': MO.RELACCENT, // top arc clockwise arrow with minus
+ '\u293D': MO.RELACCENT, // top arc anticlockwise arrow with plus
+ '\u293E': MO.REL, // lower right semicircular clockwise arrow
+ '\u293F': MO.REL, // lower left semicircular anticlockwise arrow
+ '\u2940': MO.REL, // anticlockwise closed circle arrow
+ '\u2941': MO.REL, // clockwise closed circle arrow
+ '\u2942': MO.RELACCENT, // rightwards arrow above short leftwards arrow
+ '\u2943': MO.RELACCENT, // leftwards arrow above short rightwards arrow
+ '\u2944': MO.RELACCENT, // short rightwards arrow above leftwards arrow
+ '\u2945': MO.RELACCENT, // rightwards arrow with plus below
+ '\u2946': MO.RELACCENT, // leftwards arrow with plus below
+ '\u2947': MO.RELACCENT, // rightwards arrow through x
+ '\u2948': MO.RELACCENT, // left right arrow through small circle
+ '\u2949': MO.REL, // upwards two-headed arrow from small circle
+ '\u294A': MO.RELACCENT, // left barb up right barb down harpoon
+ '\u294B': MO.RELACCENT, // left barb down right barb up harpoon
+ '\u294C': MO.REL, // up barb right down barb left harpoon
+ '\u294D': MO.REL, // up barb left down barb right harpoon
+ '\u294E': MO.WIDEREL, // left barb up right barb up harpoon
+ '\u294F': MO.RELSTRETCH, // up barb right down barb right harpoon
+ '\u2950': MO.WIDEREL, // left barb down right barb down harpoon
+ '\u2951': MO.RELSTRETCH, // up barb left down barb left harpoon
+ '\u2952': MO.WIDEREL, // leftwards harpoon with barb up to bar
+ '\u2953': MO.WIDEREL, // rightwards harpoon with barb up to bar
+ '\u2954': MO.RELSTRETCH, // upwards harpoon with barb right to bar
+ '\u2955': MO.RELSTRETCH, // downwards harpoon with barb right to bar
+ '\u2956': MO.RELSTRETCH, // leftwards harpoon with barb down to bar
+ '\u2957': MO.RELSTRETCH, // rightwards harpoon with barb down to bar
+ '\u2958': MO.RELSTRETCH, // upwards harpoon with barb left to bar
+ '\u2959': MO.RELSTRETCH, // downwards harpoon with barb left to bar
+ '\u295A': MO.WIDEREL, // leftwards harpoon with barb up from bar
+ '\u295B': MO.WIDEREL, // rightwards harpoon with barb up from bar
+ '\u295C': MO.RELSTRETCH, // upwards harpoon with barb right from bar
+ '\u295D': MO.RELSTRETCH, // downwards harpoon with barb right from bar
+ '\u295E': MO.WIDEREL, // leftwards harpoon with barb down from bar
+ '\u295F': MO.WIDEREL, // rightwards harpoon with barb down from bar
+ '\u2960': MO.RELSTRETCH, // upwards harpoon with barb left from bar
+ '\u2961': MO.RELSTRETCH, // downwards harpoon with barb left from bar
+ '\u2962': MO.RELACCENT, // leftwards harpoon with barb up above leftwards harpoon with barb down
+ '\u2963': MO.REL, // upwards harpoon with barb left beside upwards harpoon with barb right
+ '\u2964': MO.RELACCENT, // rightwards harpoon with barb up above rightwards harpoon with barb down
+ '\u2965': MO.REL, // downwards harpoon with barb left beside downwards harpoon with barb right
+ '\u2966': MO.RELACCENT, // leftwards harpoon with barb up above rightwards harpoon with barb up
+ '\u2967': MO.RELACCENT, // leftwards harpoon with barb down above rightwards harpoon with barb down
+ '\u2968': MO.RELACCENT, // rightwards harpoon with barb up above leftwards harpoon with barb up
+ '\u2969': MO.RELACCENT, // rightwards harpoon with barb down above leftwards harpoon with barb down
+ '\u296A': MO.RELACCENT, // leftwards harpoon with barb up above long dash
+ '\u296B': MO.RELACCENT, // leftwards harpoon with barb down below long dash
+ '\u296C': MO.RELACCENT, // rightwards harpoon with barb up above long dash
+ '\u296D': MO.RELACCENT, // rightwards harpoon with barb down below long dash
+ '\u296E': MO.RELSTRETCH, // upwards harpoon with barb left beside downwards harpoon with barb right
+ '\u296F': MO.RELSTRETCH, // downwards harpoon with barb left beside upwards harpoon with barb right
+ '\u2970': MO.RELACCENT, // right double arrow with rounded head
+ '\u2971': MO.RELACCENT, // equals sign above rightwards arrow
+ '\u2972': MO.RELACCENT, // tilde operator above rightwards arrow
+ '\u2973': MO.RELACCENT, // leftwards arrow above tilde operator
+ '\u2974': MO.RELACCENT, // rightwards arrow above tilde operator
+ '\u2975': MO.RELACCENT, // rightwards arrow above almost equal to
+ '\u2976': MO.RELACCENT, // less-than above leftwards arrow
+ '\u2977': MO.RELACCENT, // leftwards arrow through less-than
+ '\u2978': MO.RELACCENT, // greater-than above rightwards arrow
+ '\u2979': MO.RELACCENT, // subset above rightwards arrow
+ '\u297A': MO.RELACCENT, // leftwards arrow through subset
+ '\u297B': MO.RELACCENT, // superset above leftwards arrow
+ '\u297C': MO.RELACCENT, // left fish tail
+ '\u297D': MO.RELACCENT, // right fish tail
+ '\u297E': MO.REL, // up fish tail
+ '\u297F': MO.REL // down fish tail
+ }
+ }
+ });
+
+ MathJax.Ajax.loadComplete(MML.optableDir+"/SupplementalArrowsB.js");
+
+})(MathJax.ElementJax.mml);
diff --git a/MarkDownEditor/MathJax/jax/input/TeX/MathJax.js b/MarkDownEditor/MathJax/jax/input/TeX/MathJax.js
new file mode 100644
index 0000000..ff0a6ff
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/input/TeX/MathJax.js
@@ -0,0 +1,3273 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax.js
+ *
+ * The main support code for the MathJax Hub, including the
+ * Ajax, Callback, Messaging, and Object-Oriented Programming
+ * libraries, as well as the base Jax classes, and startup
+ * processing code.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.
+ */
+
+
+//
+// Check if browser can support MathJax (no one fails this nowadays)
+//
+if (document.getElementById && document.childNodes && document.createElement) {
+//
+// Skip if MathJax is already loaded
+//
+if (!(window.MathJax && MathJax.Hub)) {
+
+//
+// Get author configuration from MathJax variable, if any
+//
+if (window.MathJax) {window.MathJax = {AuthorConfig: window.MathJax}}
+ else {window.MathJax = {}}
+
+// MathJax.isPacked = true; // This line is uncommented by the packer.
+
+MathJax.version = "2.6.1";
+MathJax.fileversion = "2.6.1";
+MathJax.cdnVersion = "2.6.1"; // specifies a revision to break caching
+MathJax.cdnFileVersions = {}; // can be used to specify revisions for individual files
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var PROTO = []; // a static object used to indicate when a prototype is being created
+ var OBJECT = function (def) {
+ var obj = def.constructor; if (!obj) {obj = function () {}}
+ for (var id in def) {if (id !== 'constructor' && def.hasOwnProperty(id)) {obj[id] = def[id]}}
+ return obj;
+ };
+ var CONSTRUCTOR = function () {
+ return function () {return arguments.callee.Init.call(this,arguments)};
+ };
+
+ BASE.Object = OBJECT({
+ constructor: CONSTRUCTOR(),
+
+ Subclass: function (def,classdef) {
+ var obj = CONSTRUCTOR();
+ obj.SUPER = this; obj.Init = this.Init;
+ obj.Subclass = this.Subclass; obj.Augment = this.Augment;
+ obj.protoFunction = this.protoFunction;
+ obj.can = this.can; obj.has = this.has; obj.isa = this.isa;
+ obj.prototype = new this(PROTO);
+ obj.prototype.constructor = obj; // the real constructor
+ obj.Augment(def,classdef);
+ return obj;
+ },
+
+ Init: function (args) {
+ var obj = this;
+ if (args.length === 1 && args[0] === PROTO) {return obj}
+ if (!(obj instanceof args.callee)) {obj = new args.callee(PROTO)}
+ return obj.Init.apply(obj,args) || obj;
+ },
+
+ Augment: function (def,classdef) {
+ var id;
+ if (def != null) {
+ for (id in def) {if (def.hasOwnProperty(id)) {this.protoFunction(id,def[id])}}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (def.toString !== this.prototype.toString && def.toString !== {}.toString)
+ {this.protoFunction('toString',def.toString)}
+ }
+ if (classdef != null) {
+ for (id in classdef) {if (classdef.hasOwnProperty(id)) {this[id] = classdef[id]}}
+ }
+ return this;
+ },
+
+ protoFunction: function (id,def) {
+ this.prototype[id] = def;
+ if (typeof def === "function") {def.SUPER = this.SUPER.prototype}
+ },
+
+ prototype: {
+ Init: function () {},
+ SUPER: function (fn) {return fn.callee.SUPER},
+ can: function (method) {return typeof(this[method]) === "function"},
+ has: function (property) {return typeof(this[property]) !== "undefined"},
+ isa: function (obj) {return (obj instanceof Object) && (this instanceof obj)}
+ },
+
+ can: function (method) {return this.prototype.can.call(this,method)},
+ has: function (property) {return this.prototype.has.call(this,property)},
+ isa: function (obj) {
+ var constructor = this;
+ while (constructor) {
+ if (constructor === obj) {return true} else {constructor = constructor.SUPER}
+ }
+ return false;
+ },
+
+
+ SimpleSUPER: OBJECT({
+ constructor: function (def) {return this.SimpleSUPER.define(def)},
+
+ define: function (src) {
+ var dst = {};
+ if (src != null) {
+ for (var id in src) {if (src.hasOwnProperty(id)) {dst[id] = this.wrap(id,src[id])}}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (src.toString !== this.prototype.toString && src.toString !== {}.toString)
+ {dst.toString = this.wrap('toString',src.toString)}
+ }
+ return dst;
+ },
+
+ wrap: function (id,f) {
+ if (typeof(f) !== 'function' || !f.toString().match(/\.\s*SUPER\s*\(/)) {return f}
+ var fn = function () {
+ this.SUPER = fn.SUPER[id];
+ try {var result = f.apply(this,arguments)} catch (err) {delete this.SUPER; throw err}
+ delete this.SUPER;
+ return result;
+ }
+ fn.toString = function () {return f.toString.apply(f,arguments)}
+ return fn;
+ }
+
+ })
+ });
+
+})("MathJax");
+
+/**********************************************************/
+
+/*
+ * Create a callback function from various forms of data:
+ *
+ * MathJax.Callback(fn) -- callback to a function
+ *
+ * MathJax.Callback([fn]) -- callback to function
+ * MathJax.Callback([fn,data...])
+ * -- callback to function with given data as arguments
+ * MathJax.Callback([object,fn])
+ * -- call fn with object as "this"
+ * MathJax.Callback([object,fn,data...])
+ * -- call fn with object as "this" and data as arguments
+ * MathJax.Callback(["method",object])
+ * -- call method of object wth object as "this"
+ * MathJax.Callback(["method",object,data...])
+ * -- as above, but with data as arguments to method
+ *
+ * MathJax.Callback({hook: fn, data: [...], object: this})
+ * -- give function, data, and object to act as "this" explicitly
+ *
+ * MathJax.Callback("code") -- callback that compiles and executes a string
+ *
+ * MathJax.Callback([...],i)
+ * -- use slice of array starting at i and interpret
+ * result as above. (Used for passing "arguments" array
+ * and trimming initial arguments, if any.)
+ */
+
+/*
+ * MathJax.Callback.After([...],cb1,cb2,...)
+ * -- make a callback that isn't called until all the other
+ * ones are called first. I.e., wait for a union of
+ * callbacks to occur before making the given callback.
+ */
+
+/*
+ * MathJax.Callback.Queue([callback,...])
+ * -- make a synchronized queue of commands that process
+ * sequentially, waiting for those that return uncalled
+ * callbacks.
+ */
+
+/*
+ * MathJax.Callback.Signal(name)
+ * -- finds or creates a names signal, to which listeners
+ * can be attached and are signaled by messages posted
+ * to the signal. Responses can be asynchronous.
+ */
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+ //
+ // Create a callback from an associative array
+ //
+ var CALLBACK = function (data) {
+ var cb = function () {return arguments.callee.execute.apply(arguments.callee,arguments)};
+ for (var id in CALLBACK.prototype) {
+ if (CALLBACK.prototype.hasOwnProperty(id)) {
+ if (typeof(data[id]) !== 'undefined') {cb[id] = data[id]}
+ else {cb[id] = CALLBACK.prototype[id]}
+ }
+ }
+ cb.toString = CALLBACK.prototype.toString;
+ return cb;
+ };
+ CALLBACK.prototype = {
+ isCallback: true,
+ hook: function () {},
+ data: [],
+ object: window,
+ execute: function () {
+ if (!this.called || this.autoReset) {
+ this.called = !this.autoReset;
+ return this.hook.apply(this.object,this.data.concat([].slice.call(arguments,0)));
+ }
+ },
+ reset: function () {delete this.called},
+ toString: function () {return this.hook.toString.apply(this.hook,arguments)}
+ };
+ var ISCALLBACK = function (f) {
+ return (typeof(f) === "function" && f.isCallback);
+ }
+
+ //
+ // Evaluate a string in global context
+ //
+ var EVAL = function (code) {return eval.call(window,code)}
+ var TESTEVAL = function () {
+ EVAL("var __TeSt_VaR__ = 1"); // check if it works in global context
+ if (window.__TeSt_VaR__) {
+ try { delete window.__TeSt_VaR__; } // NOTE IE9 throws when in IE7 mode
+ catch (error) { window.__TeSt_VaR__ = null; }
+ } else {
+ if (window.execScript) {
+ // IE
+ EVAL = function (code) {
+ BASE.__code = code;
+ code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
+ window.execScript(code);
+ var result = BASE.__result; delete BASE.__result; delete BASE.__code;
+ if (result instanceof Error) {throw result}
+ return result;
+ }
+ } else {
+ // Safari2
+ EVAL = function (code) {
+ BASE.__code = code;
+ code = "try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";
+ var head = (document.getElementsByTagName("head"))[0]; if (!head) {head = document.body}
+ var script = document.createElement("script");
+ script.appendChild(document.createTextNode(code));
+ head.appendChild(script); head.removeChild(script);
+ var result = BASE.__result; delete BASE.__result; delete BASE.__code;
+ if (result instanceof Error) {throw result}
+ return result;
+ }
+ }
+ }
+ TESTEVAL = null;
+ }
+
+ //
+ // Create a callback from various types of data
+ //
+ var USING = function (args,i) {
+ if (arguments.length > 1) {
+ if (arguments.length === 2 && !(typeof arguments[0] === 'function') &&
+ arguments[0] instanceof Object && typeof arguments[1] === 'number')
+ {args = [].slice.call(args,i)}
+ else {args = [].slice.call(arguments,0)}
+ }
+ if (args instanceof Array && args.length === 1) {args = args[0]}
+ if (typeof args === 'function') {
+ if (args.execute === CALLBACK.prototype.execute) {return args}
+ return CALLBACK({hook: args});
+ } else if (args instanceof Array) {
+ if (typeof(args[0]) === 'string' && args[1] instanceof Object &&
+ typeof args[1][args[0]] === 'function') {
+ return CALLBACK({hook: args[1][args[0]], object: args[1], data: args.slice(2)});
+ } else if (typeof args[0] === 'function') {
+ return CALLBACK({hook: args[0], data: args.slice(1)});
+ } else if (typeof args[1] === 'function') {
+ return CALLBACK({hook: args[1], object: args[0], data: args.slice(2)});
+ }
+ } else if (typeof(args) === 'string') {
+ if (TESTEVAL) TESTEVAL();
+ return CALLBACK({hook: EVAL, data: [args]});
+ } else if (args instanceof Object) {
+ return CALLBACK(args);
+ } else if (typeof(args) === 'undefined') {
+ return CALLBACK({});
+ }
+ throw Error("Can't make callback from given data");
+ };
+
+ //
+ // Wait for a given time to elapse and then perform the callback
+ //
+ var DELAY = function (time,callback) {
+ callback = USING(callback);
+ callback.timeout = setTimeout(callback,time);
+ return callback;
+ };
+
+ //
+ // Callback used by AFTER, QUEUE, and SIGNAL to check if calls have completed
+ //
+ var WAITFOR = function (callback,signal) {
+ callback = USING(callback);
+ if (!callback.called) {WAITSIGNAL(callback,signal); signal.pending++}
+ };
+ var WAITEXECUTE = function () {
+ var signals = this.signal; delete this.signal;
+ this.execute = this.oldExecute; delete this.oldExecute;
+ var result = this.execute.apply(this,arguments);
+ if (ISCALLBACK(result) && !result.called) {WAITSIGNAL(result,signals)} else {
+ for (var i = 0, m = signals.length; i < m; i++) {
+ signals[i].pending--;
+ if (signals[i].pending <= 0) {signals[i].call()}
+ }
+ }
+ };
+ var WAITSIGNAL = function (callback,signals) {
+ if (!(signals instanceof Array)) {signals = [signals]}
+ if (!callback.signal) {
+ callback.oldExecute = callback.execute;
+ callback.execute = WAITEXECUTE;
+ callback.signal = signals;
+ } else if (signals.length === 1) {callback.signal.push(signals[0])}
+ else {callback.signal = callback.signal.concat(signals)}
+ };
+
+ //
+ // Create a callback that is called when a collection of other callbacks have
+ // all been executed. If the callback gets called immediately (i.e., the
+ // others are all already called), check if it returns another callback
+ // and return that instead.
+ //
+ var AFTER = function (callback) {
+ callback = USING(callback);
+ callback.pending = 0;
+ for (var i = 1, m = arguments.length; i < m; i++)
+ {if (arguments[i]) {WAITFOR(arguments[i],callback)}}
+ if (callback.pending === 0) {
+ var result = callback();
+ if (ISCALLBACK(result)) {callback = result}
+ }
+ return callback;
+ };
+
+ //
+ // An array of prioritized hooks that are executed sequentially
+ // with a given set of data.
+ //
+ var HOOKS = MathJax.Object.Subclass({
+ //
+ // Initialize the array and the auto-reset status
+ //
+ Init: function (reset) {
+ this.hooks = [];
+ this.remove = []; // used when hooks are removed during execution of list
+ this.reset = reset;
+ this.running = false;
+ },
+ //
+ // Add a callback to the list, in priority order (default priority is 10)
+ //
+ Add: function (hook,priority) {
+ if (priority == null) {priority = 10}
+ if (!ISCALLBACK(hook)) {hook = USING(hook)}
+ hook.priority = priority;
+ var i = this.hooks.length;
+ while (i > 0 && priority < this.hooks[i-1].priority) {i--}
+ this.hooks.splice(i,0,hook);
+ return hook;
+ },
+ Remove: function (hook) {
+ for (var i = 0, m = this.hooks.length; i < m; i++) {
+ if (this.hooks[i] === hook) {
+ if (this.running) {this.remove.push(i)}
+ else {this.hooks.splice(i,1)}
+ return;
+ }
+ }
+ },
+ //
+ // Execute the list of callbacks, resetting them if requested.
+ // If any return callbacks, return a callback that will be
+ // executed when they all have completed.
+ // Remove any hooks that requested being removed during processing.
+ //
+ Execute: function () {
+ var callbacks = [{}];
+ this.running = true;
+ for (var i = 0, m = this.hooks.length; i < m; i++) {
+ if (this.reset) {this.hooks[i].reset()}
+ var result = this.hooks[i].apply(window,arguments);
+ if (ISCALLBACK(result) && !result.called) {callbacks.push(result)}
+ }
+ this.running = false;
+ if (this.remove.length) {this.RemovePending()}
+ if (callbacks.length === 1) {return null}
+ if (callbacks.length === 2) {return callbacks[1]}
+ return AFTER.apply({},callbacks);
+ },
+ //
+ // Remove hooks that asked to be removed during execution of list
+ //
+ RemovePending: function () {
+ this.remove = this.remove.sort();
+ for (var i = this.remove.length-1; i >= 0; i--) {this.hooks.splice(i,1)}
+ this.remove = [];
+ }
+
+ });
+
+ //
+ // Run an array of callbacks passing them the given data.
+ // (Legacy function, since this has been replaced by the HOOKS object).
+ //
+ var EXECUTEHOOKS = function (hooks,data,reset) {
+ if (!hooks) {return null}
+ if (!(hooks instanceof Array)) {hooks = [hooks]}
+ if (!(data instanceof Array)) {data = (data == null ? [] : [data])}
+ var handler = HOOKS(reset);
+ for (var i = 0, m = hooks.length; i < m; i++) {handler.Add(hooks[i])}
+ return handler.Execute.apply(handler,data);
+ };
+
+ //
+ // Command queue that performs commands in order, waiting when
+ // necessary for commands to complete asynchronousely
+ //
+ var QUEUE = BASE.Object.Subclass({
+ //
+ // Create the queue and push any commands that are specified
+ //
+ Init: function () {
+ this.pending = this.running = 0;
+ this.queue = [];
+ this.Push.apply(this,arguments);
+ },
+ //
+ // Add commands to the queue and run them. Adding a callback object
+ // (rather than a callback specification) queues a wait for that callback.
+ // Return the final callback for synchronization purposes.
+ //
+ Push: function () {
+ var callback;
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ callback = USING(arguments[i]);
+ if (callback === arguments[i] && !callback.called)
+ {callback = USING(["wait",this,callback])}
+ this.queue.push(callback);
+ }
+ if (!this.running && !this.pending) {this.Process()}
+ return callback;
+ },
+ //
+ // Process the command queue if we aren't waiting on another command
+ //
+ Process: function (queue) {
+ while (!this.running && !this.pending && this.queue.length) {
+ var callback = this.queue[0];
+ queue = this.queue.slice(1); this.queue = [];
+ this.Suspend(); var result = callback(); this.Resume();
+ if (queue.length) {this.queue = queue.concat(this.queue)}
+ if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
+ }
+ },
+ //
+ // Suspend/Resume command processing on this queue
+ //
+ Suspend: function () {this.running++},
+ Resume: function () {if (this.running) {this.running--}},
+ //
+ // Used by WAITFOR to restart the queue when an action completes
+ //
+ call: function () {this.Process.apply(this,arguments)},
+ wait: function (callback) {return callback}
+ });
+
+ //
+ // Create a named signal that listeners can attach to, to be signaled by
+ // postings made to the signal. Posts are queued if they occur while one
+ // is already in process.
+ //
+ var SIGNAL = QUEUE.Subclass({
+ Init: function (name) {
+ QUEUE.prototype.Init.call(this);
+ this.name = name;
+ this.posted = []; // the messages posted so far
+ this.listeners = HOOKS(true); // those with interest in this signal
+ this.posting = false;
+ this.callback = null;
+ },
+ //
+ // Post a message to the signal listeners, with callback for when complete
+ //
+ Post: function (message,callback,forget) {
+ callback = USING(callback);
+ if (this.posting || this.pending) {
+ this.Push(["Post",this,message,callback,forget]);
+ } else {
+ this.callback = callback; callback.reset();
+ if (!forget) {this.posted.push(message)}
+ this.Suspend(); this.posting = true;
+ var result = this.listeners.Execute(message);
+ if (ISCALLBACK(result) && !result.called) {WAITFOR(result,this)}
+ this.Resume(); this.posting = false;
+ if (!this.pending) {this.call()}
+ }
+ return callback;
+ },
+ //
+ // Clear the post history (so new listeners won't get old messages)
+ //
+ Clear: function (callback) {
+ callback = USING(callback);
+ if (this.posting || this.pending) {
+ callback = this.Push(["Clear",this,callback]);
+ } else {
+ this.posted = [];
+ callback();
+ }
+ return callback;
+ },
+ //
+ // Call the callback (all replies are in) and process the command queue
+ //
+ call: function () {this.callback(this); this.Process()},
+
+ //
+ // A listener calls this to register interest in the signal (so it will be called
+ // when posts occur). If ignorePast is true, it will not be sent the post history.
+ //
+ Interest: function (callback,ignorePast,priority) {
+ callback = USING(callback);
+ this.listeners.Add(callback,priority);
+ if (!ignorePast) {
+ for (var i = 0, m = this.posted.length; i < m; i++) {
+ callback.reset();
+ var result = callback(this.posted[i]);
+ if (ISCALLBACK(result) && i === this.posted.length-1) {WAITFOR(result,this)}
+ }
+ }
+ return callback;
+ },
+ //
+ // A listener calls this to remove itself from a signal
+ //
+ NoInterest: function (callback) {
+ this.listeners.Remove(callback);
+ },
+
+ //
+ // Hook a callback to a particular message on this signal
+ //
+ MessageHook: function (msg,callback,priority) {
+ callback = USING(callback);
+ if (!this.hooks) {this.hooks = {}; this.Interest(["ExecuteHooks",this])}
+ if (!this.hooks[msg]) {this.hooks[msg] = HOOKS(true)}
+ this.hooks[msg].Add(callback,priority);
+ for (var i = 0, m = this.posted.length; i < m; i++)
+ {if (this.posted[i] == msg) {callback.reset(); callback(this.posted[i])}}
+ callback.msg = msg; // keep track so we can remove it
+ return callback;
+ },
+ //
+ // Execute the message hooks for the given message
+ //
+ ExecuteHooks: function (msg) {
+ var type = ((msg instanceof Array) ? msg[0] : msg);
+ if (!this.hooks[type]) {return null}
+ return this.hooks[type].Execute(msg);
+ },
+ //
+ // Remove a hook safely
+ //
+ RemoveHook: function (hook) {
+ this.hooks[hook.msg].Remove(hook);
+ }
+
+ },{
+ signals: {}, // the named signals
+ find: function (name) {
+ if (!SIGNAL.signals[name]) {SIGNAL.signals[name] = new SIGNAL(name)}
+ return SIGNAL.signals[name];
+ }
+ });
+
+ //
+ // The main entry-points
+ //
+ BASE.Callback = BASE.CallBack = USING;
+ BASE.Callback.Delay = DELAY;
+ BASE.Callback.After = AFTER;
+ BASE.Callback.Queue = QUEUE;
+ BASE.Callback.Signal = SIGNAL.find;
+ BASE.Callback.Hooks = HOOKS;
+ BASE.Callback.ExecuteHooks = EXECUTEHOOKS;
+})("MathJax");
+
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var isSafari2 = (navigator.vendor === "Apple Computer, Inc." &&
+ typeof navigator.vendorSub === "undefined");
+ var sheets = 0; // used by Safari2
+
+ //
+ // Update sheets count and look up the head object
+ //
+ var HEAD = function (head) {
+ if (document.styleSheets && document.styleSheets.length > sheets)
+ {sheets = document.styleSheets.length}
+ if (!head) {
+ head = document.head || ((document.getElementsByTagName("head"))[0]);
+ if (!head) {head = document.body}
+ }
+ return head;
+ };
+
+ //
+ // Remove scripts that are completed so they don't clutter up the HEAD.
+ // This runs via setTimeout since IE7 can't remove the script while it is running.
+ //
+ var SCRIPTS = []; // stores scripts to be removed after a delay
+ var REMOVESCRIPTS = function () {
+ for (var i = 0, m = SCRIPTS.length; i < m; i++) {BASE.Ajax.head.removeChild(SCRIPTS[i])}
+ SCRIPTS = [];
+ };
+
+ var PATH = {};
+ PATH[BASENAME] = ""; // empty path gets the root URL
+
+ BASE.Ajax = {
+ loaded: {}, // files already loaded
+ loading: {}, // files currently in process of loading
+ loadHooks: {}, // hooks to call when files are loaded
+ timeout: 15*1000, // timeout for loading of files (15 seconds)
+ styleDelay: 1, // delay to use before styles are available
+ config: {
+ root: "", // URL of root directory to load from
+ path: PATH // paths to named URL's (e.g., [MathJax]/...)
+ },
+
+ STATUS: {
+ OK: 1, // file is loading or did load OK
+ ERROR: -1 // file timed out during load
+ },
+
+ //
+ // Return a complete URL to a file (replacing any root names)
+ //
+ fileURL: function (file) {
+ var match = file.match(/^\[([-._a-z0-9]+)\]/i);
+ if (match && match[1] in PATH)
+ {file = (PATH[match[1]]||this.config.root) + file.substr(match[1].length+2)}
+ return file;
+ },
+ //
+ // Replace root names if URL includes one
+ //
+ fileName: function (url) {
+ var root = this.config.root;
+ if (url.substr(0,root.length) === root) {url = "["+BASENAME+"]"+url.substr(root.length)}
+ else {
+ for (var id in PATH) {if (PATH.hasOwnProperty(id) && PATH[id]) {
+ if (url.substr(0,PATH[id].length) === PATH[id])
+ {url = "["+id+"]"+url.substr(PATH[id].length); break}
+ }}
+ }
+ return url;
+ },
+ //
+ // Cache-breaking revision number for file
+ //
+ fileRev: function (file) {
+ var rev = BASE.cdnFileVersions[name] || BASE.cdnVersion;
+ if (rev) {rev = "?rev="+rev}
+ return rev;
+ },
+ urlRev: function (file) {return this.fileURL(file)+this.fileRev(file)},
+
+ //
+ // Load a file if it hasn't been already.
+ // Make sure the file URL is "safe"?
+ //
+ Require: function (file,callback) {
+ callback = BASE.Callback(callback); var type;
+ if (file instanceof Object) {
+ for (var i in file)
+ {if (file.hasOwnProperty(i)) {type = i.toUpperCase(); file = file[i]}}
+ } else {type = file.split(/\./).pop().toUpperCase()}
+ file = this.fileURL(file);
+ // FIXME: check that URL is OK
+ if (this.loaded[file]) {
+ callback(this.loaded[file]);
+ } else {
+ var FILE = {}; FILE[type] = file;
+ this.Load(FILE,callback);
+ }
+ return callback;
+ },
+
+ //
+ // Load a file regardless of where it is and whether it has
+ // already been loaded.
+ //
+ Load: function (file,callback) {
+ callback = BASE.Callback(callback); var type;
+ if (file instanceof Object) {
+ for (var i in file)
+ {if (file.hasOwnProperty(i)) {type = i.toUpperCase(); file = file[i]}}
+ } else {type = file.split(/\./).pop().toUpperCase()}
+ file = this.fileURL(file);
+ if (this.loading[file]) {
+ this.addHook(file,callback);
+ } else {
+ this.head = HEAD(this.head);
+ if (this.loader[type]) {this.loader[type].call(this,file,callback)}
+ else {throw Error("Can't load files of type "+type)}
+ }
+ return callback;
+ },
+
+ //
+ // Register a load hook for a particular file (it will be called when
+ // loadComplete() is called for that file)
+ //
+ LoadHook: function (file,callback,priority) {
+ callback = BASE.Callback(callback);
+ if (file instanceof Object)
+ {for (var i in file) {if (file.hasOwnProperty(i)) {file = file[i]}}}
+ file = this.fileURL(file);
+ if (this.loaded[file]) {callback(this.loaded[file])}
+ else {this.addHook(file,callback,priority)}
+ return callback;
+ },
+ addHook: function (file,callback,priority) {
+ if (!this.loadHooks[file]) {this.loadHooks[file] = MathJax.Callback.Hooks()}
+ this.loadHooks[file].Add(callback,priority);
+ callback.file = file;
+ },
+ removeHook: function (hook) {
+ if (this.loadHooks[hook.file]) {
+ this.loadHooks[hook.file].Remove(hook);
+ if (!this.loadHooks[hook.file].hooks.length) {delete this.loadHooks[hook.file]}
+ }
+ },
+
+ //
+ // Used when files are combined in a preloading configuration file
+ //
+ Preloading: function () {
+ for (var i = 0, m = arguments.length; i < m; i++) {
+ var file = this.fileURL(arguments[i]);
+ if (!this.loading[file]) {this.loading[file] = {preloaded: true}}
+ }
+ },
+
+ //
+ // Code used to load the various types of files
+ // (JS for JavaScript, CSS for style sheets)
+ //
+ loader: {
+ //
+ // Create a SCRIPT tag to load the file
+ //
+ JS: function (file,callback) {
+ var name = this.fileName(file);
+ var script = document.createElement("script");
+ var timeout = BASE.Callback(["loadTimeout",this,file]);
+ this.loading[file] = {
+ callback: callback,
+ timeout: setTimeout(timeout,this.timeout),
+ status: this.STATUS.OK,
+ script: script
+ };
+ //
+ // Add this to the structure above after it is created to prevent recursion
+ // when loading the initial localization file (before loading messsage is available)
+ //
+ this.loading[file].message = BASE.Message.File(name);
+ script.onerror = timeout; // doesn't work in IE and no apparent substitute
+ script.type = "text/javascript";
+ script.src = file+this.fileRev(name);
+ this.head.appendChild(script);
+ },
+ //
+ // Create a LINK tag to load the style sheet
+ //
+ CSS: function (file,callback) {
+ var name = this.fileName(file);
+ var link = document.createElement("link");
+ link.rel = "stylesheet"; link.type = "text/css";
+ link.href = file+this.fileRev(name);
+ this.loading[file] = {
+ callback: callback,
+ message: BASE.Message.File(name),
+ status: this.STATUS.OK
+ };
+ this.head.appendChild(link);
+ this.timer.create.call(this,[this.timer.file,file],link);
+ }
+ },
+
+ //
+ // Timing code for checking when style sheets are available.
+ //
+ timer: {
+ //
+ // Create the timing callback and start the timing loop.
+ // We use a delay because some browsers need it to allow the styles
+ // to be processed.
+ //
+ create: function (callback,node) {
+ callback = BASE.Callback(callback);
+ if (node.nodeName === "STYLE" && node.styleSheet &&
+ typeof(node.styleSheet.cssText) !== 'undefined') {
+ callback(this.STATUS.OK); // MSIE processes style immediately, but doesn't set its styleSheet!
+ } else if (window.chrome && node.nodeName === "LINK") {
+ callback(this.STATUS.OK); // Chrome doesn't give access to cssRules for stylesheet in
+ // a link node, so we can't detect when it is loaded.
+ } else if (isSafari2) {
+ this.timer.start(this,[this.timer.checkSafari2,sheets++,callback],this.styleDelay);
+ } else {
+ this.timer.start(this,[this.timer.checkLength,node,callback],this.styleDelay);
+ }
+ return callback;
+ },
+ //
+ // Start the timer for the given callback checker
+ //
+ start: function (AJAX,check,delay,timeout) {
+ check = BASE.Callback(check);
+ check.execute = this.execute; check.time = this.time;
+ check.STATUS = AJAX.STATUS; check.timeout = timeout || AJAX.timeout;
+ check.delay = check.total = delay || 0;
+ if (delay) {setTimeout(check,delay)} else {check()}
+ },
+ //
+ // Increment the time total, increase the delay
+ // and test if we are past the timeout time.
+ //
+ time: function (callback) {
+ this.total += this.delay;
+ this.delay = Math.floor(this.delay * 1.05 + 5);
+ if (this.total >= this.timeout) {callback(this.STATUS.ERROR); return 1}
+ return 0;
+ },
+ //
+ // For JS file loads, call the proper routine according to status
+ //
+ file: function (file,status) {
+ if (status < 0) {BASE.Ajax.loadTimeout(file)} else {BASE.Ajax.loadComplete(file)}
+ },
+ //
+ // Call the hook with the required data
+ //
+ execute: function () {this.hook.call(this.object,this,this.data[0],this.data[1])},
+ //
+ // Safari2 doesn't set the link's stylesheet, so we need to look in the
+ // document.styleSheets array for the new sheet when it is created
+ //
+ checkSafari2: function (check,length,callback) {
+ if (check.time(callback)) return;
+ if (document.styleSheets.length > length &&
+ document.styleSheets[length].cssRules &&
+ document.styleSheets[length].cssRules.length)
+ {callback(check.STATUS.OK)} else {setTimeout(check,check.delay)}
+ },
+ //
+ // Look for the stylesheets rules and check when they are defined
+ // and no longer of length zero. (This assumes there actually ARE
+ // some rules in the stylesheet.)
+ //
+ checkLength: function (check,node,callback) {
+ if (check.time(callback)) return;
+ var isStyle = 0; var sheet = (node.sheet || node.styleSheet);
+ try {if ((sheet.cssRules||sheet.rules||[]).length > 0) {isStyle = 1}} catch(err) {
+ if (err.message.match(/protected variable|restricted URI/)) {isStyle = 1}
+ else if (err.message.match(/Security error/)) {
+ // Firefox3 gives "Security error" for missing files, so
+ // can't distinguish that from OK files on remote servers.
+ // or OK files in different directory from local files.
+ isStyle = 1; // just say it is OK (can't really tell)
+ }
+ }
+ if (isStyle) {
+ // Opera 9.6 requires this setTimeout
+ setTimeout(BASE.Callback([callback,check.STATUS.OK]),0);
+ } else {
+ setTimeout(check,check.delay);
+ }
+ }
+ },
+
+ //
+ // JavaScript code must call this when they are completely initialized
+ // (this allows them to perform asynchronous actions before indicating
+ // that they are complete).
+ //
+ loadComplete: function (file) {
+ file = this.fileURL(file);
+ var loading = this.loading[file];
+ if (loading && !loading.preloaded) {
+ BASE.Message.Clear(loading.message);
+ clearTimeout(loading.timeout);
+ if (loading.script) {
+ if (SCRIPTS.length === 0) {setTimeout(REMOVESCRIPTS,0)}
+ SCRIPTS.push(loading.script);
+ }
+ this.loaded[file] = loading.status; delete this.loading[file];
+ this.addHook(file,loading.callback);
+ } else {
+ if (loading) {delete this.loading[file]}
+ this.loaded[file] = this.STATUS.OK;
+ loading = {status: this.STATUS.OK}
+ }
+ if (!this.loadHooks[file]) {return null}
+ return this.loadHooks[file].Execute(loading.status);
+ },
+
+ //
+ // If a file fails to load within the timeout period (or the onerror handler
+ // is called), this routine runs to signal the error condition.
+ //
+ loadTimeout: function (file) {
+ if (this.loading[file].timeout) {clearTimeout(this.loading[file].timeout)}
+ this.loading[file].status = this.STATUS.ERROR;
+ this.loadError(file);
+ this.loadComplete(file);
+ },
+
+ //
+ // The default error hook for file load failures
+ //
+ loadError: function (file) {
+ BASE.Message.Set(["LoadFailed","File failed to load: %1",file],null,2000);
+ BASE.Hub.signal.Post(["file load error",file]);
+ },
+
+ //
+ // Defines a style sheet from a hash of style declarations (key:value pairs
+ // where the key is the style selector and the value is a hash of CSS attributes
+ // and values).
+ //
+ Styles: function (styles,callback) {
+ var styleString = this.StyleString(styles);
+ if (styleString === "") {
+ callback = BASE.Callback(callback);
+ callback();
+ } else {
+ var style = document.createElement("style"); style.type = "text/css";
+ this.head = HEAD(this.head);
+ this.head.appendChild(style);
+ if (style.styleSheet && typeof(style.styleSheet.cssText) !== 'undefined') {
+ style.styleSheet.cssText = styleString;
+ } else {
+ style.appendChild(document.createTextNode(styleString));
+ }
+ callback = this.timer.create.call(this,callback,style);
+ }
+ return callback;
+ },
+
+ //
+ // Create a stylesheet string from a style declaration object
+ //
+ StyleString: function (styles) {
+ if (typeof(styles) === 'string') {return styles}
+ var string = "", id, style;
+ for (id in styles) {if (styles.hasOwnProperty(id)) {
+ if (typeof styles[id] === 'string') {
+ string += id + " {"+styles[id]+"}\n";
+ } else if (styles[id] instanceof Array) {
+ for (var i = 0; i < styles[id].length; i++) {
+ style = {}; style[id] = styles[id][i];
+ string += this.StyleString(style);
+ }
+ } else if (id.substr(0,6) === '@media') {
+ string += id + " {"+this.StyleString(styles[id])+"}\n";
+ } else if (styles[id] != null) {
+ style = [];
+ for (var name in styles[id]) {if (styles[id].hasOwnProperty(name)) {
+ if (styles[id][name] != null)
+ {style[style.length] = name + ': ' + styles[id][name]}
+ }}
+ string += id +" {"+style.join('; ')+"}\n";
+ }
+ }}
+ return string;
+ }
+ };
+
+})("MathJax");
+
+/**********************************************************/
+
+MathJax.HTML = {
+ //
+ // Create an HTML element with given attributes and content.
+ // The def parameter is an (optional) object containing key:value pairs
+ // of the attributes and their values, and contents is an (optional)
+ // array of strings to be inserted as text, or arrays of the form
+ // [type,def,contents] that describes an HTML element to be inserted
+ // into the current element. Thus the contents can describe a complete
+ // HTML snippet of arbitrary complexity. E.g.:
+ //
+ // MathJax.HTML.Element("span",{id:"mySpan",style{"font-style":"italic"}},[
+ // "(See the ",["a",{href:"http://www.mathjax.org"},["MathJax home page"]],
+ // " for more details.)"]);
+ //
+ Element: function (type,def,contents) {
+ var obj = document.createElement(type), id;
+ if (def) {
+ if (def.hasOwnProperty("style")) {
+ var style = def.style; def.style = {};
+ for (id in style) {if (style.hasOwnProperty(id))
+ {def.style[id.replace(/-([a-z])/g,this.ucMatch)] = style[id]}}
+ }
+ MathJax.Hub.Insert(obj,def);
+ for (id in def) {
+ if (id === "role" || id.substr(0,5) === "aria-") obj.setAttribute(id,def[id]);
+ }
+ }
+ if (contents) {
+ if (!(contents instanceof Array)) {contents = [contents]}
+ for (var i = 0, m = contents.length; i < m; i++) {
+ if (contents[i] instanceof Array) {
+ obj.appendChild(this.Element(contents[i][0],contents[i][1],contents[i][2]));
+ } else if (type === "script") { // IE throws an error if script is added as a text node
+ this.setScript(obj, contents[i]);
+ } else {
+ obj.appendChild(document.createTextNode(contents[i]));
+ }
+ }
+ }
+ return obj;
+ },
+ ucMatch: function (match,c) {return c.toUpperCase()},
+ addElement: function (span,type,def,contents) {return span.appendChild(this.Element(type,def,contents))},
+ TextNode: function (text) {return document.createTextNode(text)},
+ addText: function (span,text) {return span.appendChild(this.TextNode(text))},
+
+ //
+ // Set and get the text of a script
+ //
+ setScript: function (script,text) {
+ if (this.setScriptBug) {script.text = text} else {
+ while (script.firstChild) {script.removeChild(script.firstChild)}
+ this.addText(script,text);
+ }
+ },
+ getScript: function (script) {
+ var text = (script.text === "" ? script.innerHTML : script.text);
+ return text.replace(/^\s+/,"").replace(/\s+$/,"");
+ },
+
+ //
+ // Manage cookies
+ //
+ Cookie: {
+ prefix: "mjx",
+ expires: 365,
+
+ //
+ // Save an object as a named cookie
+ //
+ Set: function (name,def) {
+ var keys = [];
+ if (def) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {
+ keys.push(id+":"+def[id].toString().replace(/&/g,"&&"));
+ }}
+ }
+ var cookie = this.prefix+"."+name+"="+escape(keys.join('&;'));
+ if (this.expires) {
+ var time = new Date(); time.setDate(time.getDate() + this.expires);
+ cookie += '; expires='+time.toGMTString();
+ }
+ try {document.cookie = cookie+"; path=/"} catch (err) {} // ignore errors saving cookies
+ },
+
+ //
+ // Get the contents of a named cookie and incorporate
+ // it into the given object (or return a fresh one)
+ //
+ Get: function (name,obj) {
+ if (!obj) {obj = {}}
+ var pattern = new RegExp("(?:^|;\\s*)"+this.prefix+"\\."+name+"=([^;]*)(?:;|$)");
+ var match;
+ try {match = pattern.exec(document.cookie)} catch (err) {}; // ignore errors reading cookies
+ if (match && match[1] !== "") {
+ var keys = unescape(match[1]).split('&;');
+ for (var i = 0, m = keys.length; i < m; i++) {
+ match = keys[i].match(/([^:]+):(.*)/);
+ var value = match[2].replace(/&&/g,'&');
+ if (value === "true") {value = true} else if (value === "false") {value = false}
+ else if (value.match(/^-?(\d+(\.\d+)?|\.\d+)$/)) {value = parseFloat(value)}
+ obj[match[1]] = value;
+ }
+ }
+ return obj;
+ }
+ }
+
+};
+
+
+/**********************************************************/
+
+MathJax.Localization = {
+
+ locale: "en",
+ directory: "[MathJax]/localization",
+ strings: {
+ // Currently, this list is not modified by the MathJax-i18n script. You can
+ // run the following command in MathJax/unpacked/localization to update it:
+ //
+ // find . -name "*.js" | xargs grep menuTitle\: | grep -v qqq | sed 's/^\.\/\(.*\)\/.*\.js\: / "\1"\: \{/' | sed 's/,$/\},/' | sed 's/"English"/"English", isLoaded: true/' > tmp ; sort tmp > tmp2 ; sed '$ s/,$//' tmp2 ; rm tmp*
+ //
+ // This only takes languages with localization data so you must also add
+ // the languages that use a remap but are not translated at all.
+ //
+ "ast": {menuTitle: "asturianu"},
+ "bg": {menuTitle: "\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438"},
+ "bcc": {menuTitle: "\u0628\u0644\u0648\u0686\u06CC"},
+ "br": {menuTitle: "brezhoneg"},
+ "ca": {menuTitle: "catal\u00E0"},
+ "cdo": {menuTitle: "M\u00ECng-d\u0115\u0324ng-ng\u1E73\u0304"},
+ "cs": {menuTitle: "\u010De\u0161tina"},
+ "da": {menuTitle: "dansk"},
+ "de": {menuTitle: "Deutsch"},
+ "en": {menuTitle: "English", isLoaded: true},
+ "eo": {menuTitle: "Esperanto"},
+ "es": {menuTitle: "espa\u00F1ol"},
+ "fa": {menuTitle: "\u0641\u0627\u0631\u0633\u06CC"},
+ "fi": {menuTitle: "suomi"},
+ "fr": {menuTitle: "fran\u00E7ais"},
+ "gl": {menuTitle: "galego"},
+ "he": {menuTitle: "\u05E2\u05D1\u05E8\u05D9\u05EA"},
+ "ia": {menuTitle: "interlingua"},
+ "it": {menuTitle: "italiano"},
+ "ja": {menuTitle: "\u65E5\u672C\u8A9E"},
+ "kn": {menuTitle: "\u0C95\u0CA8\u0CCD\u0CA8\u0CA1"},
+ "ko": {menuTitle: "\uD55C\uAD6D\uC5B4"},
+ "lb": {menuTitle: "L\u00EBtzebuergesch"},
+ "lt": {menuTitle: "lietuvi\u0173"},
+ "mk": {menuTitle: "\u043C\u0430\u043A\u0435\u0434\u043E\u043D\u0441\u043A\u0438"},
+ "nl": {menuTitle: "Nederlands"},
+ "oc": {menuTitle: "occitan"},
+ "pl": {menuTitle: "polski"},
+ "pt": {menuTitle: "portugus\u00EA"},
+ "pt-br": {menuTitle: "portugu\u00EAs do Brasil"},
+ "ru": {menuTitle: "\u0440\u0443\u0441\u0441\u043A\u0438\u0439"},
+ "sco": {menuTitle: "Scots"},
+ "scn": {menuTitle: "sicilianu"},
+ "sl": {menuTitle: "sloven\u0161\u010Dina"},
+ "sv": {menuTitle: "svenska"},
+ "tr": {menuTitle: "T\u00FCrk\u00E7e"},
+ "uk": {menuTitle: "\u0443\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"},
+ "vi": {menuTitle: "Ti\u1EBFng Vi\u1EC7t"},
+ "zh-hans": {menuTitle: "\u4E2D\u6587\uFF08\u7B80\u4F53\uFF09"}
+ },
+
+ //
+ // The pattern for substitution escapes:
+ // %n or %{n} or %{plural:%n|option1|option1|...} or %c
+ //
+ pattern: /%(\d+|\{\d+\}|\{[a-z]+:\%\d+(?:\|(?:%\{\d+\}|%.|[^\}])*)+\}|.)/g,
+
+ SPLIT: ("axb".split(/(x)/).length === 3 ?
+ function (string,regex) {return string.split(regex)} :
+ //
+ // IE8 and below don't do split() correctly when the pattern includes
+ // parentheses (the split should include the matched exrepssions).
+ // So implement it by hand here.
+ //
+ function (string,regex) {
+ var result = [], match, last = 0;
+ regex.lastIndex = 0;
+ while ((match = regex.exec(string))) {
+ result.push(string.substr(last,match.index-last));
+ result.push.apply(result,match.slice(1));
+ last = match.index + match[0].length;
+ }
+ result.push(string.substr(last));
+ return result;
+ }),
+
+ _: function (id,phrase) {
+ if (phrase instanceof Array) {return this.processSnippet(id,phrase)}
+ return this.processString(this.lookupPhrase(id,phrase),[].slice.call(arguments,2));
+ },
+
+ processString: function (string,args,domain) {
+ //
+ // Process arguments for substitution
+ // If the argument is a snippet (and we are processing snippets) do so,
+ // Otherwise, if it is a number, convert it for the lacale
+ //
+ var i, m;
+ for (i = 0, m = args.length; i < m; i++) {
+ if (domain && args[i] instanceof Array) {args[i] = this.processSnippet(domain,args[i])}
+ }
+ //
+ // Split string at escapes and process them individually
+ //
+ var parts = this.SPLIT(string,this.pattern);
+ for (i = 1, m = parts.length; i < m; i += 2) {
+ var c = parts[i].charAt(0); // first char will be { or \d or a char to be kept literally
+ if (c >= "0" && c <= "9") { // %n
+ parts[i] = args[parts[i]-1];
+ if (typeof parts[i] === "number") parts[i] = this.number(parts[i]);
+ } else if (c === "{") { // %{n} or %{plural:%n|...}
+ c = parts[i].substr(1);
+ if (c >= "0" && c <= "9") { // %{n}
+ parts[i] = args[parts[i].substr(1,parts[i].length-2)-1];
+ if (typeof parts[i] === "number") parts[i] = this.number(parts[i]);
+ } else { // %{plural:%n|...}
+ var match = parts[i].match(/^\{([a-z]+):%(\d+)\|(.*)\}$/);
+ if (match) {
+ if (match[1] === "plural") {
+ var n = args[match[2]-1];
+ if (typeof n === "undefined") {
+ parts[i] = "???"; // argument doesn't exist
+ } else {
+ n = this.plural(n) - 1; // index of the form to use
+ var plurals = match[3].replace(/(^|[^%])(%%)*%\|/g,"$1$2%\uEFEF").split(/\|/); // the parts (replacing %| with a special character)
+ if (n >= 0 && n < plurals.length) {
+ parts[i] = this.processString(plurals[n].replace(/\uEFEF/g,"|"),args,domain);
+ } else {
+ parts[i] = "???"; // no string for this index
+ }
+ }
+ } else {parts[i] = "%"+parts[i]} // not "plural", put back the % and leave unchanged
+ }
+ }
+ }
+ if (parts[i] == null) {parts[i] = "???"}
+ }
+ //
+ // If we are not forming a snippet, return the completed string
+ //
+ if (!domain) {return parts.join("")}
+ //
+ // We need to return an HTML snippet, so buld it from the
+ // broken up string with inserted parts (that could be snippets)
+ //
+ var snippet = [], part = "";
+ for (i = 0; i < m; i++) {
+ part += parts[i]; i++; // add the string and move on to substitution result
+ if (i < m) {
+ if (parts[i] instanceof Array) { // substitution was a snippet
+ snippet.push(part); // add the accumulated string
+ snippet = snippet.concat(parts[i]); // concatenate the substution snippet
+ part = ""; // start accumulating a new string
+ } else { // substitution was a string
+ part += parts[i]; // add to accumulating string
+ }
+ }
+ }
+ if (part !== "") {snippet.push(part)} // add final string
+ return snippet;
+ },
+
+ processSnippet: function (domain,snippet) {
+ var result = []; // the new snippet
+ //
+ // Look through the original snippet for
+ // strings or snippets to translate
+ //
+ for (var i = 0, m = snippet.length; i < m; i++) {
+ if (snippet[i] instanceof Array) {
+ //
+ // This could be a sub-snippet:
+ // ["tag"] or ["tag",{properties}] or ["tag",{properties},snippet]
+ // Or it could be something to translate:
+ // [id,string,args] or [domain,snippet]
+ var data = snippet[i];
+ if (typeof data[1] === "string") { // [id,string,args]
+ var id = data[0]; if (!(id instanceof Array)) {id = [domain,id]}
+ var phrase = this.lookupPhrase(id,data[1]);
+ result = result.concat(this.processMarkdown(phrase,data.slice(2),domain));
+ } else if (data[1] instanceof Array) { // [domain,snippet]
+ result = result.concat(this.processSnippet.apply(this,data));
+ } else if (data.length >= 3) { // ["tag",{properties},snippet]
+ result.push([data[0],data[1],this.processSnippet(domain,data[2])]);
+ } else { // ["tag"] or ["tag",{properties}]
+ result.push(snippet[i]);
+ }
+ } else { // a string
+ result.push(snippet[i]);
+ }
+ }
+ return result;
+ },
+
+ markdownPattern: /(%.)|(\*{1,3})((?:%.|.)+?)\2|(`+)((?:%.|.)+?)\4|\[((?:%.|.)+?)\]\(([^\s\)]+)\)/,
+ // %c or *bold*, **italics**, ***bold-italics***, or `code`, or [link](url)
+
+ processMarkdown: function (phrase,args,domain) {
+ var result = [], data;
+ //
+ // Split the string by the Markdown pattern
+ // (the text blocks are separated by
+ // c,stars,star-text,backtics,code-text,link-text,URL).
+ // Start with teh first text string from the split.
+ //
+ var parts = phrase.split(this.markdownPattern);
+ var string = parts[0];
+ //
+ // Loop through the matches and process them
+ //
+ for (var i = 1, m = parts.length; i < m; i += 8) {
+ if (parts[i+1]) { // stars (for bold/italic)
+ //
+ // Select the tag to use by number of stars (three stars requires two tags)
+ //
+ data = this.processString(parts[i+2],args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = [["b","i","i"][parts[i+1].length-1],{},data]; // number of stars determines type
+ if (parts[i+1].length === 3) {data = ["b",{},data]} // bold-italic
+ } else if (parts[i+3]) { // backtics (for code)
+ //
+ // Remove one leading or trailing space, and process substitutions
+ // Make a tag
+ //
+ data = this.processString(parts[i+4].replace(/^\s/,"").replace(/\s$/,""),args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = ["code",{},data];
+ } else if (parts[i+5]) { // hyperlink
+ //
+ // Process the link text, and make an tag with the URL
+ //
+ data = this.processString(parts[i+5],args,domain);
+ if (!(data instanceof Array)) {data = [data]}
+ data = ["a",{href:this.processString(parts[i+6],args),target:"_blank"},data];
+ } else {
+ //
+ // Escaped character (%c) gets added into the string.
+ //
+ string += parts[i]; data = null;
+ }
+ //
+ // If there is a tag to insert,
+ // Add any pending string, then push the tag
+ //
+ if (data) {
+ result = this.concatString(result,string,args,domain);
+ result.push(data); string = "";
+ }
+ //
+ // Process the string that follows matches pattern
+ //
+ if (parts[i+7] !== "") {string += parts[i+7]}
+ };
+ //
+ // Add any pending string and return the resulting snippet
+ //
+ result = this.concatString(result,string,args,domain);
+ return result;
+ },
+ concatString: function (result,string,args,domain) {
+ if (string != "") {
+ //
+ // Process the substutions.
+ // If the result is not a snippet, turn it into one.
+ // Then concatenate the snippet to the current one
+ //
+ string = this.processString(string,args,domain);
+ if (!(string instanceof Array)) {string = [string]}
+ result = result.concat(string);
+ }
+ return result;
+ },
+
+ lookupPhrase: function (id,phrase,domain) {
+ //
+ // Get the domain and messageID
+ //
+ if (!domain) {domain = "_"}
+ if (id instanceof Array) {domain = (id[0] || "_"); id = (id[1] || "")}
+ //
+ // Check if the data is available and if not,
+ // load it and throw a restart error so the calling
+ // code can wait for the load and try again.
+ //
+ var load = this.loadDomain(domain);
+ if (load) {MathJax.Hub.RestartAfter(load)}
+ //
+ // Look up the message in the localization data
+ // (if not found, the original English is used)
+ //
+ var localeData = this.strings[this.locale];
+ if (localeData) {
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (domainData.strings && id in domainData.strings)
+ {phrase = domainData.strings[id]}
+ }
+ }
+ //
+ // return the translated phrase
+ //
+ return phrase;
+ },
+
+ //
+ // Load a langauge data file from the proper
+ // directory and file.
+ //
+ loadFile: function (file,data,callback) {
+ callback = MathJax.Callback(callback);
+ file = (data.file || file); // the data's file name or the default name
+ if (!file.match(/\.js$/)) {file += ".js"} // add .js if needed
+ //
+ // Add the directory if the file doesn't
+ // contain a full URL already.
+ //
+ if (!file.match(/^([a-z]+:|\[MathJax\])/)) {
+ var dir = (this.strings[this.locale].directory ||
+ this.directory + "/" + this.locale ||
+ "[MathJax]/localization/" + this.locale);
+ file = dir + "/" + file;
+ }
+ //
+ // Load the file and mark the data as loaded (even if it
+ // failed to load, so we don't continue to try to load it
+ // over and over).
+ //
+ var load = MathJax.Ajax.Require(file,function () {data.isLoaded = true; return callback()});
+ //
+ // Return the callback if needed, otherwise null.
+ //
+ return (load.called ? null : load);
+ },
+
+ //
+ // Check to see if the localization data are loaded
+ // for the given domain; if not, load the data file,
+ // and return a callback for the loading operation.
+ // Otherwise return null (data are loaded).
+ //
+ loadDomain: function (domain,callback) {
+ var load, localeData = this.strings[this.locale];
+ if (localeData) {
+ if (!localeData.isLoaded) {
+ load = this.loadFile(this.locale,localeData);
+ if (load) {
+ return MathJax.Callback.Queue(
+ load,["loadDomain",this,domain] // call again to load domain
+ ).Push(callback||{});
+ }
+ }
+ if (localeData.domains && domain in localeData.domains) {
+ var domainData = localeData.domains[domain];
+ if (!domainData.isLoaded) {
+ load = this.loadFile(domain,domainData);
+ if (load) {return MathJax.Callback.Queue(load).Push(callback)}
+ }
+ }
+ }
+ // localization data are loaded, so just do the callback
+ return MathJax.Callback(callback)();
+ },
+
+ //
+ // Perform a function, properly handling
+ // restarts due to localization file loads.
+ //
+ // Note that this may return before the function
+ // has been called successfully, so you should
+ // consider fn as running asynchronously. (Callbacks
+ // can be used to synchronize it with other actions.)
+ //
+ Try: function (fn) {
+ fn = MathJax.Callback(fn); fn.autoReset = true;
+ try {fn()} catch (err) {
+ if (!err.restart) {throw err}
+ MathJax.Callback.After(["Try",this,fn],err.restart);
+ }
+ },
+
+ //
+ // Reset the current language
+ //
+ resetLocale: function(locale) {
+ // Selection algorithm:
+ // 1) Downcase locale name (e.g. "en-US" => "en-us")
+ // 2) Try a parent language (e.g. "en-us" => "en")
+ // 3) Try the fallback specified in the data (e.g. "pt" => "pt-br")
+ // 4) Otherwise don't change the locale.
+ if (!locale) return;
+ locale = locale.toLowerCase();
+ while (!this.strings[locale]) {
+ var dashPos = locale.lastIndexOf("-");
+ if (dashPos === -1) return;
+ locale = locale.substring(0, dashPos);
+ }
+ var remap = this.strings[locale].remap;
+ this.locale = remap ? remap : locale;
+ },
+
+ //
+ // Set the current language
+ //
+ setLocale: function(locale) {
+ this.resetLocale(locale);
+ if (MathJax.Menu) {this.loadDomain("MathMenu")}
+ },
+
+ //
+ // Add or update a language or domain
+ //
+ addTranslation: function (locale,domain,definition) {
+ var data = this.strings[locale], isNew = false;
+ if (!data) {data = this.strings[locale] = {}; isNew = true}
+ if (!data.domains) {data.domains = {}}
+ if (domain) {
+ if (!data.domains[domain]) {data.domains[domain] = {}}
+ data = data.domains[domain];
+ }
+ MathJax.Hub.Insert(data,definition);
+ if (isNew && MathJax.Menu.menu) {MathJax.Menu.CreateLocaleMenu()}
+ },
+
+ //
+ // Set CSS for an element based on font requirements
+ //
+ setCSS: function (div) {
+ var locale = this.strings[this.locale];
+ if (locale) {
+ if (locale.fontFamily) {div.style.fontFamily = locale.fontFamily}
+ if (locale.fontDirection) {
+ div.style.direction = locale.fontDirection;
+ if (locale.fontDirection === "rtl") {div.style.textAlign = "right"}
+ }
+ }
+ return div;
+ },
+
+ //
+ // Get the language's font family or direction
+ //
+ fontFamily: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontFamily : null);
+ },
+ fontDirection: function () {
+ var locale = this.strings[this.locale];
+ return (locale ? locale.fontDirection : null);
+ },
+
+ //
+ // Get the language's plural index for a number
+ //
+ plural: function (n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.plural) {return locale.plural(n)}
+ // default
+ if (n == 1) {return 1} // one
+ return 2; // other
+ },
+
+ //
+ // Convert a number to language-specific form
+ //
+ number: function(n) {
+ var locale = this.strings[this.locale];
+ if (locale && locale.number) {return locale.number(n)}
+ // default
+ return n;
+ }
+};
+
+
+/**********************************************************/
+
+MathJax.Message = {
+ ready: false, // used to tell when the styles are available
+ log: [{}], current: null,
+ textNodeBug: (navigator.vendor === "Apple Computer, Inc." &&
+ typeof navigator.vendorSub === "undefined") ||
+ (window.hasOwnProperty && window.hasOwnProperty("konqueror")), // Konqueror displays some gibberish with text.nodeValue = "..."
+
+ styles: {
+ "#MathJax_Message": {
+ position: "fixed", left: "1px", bottom: "2px",
+ 'background-color': "#E6E6E6", border: "1px solid #959595",
+ margin: "0px", padding: "2px 8px",
+ 'z-index': "102", color: "black", 'font-size': "80%",
+ width: "auto", 'white-space': "nowrap"
+ },
+
+ "#MathJax_MSIE_Frame": {
+ position: "absolute",
+ top:0, left: 0, width: "0px", 'z-index': 101,
+ border: "0px", margin: "0px", padding: "0px"
+ }
+ },
+
+ browsers: {
+ MSIE: function (browser) {
+ MathJax.Message.msieFixedPositionBug = ((document.documentMode||0) < 7);
+ if (MathJax.Message.msieFixedPositionBug)
+ {MathJax.Hub.config.styles["#MathJax_Message"].position = "absolute"}
+ MathJax.Message.quirks = (document.compatMode === "BackCompat");
+ },
+ Chrome: function (browser) {
+ MathJax.Hub.config.styles["#MathJax_Message"].bottom = "1.5em";
+ MathJax.Hub.config.styles["#MathJax_Message"].left = "1em";
+ }
+ },
+
+ Init: function (styles) {
+ if (styles) {this.ready = true}
+ if (!document.body || !this.ready) {return false}
+ //
+ // ASCIIMathML replaces the entire page with a copy of itself (@#!#%@!!)
+ // so check that this.div is still part of the page, otherwise look up
+ // the copy and use that.
+ //
+ if (this.div && this.div.parentNode == null) {
+ this.div = document.getElementById("MathJax_Message");
+ if (this.div) {this.text = this.div.firstChild}
+ }
+ if (!this.div) {
+ var frame = document.body;
+ if (this.msieFixedPositionBug && window.attachEvent) {
+ frame = this.frame = this.addDiv(document.body); frame.removeAttribute("id");
+ frame.style.position = "absolute";
+ frame.style.border = frame.style.margin = frame.style.padding = "0px";
+ frame.style.zIndex = "101"; frame.style.height = "0px";
+ frame = this.addDiv(frame);
+ frame.id = "MathJax_MSIE_Frame";
+ window.attachEvent("onscroll",this.MoveFrame);
+ window.attachEvent("onresize",this.MoveFrame);
+ this.MoveFrame();
+ }
+ this.div = this.addDiv(frame); this.div.style.display = "none";
+ this.text = this.div.appendChild(document.createTextNode(""));
+ }
+ return true;
+ },
+
+ addDiv: function (parent) {
+ var div = document.createElement("div");
+ div.id = "MathJax_Message";
+ if (parent.firstChild) {parent.insertBefore(div,parent.firstChild)}
+ else {parent.appendChild(div)}
+ return div;
+ },
+
+ MoveFrame: function () {
+ var body = (MathJax.Message.quirks ? document.body : document.documentElement);
+ var frame = MathJax.Message.frame;
+ frame.style.left = body.scrollLeft + 'px';
+ frame.style.top = body.scrollTop + 'px';
+ frame.style.width = body.clientWidth + 'px';
+ frame = frame.firstChild;
+ frame.style.height = body.clientHeight + 'px';
+ },
+
+ localize: function (message) {
+ return MathJax.Localization._(message,message);
+ },
+
+ filterText: function (text,n,id) {
+ if (MathJax.Hub.config.messageStyle === "simple") {
+ if (id === "LoadFile") {
+ if (!this.loading) {this.loading = this.localize("Loading") + " "}
+ text = this.loading; this.loading += ".";
+ } else if (id === "ProcessMath") {
+ if (!this.processing) {this.processing = this.localize("Processing") + " "}
+ text = this.processing; this.processing += ".";
+ } else if (id === "TypesetMath") {
+ if (!this.typesetting) {this.typesetting = this.localize("Typesetting") + " "}
+ text = this.typesetting; this.typesetting += ".";
+ }
+ }
+ return text;
+ },
+
+ Set: function (text,n,clearDelay) {
+ if (n == null) {n = this.log.length; this.log[n] = {}}
+ //
+ // Translate message if it is [id,message,arguments]
+ //
+ var id = "";
+ if (text instanceof Array) {
+ id = text[0]; if (id instanceof Array) {id = id[1]}
+ //
+ // Localization._() will throw a restart error if a localization file
+ // needs to be loaded, so trap that and redo the Set() call
+ // after it is loaded.
+ //
+ try {
+ text = MathJax.Localization._.apply(MathJax.Localization,text);
+ } catch (err) {
+ if (!err.restart) {throw err}
+ if (!err.restart.called) {
+ //
+ // Mark it so we can tell if the Clear() comes before the message is displayed
+ //
+ if (this.log[n].restarted == null) {this.log[n].restarted = 0}
+ this.log[n].restarted++; delete this.log[n].cleared;
+ MathJax.Callback.After(["Set",this,text,n,clearDelay],err.restart);
+ return n;
+ }
+ }
+ }
+ //
+ // Clear the timout timer.
+ //
+ if (this.timer) {clearTimeout(this.timer); delete this.timer}
+ //
+ // Save the message and filtered message.
+ //
+ this.log[n].text = text; this.log[n].filteredText = text = this.filterText(text,n,id);
+ //
+ // Hook the message into the message list so we can tell
+ // what message to put up when this one is removed.
+ //
+ if (typeof(this.log[n].next) === "undefined") {
+ this.log[n].next = this.current;
+ if (this.current != null) {this.log[this.current].prev = n}
+ this.current = n;
+ }
+ //
+ // Show the message if it is the currently active one.
+ //
+ if (this.current === n && MathJax.Hub.config.messageStyle !== "none") {
+ if (this.Init()) {
+ if (this.textNodeBug) {this.div.innerHTML = text} else {this.text.nodeValue = text}
+ this.div.style.display = "";
+ if (this.status) {window.status = ""; delete this.status}
+ } else {
+ window.status = text;
+ this.status = true;
+ }
+ }
+ //
+ // Check if the message was resetarted to load a localization file
+ // and if it has been cleared in the meanwhile.
+ //
+ if (this.log[n].restarted) {
+ if (this.log[n].cleared) {clearDelay = 0}
+ if (--this.log[n].restarted === 0) {delete this.log[n].cleared}
+ }
+ //
+ // Check if we need to clear the message automatically.
+ //
+ if (clearDelay) {setTimeout(MathJax.Callback(["Clear",this,n]),clearDelay)}
+ else if (clearDelay == 0) {this.Clear(n,0)}
+ //
+ // Return the message number.
+ //
+ return n;
+ },
+
+ Clear: function (n,delay) {
+ //
+ // Detatch the message from the active list.
+ //
+ if (this.log[n].prev != null) {this.log[this.log[n].prev].next = this.log[n].next}
+ if (this.log[n].next != null) {this.log[this.log[n].next].prev = this.log[n].prev}
+ //
+ // If it is the current message, get the next one to show.
+ //
+ if (this.current === n) {
+ this.current = this.log[n].next;
+ if (this.text) {
+ if (this.div.parentNode == null) {this.Init()} // see ASCIIMathML comments above
+ if (this.current == null) {
+ //
+ // If there are no more messages, remove the message box.
+ //
+ if (this.timer) {clearTimeout(this.timer); delete this.timer}
+ if (delay == null) {delay = 600}
+ if (delay === 0) {this.Remove()}
+ else {this.timer = setTimeout(MathJax.Callback(["Remove",this]),delay)}
+ } else if (MathJax.Hub.config.messageStyle !== "none") {
+ //
+ // If there is an old message, put it in place
+ //
+ if (this.textNodeBug) {this.div.innerHTML = this.log[this.current].filteredText}
+ else {this.text.nodeValue = this.log[this.current].filteredText}
+ }
+ if (this.status) {window.status = ""; delete this.status}
+ } else if (this.status) {
+ window.status = (this.current == null ? "" : this.log[this.current].text);
+ }
+ }
+ //
+ // Clean up the log data no longer needed
+ //
+ delete this.log[n].next; delete this.log[n].prev;
+ delete this.log[n].filteredText;
+ //
+ // If this is a restarted localization message, mark that it has been cleared
+ // while waiting for the file to load.
+ //
+ if (this.log[n].restarted) {this.log[n].cleared = true}
+ },
+
+ Remove: function () {
+ // FIXME: do a fade out or something else interesting?
+ this.text.nodeValue = "";
+ this.div.style.display = "none";
+ },
+
+ File: function (file) {
+ return this.Set(["LoadFile","Loading %1",file],null,null);
+ },
+
+ Log: function () {
+ var strings = [];
+ for (var i = 1, m = this.log.length; i < m; i++) {strings[i] = this.log[i].text}
+ return strings.join("\n");
+ }
+
+};
+
+/**********************************************************/
+
+MathJax.Hub = {
+ config: {
+ root: "",
+ config: [], // list of configuration files to load
+ styleSheets: [], // list of CSS files to load
+ styles: { // styles to generate in-line
+ ".MathJax_Preview": {color: "#888"}
+ },
+ jax: [], // list of input and output jax to load
+ extensions: [], // list of extensions to load
+ preJax: null, // pattern to remove from before math script tag
+ postJax: null, // pattern to remove from after math script tag
+ displayAlign: 'center', // how to align displayed equations (left, center, right)
+ displayIndent: '0', // indentation for displayed equations (when not centered)
+ preRemoveClass: 'MathJax_Preview', // class of objects to remove preceeding math script
+ showProcessingMessages: true, // display "Processing math: nn%" messages or not
+ messageStyle: "normal", // set to "none" or "simple" (for "Loading..." and "Processing...")
+ delayStartupUntil: "none", // set to "onload" to delay setup until the onload handler runs
+ // set to "configured" to delay startup until MathJax.Hub.Configured() is called
+ // set to a Callback to wait for before continuing with the startup
+ skipStartupTypeset: false, // set to true to skip PreProcess and Process during startup
+ elements: [], // array of elements to process when none is given explicitly
+ positionToHash: true, // after initial typeset pass, position to #hash location?
+
+ showMathMenu: true, // attach math context menu to typeset math?
+ showMathMenuMSIE: true, // separtely determine if MSIE should have math menu
+ // (since the code for that is a bit delicate)
+
+ menuSettings: {
+ zoom: "None", // when to do MathZoom
+ CTRL: false, // require CTRL for MathZoom?
+ ALT: false, // require Alt or Option?
+ CMD: false, // require CMD?
+ Shift: false, // require Shift?
+ discoverable: false, // make math menu discoverable on hover?
+ zscale: "200%", // the scaling factor for MathZoom
+ renderer: null, // set when Jax are loaded
+ font: "Auto", // what font HTML-CSS should use
+ context: "MathJax", // or "Browser" for pass-through to browser menu
+ locale: null, // the language to use for messages
+ mpContext: false, // true means pass menu events to MathPlayer in IE
+ mpMouse: false, // true means pass mouse events to MathPlayer in IE
+ texHints: true, // include class names for TeXAtom elements
+ FastPreview: null, // use PreviewHTML output as preview?
+ assistiveMML: null, // include hidden MathML for screen readers?
+ inTabOrder: true, // set to false if math elements should be included in the tabindex
+ semantics: false // add semantics tag with original form in MathML output
+ },
+
+ errorSettings: {
+ // localized HTML snippet structure for message to use
+ message: ["[",["MathProcessingError","Math Processing Error"],"]"],
+ style: {color: "#CC0000", "font-style":"italic"} // style for message
+ },
+
+ ignoreMMLattributes: {} // attributes not to copy to HTML-CSS or SVG output
+ // from MathML input (in addition to the ones in MML.nocopyAttributes).
+ // An id set to true will be ignored, one set to false will
+ // be allowed (even if other criteria normally would prevent
+ // it from being copied); use false carefully!
+ },
+
+ preProcessors: MathJax.Callback.Hooks(true), // list of callbacks for preprocessing (initialized by extensions)
+ inputJax: {}, // mime-type mapped to input jax (by registration)
+ outputJax: {order:{}}, // mime-type mapped to output jax list (by registration)
+
+ processSectionDelay: 50, // pause between input and output phases of processing
+ processUpdateTime: 250, // time between screen updates when processing math (milliseconds)
+ processUpdateDelay: 10, // pause between screen updates to allow other processing (milliseconds)
+
+ signal: MathJax.Callback.Signal("Hub"), // Signal used for Hub events
+
+ Config: function (def) {
+ this.Insert(this.config,def);
+ if (this.config.Augment) {this.Augment(this.config.Augment)}
+ },
+ CombineConfig: function (name,def) {
+ var config = this.config, id, parent; name = name.split(/\./);
+ for (var i = 0, m = name.length; i < m; i++) {
+ id = name[i]; if (!config[id]) {config[id] = {}}
+ parent = config; config = config[id];
+ }
+ parent[id] = config = this.Insert(def,config);
+ return config;
+ },
+
+ Register: {
+ PreProcessor: function () {return MathJax.Hub.preProcessors.Add.apply(MathJax.Hub.preProcessors,arguments)},
+ MessageHook: function () {return MathJax.Hub.signal.MessageHook.apply(MathJax.Hub.signal,arguments)},
+ StartupHook: function () {return MathJax.Hub.Startup.signal.MessageHook.apply(MathJax.Hub.Startup.signal,arguments)},
+ LoadHook: function () {return MathJax.Ajax.LoadHook.apply(MathJax.Ajax,arguments)}
+ },
+ UnRegister: {
+ PreProcessor: function (hook) {MathJax.Hub.preProcessors.Remove(hook)},
+ MessageHook: function (hook) {MathJax.Hub.signal.RemoveHook(hook)},
+ StartupHook: function (hook) {MathJax.Hub.Startup.signal.RemoveHook(hook)},
+ LoadHook: function (hook) {MathJax.Ajax.removeHook(hook)}
+ },
+
+ getAllJax: function (element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxByType: function (type,element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
+ scripts[i].MathJax.elementJax.mimeType === type)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxByInputType: function (type,element) {
+ var jax = [], scripts = this.elementScripts(element);
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ if (scripts[i].MathJax && scripts[i].MathJax.elementJax &&
+ scripts[i].type && scripts[i].type.replace(/ *;(.|\s)*/,"") === type)
+ {jax.push(scripts[i].MathJax.elementJax)}
+ }
+ return jax;
+ },
+
+ getJaxFor: function (element) {
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (element && element.MathJax) {return element.MathJax.elementJax}
+ if (this.isMathJaxNode(element)) {
+ if (!element.isMathJax) {element = element.firstChild} // for NativeMML output
+ while (element && !element.jaxID) {element = element.parentNode}
+ if (element) {return MathJax.OutputJax[element.jaxID].getJaxFromMath(element)}
+ }
+ return null;
+ },
+
+ isJax: function (element) {
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (this.isMathJaxNode(element)) {return 1}
+ if (element && (element.tagName||"").toLowerCase() === 'script') {
+ if (element.MathJax)
+ {return (element.MathJax.state === MathJax.ElementJax.STATE.PROCESSED ? 1 : -1)}
+ if (element.type && this.inputJax[element.type.replace(/ *;(.|\s)*/,"")]) {return -1}
+ }
+ return 0;
+ },
+ isMathJaxNode: function (element) {
+ return !!element && (element.isMathJax || (element.className||"") === "MathJax_MathML");
+ },
+
+ setRenderer: function (renderer,type) {
+ if (!renderer) return;
+ if (!MathJax.OutputJax[renderer]) {
+ this.config.menuSettings.renderer = "";
+ var file = "[MathJax]/jax/output/"+renderer+"/config.js";
+ return MathJax.Ajax.Require(file,["setRenderer",this,renderer,type]);
+ } else {
+ this.config.menuSettings.renderer = renderer;
+ if (type == null) {type = "jax/mml"}
+ var jax = this.outputJax;
+ if (jax[type] && jax[type].length) {
+ if (renderer !== jax[type][0].id) {
+ jax[type].unshift(MathJax.OutputJax[renderer]);
+ return this.signal.Post(["Renderer Selected",renderer]);
+ }
+ }
+ return null;
+ }
+ },
+
+ Queue: function () {
+ return this.queue.Push.apply(this.queue,arguments);
+ },
+
+ Typeset: function (element,callback) {
+ if (!MathJax.isReady) return null;
+ var ec = this.elementCallback(element,callback);
+ if (ec.count) {
+ var queue = MathJax.Callback.Queue(
+ ["PreProcess",this,ec.elements],
+ ["Process",this,ec.elements]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ PreProcess: function (element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var queue = MathJax.Callback.Queue();
+ if (ec.count) {
+ var elements = (ec.count === 1 ? [ec.elements] : ec.elements);
+ queue.Push(["Post",this.signal,["Begin PreProcess",ec.elements]]);
+ for (var i = 0, m = elements.length; i < m; i++) {
+ if (elements[i]) {queue.Push(["Execute",this.preProcessors,elements[i]])}
+ }
+ queue.Push(["Post",this.signal,["End PreProcess",ec.elements]]);
+ }
+ return queue.Push(ec.callback);
+ },
+
+ Process: function (element,callback) {return this.takeAction("Process",element,callback)},
+ Update: function (element,callback) {return this.takeAction("Update",element,callback)},
+ Reprocess: function (element,callback) {return this.takeAction("Reprocess",element,callback)},
+ Rerender: function (element,callback) {return this.takeAction("Rerender",element,callback)},
+
+ takeAction: function (action,element,callback) {
+ var ec = this.elementCallback(element,callback);
+ var elements = ec.elements;
+ var queue = MathJax.Callback.Queue(["Clear",this.signal]);
+ var state = {
+ scripts: [], // filled in by prepareScripts
+ start: new Date().getTime(), // timer for processing messages
+ i: 0, j: 0, // current script, current jax
+ jax: {}, // scripts grouped by output jax
+ jaxIDs: [] // id's of jax used
+ };
+ if (ec.count) {
+ var delay = ["Delay",MathJax.Callback,this.processSectionDelay];
+ if (!delay[2]) {delay = {}}
+ queue.Push(
+ ["Post",this.signal,["Begin "+action,elements]],
+ ["Post",this.signal,["Begin Math",elements,action]],
+ ["prepareScripts",this,action,elements,state],
+ ["Post",this.signal,["Begin Math Input",elements,action]],
+ ["processInput",this,state],
+ ["Post",this.signal,["End Math Input",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"preProcess"],
+ delay,
+ ["Post",this.signal,["Begin Math Output",elements,action]],
+ ["processOutput",this,state],
+ ["Post",this.signal,["End Math Output",elements,action]],
+ delay,
+ ["prepareOutput",this,state,"postProcess"],
+ delay,
+ ["Post",this.signal,["End Math",elements,action]],
+ ["Post",this.signal,["End "+action,elements]]
+ );
+ }
+ return queue.Push(ec.callback);
+ },
+
+ scriptAction: {
+ Process: function (script) {},
+ Update: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax && jax.needsUpdate()) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ else {script.MathJax.state = jax.STATE.PROCESSED}
+ },
+ Reprocess: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.UPDATE}
+ },
+ Rerender: function (script) {
+ var jax = script.MathJax.elementJax;
+ if (jax) {jax.Remove(true); script.MathJax.state = jax.STATE.OUTPUT}
+ }
+ },
+
+ prepareScripts: function (action,element,state) {
+ if (arguments.callee.disabled) return;
+ var scripts = this.elementScripts(element);
+ var STATE = MathJax.ElementJax.STATE;
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var script = scripts[i];
+ if (script.type && this.inputJax[script.type.replace(/ *;(.|\n)*/,"")]) {
+ if (script.MathJax) {
+ if (script.MathJax.elementJax && script.MathJax.elementJax.hover) {
+ MathJax.Extension.MathEvents.Hover.ClearHover(script.MathJax.elementJax);
+ }
+ if (script.MathJax.state !== STATE.PENDING) {this.scriptAction[action](script)}
+ }
+ if (!script.MathJax) {script.MathJax = {state: STATE.PENDING}}
+ if (script.MathJax.error) delete script.MathJax.error;
+ if (script.MathJax.state !== STATE.PROCESSED) {state.scripts.push(script)}
+ }
+ }
+ },
+
+ checkScriptSiblings: function (script) {
+ if (script.MathJax.checked) return;
+ var config = this.config, pre = script.previousSibling;
+ if (pre && pre.nodeName === "#text") {
+ var preJax,postJax, post = script.nextSibling;
+ if (post && post.nodeName !== "#text") {post = null}
+ if (config.preJax) {
+ if (typeof(config.preJax) === "string") {config.preJax = new RegExp(config.preJax+"$")}
+ preJax = pre.nodeValue.match(config.preJax);
+ }
+ if (config.postJax && post) {
+ if (typeof(config.postJax) === "string") {config.postJax = new RegExp("^"+config.postJax)}
+ postJax = post.nodeValue.match(config.postJax);
+ }
+ if (preJax && (!config.postJax || postJax)) {
+ pre.nodeValue = pre.nodeValue.replace
+ (config.preJax,(preJax.length > 1? preJax[1] : ""));
+ pre = null;
+ }
+ if (postJax && (!config.preJax || preJax)) {
+ post.nodeValue = post.nodeValue.replace
+ (config.postJax,(postJax.length > 1? postJax[1] : ""));
+ }
+ if (pre && !pre.nodeValue.match(/\S/)) {pre = pre.previousSibling}
+ }
+ if (config.preRemoveClass && pre && pre.className === config.preRemoveClass)
+ {script.MathJax.preview = pre}
+ script.MathJax.checked = 1;
+ },
+
+ processInput: function (state) {
+ var jax, STATE = MathJax.ElementJax.STATE;
+ var script, prev, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ script = state.scripts[state.i]; if (!script) {state.i++; continue}
+ //
+ // Remove previous error marker, if any
+ //
+ prev = script.previousSibling;
+ if (prev && prev.className === "MathJax_Error") {prev.parentNode.removeChild(prev)}
+ //
+ // Check if already processed or needs processing
+ //
+ if (!script.MathJax || script.MathJax.state === STATE.PROCESSED) {state.i++; continue};
+ if (!script.MathJax.elementJax || script.MathJax.state === STATE.UPDATE) {
+ this.checkScriptSiblings(script); // remove preJax/postJax etc.
+ var type = script.type.replace(/ *;(.|\s)*/,""); // the input jax type
+ var input = this.inputJax[type]; // the input jax itself
+ jax = input.Process(script,state); // run the input jax
+ if (typeof jax === 'function') { // if a callback was returned
+ if (jax.called) continue; // go back and call Process() again
+ this.RestartAfter(jax); // wait for the callback
+ }
+ jax = jax.Attach(script,input.id); // register the jax on the script
+ this.saveScript(jax,state,script,STATE); // add script to state
+ this.postInputHooks.Execute(jax,input.id,script); // run global jax filters
+ } else if (script.MathJax.state === STATE.OUTPUT) {
+ this.saveScript(script.MathJax.elementJax,state,script,STATE); // add script to state
+ }
+ //
+ // Go on to the next script, and check if we need to update the processing message
+ //
+ state.i++; var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(1))}
+ }
+ } catch (err) {return this.processError(err,state,"Input")}
+ //
+ // Put up final message, reset the state and return
+ //
+ if (state.scripts.length && this.config.showProcessingMessages)
+ {MathJax.Message.Set(["ProcessMath","Processing math: %1%%",100],0)}
+ state.start = new Date().getTime(); state.i = state.j = 0;
+ return null;
+ },
+ postInputHooks: MathJax.Callback.Hooks(true), // hooks to run after element jax is created
+ saveScript: function (jax,state,script,STATE) {
+ //
+ // Check that output jax exists
+ //
+ if (!this.outputJax[jax.mimeType]) {
+ script.MathJax.state = STATE.UPDATE;
+ throw Error("No output jax registered for "+jax.mimeType);
+ }
+ //
+ // Record the output jax
+ // and put this script in the queue for that jax
+ //
+ jax.outputJax = this.outputJax[jax.mimeType][0].id;
+ if (!state.jax[jax.outputJax]) {
+ if (state.jaxIDs.length === 0) {
+ // use original array until we know there are more (rather than two copies)
+ state.jax[jax.outputJax] = state.scripts;
+ } else {
+ if (state.jaxIDs.length === 1) // get the script so far for the existing jax
+ {state.jax[state.jaxIDs[0]] = state.scripts.slice(0,state.i)}
+ state.jax[jax.outputJax] = []; // start a new array for the new jax
+ }
+ state.jaxIDs.push(jax.outputJax); // save the ID of the jax
+ }
+ if (state.jaxIDs.length > 1) {state.jax[jax.outputJax].push(script)}
+ //
+ // Mark script as needing output
+ //
+ script.MathJax.state = STATE.OUTPUT;
+ },
+
+ //
+ // Pre- and post-process scripts by jax
+ // (to get scaling factors, hide/show output, and so on)
+ // Since this can cause the jax to load, we need to trap restarts
+ //
+ prepareOutput: function (state,method) {
+ while (state.j < state.jaxIDs.length) {
+ var id = state.jaxIDs[state.j], JAX = MathJax.OutputJax[id];
+ if (JAX[method]) {
+ try {
+ var result = JAX[method](state);
+ if (typeof result === 'function') {
+ if (result.called) continue; // go back and try again
+ this.RestartAfter(result);
+ }
+ } catch (err) {
+ if (!err.restart) {
+ MathJax.Message.Set(["PrepError","Error preparing %1 output (%2)",id,method],null,600);
+ MathJax.Hub.lastPrepError = err;
+ state.j++;
+ }
+ return MathJax.Callback.After(["prepareOutput",this,state,method],err.restart);
+ }
+ }
+ state.j++;
+ }
+ return null;
+ },
+
+ processOutput: function (state) {
+ var result, STATE = MathJax.ElementJax.STATE, script, m = state.scripts.length;
+ try {
+ //
+ // Loop through the scripts
+ //
+ while (state.i < m) {
+ //
+ // Check that there is an element jax
+ //
+ script = state.scripts[state.i];
+ if (!script || !script.MathJax || script.MathJax.error) {state.i++; continue}
+ var jax = script.MathJax.elementJax; if (!jax) {state.i++; continue}
+ //
+ // Call the output Jax's Process method (which will be its Translate()
+ // method once loaded). Mark it as complete and remove the preview unless
+ // the Process() call returns an explicit false value (in which case, it will
+ // handle this later during the postProcess phase, as HTML-CSS does).
+ //
+ result = MathJax.OutputJax[jax.outputJax].Process(script,state);
+ if (result !== false) {
+ script.MathJax.state = STATE.PROCESSED;
+ if (script.MathJax.preview) {script.MathJax.preview.innerHTML = ""}
+ //
+ // Signal that new math is available
+ //
+ this.signal.Post(["New Math",jax.inputID]); // FIXME: wait for this? (i.e., restart if returns uncalled callback)
+ }
+ //
+ // Go on to next math expression
+ //
+ state.i++;
+ //
+ // Update the processing message, if needed
+ //
+ var now = new Date().getTime();
+ if (now - state.start > this.processUpdateTime && state.i < state.scripts.length)
+ {state.start = now; this.RestartAfter(MathJax.Callback.Delay(this.processUpdateDelay))}
+ }
+ } catch (err) {return this.processError(err,state,"Output")}
+ //
+ // Put up the typesetting-complete message
+ //
+ if (state.scripts.length && this.config.showProcessingMessages) {
+ MathJax.Message.Set(["TypesetMath","Typesetting math: %1%%",100],0);
+ MathJax.Message.Clear(0);
+ }
+ state.i = state.j = 0;
+ return null;
+ },
+
+ processMessage: function (state,type) {
+ var m = Math.floor(state.i/(state.scripts.length)*100);
+ var message = (type === "Output" ? ["TypesetMath","Typesetting math: %1%%"] :
+ ["ProcessMath","Processing math: %1%%"]);
+ if (this.config.showProcessingMessages) {MathJax.Message.Set(message.concat(m),0)}
+ },
+
+ processError: function (err,state,type) {
+ if (!err.restart) {
+ if (!this.config.errorSettings.message) {throw err}
+ this.formatError(state.scripts[state.i],err); state.i++;
+ }
+ this.processMessage(state,type);
+ return MathJax.Callback.After(["process"+type,this,state],err.restart);
+ },
+
+ formatError: function (script,err) {
+ var LOCALIZE = function (id,text,arg1,arg2) {return MathJax.Localization._(id,text,arg1,arg2)};
+ //
+ // Get the error message, URL, and line, and save it for
+ // reporting in the Show Math As Error menu
+ //
+ var message = LOCALIZE("ErrorMessage","Error: %1",err.message)+"\n";
+ if (err.sourceURL||err.fileName) message += "\n"+LOCALIZE("ErrorFile","file: %1",err.sourceURL||err.fileName);
+ if (err.line||err.lineNumber) message += "\n"+LOCALIZE("ErrorLine","line: %1",err.line||err.lineNumber);
+ message += "\n\n"+LOCALIZE("ErrorTips","Debugging tips: use %1, inspect %2 in the browser console","'unpacked/MathJax.js'","'MathJax.Hub.lastError'");
+ script.MathJax.error = MathJax.OutputJax.Error.Jax(message,script);
+ if (script.MathJax.elementJax)
+ script.MathJax.error.inputID = script.MathJax.elementJax.inputID;
+ //
+ // Create the [Math Processing Error] span
+ //
+ var errorSettings = this.config.errorSettings;
+ var errorText = LOCALIZE(errorSettings.messageId,errorSettings.message);
+ var error = MathJax.HTML.Element("span", {
+ className:"MathJax_Error", jaxID:"Error", isMathJax:true,
+ id: script.MathJax.error.inputID+"-Frame"
+ },[["span",null,errorText]]);
+ //
+ // Attach the menu events
+ //
+ MathJax.Ajax.Require("[MathJax]/extensions/MathEvents.js",function () {
+ var EVENT = MathJax.Extension.MathEvents.Event,
+ HUB = MathJax.Hub;
+ error.oncontextmenu = EVENT.Menu;
+ error.onmousedown = EVENT.Mousedown;
+ error.onkeydown = EVENT.Keydown;
+ error.tabIndex = HUB.getTabOrder(HUB.getJaxFor(script));
+ });
+ //
+ // Insert the error into the page and remove any preview
+ //
+ var node = document.getElementById(error.id);
+ if (node) node.parentNode.removeChild(node);
+ script.parentNode.insertBefore(error,script);
+ if (script.MathJax.preview) {script.MathJax.preview.innerHTML = ""}
+ //
+ // Save the error for debugging purposes
+ // Report the error as a signal
+ //
+ this.lastError = err;
+ this.signal.Post(["Math Processing Error",script,err]);
+ },
+
+ RestartAfter: function (callback) {
+ throw this.Insert(Error("restart"),{restart: MathJax.Callback(callback)});
+ },
+
+ elementCallback: function (element,callback) {
+ if (callback == null && (element instanceof Array || typeof element === 'function'))
+ {try {MathJax.Callback(element); callback = element; element = null} catch(e) {}}
+ if (element == null) {element = this.config.elements || []}
+ if (this.isHTMLCollection(element)) {element = this.HTMLCollection2Array(element)}
+ if (!(element instanceof Array)) {element = [element]}
+ element = [].concat(element); // make a copy so the original isn't changed
+ for (var i = 0, m = element.length; i < m; i++)
+ {if (typeof(element[i]) === 'string') {element[i] = document.getElementById(element[i])}}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element.length == 0) {element.push(document.body)}
+ if (!callback) {callback = {}}
+ return {
+ count: element.length,
+ elements: (element.length === 1 ? element[0] : element),
+ callback: callback
+ };
+ },
+
+ elementScripts: function (element) {
+ var scripts = [];
+ if (element instanceof Array || this.isHTMLCollection(element)) {
+ for (var i = 0, m = element.length; i < m; i++) {
+ var alreadyDone = 0;
+ for (var j = 0; j < i && !alreadyDone; j++)
+ {alreadyDone = element[j].contains(element[i])}
+ if (!alreadyDone) scripts.push.apply(scripts,this.elementScripts(element[i]));
+ }
+ return scripts;
+ }
+ if (typeof(element) === 'string') {element = document.getElementById(element)}
+ if (!document.body) {document.body = document.getElementsByTagName("body")[0]}
+ if (element == null) {element = document.body}
+ if (element.tagName != null && element.tagName.toLowerCase() === "script") {return [element]}
+ scripts = element.getElementsByTagName("script");
+ if (this.msieHTMLCollectionBug) {scripts = this.HTMLCollection2Array(scripts)}
+ return scripts;
+ },
+
+ //
+ // IE8 fails to check "obj instanceof HTMLCollection" for some values of obj.
+ //
+ isHTMLCollection: function (obj) {
+ return ("HTMLCollection" in window && typeof(obj) === "object" && obj instanceof HTMLCollection);
+ },
+ //
+ // IE8 doesn't deal with HTMLCollection as an array, so convert to array
+ //
+ HTMLCollection2Array: function (nodes) {
+ if (!this.msieHTMLCollectionBug) {return [].slice.call(nodes)}
+ var NODES = [];
+ for (var i = 0, m = nodes.length; i < m; i++) {NODES[i] = nodes[i]}
+ return NODES;
+ },
+
+ Insert: function (dst,src) {
+ for (var id in src) {if (src.hasOwnProperty(id)) {
+ // allow for concatenation of arrays?
+ if (typeof src[id] === 'object' && !(src[id] instanceof Array) &&
+ (typeof dst[id] === 'object' || typeof dst[id] === 'function')) {
+ this.Insert(dst[id],src[id]);
+ } else {
+ dst[id] = src[id];
+ }
+ }}
+ return dst;
+ },
+
+ getTabOrder: function(script) {
+ return this.config.menuSettings.inTabOrder ? 0 : -1;
+ },
+
+ // Old browsers (e.g. Internet Explorer <= 8) do not support trim().
+ SplitList: ("trim" in String.prototype ?
+ function (list) {return list.trim().split(/\s+/)} :
+ function (list) {return list.replace(/^\s+/,'').
+ replace(/\s+$/,'').split(/\s+/)})
+};
+MathJax.Hub.Insert(MathJax.Hub.config.styles,MathJax.Message.styles);
+MathJax.Hub.Insert(MathJax.Hub.config.styles,{".MathJax_Error":MathJax.Hub.config.errorSettings.style});
+
+//
+// Storage area for extensions and preprocessors
+//
+MathJax.Extension = {};
+
+//
+// Hub Startup code
+//
+MathJax.Hub.Configured = MathJax.Callback({}); // called when configuration is complete
+MathJax.Hub.Startup = {
+ script: "", // the startup script from the SCRIPT call that loads MathJax.js
+ queue: MathJax.Callback.Queue(), // Queue used for startup actions
+ signal: MathJax.Callback.Signal("Startup"), // Signal used for startup events
+ params: {},
+
+ //
+ // Load the configuration files
+ //
+ Config: function () {
+ this.queue.Push(["Post",this.signal,"Begin Config"]);
+ //
+ // If a locale is given as a parameter,
+ // set the locale and the default menu value for the locale
+ //
+ if (this.params.locale) {
+ MathJax.Localization.resetLocale(this.params.locale);
+ MathJax.Hub.config.menuSettings.locale = this.params.locale;
+ }
+ //
+ // Run the config files, if any are given in the parameter list
+ //
+ if (this.params.config) {
+ var files = this.params.config.split(/,/);
+ for (var i = 0, m = files.length; i < m; i++) {
+ if (!files[i].match(/\.js$/)) {files[i] += ".js"}
+ this.queue.Push(["Require",MathJax.Ajax,this.URL("config",files[i])]);
+ }
+ }
+ //
+ // Perform author configuration from in-line MathJax = {...}
+ //
+ this.queue.Push(["Config",MathJax.Hub,MathJax.AuthorConfig]);
+ //
+ // Run the deprecated configuration script, if any (ignoring return value)
+ // Wait for the startup delay signal
+ // Run the mathjax-config blocks
+ // Load the files in the configuration's config array
+ //
+ if (this.script.match(/\S/)) {this.queue.Push(this.script+";\n1;")}
+ this.queue.Push(
+ ["ConfigDelay",this],
+ ["ConfigBlocks",this],
+ [function (THIS) {return THIS.loadArray(MathJax.Hub.config.config,"config",null,true)},this],
+ ["Post",this.signal,"End Config"]
+ );
+ },
+ //
+ // Return the delay callback
+ //
+ ConfigDelay: function () {
+ var delay = this.params.delayStartupUntil || MathJax.Hub.config.delayStartupUntil;
+ if (delay === "onload") {return this.onload}
+ if (delay === "configured") {return MathJax.Hub.Configured}
+ return delay;
+ },
+ //
+ // Run the scripts of type=text/x-mathjax-config
+ //
+ ConfigBlocks: function () {
+ var scripts = document.getElementsByTagName("script");
+ var last = null, queue = MathJax.Callback.Queue();
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var type = String(scripts[i].type).replace(/ /g,"");
+ if (type.match(/^text\/x-mathjax-config(;.*)?$/) && !type.match(/;executed=true/)) {
+ scripts[i].type += ";executed=true";
+ last = queue.Push(scripts[i].innerHTML+";\n1;");
+ }
+ }
+ return last;
+ },
+
+ //
+ // Read cookie and set up menu defaults
+ // (set the locale according to the cookie)
+ // (adjust the jax to accommodate renderer preferences)
+ //
+ Cookie: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Cookie"],
+ ["Get",MathJax.HTML.Cookie,"menu",MathJax.Hub.config.menuSettings],
+ [function (config) {
+ var SETTINGS = config.menuSettings;
+ if (SETTINGS.locale) MathJax.Localization.resetLocale(SETTINGS.locale);
+ var renderer = config.menuSettings.renderer, jax = config.jax;
+ if (renderer) {
+ var name = "output/"+renderer; jax.sort();
+ for (var i = 0, m = jax.length; i < m; i++) {
+ if (jax[i].substr(0,7) === "output/") break;
+ }
+ if (i == m-1) {jax.pop()} else {
+ while (i < m) {if (jax[i] === name) {jax.splice(i,1); break}; i++}
+ }
+ jax.unshift(name);
+ }
+ if (SETTINGS.CHTMLpreview != null) {
+ if (SETTINGS.FastPreview == null) SETTINGS.FastPreview = SETTINGS.CHTMLpreview;
+ delete SETTINGS.CHTMLpreview;
+ }
+ if (SETTINGS.FastPreview && !MathJax.Extension["fast-preview"])
+ MathJax.Hub.config.extensions.push("fast-preview.js");
+ if (config.menuSettings.assistiveMML && !MathJax.Extension.AssistiveMML)
+ MathJax.Hub.config.extensions.push("AssistiveMML.js");
+ },MathJax.Hub.config],
+ ["Post",this.signal,"End Cookie"]
+ );
+ },
+ //
+ // Setup stylesheets and extra styles
+ //
+ Styles: function () {
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Styles"],
+ ["loadArray",this,MathJax.Hub.config.styleSheets,"config"],
+ ["Styles",MathJax.Ajax,MathJax.Hub.config.styles],
+ ["Post",this.signal,"End Styles"]
+ );
+ },
+ //
+ // Load the input and output jax
+ //
+ Jax: function () {
+ var config = MathJax.Hub.config, jax = MathJax.Hub.outputJax;
+ // Save the order of the output jax since they are loading asynchronously
+ for (var i = 0, m = config.jax.length, k = 0; i < m; i++) {
+ var name = config.jax[i].substr(7);
+ if (config.jax[i].substr(0,7) === "output/" && jax.order[name] == null)
+ {jax.order[name] = k; k++}
+ }
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Jax"],
+ ["loadArray",this,config.jax,"jax","config.js"],
+ ["Post",this.signal,"End Jax"]
+ );
+ },
+ //
+ // Load the extensions
+ //
+ Extensions: function () {
+ var queue = MathJax.Callback.Queue();
+ return queue.Push(
+ ["Post",this.signal,"Begin Extensions"],
+ ["loadArray",this,MathJax.Hub.config.extensions,"extensions"],
+ ["Post",this.signal,"End Extensions"]
+ );
+ },
+
+ //
+ // Initialize the Message system
+ //
+ Message: function () {
+ MathJax.Message.Init(true);
+ },
+
+ //
+ // Set the math menu renderer, if it isn't already
+ // (this must come after the jax are loaded)
+ //
+ Menu: function () {
+ var menu = MathJax.Hub.config.menuSettings, jax = MathJax.Hub.outputJax, registered;
+ for (var id in jax) {if (jax.hasOwnProperty(id)) {
+ if (jax[id].length) {registered = jax[id]; break}
+ }}
+ if (registered && registered.length) {
+ if (menu.renderer && menu.renderer !== registered[0].id)
+ {registered.unshift(MathJax.OutputJax[menu.renderer])}
+ menu.renderer = registered[0].id;
+ }
+ },
+
+ //
+ // Set the location to the designated hash position
+ //
+ Hash: function () {
+ if (MathJax.Hub.config.positionToHash && document.location.hash &&
+ document.body && document.body.scrollIntoView) {
+ var name = document.location.hash.substr(1);
+ var target = document.getElementById(name);
+ if (!target) {
+ var a = document.getElementsByTagName("a");
+ for (var i = 0, m = a.length; i < m; i++)
+ {if (a[i].name === name) {target = a[i]; break}}
+ }
+ if (target) {
+ while (!target.scrollIntoView) {target = target.parentNode}
+ target = this.HashCheck(target);
+ if (target && target.scrollIntoView)
+ {setTimeout(function () {target.scrollIntoView(true)},1)}
+ }
+ }
+ },
+ HashCheck: function (target) {
+ var jax = MathJax.Hub.getJaxFor(target);
+ if (jax && MathJax.OutputJax[jax.outputJax].hashCheck)
+ {target = MathJax.OutputJax[jax.outputJax].hashCheck(target)}
+ return target;
+ },
+
+ //
+ // Load the Menu and Zoom code, if it hasn't already been loaded.
+ // This is called after the initial typeset, so should no longer be
+ // competing with other page loads, but will make these available
+ // if needed later on.
+ //
+ MenuZoom: function () {
+ if (MathJax.Hub.config.showMathMenu) {
+ if (!MathJax.Extension.MathMenu) {
+ setTimeout(
+ function () {
+ MathJax.Callback.Queue(
+ ["Require",MathJax.Ajax,"[MathJax]/extensions/MathMenu.js",{}],
+ ["loadDomain",MathJax.Localization,"MathMenu"]
+ )
+ },1000
+ );
+ } else {
+ setTimeout(
+ MathJax.Callback(["loadDomain",MathJax.Localization,"MathMenu"]),
+ 1000
+ );
+ }
+ if (!MathJax.Extension.MathZoom) {
+ setTimeout(
+ MathJax.Callback(["Require",MathJax.Ajax,"[MathJax]/extensions/MathZoom.js",{}]),
+ 2000
+ );
+ }
+ }
+ },
+
+ //
+ // Setup the onload callback
+ //
+ onLoad: function () {
+ var onload = this.onload =
+ MathJax.Callback(function () {MathJax.Hub.Startup.signal.Post("onLoad")});
+ if (document.body && document.readyState)
+ if (MathJax.Hub.Browser.isMSIE) {
+ // IE can change from loading to interactive before
+ // full page is ready, so go with complete (even though
+ // that means we may have to wait longer).
+ if (document.readyState === "complete") {return [onload]}
+ } else if (document.readyState !== "loading") {return [onload]}
+ if (window.addEventListener) {
+ window.addEventListener("load",onload,false);
+ if (!this.params.noDOMContentEvent)
+ {window.addEventListener("DOMContentLoaded",onload,false)}
+ }
+ else if (window.attachEvent) {window.attachEvent("onload",onload)}
+ else {window.onload = onload}
+ return onload;
+ },
+
+ //
+ // Perform the initial typesetting (or skip if configuration says to)
+ //
+ Typeset: function (element,callback) {
+ if (MathJax.Hub.config.skipStartupTypeset) {return function () {}}
+ return this.queue.Push(
+ ["Post",this.signal,"Begin Typeset"],
+ ["Typeset",MathJax.Hub,element,callback],
+ ["Post",this.signal,"End Typeset"]
+ );
+ },
+
+ //
+ // Create a URL in the MathJax hierarchy
+ //
+ URL: function (dir,name) {
+ if (!name.match(/^([a-z]+:\/\/|\[|\/)/)) {name = "[MathJax]/"+dir+"/"+name}
+ return name;
+ },
+
+ //
+ // Load an array of files, waiting for all of them
+ // to be loaded before going on
+ //
+ loadArray: function (files,dir,name,synchronous) {
+ if (files) {
+ if (!(files instanceof Array)) {files = [files]}
+ if (files.length) {
+ var queue = MathJax.Callback.Queue(), callback = {}, file;
+ for (var i = 0, m = files.length; i < m; i++) {
+ file = this.URL(dir,files[i]);
+ if (name) {file += "/" + name}
+ if (synchronous) {queue.Push(["Require",MathJax.Ajax,file,callback])}
+ else {queue.Push(MathJax.Ajax.Require(file,callback))}
+ }
+ return queue.Push({}); // wait for everything to finish
+ }
+ }
+ return null;
+ }
+
+};
+
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME], ROOT = "["+BASENAME+"]";
+ var HUB = BASE.Hub, AJAX = BASE.Ajax, CALLBACK = BASE.Callback;
+
+ var JAX = MathJax.Object.Subclass({
+ JAXFILE: "jax.js",
+ require: null, // array of files to load before jax.js is complete
+ config: {},
+ //
+ // Make a subclass and return an instance of it.
+ // (FIXME: should we replace config with a copy of the constructor's
+ // config? Otherwise all subclasses share the same config structure.)
+ //
+ Init: function (def,cdef) {
+ if (arguments.length === 0) {return this}
+ return (this.constructor.Subclass(def,cdef))();
+ },
+ //
+ // Augment by merging with class definition (not replacing)
+ //
+ Augment: function (def,cdef) {
+ var cObject = this.constructor, ndef = {};
+ if (def != null) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {
+ if (typeof def[id] === "function")
+ {cObject.protoFunction(id,def[id])} else {ndef[id] = def[id]}
+ }}
+ // MSIE doesn't list toString even if it is not native so handle it separately
+ if (def.toString !== cObject.prototype.toString && def.toString !== {}.toString)
+ {cObject.protoFunction('toString',def.toString)}
+ }
+ HUB.Insert(cObject.prototype,ndef);
+ cObject.Augment(null,cdef);
+ return this;
+ },
+ Translate: function (script,state) {
+ throw Error(this.directory+"/"+this.JAXFILE+" failed to define the Translate() method");
+ },
+ Register: function (mimetype) {},
+ Config: function () {
+ this.config = HUB.CombineConfig(this.id,this.config);
+ if (this.config.Augment) {this.Augment(this.config.Augment)}
+ },
+ Startup: function () {},
+ loadComplete: function (file) {
+ if (file === "config.js") {
+ return AJAX.loadComplete(this.directory+"/"+file);
+ } else {
+ var queue = CALLBACK.Queue();
+ queue.Push(
+ HUB.Register.StartupHook("End Config",{}), // wait until config complete
+ ["Post",HUB.Startup.signal,this.id+" Jax Config"],
+ ["Config",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Require"],
+ // Config may set the required and extensions array,
+ // so use functions to delay making the reference until needed
+ [function (THIS) {return MathJax.Hub.Startup.loadArray(THIS.require,this.directory)},this],
+ [function (config,id) {return MathJax.Hub.Startup.loadArray(config.extensions,"extensions/"+id)},this.config||{},this.id],
+ ["Post",HUB.Startup.signal,this.id+" Jax Startup"],
+ ["Startup",this],
+ ["Post",HUB.Startup.signal,this.id+" Jax Ready"]
+ );
+ if (this.copyTranslate) {
+ queue.Push(
+ [function (THIS) {
+ THIS.preProcess = THIS.preTranslate;
+ THIS.Process = THIS.Translate;
+ THIS.postProcess = THIS.postTranslate;
+ },this.constructor.prototype]
+ );
+ }
+ return queue.Push(["loadComplete",AJAX,this.directory+"/"+file]);
+ }
+ }
+ },{
+ id: "Jax",
+ version: "2.6.0",
+ directory: ROOT+"/jax",
+ extensionDir: ROOT+"/extensions"
+ });
+
+ /***********************************/
+
+ BASE.InputJax = JAX.Subclass({
+ elementJax: "mml", // the element jax to load for this input jax
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"],
+ copyTranslate: true,
+ Process: function (script,state) {
+ var queue = CALLBACK.Queue(), file;
+ // Load any needed element jax
+ var jax = this.elementJax; if (!(jax instanceof Array)) {jax = [jax]}
+ for (var i = 0, m = jax.length; i < m; i++) {
+ file = BASE.ElementJax.directory+"/"+jax[i]+"/"+this.JAXFILE;
+ if (!this.require) {this.require = []}
+ else if (!(this.require instanceof Array)) {this.require = [this.require]};
+ this.require.push(file); // so Startup will wait for it to be loaded
+ queue.Push(AJAX.Require(file));
+ }
+ // Load the input jax
+ file = this.directory+"/"+this.JAXFILE;
+ var load = queue.Push(AJAX.Require(file));
+ if (!load.called) {
+ this.constructor.prototype.Process = function () {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ }
+ // Load the associated output jax
+ jax = HUB.outputJax["jax/"+jax[0]];
+ if (jax) {queue.Push(AJAX.Require(jax[0].directory+"/"+this.JAXFILE))}
+ return queue.Push({});
+ },
+ needsUpdate: function (jax) {
+ var script = jax.SourceElement();
+ return (jax.originalText !== BASE.HTML.getScript(script));
+ },
+ Register: function (mimetype) {
+ if (!HUB.inputJax) {HUB.inputJax = {}}
+ HUB.inputJax[mimetype] = this;
+ }
+ },{
+ id: "InputJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/input",
+ extensionDir: JAX.extensionDir
+ });
+
+ /***********************************/
+
+ BASE.OutputJax = JAX.Subclass({
+ copyTranslate: true,
+ preProcess: function (state) {
+ var load, file = this.directory+"/"+this.JAXFILE;
+ this.constructor.prototype.preProcess = function (state) {
+ if (!load.called) {return load}
+ throw Error(file+" failed to load properly");
+ }
+ load = AJAX.Require(file);
+ return load;
+ },
+ Register: function (mimetype) {
+ var jax = HUB.outputJax;
+ if (!jax[mimetype]) {jax[mimetype] = []}
+ // If the output jax is earlier in the original configuration list, put it first here
+ if (jax[mimetype].length && (this.id === HUB.config.menuSettings.renderer ||
+ (jax.order[this.id]||0) < (jax.order[jax[mimetype][0].id]||0)))
+ {jax[mimetype].unshift(this)} else {jax[mimetype].push(this)}
+ // Make sure the element jax is loaded before Startup is called
+ if (!this.require) {this.require = []}
+ else if (!(this.require instanceof Array)) {this.require = [this.require]};
+ this.require.push(BASE.ElementJax.directory+"/"+(mimetype.split(/\//)[1])+"/"+this.JAXFILE);
+ },
+ Remove: function (jax) {}
+ },{
+ id: "OutputJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/output",
+ extensionDir: JAX.extensionDir,
+ fontDir: ROOT+(BASE.isPacked?"":"/..")+"/fonts",
+ imageDir: ROOT+(BASE.isPacked?"":"/..")+"/images"
+ });
+
+ /***********************************/
+
+ BASE.ElementJax = JAX.Subclass({
+ // make a subclass, not an instance
+ Init: function (def,cdef) {return this.constructor.Subclass(def,cdef)},
+
+ inputJax: null,
+ outputJax: null,
+ inputID: null,
+ originalText: "",
+ mimeType: "",
+ sourceMenuTitle: /*_(MathMenu)*/ ["MathMLcode","MathML Code"],
+
+ Text: function (text,callback) {
+ var script = this.SourceElement();
+ BASE.HTML.setScript(script,text);
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Update(script,callback);
+ },
+ Reprocess: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.UPDATE;
+ return HUB.Reprocess(script,callback);
+ },
+ Update: function (callback) {return this.Rerender(callback)},
+ Rerender: function (callback) {
+ var script = this.SourceElement();
+ script.MathJax.state = this.STATE.OUTPUT;
+ return HUB.Process(script,callback);
+ },
+ Remove: function (keep) {
+ if (this.hover) {this.hover.clear(this)}
+ BASE.OutputJax[this.outputJax].Remove(this);
+ if (!keep) {
+ HUB.signal.Post(["Remove Math",this.inputID]); // wait for this to finish?
+ this.Detach();
+ }
+ },
+ needsUpdate: function () {
+ return BASE.InputJax[this.inputJax].needsUpdate(this);
+ },
+
+ SourceElement: function () {return document.getElementById(this.inputID)},
+
+ Attach: function (script,inputJax) {
+ var jax = script.MathJax.elementJax;
+ if (script.MathJax.state === this.STATE.UPDATE) {
+ jax.Clone(this);
+ } else {
+ jax = script.MathJax.elementJax = this;
+ if (script.id) {this.inputID = script.id}
+ else {script.id = this.inputID = BASE.ElementJax.GetID(); this.newID = 1}
+ }
+ jax.originalText = BASE.HTML.getScript(script);
+ jax.inputJax = inputJax;
+ if (jax.root) {jax.root.inputID = jax.inputID}
+ return jax;
+ },
+ Detach: function () {
+ var script = this.SourceElement(); if (!script) return;
+ try {delete script.MathJax} catch(err) {script.MathJax = null}
+ if (this.newID) {script.id = ""}
+ },
+ Clone: function (jax) {
+ var id;
+ for (id in this) {
+ if (!this.hasOwnProperty(id)) continue;
+ if (typeof(jax[id]) === 'undefined' && id !== 'newID') {delete this[id]}
+ }
+ for (id in jax) {
+ if (!jax.hasOwnProperty(id)) continue;
+ if (typeof(this[id]) === 'undefined' || (this[id] !== jax[id] && id !== 'inputID'))
+ {this[id] = jax[id]}
+ }
+ }
+ },{
+ id: "ElementJax",
+ version: "2.6.0",
+ directory: JAX.directory+"/element",
+ extensionDir: JAX.extensionDir,
+ ID: 0, // jax counter (for IDs)
+ STATE: {
+ PENDING: 1, // script is identified as math but not yet processed
+ PROCESSED: 2, // script has been processed
+ UPDATE: 3, // elementJax should be updated
+ OUTPUT: 4 // output should be updated (input is OK)
+ },
+
+ GetID: function () {this.ID++; return "MathJax-Element-"+this.ID},
+ Subclass: function () {
+ var obj = JAX.Subclass.apply(this,arguments);
+ obj.loadComplete = this.prototype.loadComplete;
+ return obj;
+ }
+ });
+ BASE.ElementJax.prototype.STATE = BASE.ElementJax.STATE;
+
+ //
+ // Some "Fake" jax used to allow menu access for "Math Processing Error" messages
+ //
+ BASE.OutputJax.Error = {
+ id: "Error", version: "2.6.0", config: {}, errors: 0,
+ ContextMenu: function () {return BASE.Extension.MathEvents.Event.ContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ Mousedown: function () {return BASE.Extension.MathEvents.Event.AltContextMenu.apply(BASE.Extension.MathEvents.Event,arguments)},
+ getJaxFromMath: function (math) {return (math.nextSibling.MathJax||{}).error},
+ Jax: function (text,script) {
+ var jax = MathJax.Hub.inputJax[script.type.replace(/ *;(.|\s)*/,"")];
+ this.errors++;
+ return {
+ inputJax: (jax||{id:"Error"}).id, // Use Error InputJax as fallback
+ outputJax: "Error",
+ inputID: "MathJax-Error-"+this.errors,
+ sourceMenuTitle: /*_(MathMenu)*/ ["ErrorMessage","Error Message"],
+ sourceMenuFormat: "Error",
+ originalText: MathJax.HTML.getScript(script),
+ errorText: text
+ }
+ }
+ };
+ BASE.InputJax.Error = {
+ id: "Error", version: "2.6.0", config: {},
+ sourceMenuTitle: /*_(MathMenu)*/ ["Original","Original Form"]
+ };
+
+})("MathJax");
+
+/**********************************************************/
+
+(function (BASENAME) {
+ var BASE = window[BASENAME];
+ if (!BASE) {BASE = window[BASENAME] = {}}
+
+ var HUB = BASE.Hub; var STARTUP = HUB.Startup; var CONFIG = HUB.config;
+ var HEAD = document.head || (document.getElementsByTagName("head")[0]);
+ if (!HEAD) {HEAD = document.childNodes[0]};
+ var scripts = (document.documentElement || document).getElementsByTagName("script");
+ if (scripts.length === 0 && HEAD.namespaceURI)
+ scripts = document.getElementsByTagNameNS(HEAD.namespaceURI,"script");
+ var namePattern = new RegExp("(^|/)"+BASENAME+"\\.js(\\?.*)?$");
+ for (var i = scripts.length-1; i >= 0; i--) {
+ if ((scripts[i].src||"").match(namePattern)) {
+ STARTUP.script = scripts[i].innerHTML;
+ if (RegExp.$2) {
+ var params = RegExp.$2.substr(1).split(/\&/);
+ for (var j = 0, m = params.length; j < m; j++) {
+ var KV = params[j].match(/(.*)=(.*)/);
+ if (KV) {STARTUP.params[unescape(KV[1])] = unescape(KV[2])}
+ }
+ }
+ CONFIG.root = scripts[i].src.replace(/(^|\/)[^\/]*(\?.*)?$/,'')
+ // convert mathjax/latest to mathjax/x.y-latest so that all files are the same version
+ .replace(/^(https?:\/\/cdn.mathjax.org\/mathjax\/)(latest)/,"$1"+BASE.version.split(/\./).slice(0,2).join(".")+"-$2");
+ BASE.Ajax.config.root = CONFIG.root;
+ break;
+ }
+ }
+
+ var AGENT = navigator.userAgent;
+ var BROWSERS = {
+ isMac: (navigator.platform.substr(0,3) === "Mac"),
+ isPC: (navigator.platform.substr(0,3) === "Win"),
+ isMSIE: ("ActiveXObject" in window && "clipboardData" in window),
+ isEdge: ("MSGestureEvent" in window && "chrome" in window &&
+ window.chrome.loadTimes == null),
+ isFirefox: (!!AGENT.match(/Gecko\//) && !AGENT.match(/like Gecko/)),
+ isSafari: (!!AGENT.match(/ (Apple)?WebKit\//) && !AGENT.match(/ like iPhone /) &&
+ (!window.chrome || window.chrome.app == null)),
+ isChrome: ("chrome" in window && window.chrome.loadTimes != null),
+ isOpera: ("opera" in window && window.opera.version != null),
+ isKonqueror: ("konqueror" in window && navigator.vendor == "KDE"),
+ versionAtLeast: function (v) {
+ var bv = (this.version).split('.'); v = (new String(v)).split('.');
+ for (var i = 0, m = v.length; i < m; i++)
+ {if (bv[i] != v[i]) {return parseInt(bv[i]||"0") >= parseInt(v[i])}}
+ return true;
+ },
+ Select: function (choices) {
+ var browser = choices[HUB.Browser];
+ if (browser) {return browser(HUB.Browser)}
+ return null;
+ }
+ };
+
+ var xAGENT = AGENT
+ .replace(/^Mozilla\/(\d+\.)+\d+ /,"") // remove initial Mozilla, which is never right
+ .replace(/[a-z][-a-z0-9._: ]+\/\d+[^ ]*-[^ ]*\.([a-z][a-z])?\d+ /i,"") // remove linux version
+ .replace(/Gentoo |Ubuntu\/(\d+\.)*\d+ (\([^)]*\) )?/,""); // special case for these
+
+ HUB.Browser = HUB.Insert(HUB.Insert(new String("Unknown"),{version: "0.0"}),BROWSERS);
+ for (var browser in BROWSERS) {if (BROWSERS.hasOwnProperty(browser)) {
+ if (BROWSERS[browser] && browser.substr(0,2) === "is") {
+ browser = browser.slice(2);
+ if (browser === "Mac" || browser === "PC") continue;
+ HUB.Browser = HUB.Insert(new String(browser),BROWSERS);
+ var VERSION = new RegExp(
+ ".*(Version/| Trident/.*; rv:)((?:\\d+\\.)+\\d+)|" + // for Safari, Opera10, and IE11+
+ ".*("+browser+")"+(browser == "MSIE" ? " " : "/")+"((?:\\d+\\.)*\\d+)|"+ // for one of the main browsers
+ "(?:^|\\(| )([a-z][-a-z0-9._: ]+|(?:Apple)?WebKit)/((?:\\d+\\.)+\\d+)"); // for unrecognized browser
+ var MATCH = VERSION.exec(xAGENT) || ["","","","unknown","0.0"];
+ HUB.Browser.name = (MATCH[1] != "" ? browser : (MATCH[3] || MATCH[5]));
+ HUB.Browser.version = MATCH[2] || MATCH[4] || MATCH[6];
+ break;
+ }
+ }};
+
+ //
+ // Initial browser-specific info (e.g., touch up version or name, check for MathPlayer, etc.)
+ // Wrap in try/catch just in case of error (see issue #1155).
+ //
+ try {HUB.Browser.Select({
+ Safari: function (browser) {
+ var v = parseInt((String(browser.version).split("."))[0]);
+ if (v > 85) {browser.webkit = browser.version}
+ if (v >= 538) {browser.version = "8.0"}
+ else if (v >= 537) {browser.version = "7.0"}
+ else if (v >= 536) {browser.version = "6.0"}
+ else if (v >= 534) {browser.version = "5.1"}
+ else if (v >= 533) {browser.version = "5.0"}
+ else if (v >= 526) {browser.version = "4.0"}
+ else if (v >= 525) {browser.version = "3.1"}
+ else if (v > 500) {browser.version = "3.0"}
+ else if (v > 400) {browser.version = "2.0"}
+ else if (v > 85) {browser.version = "1.0"}
+ browser.webkit = (navigator.appVersion.match(/WebKit\/(\d+)\./))[1];
+ browser.isMobile = (navigator.appVersion.match(/Mobile/i) != null);
+ browser.noContextMenu = browser.isMobile;
+ },
+ Firefox: function (browser) {
+ if ((browser.version === "0.0" || AGENT.match(/Firefox/) == null) &&
+ navigator.product === "Gecko") {
+ var rv = AGENT.match(/[\/ ]rv:(\d+\.\d.*?)[\) ]/);
+ if (rv) {browser.version = rv[1]}
+ else {
+ var date = (navigator.buildID||navigator.productSub||"0").substr(0,8);
+ if (date >= "20111220") {browser.version = "9.0"}
+ else if (date >= "20111120") {browser.version = "8.0"}
+ else if (date >= "20110927") {browser.version = "7.0"}
+ else if (date >= "20110816") {browser.version = "6.0"}
+ else if (date >= "20110621") {browser.version = "5.0"}
+ else if (date >= "20110320") {browser.version = "4.0"}
+ else if (date >= "20100121") {browser.version = "3.6"}
+ else if (date >= "20090630") {browser.version = "3.5"}
+ else if (date >= "20080617") {browser.version = "3.0"}
+ else if (date >= "20061024") {browser.version = "2.0"}
+ }
+ }
+ browser.isMobile = (navigator.appVersion.match(/Android/i) != null ||
+ AGENT.match(/ Fennec\//) != null ||
+ AGENT.match(/Mobile/) != null);
+ },
+ Chrome: function (browser) {
+ browser.noContextMenu = browser.isMobile = !!navigator.userAgent.match(/ Mobile[ \/]/);
+ },
+ Opera: function (browser) {browser.version = opera.version()},
+ Edge: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ },
+ MSIE: function (browser) {
+ browser.isMobile = !!navigator.userAgent.match(/ Phone/);
+ browser.isIE9 = !!(document.documentMode && (window.performance || window.msPerformance));
+ MathJax.HTML.setScriptBug = !browser.isIE9 || document.documentMode < 9;
+ MathJax.Hub.msieHTMLCollectionBug = (document.documentMode < 9);
+ //
+ // MathPlayer doesn't function properly in IE10, and not at all in IE11,
+ // so don't even try to load it.
+ //
+ if (document.documentMode < 10 && !STARTUP.params.NoMathPlayer) {
+ try {
+ new ActiveXObject("MathPlayer.Factory.1");
+ browser.hasMathPlayer = true;
+ } catch (err) {}
+ try {
+ if (browser.hasMathPlayer) {
+ var mathplayer = document.createElement("object");
+ mathplayer.id = "mathplayer"; mathplayer.classid = "clsid:32F66A20-7614-11D4-BD11-00104BD3F987";
+ HEAD.appendChild(mathplayer);
+ document.namespaces.add("m","http://www.w3.org/1998/Math/MathML");
+ browser.mpNamespace = true;
+ if (document.readyState && (document.readyState === "loading" ||
+ document.readyState === "interactive")) {
+ document.write('');
+ browser.mpImported = true;
+ }
+ } else {
+ // Adding any namespace avoids a crash in IE9 in IE9-standards mode
+ // (any reference to document.namespaces before document.readyState is
+ // "complete" causes an "unspecified error" to be thrown)
+ document.namespaces.add("mjx_IE_fix","http://www.w3.org/1999/xlink");
+ }
+ } catch (err) {}
+ }
+ }
+ });} catch (err) {
+ console.error(err.message);
+ }
+ HUB.Browser.Select(MathJax.Message.browsers);
+
+ if (BASE.AuthorConfig && typeof BASE.AuthorConfig.AuthorInit === "function") {BASE.AuthorConfig.AuthorInit()}
+ HUB.queue = BASE.Callback.Queue();
+ HUB.queue.Push(
+ ["Post",STARTUP.signal,"Begin"],
+ ["Config",STARTUP],
+ ["Cookie",STARTUP],
+ ["Styles",STARTUP],
+ ["Message",STARTUP],
+ function () {
+ // Do Jax and Extensions in parallel, but wait for them all to complete
+ var queue = BASE.Callback.Queue(
+ STARTUP.Jax(),
+ STARTUP.Extensions()
+ );
+ return queue.Push({});
+ },
+ ["Menu",STARTUP],
+ STARTUP.onLoad(),
+ function () {MathJax.isReady = true}, // indicates that MathJax is ready to process math
+ ["Typeset",STARTUP],
+ ["Hash",STARTUP],
+ ["MenuZoom",STARTUP],
+ ["Post",STARTUP.signal,"End"]
+ );
+
+})("MathJax");
+
+}}
diff --git a/MarkDownEditor/MathJax/jax/input/TeX/config.js b/MarkDownEditor/MathJax/jax/input/TeX/config.js
new file mode 100644
index 0000000..22c2e78
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/input/TeX/config.js
@@ -0,0 +1,52 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/jax/input/TeX/config.js
+ *
+ * Initializes the TeX InputJax (the main definition is in
+ * MathJax/jax/input/TeX/jax.js, which is loaded when needed).
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.InputJax.TeX = MathJax.InputJax({
+ id: "TeX",
+ version: "2.6.1",
+ directory: MathJax.InputJax.directory + "/TeX",
+ extensionDir: MathJax.InputJax.extensionDir + "/TeX",
+
+ config: {
+ TagSide: "right",
+ TagIndent: "0.8em",
+ MultLineWidth: "85%",
+
+ equationNumbers: {
+ autoNumber: "none", // "AMS" for standard AMS numbering,
+ // or "all" for all displayed equations
+ formatNumber: function (n) {return n},
+ formatTag: function (n) {return '('+n+')'},
+ formatID: function (n) {return 'mjx-eqn-'+String(n).replace(/[:"'<>&]/g,"")},
+ formatURL: function (id) {return '#'+escape(id)},
+ useLabelIds: true
+ }
+ }
+});
+MathJax.InputJax.TeX.Register("math/tex");
+
+MathJax.InputJax.TeX.loadComplete("config.js");
diff --git a/MarkDownEditor/MathJax/jax/input/TeX/jax.js b/MarkDownEditor/MathJax/jax/input/TeX/jax.js
new file mode 100644
index 0000000..8463c8b
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/input/TeX/jax.js
@@ -0,0 +1,2275 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/jax/input/TeX/jax.js
+ *
+ * Implements the TeX InputJax that reads mathematics in
+ * TeX and LaTeX format and converts it to the MML ElementJax
+ * internal format.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2015 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.
+ */
+
+(function (TEX,HUB,AJAX) {
+ var MML, NBSP = "\u00A0";
+
+ var _ = function (id) {
+ return MathJax.Localization._.apply(MathJax.Localization,
+ [["TeX", id]].concat([].slice.call(arguments,1)));
+ };
+
+ var STACK = MathJax.Object.Subclass({
+ Init: function (env,inner) {
+ this.global = {isInner: inner};
+ this.data = [STACKITEM.start(this.global)];
+ if (env) {this.data[0].env = env}
+ this.env = this.data[0].env;
+ },
+ Push: function () {
+ var i, m, item, top;
+ for (i = 0, m = arguments.length; i < m; i++) {
+ item = arguments[i]; if (!item) continue;
+ if (item instanceof MML.mbase) {item = STACKITEM.mml(item)}
+ item.global = this.global;
+ top = (this.data.length ? this.Top().checkItem(item) : true);
+ if (top instanceof Array) {this.Pop(); this.Push.apply(this,top)}
+ else if (top instanceof STACKITEM) {this.Pop(); this.Push(top)}
+ else if (top) {
+ this.data.push(item);
+ if (item.env) {
+ for (var id in this.env)
+ {if (this.env.hasOwnProperty(id)) {item.env[id] = this.env[id]}}
+ this.env = item.env;
+ } else {item.env = this.env}
+ }
+ }
+ },
+ Pop: function () {
+ var item = this.data.pop(); if (!item.isOpen) {delete item.env}
+ this.env = (this.data.length ? this.Top().env : {});
+ return item;
+ },
+ Top: function (n) {
+ if (n == null) {n = 1}
+ if (this.data.length < n) {return null}
+ return this.data[this.data.length-n];
+ },
+ Prev: function (noPop) {
+ var top = this.Top();
+ if (noPop) {return top.data[top.data.length-1]}
+ else {return top.Pop()}
+ },
+ toString: function () {return "stack[\n "+this.data.join("\n ")+"\n]"}
+ });
+
+ var STACKITEM = STACK.Item = MathJax.Object.Subclass({
+ type: "base",
+ endError: /*_()*/ ["ExtraOpenMissingClose","Extra open brace or missing close brace"],
+ closeError: /*_()*/ ["ExtraCloseMissingOpen","Extra close brace or missing open brace"],
+ rightError: /*_()*/ ["MissingLeftExtraRight","Missing \\left or extra \\right"],
+ Init: function () {
+ if (this.isOpen) {this.env = {}}
+ this.data = [];
+ this.Push.apply(this,arguments);
+ },
+ Push: function () {this.data.push.apply(this.data,arguments)},
+ Pop: function () {return this.data.pop()},
+ mmlData: function (inferred,forceRow) {
+ if (inferred == null) {inferred = true}
+ if (this.data.length === 1 && !forceRow) {return this.data[0]}
+ return MML.mrow.apply(MML,this.data).With((inferred ? {inferred: true}: {}));
+ },
+ checkItem: function (item) {
+ if (item.type === "over" && this.isOpen) {item.num = this.mmlData(false); this.data = []}
+ if (item.type === "cell" && this.isOpen) {
+ if (item.linebreak) {return false}
+ TEX.Error(["Misplaced","Misplaced %1",item.name]);
+ }
+ if (item.isClose && this[item.type+"Error"]) {TEX.Error(this[item.type+"Error"])}
+ if (!item.isNotStack) {return true}
+ this.Push(item.data[0]); return false;
+ },
+ With: function (def) {
+ for (var id in def) {if (def.hasOwnProperty(id)) {this[id] = def[id]}}
+ return this;
+ },
+ toString: function () {return this.type+"["+this.data.join("; ")+"]"}
+ });
+
+ STACKITEM.start = STACKITEM.Subclass({
+ type: "start", isOpen: true,
+ Init: function (global) {
+ this.SUPER(arguments).Init.call(this);
+ this.global = global;
+ },
+ checkItem: function (item) {
+ if (item.type === "stop") {return STACKITEM.mml(this.mmlData())}
+ return this.SUPER(arguments).checkItem.call(this,item);
+ }
+ });
+
+ STACKITEM.stop = STACKITEM.Subclass({
+ type: "stop", isClose: true
+ });
+
+ STACKITEM.open = STACKITEM.Subclass({
+ type: "open", isOpen: true,
+ stopError: /*_()*/ ["ExtraOpenMissingClose","Extra open brace or missing close brace"],
+ checkItem: function (item) {
+ if (item.type === "close") {
+ var mml = this.mmlData();
+ return STACKITEM.mml(MML.TeXAtom(mml)); // TeXAtom make it an ORD to prevent spacing (FIXME: should be another way)
+ }
+ return this.SUPER(arguments).checkItem.call(this,item);
+ }
+ });
+
+ STACKITEM.close = STACKITEM.Subclass({
+ type: "close", isClose: true
+ });
+
+ STACKITEM.prime = STACKITEM.Subclass({
+ type: "prime",
+ checkItem: function (item) {
+ if (this.data[0].type !== "msubsup")
+ {return [MML.msup(this.data[0],this.data[1]),item]}
+ this.data[0].SetData(this.data[0].sup,this.data[1]);
+ return [this.data[0],item];
+ }
+ });
+
+ STACKITEM.subsup = STACKITEM.Subclass({
+ type: "subsup",
+ stopError: /*_()*/ ["MissingScript","Missing superscript or subscript argument"],
+ supError: /*_()*/ ["MissingOpenForSup","Missing open brace for superscript"],
+ subError: /*_()*/ ["MissingOpenForSub","Missing open brace for subscript"],
+ checkItem: function (item) {
+ if (item.type === "open" || item.type === "left") {return true}
+ if (item.type === "mml") {
+ if (this.primes) {
+ if (this.position !== 2) {this.data[0].SetData(2,this.primes)}
+ else {item.data[0] = MML.mrow(this.primes.With({variantForm:true}),item.data[0])}
+ }
+ this.data[0].SetData(this.position,item.data[0]);
+ if (this.movesupsub != null) {this.data[0].movesupsub = this.movesupsub}
+ return STACKITEM.mml(this.data[0]);
+ }
+ if (this.SUPER(arguments).checkItem.call(this,item))
+ {TEX.Error(this[["","subError","supError"][this.position]])}
+ },
+ Pop: function () {}
+ });
+
+ STACKITEM.over = STACKITEM.Subclass({
+ type: "over", isClose: true, name: "\\over",
+ checkItem: function (item,stack) {
+ if (item.type === "over")
+ {TEX.Error(["AmbiguousUseOf","Ambiguous use of %1",item.name])}
+ if (item.isClose) {
+ var mml = MML.mfrac(this.num,this.mmlData(false));
+ if (this.thickness != null) {mml.linethickness = this.thickness}
+ if (this.open || this.close) {
+ mml.texWithDelims = true;
+ mml = TEX.fixedFence(this.open,mml,this.close);
+ }
+ return [STACKITEM.mml(mml), item];
+ }
+ return this.SUPER(arguments).checkItem.call(this,item);
+ },
+ toString: function () {return "over["+this.num+" / "+this.data.join("; ")+"]"}
+ });
+
+ STACKITEM.left = STACKITEM.Subclass({
+ type: "left", isOpen: true, delim: '(',
+ stopError: /*_()*/ ["ExtraLeftMissingRight", "Extra \\left or missing \\right"],
+ checkItem: function (item) {
+ if (item.type === "right")
+ {return STACKITEM.mml(TEX.fenced(this.delim,this.mmlData(),item.delim))}
+ return this.SUPER(arguments).checkItem.call(this,item);
+ }
+ });
+
+ STACKITEM.right = STACKITEM.Subclass({
+ type: "right", isClose: true, delim: ')'
+ });
+
+ STACKITEM.begin = STACKITEM.Subclass({
+ type: "begin", isOpen: true,
+ checkItem: function (item) {
+ if (item.type === "end") {
+ if (item.name !== this.name)
+ {TEX.Error(["EnvBadEnd","\\begin{%1} ended with \\end{%2}",this.name,item.name])}
+ if (!this.end) {return STACKITEM.mml(this.mmlData())}
+ return this.parse[this.end].call(this.parse,this,this.data);
+ }
+ if (item.type === "stop")
+ {TEX.Error(["EnvMissingEnd","Missing \\end{%1}",this.name])}
+ return this.SUPER(arguments).checkItem.call(this,item);
+ }
+ });
+
+ STACKITEM.end = STACKITEM.Subclass({
+ type: "end", isClose: true
+ });
+
+ STACKITEM.style = STACKITEM.Subclass({
+ type: "style",
+ checkItem: function (item) {
+ if (!item.isClose) {return this.SUPER(arguments).checkItem.call(this,item)}
+ var mml = MML.mstyle.apply(MML,this.data).With(this.styles);
+ return [STACKITEM.mml(mml),item];
+ }
+ });
+
+ STACKITEM.position = STACKITEM.Subclass({
+ type: "position",
+ checkItem: function (item) {
+ if (item.isClose) {TEX.Error(["MissingBoxFor","Missing box for %1",this.name])}
+ if (item.isNotStack) {
+ var mml = item.mmlData();
+ switch (this.move) {
+ case 'vertical':
+ mml = MML.mpadded(mml).With({height: this.dh, depth: this.dd, voffset: this.dh});
+ return [STACKITEM.mml(mml)];
+ case 'horizontal':
+ return [STACKITEM.mml(this.left),item,STACKITEM.mml(this.right)];
+ }
+ }
+ return this.SUPER(arguments).checkItem.call(this,item);
+ }
+ });
+
+ STACKITEM.array = STACKITEM.Subclass({
+ type: "array", isOpen: true, arraydef: {},
+ Init: function () {
+ this.table = []; this.row = []; this.env = {}; this.frame = []; this.hfill = [];
+ this.SUPER(arguments).Init.apply(this,arguments);
+ },
+ checkItem: function (item) {
+ if (item.isClose && item.type !== "over") {
+ if (item.isEntry) {this.EndEntry(); this.clearEnv(); return false}
+ if (item.isCR) {this.EndEntry(); this.EndRow(); this.clearEnv(); return false}
+ this.EndTable(); this.clearEnv();
+ var scriptlevel = this.arraydef.scriptlevel; delete this.arraydef.scriptlevel;
+ var mml = MML.mtable.apply(MML,this.table).With(this.arraydef);
+ if (this.frame.length === 4) {
+ mml.frame = (this.frame.dashed ? "dashed" : "solid");
+ } else if (this.frame.length) {
+ mml.hasFrame = true;
+ if (this.arraydef.rowlines) {this.arraydef.rowlines = this.arraydef.rowlines.replace(/none( none)+$/,"none")}
+ mml = MML.menclose(mml).With({notation: this.frame.join(" "), isFrame: true});
+ if ((this.arraydef.columnlines||"none") != "none" ||
+ (this.arraydef.rowlines||"none") != "none") {mml.padding = 0} // HTML-CSS jax implements this
+ }
+ if (scriptlevel) {mml = MML.mstyle(mml).With({scriptlevel: scriptlevel})}
+ if (this.open || this.close) {mml = TEX.fenced(this.open,mml,this.close)}
+ mml = STACKITEM.mml(mml);
+ if (this.requireClose) {
+ if (item.type === 'close') {return mml}
+ TEX.Error(["MissingCloseBrace","Missing close brace"]);
+ }
+ return [mml,item];
+ }
+ return this.SUPER(arguments).checkItem.call(this,item);
+ },
+ EndEntry: function () {
+ var mtd = MML.mtd.apply(MML,this.data);
+ if (this.hfill.length) {
+ if (this.hfill[0] === 0) mtd.columnalign = "right";
+ if (this.hfill[this.hfill.length-1] === this.data.length)
+ mtd.columnalign = (mtd.columnalign ? "center" : "left");
+ }
+ this.row.push(mtd); this.data = []; this.hfill = [];
+ },
+ EndRow: function () {
+ var mtr = MML.mtr;
+ if (this.isNumbered && this.row.length === 3) {
+ this.row.unshift(this.row.pop()); // move equation number to first position
+ mtr = MML.mlabeledtr;
+ }
+ this.table.push(mtr.apply(MML,this.row)); this.row = [];
+ },
+ EndTable: function () {
+ if (this.data.length || this.row.length) {this.EndEntry(); this.EndRow()}
+ this.checkLines();
+ },
+ checkLines: function () {
+ if (this.arraydef.rowlines) {
+ var lines = this.arraydef.rowlines.split(/ /);
+ if (lines.length === this.table.length) {
+ this.frame.push("bottom"); lines.pop();
+ this.arraydef.rowlines = lines.join(' ');
+ } else if (lines.length < this.table.length-1) {
+ this.arraydef.rowlines += " none";
+ }
+ }
+ if (this.rowspacing) {
+ var rows = this.arraydef.rowspacing.split(/ /);
+ while (rows.length < this.table.length) {rows.push(this.rowspacing+"em")}
+ this.arraydef.rowspacing = rows.join(' ');
+ }
+ },
+ clearEnv: function () {
+ for (var id in this.env) {if (this.env.hasOwnProperty(id)) {delete this.env[id]}}
+ }
+ });
+
+ STACKITEM.cell = STACKITEM.Subclass({
+ type: "cell", isClose: true
+ });
+
+ STACKITEM.mml = STACKITEM.Subclass({
+ type: "mml", isNotStack: true,
+ Add: function () {this.data.push.apply(this.data,arguments); return this}
+ });
+
+ STACKITEM.fn = STACKITEM.Subclass({
+ type: "fn",
+ checkItem: function (item) {
+ if (this.data[0]) {
+ if (item.isOpen) {return true}
+ if (item.type !== "fn") {
+ if (item.type !== "mml" || !item.data[0]) {return [this.data[0],item]}
+ if (item.data[0].isa(MML.mspace)) {return [this.data[0],item]}
+ var mml = item.data[0]; if (mml.isEmbellished()) {mml = mml.CoreMO()}
+ if ([0,0,1,1,0,1,1,0,0,0][mml.Get("texClass")]) {return [this.data[0],item]}
+ }
+ return [this.data[0],MML.mo(MML.entity("#x2061")).With({texClass:MML.TEXCLASS.NONE}),item];
+ }
+ return this.SUPER(arguments).checkItem.apply(this,arguments);
+ }
+ });
+
+ STACKITEM.not = STACKITEM.Subclass({
+ type: "not",
+ checkItem: function (item) {
+ var mml, c;
+ if (item.type === "open" || item.type === "left") {return true}
+ if (item.type === "mml" && item.data[0].type.match(/^(mo|mi|mtext)$/)) {
+ mml = item.data[0], c = mml.data.join("");
+ if (c.length === 1 && !mml.movesupsub) {
+ c = STACKITEM.not.remap[c.charCodeAt(0)];
+ if (c) {mml.SetData(0,MML.chars(String.fromCharCode(c)))}
+ else {mml.Append(MML.chars("\u0338"))}
+ return item;
+ }
+ }
+ // \mathrel{\rlap{\notChar}}
+ mml = MML.mpadded(MML.mtext("\u29F8")).With({width:0});
+ mml = MML.TeXAtom(mml).With({texClass:MML.TEXCLASS.REL});
+ return [mml,item];
+ }
+ });
+ STACKITEM.not.remap = {
+ 0x2190:0x219A, 0x2192:0x219B, 0x2194:0x21AE,
+ 0x21D0:0x21CD, 0x21D2:0x21CF, 0x21D4:0x21CE,
+ 0x2208:0x2209, 0x220B:0x220C, 0x2223:0x2224, 0x2225:0x2226,
+ 0x223C:0x2241, 0x007E:0x2241, 0x2243:0x2244, 0x2245:0x2247,
+ 0x2248:0x2249, 0x224D:0x226D, 0x003D:0x2260, 0x2261:0x2262,
+ 0x003C:0x226E, 0x003E:0x226F, 0x2264:0x2270, 0x2265:0x2271,
+ 0x2272:0x2274, 0x2273:0x2275, 0x2276:0x2278, 0x2277:0x2279,
+ 0x227A:0x2280, 0x227B:0x2281, 0x2282:0x2284, 0x2283:0x2285,
+ 0x2286:0x2288, 0x2287:0x2289, 0x22A2:0x22AC, 0x22A8:0x22AD,
+ 0x22A9:0x22AE, 0x22AB:0x22AF, 0x227C:0x22E0, 0x227D:0x22E1,
+ 0x2291:0x22E2, 0x2292:0x22E3, 0x22B2:0x22EA, 0x22B3:0x22EB,
+ 0x22B4:0x22EC, 0x22B5:0x22ED, 0x2203:0x2204
+ };
+
+ STACKITEM.dots = STACKITEM.Subclass({
+ type: "dots",
+ checkItem: function (item) {
+ if (item.type === "open" || item.type === "left") {return true}
+ var dots = this.ldots;
+ if (item.type === "mml" && item.data[0].isEmbellished()) {
+ var tclass = item.data[0].CoreMO().Get("texClass");
+ if (tclass === MML.TEXCLASS.BIN || tclass === MML.TEXCLASS.REL) {dots = this.cdots}
+ }
+ return [dots,item];
+ }
+ });
+
+
+ var TEXDEF = {
+ //
+ // Add new definitions without overriding user-defined ones
+ //
+ Add: function (src,dst,nouser) {
+ if (!dst) {dst = this}
+ for (var id in src) {if (src.hasOwnProperty(id)) {
+ if (typeof src[id] === 'object' && !(src[id] instanceof Array) &&
+ (typeof dst[id] === 'object' || typeof dst[id] === 'function'))
+ {this.Add(src[id],dst[id],src[id],nouser)}
+ else if (!dst[id] || !dst[id].isUser || !nouser) {dst[id] = src[id]}
+ }}
+ return dst;
+ }
+ };
+ var STARTUP = function () {
+ MML = MathJax.ElementJax.mml;
+ HUB.Insert(TEXDEF,{
+
+ // patterns for letters and numbers
+ letter: /[a-z]/i,
+ digit: /[0-9.]/,
+ number: /^(?:[0-9]+(?:\{,\}[0-9]{3})*(?:\.[0-9]*)*|\.[0-9]+)/,
+
+ special: {
+ '\\': 'ControlSequence',
+ '{': 'Open',
+ '}': 'Close',
+ '~': 'Tilde',
+ '^': 'Superscript',
+ '_': 'Subscript',
+ ' ': 'Space',
+ "\t": 'Space',
+ "\r": 'Space',
+ "\n": 'Space',
+ "'": 'Prime',
+ '%': 'Comment',
+ '&': 'Entry',
+ '#': 'Hash',
+ '\u00A0': 'Space',
+ '\u2019': 'Prime'
+ },
+
+ remap: {
+ '-': '2212',
+ '*': '2217',
+ '`': '2018' // map ` to back quote
+ },
+
+ mathchar0mi: {
+ // Lower-case greek
+ alpha: '03B1',
+ beta: '03B2',
+ gamma: '03B3',
+ delta: '03B4',
+ epsilon: '03F5',
+ zeta: '03B6',
+ eta: '03B7',
+ theta: '03B8',
+ iota: '03B9',
+ kappa: '03BA',
+ lambda: '03BB',
+ mu: '03BC',
+ nu: '03BD',
+ xi: '03BE',
+ omicron: '03BF', // added for completeness
+ pi: '03C0',
+ rho: '03C1',
+ sigma: '03C3',
+ tau: '03C4',
+ upsilon: '03C5',
+ phi: '03D5',
+ chi: '03C7',
+ psi: '03C8',
+ omega: '03C9',
+ varepsilon: '03B5',
+ vartheta: '03D1',
+ varpi: '03D6',
+ varrho: '03F1',
+ varsigma: '03C2',
+ varphi: '03C6',
+
+ // Ord symbols
+ S: ['00A7',{mathvariant: MML.VARIANT.NORMAL}],
+ aleph: ['2135',{mathvariant: MML.VARIANT.NORMAL}],
+ hbar: ['210F',{variantForm:true}],
+ imath: '0131',
+ jmath: '0237',
+ ell: '2113',
+ wp: ['2118',{mathvariant: MML.VARIANT.NORMAL}],
+ Re: ['211C',{mathvariant: MML.VARIANT.NORMAL}],
+ Im: ['2111',{mathvariant: MML.VARIANT.NORMAL}],
+ partial: ['2202',{mathvariant: MML.VARIANT.NORMAL}],
+ infty: ['221E',{mathvariant: MML.VARIANT.NORMAL}],
+ prime: ['2032',{mathvariant: MML.VARIANT.NORMAL, variantForm:true}],
+ emptyset: ['2205',{mathvariant: MML.VARIANT.NORMAL}],
+ nabla: ['2207',{mathvariant: MML.VARIANT.NORMAL}],
+ top: ['22A4',{mathvariant: MML.VARIANT.NORMAL}],
+ bot: ['22A5',{mathvariant: MML.VARIANT.NORMAL}],
+ angle: ['2220',{mathvariant: MML.VARIANT.NORMAL}],
+ triangle: ['25B3',{mathvariant: MML.VARIANT.NORMAL}],
+ backslash: ['2216',{mathvariant: MML.VARIANT.NORMAL, variantForm:true}],
+ forall: ['2200',{mathvariant: MML.VARIANT.NORMAL}],
+ exists: ['2203',{mathvariant: MML.VARIANT.NORMAL}],
+ neg: ['00AC',{mathvariant: MML.VARIANT.NORMAL}],
+ lnot: ['00AC',{mathvariant: MML.VARIANT.NORMAL}],
+ flat: ['266D',{mathvariant: MML.VARIANT.NORMAL}],
+ natural: ['266E',{mathvariant: MML.VARIANT.NORMAL}],
+ sharp: ['266F',{mathvariant: MML.VARIANT.NORMAL}],
+ clubsuit: ['2663',{mathvariant: MML.VARIANT.NORMAL}],
+ diamondsuit: ['2662',{mathvariant: MML.VARIANT.NORMAL}],
+ heartsuit: ['2661',{mathvariant: MML.VARIANT.NORMAL}],
+ spadesuit: ['2660',{mathvariant: MML.VARIANT.NORMAL}]
+ },
+
+ mathchar0mo: {
+ surd: '221A',
+
+ // big ops
+ coprod: ['2210',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigvee: ['22C1',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigwedge: ['22C0',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ biguplus: ['2A04',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigcap: ['22C2',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigcup: ['22C3',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ 'int': ['222B',{texClass: MML.TEXCLASS.OP}],
+ intop: ['222B',{texClass: MML.TEXCLASS.OP, movesupsub:true, movablelimits:true}],
+ iint: ['222C',{texClass: MML.TEXCLASS.OP}],
+ iiint: ['222D',{texClass: MML.TEXCLASS.OP}],
+ prod: ['220F',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ sum: ['2211',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigotimes: ['2A02',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigoplus: ['2A01',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ bigodot: ['2A00',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ oint: ['222E',{texClass: MML.TEXCLASS.OP}],
+ bigsqcup: ['2A06',{texClass: MML.TEXCLASS.OP, movesupsub:true}],
+ smallint: ['222B',{largeop:false}],
+
+ // binary operations
+ triangleleft: '25C3',
+ triangleright: '25B9',
+ bigtriangleup: '25B3',
+ bigtriangledown: '25BD',
+ wedge: '2227',
+ land: '2227',
+ vee: '2228',
+ lor: '2228',
+ cap: '2229',
+ cup: '222A',
+ ddagger: '2021',
+ dagger: '2020',
+ sqcap: '2293',
+ sqcup: '2294',
+ uplus: '228E',
+ amalg: '2A3F',
+ diamond: '22C4',
+ bullet: '2219',
+ wr: '2240',
+ div: '00F7',
+ odot: ['2299',{largeop: false}],
+ oslash: ['2298',{largeop: false}],
+ otimes: ['2297',{largeop: false}],
+ ominus: ['2296',{largeop: false}],
+ oplus: ['2295',{largeop: false}],
+ mp: '2213',
+ pm: '00B1',
+ circ: '2218',
+ bigcirc: '25EF',
+ setminus: ['2216',{variantForm:true}],
+ cdot: '22C5',
+ ast: '2217',
+ times: '00D7',
+ star: '22C6',
+
+ // Relations
+ propto: '221D',
+ sqsubseteq: '2291',
+ sqsupseteq: '2292',
+ parallel: '2225',
+ mid: '2223',
+ dashv: '22A3',
+ vdash: '22A2',
+ leq: '2264',
+ le: '2264',
+ geq: '2265',
+ ge: '2265',
+ lt: '003C',
+ gt: '003E',
+ succ: '227B',
+ prec: '227A',
+ approx: '2248',
+ succeq: '2AB0', // or '227C',
+ preceq: '2AAF', // or '227D',
+ supset: '2283',
+ subset: '2282',
+ supseteq: '2287',
+ subseteq: '2286',
+ 'in': '2208',
+ ni: '220B',
+ notin: '2209',
+ owns: '220B',
+ gg: '226B',
+ ll: '226A',
+ sim: '223C',
+ simeq: '2243',
+ perp: '22A5',
+ equiv: '2261',
+ asymp: '224D',
+ smile: '2323',
+ frown: '2322',
+ ne: '2260',
+ neq: '2260',
+ cong: '2245',
+ doteq: '2250',
+ bowtie: '22C8',
+ models: '22A8',
+
+ notChar: '29F8',
+
+
+ // Arrows
+ Leftrightarrow: '21D4',
+ Leftarrow: '21D0',
+ Rightarrow: '21D2',
+ leftrightarrow: '2194',
+ leftarrow: '2190',
+ gets: '2190',
+ rightarrow: '2192',
+ to: '2192',
+ mapsto: '21A6',
+ leftharpoonup: '21BC',
+ leftharpoondown: '21BD',
+ rightharpoonup: '21C0',
+ rightharpoondown: '21C1',
+ nearrow: '2197',
+ searrow: '2198',
+ nwarrow: '2196',
+ swarrow: '2199',
+ rightleftharpoons: '21CC',
+ hookrightarrow: '21AA',
+ hookleftarrow: '21A9',
+ longleftarrow: '27F5',
+ Longleftarrow: '27F8',
+ longrightarrow: '27F6',
+ Longrightarrow: '27F9',
+ Longleftrightarrow: '27FA',
+ longleftrightarrow: '27F7',
+ longmapsto: '27FC',
+
+
+ // Misc.
+ ldots: '2026',
+ cdots: '22EF',
+ vdots: '22EE',
+ ddots: '22F1',
+ dotsc: '2026', // dots with commas
+ dotsb: '22EF', // dots with binary ops and relations
+ dotsm: '22EF', // dots with multiplication
+ dotsi: '22EF', // dots with integrals
+ dotso: '2026', // other dots
+
+ ldotp: ['002E', {texClass: MML.TEXCLASS.PUNCT}],
+ cdotp: ['22C5', {texClass: MML.TEXCLASS.PUNCT}],
+ colon: ['003A', {texClass: MML.TEXCLASS.PUNCT}]
+ },
+
+ mathchar7: {
+ Gamma: '0393',
+ Delta: '0394',
+ Theta: '0398',
+ Lambda: '039B',
+ Xi: '039E',
+ Pi: '03A0',
+ Sigma: '03A3',
+ Upsilon: '03A5',
+ Phi: '03A6',
+ Psi: '03A8',
+ Omega: '03A9',
+
+ '_': '005F',
+ '#': '0023',
+ '$': '0024',
+ '%': '0025',
+ '&': '0026',
+ And: '0026'
+ },
+
+ delimiter: {
+ '(': '(',
+ ')': ')',
+ '[': '[',
+ ']': ']',
+ '<': '27E8',
+ '>': '27E9',
+ '\\lt': '27E8',
+ '\\gt': '27E9',
+ '/': '/',
+ '|': ['|',{texClass:MML.TEXCLASS.ORD}],
+ '.': '',
+ '\\\\': '\\',
+ '\\lmoustache': '23B0', // non-standard
+ '\\rmoustache': '23B1', // non-standard
+ '\\lgroup': '27EE', // non-standard
+ '\\rgroup': '27EF', // non-standard
+ '\\arrowvert': '23D0',
+ '\\Arrowvert': '2016',
+ '\\bracevert': '23AA', // non-standard
+ '\\Vert': ['2225',{texClass:MML.TEXCLASS.ORD}],
+ '\\|': ['2225',{texClass:MML.TEXCLASS.ORD}],
+ '\\vert': ['|',{texClass:MML.TEXCLASS.ORD}],
+ '\\uparrow': '2191',
+ '\\downarrow': '2193',
+ '\\updownarrow': '2195',
+ '\\Uparrow': '21D1',
+ '\\Downarrow': '21D3',
+ '\\Updownarrow': '21D5',
+ '\\backslash': '\\',
+ '\\rangle': '27E9',
+ '\\langle': '27E8',
+ '\\rbrace': '}',
+ '\\lbrace': '{',
+ '\\}': '}',
+ '\\{': '{',
+ '\\rceil': '2309',
+ '\\lceil': '2308',
+ '\\rfloor': '230B',
+ '\\lfloor': '230A',
+ '\\lbrack': '[',
+ '\\rbrack': ']'
+ },
+
+ macros: {
+ displaystyle: ['SetStyle','D',true,0],
+ textstyle: ['SetStyle','T',false,0],
+ scriptstyle: ['SetStyle','S',false,1],
+ scriptscriptstyle: ['SetStyle','SS',false,2],
+
+ rm: ['SetFont',MML.VARIANT.NORMAL],
+ mit: ['SetFont',MML.VARIANT.ITALIC],
+ oldstyle: ['SetFont',MML.VARIANT.OLDSTYLE],
+ cal: ['SetFont',MML.VARIANT.CALIGRAPHIC],
+ it: ['SetFont',"-tex-mathit"], // needs special handling
+ bf: ['SetFont',MML.VARIANT.BOLD],
+ bbFont: ['SetFont',MML.VARIANT.DOUBLESTRUCK],
+ scr: ['SetFont',MML.VARIANT.SCRIPT],
+ frak: ['SetFont',MML.VARIANT.FRAKTUR],
+ sf: ['SetFont',MML.VARIANT.SANSSERIF],
+ tt: ['SetFont',MML.VARIANT.MONOSPACE],
+
+// font:
+
+ tiny: ['SetSize',0.5],
+ Tiny: ['SetSize',0.6], // non-standard
+ scriptsize: ['SetSize',0.7],
+ small: ['SetSize',0.85],
+ normalsize: ['SetSize',1.0],
+ large: ['SetSize',1.2],
+ Large: ['SetSize',1.44],
+ LARGE: ['SetSize',1.73],
+ huge: ['SetSize',2.07],
+ Huge: ['SetSize',2.49],
+
+ arcsin: ['NamedFn'],
+ arccos: ['NamedFn'],
+ arctan: ['NamedFn'],
+ arg: ['NamedFn'],
+ cos: ['NamedFn'],
+ cosh: ['NamedFn'],
+ cot: ['NamedFn'],
+ coth: ['NamedFn'],
+ csc: ['NamedFn'],
+ deg: ['NamedFn'],
+ det: 'NamedOp',
+ dim: ['NamedFn'],
+ exp: ['NamedFn'],
+ gcd: 'NamedOp',
+ hom: ['NamedFn'],
+ inf: 'NamedOp',
+ ker: ['NamedFn'],
+ lg: ['NamedFn'],
+ lim: 'NamedOp',
+ liminf: ['NamedOp','lim inf'],
+ limsup: ['NamedOp','lim sup'],
+ ln: ['NamedFn'],
+ log: ['NamedFn'],
+ max: 'NamedOp',
+ min: 'NamedOp',
+ Pr: 'NamedOp',
+ sec: ['NamedFn'],
+ sin: ['NamedFn'],
+ sinh: ['NamedFn'],
+ sup: 'NamedOp',
+ tan: ['NamedFn'],
+ tanh: ['NamedFn'],
+
+ limits: ['Limits',1],
+ nolimits: ['Limits',0],
+
+ overline: ['UnderOver','00AF',null,1],
+ underline: ['UnderOver','005F'],
+ overbrace: ['UnderOver','23DE',1],
+ underbrace: ['UnderOver','23DF',1],
+ overparen: ['UnderOver','23DC'],
+ underparen: ['UnderOver','23DD'],
+ overrightarrow: ['UnderOver','2192'],
+ underrightarrow: ['UnderOver','2192'],
+ overleftarrow: ['UnderOver','2190'],
+ underleftarrow: ['UnderOver','2190'],
+ overleftrightarrow: ['UnderOver','2194'],
+ underleftrightarrow: ['UnderOver','2194'],
+
+ overset: 'Overset',
+ underset: 'Underset',
+ stackrel: ['Macro','\\mathrel{\\mathop{#2}\\limits^{#1}}',2],
+
+ over: 'Over',
+ overwithdelims: 'Over',
+ atop: 'Over',
+ atopwithdelims: 'Over',
+ above: 'Over',
+ abovewithdelims: 'Over',
+ brace: ['Over','{','}'],
+ brack: ['Over','[',']'],
+ choose: ['Over','(',')'],
+
+ frac: 'Frac',
+ sqrt: 'Sqrt',
+ root: 'Root',
+ uproot: ['MoveRoot','upRoot'],
+ leftroot: ['MoveRoot','leftRoot'],
+
+ left: 'LeftRight',
+ right: 'LeftRight',
+ middle: 'Middle',
+
+ llap: 'Lap',
+ rlap: 'Lap',
+ raise: 'RaiseLower',
+ lower: 'RaiseLower',
+ moveleft: 'MoveLeftRight',
+ moveright: 'MoveLeftRight',
+
+ ',': ['Spacer',MML.LENGTH.THINMATHSPACE],
+ ':': ['Spacer',MML.LENGTH.MEDIUMMATHSPACE], // for LaTeX
+ '>': ['Spacer',MML.LENGTH.MEDIUMMATHSPACE],
+ ';': ['Spacer',MML.LENGTH.THICKMATHSPACE],
+ '!': ['Spacer',MML.LENGTH.NEGATIVETHINMATHSPACE],
+ enspace: ['Spacer',".5em"],
+ quad: ['Spacer',"1em"],
+ qquad: ['Spacer',"2em"],
+ thinspace: ['Spacer',MML.LENGTH.THINMATHSPACE],
+ negthinspace: ['Spacer',MML.LENGTH.NEGATIVETHINMATHSPACE],
+
+ hskip: 'Hskip',
+ hspace: 'Hskip',
+ kern: 'Hskip',
+ mskip: 'Hskip',
+ mspace: 'Hskip',
+ mkern: 'Hskip',
+ Rule: ['Rule'],
+ Space: ['Rule','blank'],
+
+ big: ['MakeBig',MML.TEXCLASS.ORD,0.85],
+ Big: ['MakeBig',MML.TEXCLASS.ORD,1.15],
+ bigg: ['MakeBig',MML.TEXCLASS.ORD,1.45],
+ Bigg: ['MakeBig',MML.TEXCLASS.ORD,1.75],
+ bigl: ['MakeBig',MML.TEXCLASS.OPEN,0.85],
+ Bigl: ['MakeBig',MML.TEXCLASS.OPEN,1.15],
+ biggl: ['MakeBig',MML.TEXCLASS.OPEN,1.45],
+ Biggl: ['MakeBig',MML.TEXCLASS.OPEN,1.75],
+ bigr: ['MakeBig',MML.TEXCLASS.CLOSE,0.85],
+ Bigr: ['MakeBig',MML.TEXCLASS.CLOSE,1.15],
+ biggr: ['MakeBig',MML.TEXCLASS.CLOSE,1.45],
+ Biggr: ['MakeBig',MML.TEXCLASS.CLOSE,1.75],
+ bigm: ['MakeBig',MML.TEXCLASS.REL,0.85],
+ Bigm: ['MakeBig',MML.TEXCLASS.REL,1.15],
+ biggm: ['MakeBig',MML.TEXCLASS.REL,1.45],
+ Biggm: ['MakeBig',MML.TEXCLASS.REL,1.75],
+
+ mathord: ['TeXAtom',MML.TEXCLASS.ORD],
+ mathop: ['TeXAtom',MML.TEXCLASS.OP],
+ mathopen: ['TeXAtom',MML.TEXCLASS.OPEN],
+ mathclose: ['TeXAtom',MML.TEXCLASS.CLOSE],
+ mathbin: ['TeXAtom',MML.TEXCLASS.BIN],
+ mathrel: ['TeXAtom',MML.TEXCLASS.REL],
+ mathpunct: ['TeXAtom',MML.TEXCLASS.PUNCT],
+ mathinner: ['TeXAtom',MML.TEXCLASS.INNER],
+
+ vcenter: ['TeXAtom',MML.TEXCLASS.VCENTER],
+
+ mathchoice: ['Extension','mathchoice'],
+ buildrel: 'BuildRel',
+
+ hbox: ['HBox',0],
+ text: 'HBox',
+ mbox: ['HBox',0],
+ fbox: 'FBox',
+
+ strut: 'Strut',
+ mathstrut: ['Macro','\\vphantom{(}'],
+ phantom: 'Phantom',
+ vphantom: ['Phantom',1,0],
+ hphantom: ['Phantom',0,1],
+ smash: 'Smash',
+
+ acute: ['Accent', "00B4"], // or 0301 or 02CA
+ grave: ['Accent', "0060"], // or 0300 or 02CB
+ ddot: ['Accent', "00A8"], // or 0308
+ tilde: ['Accent', "007E"], // or 0303 or 02DC
+ bar: ['Accent', "00AF"], // or 0304 or 02C9
+ breve: ['Accent', "02D8"], // or 0306
+ check: ['Accent', "02C7"], // or 030C
+ hat: ['Accent', "005E"], // or 0302 or 02C6
+ vec: ['Accent', "2192"], // or 20D7
+ dot: ['Accent', "02D9"], // or 0307
+ widetilde: ['Accent', "007E",1], // or 0303 or 02DC
+ widehat: ['Accent', "005E",1], // or 0302 or 02C6
+
+ matrix: 'Matrix',
+ array: 'Matrix',
+ pmatrix: ['Matrix','(',')'],
+ cases: ['Matrix','{','',"left left",null,".1em",null,true],
+ eqalign: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D'],
+ displaylines: ['Matrix',null,null,"center",null,".5em",'D'],
+ cr: 'Cr',
+ '\\': 'CrLaTeX',
+ newline: 'Cr',
+ hline: ['HLine','solid'],
+ hdashline: ['HLine','dashed'],
+// noalign: 'HandleNoAlign',
+ eqalignno: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D',null,"right"],
+ leqalignno: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D',null,"left"],
+ hfill: 'HFill',
+ hfil: 'HFill', // \hfil treated as \hfill for now
+ hfilll: 'HFill', // \hfilll treated as \hfill for now
+
+ // TeX substitution macros
+ bmod: ['Macro','\\mmlToken{mo}[lspace="thickmathspace" rspace="thickmathspace"]{mod}'],
+ pmod: ['Macro','\\pod{\\mmlToken{mi}{mod}\\kern 6mu #1}',1],
+ mod: ['Macro','\\mathchoice{\\kern18mu}{\\kern12mu}{\\kern12mu}{\\kern12mu}\\mmlToken{mi}{mod}\\,\\,#1',1],
+ pod: ['Macro','\\mathchoice{\\kern18mu}{\\kern8mu}{\\kern8mu}{\\kern8mu}(#1)',1],
+ iff: ['Macro','\\;\\Longleftrightarrow\\;'],
+ skew: ['Macro','{{#2{#3\\mkern#1mu}\\mkern-#1mu}{}}',3],
+ mathcal: ['Macro','{\\cal #1}',1],
+ mathscr: ['Macro','{\\scr #1}',1],
+ mathrm: ['Macro','{\\rm #1}',1],
+ mathbf: ['Macro','{\\bf #1}',1],
+ mathbb: ['Macro','{\\bbFont #1}',1],
+ Bbb: ['Macro','{\\bbFont #1}',1],
+ mathit: ['Macro','{\\it #1}',1],
+ mathfrak: ['Macro','{\\frak #1}',1],
+ mathsf: ['Macro','{\\sf #1}',1],
+ mathtt: ['Macro','{\\tt #1}',1],
+ textrm: ['Macro','\\mathord{\\rm\\text{#1}}',1],
+ textit: ['Macro','\\mathord{\\it\\text{#1}}',1],
+ textbf: ['Macro','\\mathord{\\bf\\text{#1}}',1],
+ textsf: ['Macro','\\mathord{\\sf\\text{#1}}',1],
+ texttt: ['Macro','\\mathord{\\tt\\text{#1}}',1],
+ pmb: ['Macro','\\rlap{#1}\\kern1px{#1}',1],
+ TeX: ['Macro','T\\kern-.14em\\lower.5ex{E}\\kern-.115em X'],
+ LaTeX: ['Macro','L\\kern-.325em\\raise.21em{\\scriptstyle{A}}\\kern-.17em\\TeX'],
+ ' ': ['Macro','\\text{ }'],
+
+ // Specially handled
+ not: 'Not',
+ dots: 'Dots',
+ space: 'Tilde',
+ '\u00A0': 'Tilde',
+
+
+ // LaTeX
+ begin: 'BeginEnd',
+ end: 'BeginEnd',
+
+ newcommand: ['Extension','newcommand'],
+ renewcommand: ['Extension','newcommand'],
+ newenvironment: ['Extension','newcommand'],
+ renewenvironment: ['Extension','newcommand'],
+ def: ['Extension','newcommand'],
+ let: ['Extension','newcommand'],
+
+ verb: ['Extension','verb'],
+
+ boldsymbol: ['Extension','boldsymbol'],
+
+ tag: ['Extension','AMSmath'],
+ notag: ['Extension','AMSmath'],
+ label: ['Extension','AMSmath'],
+ ref: ['Extension','AMSmath'],
+ eqref: ['Extension','AMSmath'],
+ nonumber: ['Macro','\\notag'],
+
+ // Extensions to TeX
+ unicode: ['Extension','unicode'],
+ color: 'Color',
+
+ href: ['Extension','HTML'],
+ 'class': ['Extension','HTML'],
+ style: ['Extension','HTML'],
+ cssId: ['Extension','HTML'],
+ bbox: ['Extension','bbox'],
+
+ mmlToken: 'MmlToken',
+
+ require: 'Require'
+
+ },
+
+ environment: {
+ array: ['AlignedArray'],
+ matrix: ['Array',null,null,null,'c'],
+ pmatrix: ['Array',null,'(',')','c'],
+ bmatrix: ['Array',null,'[',']','c'],
+ Bmatrix: ['Array',null,'\\{','\\}','c'],
+ vmatrix: ['Array',null,'\\vert','\\vert','c'],
+ Vmatrix: ['Array',null,'\\Vert','\\Vert','c'],
+ cases: ['Array',null,'\\{','.','ll',null,".2em",'T'],
+
+ equation: [null,'Equation'],
+ 'equation*': [null,'Equation'],
+
+ eqnarray: ['ExtensionEnv',null,'AMSmath'],
+ 'eqnarray*': ['ExtensionEnv',null,'AMSmath'],
+
+ align: ['ExtensionEnv',null,'AMSmath'],
+ 'align*': ['ExtensionEnv',null,'AMSmath'],
+ aligned: ['ExtensionEnv',null,'AMSmath'],
+ multline: ['ExtensionEnv',null,'AMSmath'],
+ 'multline*': ['ExtensionEnv',null,'AMSmath'],
+ split: ['ExtensionEnv',null,'AMSmath'],
+ gather: ['ExtensionEnv',null,'AMSmath'],
+ 'gather*': ['ExtensionEnv',null,'AMSmath'],
+ gathered: ['ExtensionEnv',null,'AMSmath'],
+ alignat: ['ExtensionEnv',null,'AMSmath'],
+ 'alignat*': ['ExtensionEnv',null,'AMSmath'],
+ alignedat: ['ExtensionEnv',null,'AMSmath']
+ },
+
+ p_height: 1.2 / .85 // cmex10 height plus depth over .85
+
+ });
+
+ //
+ // Add macros defined in the configuration
+ //
+ if (this.config.Macros) {
+ var MACROS = this.config.Macros;
+ for (var id in MACROS) {if (MACROS.hasOwnProperty(id)) {
+ if (typeof(MACROS[id]) === "string") {TEXDEF.macros[id] = ['Macro',MACROS[id]]}
+ else {TEXDEF.macros[id] = ["Macro"].concat(MACROS[id])}
+ TEXDEF.macros[id].isUser = true;
+ }}
+ }
+ };
+
+ /************************************************************************/
+ /*
+ * The TeX Parser
+ */
+
+ var PARSE = MathJax.Object.Subclass({
+ Init: function (string,env) {
+ this.string = string; this.i = 0; this.macroCount = 0;
+ var ENV; if (env) {ENV = {}; for (var id in env) {if (env.hasOwnProperty(id)) {ENV[id] = env[id]}}}
+ this.stack = TEX.Stack(ENV,!!env);
+ this.Parse(); this.Push(STACKITEM.stop());
+ },
+ Parse: function () {
+ var c, n;
+ while (this.i < this.string.length) {
+ c = this.string.charAt(this.i++); n = c.charCodeAt(0);
+ if (n >= 0xD800 && n < 0xDC00) {c += this.string.charAt(this.i++)}
+ if (TEXDEF.special[c]) {this[TEXDEF.special[c]](c)}
+ else if (TEXDEF.letter.test(c)) {this.Variable(c)}
+ else if (TEXDEF.digit.test(c)) {this.Number(c)}
+ else {this.Other(c)}
+ }
+ },
+ Push: function () {this.stack.Push.apply(this.stack,arguments)},
+ mml: function () {
+ if (this.stack.Top().type !== "mml") {return null}
+ return this.stack.Top().data[0];
+ },
+ mmlToken: function (token) {return token}, // used by boldsymbol extension
+
+ /************************************************************************/
+ /*
+ * Handle various token classes
+ */
+
+ /*
+ * Lookup a control-sequence and process it
+ */
+ ControlSequence: function (c) {
+ var name = this.GetCS(), macro = this.csFindMacro(name);
+ if (macro) {
+ if (!(macro instanceof Array)) {macro = [macro]}
+ var fn = macro[0]; if (!(fn instanceof Function)) {fn = this[fn]}
+ fn.apply(this,[c+name].concat(macro.slice(1)));
+ } else if (TEXDEF.mathchar0mi[name]) {this.csMathchar0mi(name,TEXDEF.mathchar0mi[name])}
+ else if (TEXDEF.mathchar0mo[name]) {this.csMathchar0mo(name,TEXDEF.mathchar0mo[name])}
+ else if (TEXDEF.mathchar7[name]) {this.csMathchar7(name,TEXDEF.mathchar7[name])}
+ else if (TEXDEF.delimiter["\\"+name] != null) {this.csDelimiter(name,TEXDEF.delimiter["\\"+name])}
+ else {this.csUndefined(c+name)}
+ },
+ //
+ // Look up a macro in the macros list
+ // (overridden in begingroup extension)
+ //
+ csFindMacro: function (name) {return TEXDEF.macros[name]},
+ //
+ // Handle normal mathchar (as an mi)
+ //
+ csMathchar0mi: function (name,mchar) {
+ var def = {mathvariant: MML.VARIANT.ITALIC};
+ if (mchar instanceof Array) {def = mchar[1]; mchar = mchar[0]}
+ this.Push(this.mmlToken(MML.mi(MML.entity("#x"+mchar)).With(def)));
+ },
+ //
+ // Handle normal mathchar (as an mo)
+ //
+ csMathchar0mo: function (name,mchar) {
+ var def = {stretchy: false};
+ if (mchar instanceof Array) {def = mchar[1]; def.stretchy = false; mchar = mchar[0]}
+ this.Push(this.mmlToken(MML.mo(MML.entity("#x"+mchar)).With(def)));
+ },
+ //
+ // Handle mathchar in current family
+ //
+ csMathchar7: function (name,mchar) {
+ var def = {mathvariant: MML.VARIANT.NORMAL};
+ if (mchar instanceof Array) {def = mchar[1]; mchar = mchar[0]}
+ if (this.stack.env.font) {def.mathvariant = this.stack.env.font}
+ this.Push(this.mmlToken(MML.mi(MML.entity("#x"+mchar)).With(def)));
+ },
+ //
+ // Handle delimiter
+ //
+ csDelimiter: function (name,delim) {
+ var def = {};
+ if (delim instanceof Array) {def = delim[1]; delim = delim[0]}
+ if (delim.length === 4) {delim = MML.entity('#x'+delim)} else {delim = MML.chars(delim)}
+ this.Push(this.mmlToken(MML.mo(delim).With({fence: false, stretchy: false}).With(def)));
+ },
+ //
+ // Handle undefined control sequence
+ // (overridden in noUndefined extension)
+ //
+ csUndefined: function (name) {
+ TEX.Error(["UndefinedControlSequence","Undefined control sequence %1",name]);
+ },
+
+ /*
+ * Handle a variable (a single letter)
+ */
+ Variable: function (c) {
+ var def = {}; if (this.stack.env.font) {def.mathvariant = this.stack.env.font}
+ this.Push(this.mmlToken(MML.mi(MML.chars(c)).With(def)));
+ },
+
+ /*
+ * Determine the extent of a number (pattern may need work)
+ */
+ Number: function (c) {
+ var mml, n = this.string.slice(this.i-1).match(TEXDEF.number);
+ if (n) {mml = MML.mn(n[0].replace(/[{}]/g,"")); this.i += n[0].length - 1}
+ else {mml = MML.mo(MML.chars(c))}
+ if (this.stack.env.font) {mml.mathvariant = this.stack.env.font}
+ this.Push(this.mmlToken(mml));
+ },
+
+ /*
+ * Handle { and }
+ */
+ Open: function (c) {this.Push(STACKITEM.open())},
+ Close: function (c) {this.Push(STACKITEM.close())},
+
+ /*
+ * Handle tilde and spaces
+ */
+ Tilde: function (c) {this.Push(MML.mtext(MML.chars(NBSP)))},
+ Space: function (c) {},
+
+ /*
+ * Handle ^, _, and '
+ */
+ Superscript: function (c) {
+ if (this.GetNext().match(/\d/)) // don't treat numbers as a unit
+ {this.string = this.string.substr(0,this.i+1)+" "+this.string.substr(this.i+1)}
+ var primes, base, top = this.stack.Top();
+ if (top.type === "prime") {base = top.data[0]; primes = top.data[1]; this.stack.Pop()}
+ else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}}
+ if (base.isEmbellishedWrapper) {base = base.data[0].data[0]}
+ var movesupsub = base.movesupsub, position = base.sup;
+ if ((base.type === "msubsup" && base.data[base.sup]) ||
+ (base.type === "munderover" && base.data[base.over] && !base.subsupOK))
+ {TEX.Error(["DoubleExponent","Double exponent: use braces to clarify"])}
+ if (base.type !== "msubsup") {
+ if (movesupsub) {
+ if (base.type !== "munderover" || base.data[base.over]) {
+ if (base.movablelimits && base.isa(MML.mi)) {base = this.mi2mo(base)}
+ base = MML.munderover(base,null,null).With({movesupsub:true})
+ }
+ position = base.over;
+ } else {
+ base = MML.msubsup(base,null,null);
+ position = base.sup;
+ }
+ }
+ this.Push(STACKITEM.subsup(base).With({
+ position: position, primes: primes, movesupsub: movesupsub
+ }));
+ },
+ Subscript: function (c) {
+ if (this.GetNext().match(/\d/)) // don't treat numbers as a unit
+ {this.string = this.string.substr(0,this.i+1)+" "+this.string.substr(this.i+1)}
+ var primes, base, top = this.stack.Top();
+ if (top.type === "prime") {base = top.data[0]; primes = top.data[1]; this.stack.Pop()}
+ else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}}
+ if (base.isEmbellishedWrapper) {base = base.data[0].data[0]}
+ var movesupsub = base.movesupsub, position = base.sub;
+ if ((base.type === "msubsup" && base.data[base.sub]) ||
+ (base.type === "munderover" && base.data[base.under] && !base.subsupOK))
+ {TEX.Error(["DoubleSubscripts","Double subscripts: use braces to clarify"])}
+ if (base.type !== "msubsup") {
+ if (movesupsub) {
+ if (base.type !== "munderover" || base.data[base.under]) {
+ if (base.movablelimits && base.isa(MML.mi)) {base = this.mi2mo(base)}
+ base = MML.munderover(base,null,null).With({movesupsub:true})
+ }
+ position = base.under;
+ } else {
+ base = MML.msubsup(base,null,null);
+ position = base.sub;
+ }
+ }
+ this.Push(STACKITEM.subsup(base).With({
+ position: position, primes: primes, movesupsub: movesupsub
+ }));
+ },
+ PRIME: "\u2032", SMARTQUOTE: "\u2019",
+ Prime: function (c) {
+ var base = this.stack.Prev(); if (!base) {base = MML.mi()}
+ if (base.type === "msubsup" && base.data[base.sup]) {
+ TEX.Error(["DoubleExponentPrime",
+ "Prime causes double exponent: use braces to clarify"]);
+ }
+ var sup = ""; this.i--;
+ do {sup += this.PRIME; this.i++, c = this.GetNext()}
+ while (c === "'" || c === this.SMARTQUOTE);
+ sup = ["","\u2032","\u2033","\u2034","\u2057"][sup.length] || sup;
+ this.Push(STACKITEM.prime(base,this.mmlToken(MML.mo(sup))));
+ },
+ mi2mo: function (mi) {
+ var mo = MML.mo(); mo.Append.apply(mo,mi.data); var id;
+ for (id in mo.defaults)
+ {if (mo.defaults.hasOwnProperty(id) && mi[id] != null) {mo[id] = mi[id]}}
+ for (id in MML.copyAttributes)
+ {if (MML.copyAttributes.hasOwnProperty(id) && mi[id] != null) {mo[id] = mi[id]}}
+ mo.lspace = mo.rspace = "0"; // prevent mo from having space in NativeMML
+ mo.useMMLspacing &= ~(mo.SPACE_ATTR.lspace | mo.SPACE_ATTR.rspace); // don't count these explicit settings
+ return mo;
+ },
+
+ /*
+ * Handle comments
+ */
+ Comment: function (c) {
+ while (this.i < this.string.length && this.string.charAt(this.i) != "\n") {this.i++}
+ },
+
+ /*
+ * Handle hash marks outside of definitions
+ */
+ Hash: function (c) {
+ TEX.Error(["CantUseHash1",
+ "You can't use 'macro parameter character #' in math mode"]);
+ },
+
+ /*
+ * Handle other characters (as elements)
+ */
+ Other: function (c) {
+ var def, mo;
+ if (this.stack.env.font) {def = {mathvariant: this.stack.env.font}}
+ if (TEXDEF.remap[c]) {
+ c = TEXDEF.remap[c];
+ if (c instanceof Array) {def = c[1]; c = c[0]}
+ mo = MML.mo(MML.entity('#x'+c)).With(def);
+ } else {
+ mo = MML.mo(c).With(def);
+ }
+ if (mo.autoDefault("stretchy",true)) {mo.stretchy = false}
+ if (mo.autoDefault("texClass",true) == "") {mo = MML.TeXAtom(mo)}
+ this.Push(this.mmlToken(mo));
+ },
+
+ /************************************************************************/
+ /*
+ * Macros
+ */
+
+ SetFont: function (name,font) {this.stack.env.font = font},
+ SetStyle: function (name,texStyle,style,level) {
+ this.stack.env.style = texStyle; this.stack.env.level = level;
+ this.Push(STACKITEM.style().With({styles: {displaystyle: style, scriptlevel: level}}));
+ },
+ SetSize: function (name,size) {
+ this.stack.env.size = size;
+ this.Push(STACKITEM.style().With({styles: {mathsize: size+"em"}})); // convert to absolute?
+ },
+
+ Color: function (name) {
+ var color = this.GetArgument(name);
+ var old = this.stack.env.color; this.stack.env.color = color;
+ var math = this.ParseArg(name);
+ if (old) {this.stack.env.color} else {delete this.stack.env.color}
+ this.Push(MML.mstyle(math).With({mathcolor: color}));
+ },
+
+ Spacer: function (name,space) {
+ this.Push(MML.mspace().With({width: space, mathsize: MML.SIZE.NORMAL, scriptlevel:0}));
+ },
+
+ LeftRight: function (name) {
+ this.Push(STACKITEM[name.substr(1)]().With({delim: this.GetDelimiter(name)}));
+ },
+
+ Middle: function (name) {
+ var delim = this.GetDelimiter(name);
+ if (this.stack.Top().type !== "left")
+ {TEX.Error(["MisplacedMiddle","%1 must be within \\left and \\right",name])}
+ this.Push(MML.mo(delim).With({stretchy:true}));
+ },
+
+ NamedFn: function (name,id) {
+ if (!id) {id = name.substr(1)};
+ var mml = MML.mi(id).With({texClass: MML.TEXCLASS.OP});
+ this.Push(STACKITEM.fn(this.mmlToken(mml)));
+ },
+ NamedOp: function (name,id) {
+ if (!id) {id = name.substr(1)};
+ id = id.replace(/ /,"\u2006");
+ var mml = MML.mo(id).With({
+ movablelimits: true,
+ movesupsub: true,
+ form: MML.FORM.PREFIX,
+ texClass: MML.TEXCLASS.OP
+ });
+ mml.useMMLspacing &= ~mml.SPACE_ATTR.form; // don't count this explicit form setting
+ this.Push(this.mmlToken(mml));
+ },
+ Limits: function (name,limits) {
+ var op = this.stack.Prev("nopop");
+ if (!op || (op.Get("texClass") !== MML.TEXCLASS.OP && op.movesupsub == null))
+ {TEX.Error(["MisplacedLimits","%1 is allowed only on operators",name])}
+ var top = this.stack.Top();
+ if (op.type === "munderover" && !limits) {
+ op = top.data[top.data.length-1] = MML.msubsup.apply(MML.subsup,op.data);
+ } else if (op.type === "msubsup" && limits) {
+ op = top.data[top.data.length-1] = MML.munderover.apply(MML.underover,op.data);
+ }
+ op.movesupsub = (limits ? true : false);
+ op.Core().movablelimits = false;
+ if (op.movablelimits) op.movablelimits = false;
+ },
+
+ Over: function (name,open,close) {
+ var mml = STACKITEM.over().With({name: name});
+ if (open || close) {
+ mml.open = open; mml.close = close;
+ } else if (name.match(/withdelims$/)) {
+ mml.open = this.GetDelimiter(name);
+ mml.close = this.GetDelimiter(name);
+ }
+ if (name.match(/^\\above/)) {mml.thickness = this.GetDimen(name)}
+ else if (name.match(/^\\atop/) || open || close) {mml.thickness = 0}
+ this.Push(mml);
+ },
+
+ Frac: function (name) {
+ var num = this.ParseArg(name);
+ var den = this.ParseArg(name);
+ this.Push(MML.mfrac(num,den));
+ },
+
+ Sqrt: function (name) {
+ var n = this.GetBrackets(name), arg = this.GetArgument(name);
+ if (arg === "\\frac") {arg += "{"+this.GetArgument(arg)+"}{"+this.GetArgument(arg)+"}"}
+ var mml = TEX.Parse(arg,this.stack.env).mml();
+ if (!n) {mml = MML.msqrt.apply(MML,mml.array())}
+ else {mml = MML.mroot(mml,this.parseRoot(n))}
+ this.Push(mml);
+ },
+ Root: function (name) {
+ var n = this.GetUpTo(name,"\\of");
+ var arg = this.ParseArg(name);
+ this.Push(MML.mroot(arg,this.parseRoot(n)));
+ },
+ parseRoot: function (n) {
+ var env = this.stack.env, inRoot = env.inRoot; env.inRoot = true;
+ var parser = TEX.Parse(n,env); n = parser.mml(); var global = parser.stack.global;
+ if (global.leftRoot || global.upRoot) {
+ n = MML.mpadded(n);
+ if (global.leftRoot) {n.width = global.leftRoot}
+ if (global.upRoot) {n.voffset = global.upRoot; n.height = global.upRoot}
+ }
+ env.inRoot = inRoot;
+ return n;
+ },
+ MoveRoot: function (name,id) {
+ if (!this.stack.env.inRoot)
+ {TEX.Error(["MisplacedMoveRoot","%1 can appear only within a root",name])}
+ if (this.stack.global[id])
+ {TEX.Error(["MultipleMoveRoot","Multiple use of %1",name])}
+ var n = this.GetArgument(name);
+ if (!n.match(/-?[0-9]+/))
+ {TEX.Error(["IntegerArg","The argument to %1 must be an integer",name])}
+ n = (n/15)+"em";
+ if (n.substr(0,1) !== "-") {n = "+"+n}
+ this.stack.global[id] = n;
+ },
+
+ Accent: function (name,accent,stretchy) {
+ var c = this.ParseArg(name);
+ var def = {accent: true}; if (this.stack.env.font) {def.mathvariant = this.stack.env.font}
+ var mml = this.mmlToken(MML.mo(MML.entity("#x"+accent)).With(def));
+ mml.stretchy = (stretchy ? true : false);
+ this.Push(MML.TeXAtom(MML.munderover(c,null,mml).With({accent: true})));
+ },
+
+ UnderOver: function (name,c,stack,noaccent) {
+ var pos = {o: "over", u: "under"}[name.charAt(1)];
+ var base = this.ParseArg(name);
+ if (base.Get("movablelimits")) {base.movablelimits = false}
+ if (base.isa(MML.munderover) && base.isEmbellished()) {
+ base.Core().With({lspace:0,rspace:0}); // get spacing right for NativeMML
+ base = MML.mrow(MML.mo().With({rspace:0}),base); // add an empty so it's not embellished any more
+ }
+ var mml = MML.munderover(base,null,null);
+ mml.SetData(
+ mml[pos],
+ this.mmlToken(MML.mo(MML.entity("#x"+c)).With({stretchy:true, accent:!noaccent}))
+ );
+ if (stack) {mml = MML.TeXAtom(mml).With({texClass:MML.TEXCLASS.OP, movesupsub:true})}
+ this.Push(mml.With({subsupOK:true}));
+ },
+
+ Overset: function (name) {
+ var top = this.ParseArg(name), base = this.ParseArg(name);
+ if (base.movablelimits) base.movablelimits = false;
+ this.Push(MML.mover(base,top));
+ },
+ Underset: function (name) {
+ var bot = this.ParseArg(name), base = this.ParseArg(name);
+ if (base.movablelimits) base.movablelimits = false;
+ this.Push(MML.munder(base,bot));
+ },
+
+ TeXAtom: function (name,mclass) {
+ var def = {texClass: mclass}, mml;
+ if (mclass == MML.TEXCLASS.OP) {
+ def.movesupsub = def.movablelimits = true;
+ var arg = this.GetArgument(name);
+ var match = arg.match(/^\s*\\rm\s+([a-zA-Z0-9 ]+)$/);
+ if (match) {
+ def.mathvariant = MML.VARIANT.NORMAL;
+ mml = STACKITEM.fn(this.mmlToken(MML.mi(match[1]).With(def)));
+ } else {
+ mml = STACKITEM.fn(MML.TeXAtom(TEX.Parse(arg,this.stack.env).mml()).With(def));
+ }
+ } else {mml = MML.TeXAtom(this.ParseArg(name)).With(def)}
+ this.Push(mml);
+ },
+
+ MmlToken: function (name) {
+ var type = this.GetArgument(name),
+ attr = this.GetBrackets(name,"").replace(/^\s+/,""),
+ data = this.GetArgument(name),
+ def = {attrNames:[]}, match;
+ if (!MML[type] || !MML[type].prototype.isToken)
+ {TEX.Error(["NotMathMLToken","%1 is not a token element",type])}
+ while (attr !== "") {
+ match = attr.match(/^([a-z]+)\s*=\s*('[^']*'|"[^"]*"|[^ ,]*)\s*,?\s*/i);
+ if (!match)
+ {TEX.Error(["InvalidMathMLAttr","Invalid MathML attribute: %1",attr])}
+ if (MML[type].prototype.defaults[match[1]] == null && !this.MmlTokenAllow[match[1]]) {
+ TEX.Error(["UnknownAttrForElement",
+ "%1 is not a recognized attribute for %2",
+ match[1],type]);
+ }
+ var value = this.MmlFilterAttribute(match[1],match[2].replace(/^(['"])(.*)\1$/,"$2"));
+ if (value) {
+ if (value.toLowerCase() === "true") {value = true}
+ else if (value.toLowerCase() === "false") {value = false}
+ def[match[1]] = value;
+ def.attrNames.push(match[1]);
+ }
+ attr = attr.substr(match[0].length);
+ }
+ this.Push(this.mmlToken(MML[type](data).With(def)));
+ },
+ MmlFilterAttribute: function (name,value) {return value},
+ MmlTokenAllow: {
+ fontfamily:1, fontsize:1, fontweight:1, fontstyle:1,
+ color:1, background:1,
+ id:1, "class":1, href:1, style:1
+ },
+
+ Strut: function (name) {
+ this.Push(MML.mpadded(MML.mrow()).With({height: "8.6pt", depth: "3pt", width: 0}));
+ },
+
+ Phantom: function (name,v,h) {
+ var box = MML.mphantom(this.ParseArg(name));
+ if (v || h) {
+ box = MML.mpadded(box);
+ if (h) {box.height = box.depth = 0}
+ if (v) {box.width = 0}
+ }
+ this.Push(MML.TeXAtom(box));
+ },
+
+ Smash: function (name) {
+ var bt = this.trimSpaces(this.GetBrackets(name,""));
+ var smash = MML.mpadded(this.ParseArg(name));
+ switch (bt) {
+ case "b": smash.depth = 0; break;
+ case "t": smash.height = 0; break;
+ default: smash.height = smash.depth = 0;
+ }
+ this.Push(MML.TeXAtom(smash));
+ },
+
+ Lap: function (name) {
+ var mml = MML.mpadded(this.ParseArg(name)).With({width: 0});
+ if (name === "\\llap") {mml.lspace = "-1width"}
+ this.Push(MML.TeXAtom(mml));
+ },
+
+ RaiseLower: function (name) {
+ var h = this.GetDimen(name);
+ var item = STACKITEM.position().With({name: name, move: 'vertical'});
+ if (h.charAt(0) === '-') {h = h.slice(1); name = {raise: "\\lower", lower: "\\raise"}[name.substr(1)]}
+ if (name === "\\lower") {item.dh = '-'+h; item.dd = '+'+h} else {item.dh = '+'+h; item.dd = '-'+h}
+ this.Push(item);
+ },
+
+ MoveLeftRight: function (name) {
+ var h = this.GetDimen(name);
+ var nh = (h.charAt(0) === '-' ? h.slice(1) : '-'+h);
+ if (name === "\\moveleft") {var tmp = h; h = nh; nh = tmp}
+ this.Push(STACKITEM.position().With({
+ name: name, move: 'horizontal',
+ left: MML.mspace().With({width: h, mathsize: MML.SIZE.NORMAL}),
+ right: MML.mspace().With({width: nh, mathsize: MML.SIZE.NORMAL})
+ }));
+ },
+
+ Hskip: function (name) {
+ this.Push(MML.mspace().With({width: this.GetDimen(name), mathsize: MML.SIZE.NORMAL}));
+ },
+
+ Rule: function (name,style) {
+ var w = this.GetDimen(name),
+ h = this.GetDimen(name),
+ d = this.GetDimen(name);
+ var mml, def = {width:w, height:h, depth:d};
+ if (style !== 'blank') {
+ if (parseFloat(w) && parseFloat(h)+parseFloat(d))
+ {def.mathbackground = (this.stack.env.color || "black")}
+ mml = MML.mpadded(MML.mrow()).With(def);
+ } else {
+ mml = MML.mspace().With(def);
+ }
+ this.Push(mml);
+ },
+
+ MakeBig: function (name,mclass,size) {
+ size *= TEXDEF.p_height;
+ size = String(size).replace(/(\.\d\d\d).+/,'$1')+"em";
+ var delim = this.GetDelimiter(name,true);
+ this.Push(MML.TeXAtom(MML.mo(delim).With({
+ minsize: size, maxsize: size,
+ fence: true, stretchy: true, symmetric: true
+ })).With({texClass: mclass}));
+ },
+
+ BuildRel: function (name) {
+ var top = this.ParseUpTo(name,"\\over");
+ var bot = this.ParseArg(name);
+ this.Push(MML.TeXAtom(MML.munderover(bot,null,top)).With({texClass: MML.TEXCLASS.REL}));
+ },
+
+ HBox: function (name,style) {
+ this.Push.apply(this,this.InternalMath(this.GetArgument(name),style));
+ },
+
+ FBox: function (name) {
+ this.Push(MML.menclose.apply(MML,this.InternalMath(this.GetArgument(name))).With({notation:"box"}));
+ },
+
+ Not: function (name) {
+ this.Push(STACKITEM.not());
+ },
+
+ Dots: function (name) {
+ this.Push(STACKITEM.dots().With({
+ ldots: this.mmlToken(MML.mo(MML.entity("#x2026")).With({stretchy:false})),
+ cdots: this.mmlToken(MML.mo(MML.entity("#x22EF")).With({stretchy:false}))
+ }));
+ },
+
+ Require: function (name) {
+ var file = this.GetArgument(name)
+ .replace(/.*\//,"") // remove any leading path
+ .replace(/[^a-z0-9_.-]/ig,""); // remove illegal characters
+ this.Extension(null,file);
+ },
+
+ Extension: function (name,file,array) {
+ if (name && !typeof(name) === "string") {name = name.name}
+ file = TEX.extensionDir+"/"+file;
+ if (!file.match(/\.js$/)) {file += ".js"}
+ if (!AJAX.loaded[AJAX.fileURL(file)]) {
+ if (name != null) {delete TEXDEF[array || 'macros'][name.replace(/^\\/,"")]}
+ HUB.RestartAfter(AJAX.Require(file));
+ }
+ },
+
+ Macro: function (name,macro,argcount,def) {
+ if (argcount) {
+ var args = [];
+ if (def != null) {
+ var optional = this.GetBrackets(name);
+ args.push(optional == null ? def : optional);
+ }
+ for (var i = args.length; i < argcount; i++) {args.push(this.GetArgument(name))}
+ macro = this.SubstituteArgs(args,macro);
+ }
+ this.string = this.AddArgs(macro,this.string.slice(this.i));
+ this.i = 0;
+ if (++this.macroCount > TEX.config.MAXMACROS) {
+ TEX.Error(["MaxMacroSub1",
+ "MathJax maximum macro substitution count exceeded; " +
+ "is there a recursive macro call?"]);
+ }
+ },
+
+ Matrix: function (name,open,close,align,spacing,vspacing,style,cases,numbered) {
+ var c = this.GetNext();
+ if (c === "")
+ {TEX.Error(["MissingArgFor","Missing argument for %1",name])}
+ if (c === "{") {this.i++} else {this.string = c+"}"+this.string.slice(this.i+1); this.i = 0}
+ var array = STACKITEM.array().With({
+ requireClose: true,
+ arraydef: {
+ rowspacing: (vspacing||"4pt"),
+ columnspacing: (spacing||"1em")
+ }
+ });
+ if (cases) {array.isCases = true}
+ if (numbered) {array.isNumbered = true; array.arraydef.side = numbered}
+ if (open || close) {array.open = open; array.close = close}
+ if (style === "D") {array.arraydef.displaystyle = true}
+ if (align != null) {array.arraydef.columnalign = align}
+ this.Push(array);
+ },
+
+ Entry: function (name) {
+ this.Push(STACKITEM.cell().With({isEntry: true, name: name}));
+ if (this.stack.Top().isCases) {
+ var string = this.string;
+ var braces = 0, i = this.i, m = string.length;
+ while (i < m) {
+ var c = string.charAt(i);
+ if (c === "{") {braces++; i++}
+ else if (c === "}") {if (braces === 0) {m = 0} else {braces--; i++}}
+ else if (c === "&" && braces === 0) {
+ TEX.Error(["ExtraAlignTab","Extra alignment tab in \\cases text"]);
+ } else if (c === "\\") {
+ if (string.substr(i).match(/^((\\cr)[^a-zA-Z]|\\\\)/)) {m = 0} else {i += 2}
+ } else {i++}
+ }
+ var text = string.substr(this.i,i-this.i);
+ if (!text.match(/^\s*\\text[^a-zA-Z]/)) {
+ this.Push.apply(this,this.InternalMath(text,0));
+ this.i = i;
+ }
+ }
+ },
+
+ Cr: function (name) {
+ this.Push(STACKITEM.cell().With({isCR: true, name: name}));
+ },
+
+ CrLaTeX: function (name) {
+ var n;
+ if (this.string.charAt(this.i) === "[") {
+ n = this.GetBrackets(name,"").replace(/ /g,"").replace(/,/,".");
+ if (n && !this.matchDimen(n)) {
+ TEX.Error(["BracketMustBeDimension",
+ "Bracket argument to %1 must be a dimension",name]);
+ }
+ }
+ this.Push(STACKITEM.cell().With({isCR: true, name: name, linebreak: true}));
+ var top = this.stack.Top();
+ if (top.isa(STACKITEM.array)) {
+ if (n && top.arraydef.rowspacing) {
+ var rows = top.arraydef.rowspacing.split(/ /);
+ if (!top.rowspacing) {top.rowspacing = this.dimen2em(rows[0])}
+ while (rows.length < top.table.length) {rows.push(this.Em(top.rowspacing))}
+ rows[top.table.length-1] = this.Em(Math.max(0,top.rowspacing+this.dimen2em(n)));
+ top.arraydef.rowspacing = rows.join(' ');
+ }
+ } else {
+ if (n) {this.Push(MML.mspace().With({depth:n}))}
+ this.Push(MML.mspace().With({linebreak:MML.LINEBREAK.NEWLINE}));
+ }
+ },
+ emPerInch: 7.2,
+ pxPerInch: 72,
+ matchDimen: function (dim) {
+ return dim.match(/^(-?(?:\.\d+|\d+(?:\.\d*)?))(px|pt|em|ex|mu|pc|in|mm|cm)$/);
+ },
+ dimen2em: function (dim) {
+ var match = this.matchDimen(dim);
+ var m = parseFloat(match[1]||"1"), unit = match[2];
+ if (unit === "em") {return m}
+ if (unit === "ex") {return m * .43}
+ if (unit === "pt") {return m / 10} // 10 pt to an em
+ if (unit === "pc") {return m * 1.2} // 12 pt to a pc
+ if (unit === "px") {return m * this.emPerInch / this.pxPerInch}
+ if (unit === "in") {return m * this.emPerInch}
+ if (unit === "cm") {return m * this.emPerInch / 2.54} // 2.54 cm to an inch
+ if (unit === "mm") {return m * this.emPerInch / 25.4} // 10 mm to a cm
+ if (unit === "mu") {return m / 18}
+ return 0;
+ },
+ Em: function (m) {
+ if (Math.abs(m) < .0006) {return "0em"}
+ return m.toFixed(3).replace(/\.?0+$/,"") + "em";
+ },
+
+ HLine: function (name,style) {
+ if (style == null) {style = "solid"}
+ var top = this.stack.Top();
+ if (!top.isa(STACKITEM.array) || top.data.length)
+ {TEX.Error(["Misplaced","Misplaced %1",name])}
+ if (top.table.length == 0) {
+ top.frame.push("top");
+ } else {
+ var lines = (top.arraydef.rowlines ? top.arraydef.rowlines.split(/ /) : []);
+ while (lines.length < top.table.length) {lines.push("none")}
+ lines[top.table.length-1] = style;
+ top.arraydef.rowlines = lines.join(' ');
+ }
+ },
+
+ HFill: function (name) {
+ var top = this.stack.Top();
+ if (top.isa(STACKITEM.array)) top.hfill.push(top.data.length);
+ else TEX.Error(["UnsupportedHFill","Unsupported use of %1",name]);
+ },
+
+
+
+ /************************************************************************/
+ /*
+ * LaTeX environments
+ */
+
+ BeginEnd: function (name) {
+ var env = this.GetArgument(name), isEnd = false;
+ if (env.match(/^\\end\\/)) {isEnd = true; env = env.substr(5)} // special \end{} for \newenvironment environments
+ if (env.match(/\\/i)) {TEX.Error(["InvalidEnv","Invalid environment name '%1'",env])}
+ var cmd = this.envFindName(env);
+ if (!cmd) {TEX.Error(["UnknownEnv","Unknown environment '%1'",env])}
+ if (!(cmd instanceof Array)) {cmd = [cmd]}
+ var end = (cmd[1] instanceof Array ? cmd[1][0] : cmd[1]);
+ var mml = STACKITEM.begin().With({name: env, end: end, parse:this});
+ if (name === "\\end") {
+ if (!isEnd && cmd[1] instanceof Array && this[cmd[1][1]]) {
+ mml = this[cmd[1][1]].apply(this,[mml].concat(cmd.slice(2)));
+ } else {
+ mml = STACKITEM.end().With({name: env});
+ }
+ } else {
+ if (++this.macroCount > TEX.config.MAXMACROS) {
+ TEX.Error(["MaxMacroSub2",
+ "MathJax maximum substitution count exceeded; " +
+ "is there a recursive latex environment?"]);
+ }
+ if (cmd[0] && this[cmd[0]]) {mml = this[cmd[0]].apply(this,[mml].concat(cmd.slice(2)))}
+ }
+ this.Push(mml);
+ },
+ envFindName: function (name) {return TEXDEF.environment[name]},
+
+ Equation: function (begin,row) {return row},
+
+ ExtensionEnv: function (begin,file) {this.Extension(begin.name,file,"environment")},
+
+ Array: function (begin,open,close,align,spacing,vspacing,style,raggedHeight) {
+ if (!align) {align = this.GetArgument("\\begin{"+begin.name+"}")}
+ var lines = ("c"+align).replace(/[^clr|:]/g,'').replace(/[^|:]([|:])+/g,'$1');
+ align = align.replace(/[^clr]/g,'').split('').join(' ');
+ align = align.replace(/l/g,'left').replace(/r/g,'right').replace(/c/g,'center');
+ var array = STACKITEM.array().With({
+ arraydef: {
+ columnalign: align,
+ columnspacing: (spacing||"1em"),
+ rowspacing: (vspacing||"4pt")
+ }
+ });
+ if (lines.match(/[|:]/)) {
+ if (lines.charAt(0).match(/[|:]/)) {array.frame.push("left"); array.frame.dashed = lines.charAt(0) === ":"}
+ if (lines.charAt(lines.length-1).match(/[|:]/)) {array.frame.push("right")}
+ lines = lines.substr(1,lines.length-2);
+ array.arraydef.columnlines =
+ lines.split('').join(' ').replace(/[^|: ]/g,'none').replace(/\|/g,'solid').replace(/:/g,'dashed');
+ }
+ if (open) {array.open = this.convertDelimiter(open)}
+ if (close) {array.close = this.convertDelimiter(close)}
+ if (style === "D") {array.arraydef.displaystyle = true}
+ else if (style) {array.arraydef.displaystyle = false}
+ if (style === "S") {array.arraydef.scriptlevel = 1} // FIXME: should use mstyle?
+ if (raggedHeight) {array.arraydef.useHeight = false}
+ this.Push(begin);
+ return array;
+ },
+
+ AlignedArray: function (begin) {
+ var align = this.GetBrackets("\\begin{"+begin.name+"}");
+ return this.setArrayAlign(this.Array.apply(this,arguments),align);
+ },
+ setArrayAlign: function (array,align) {
+ align = this.trimSpaces(align||"");
+ if (align === "t") {array.arraydef.align = "baseline 1"}
+ else if (align === "b") {array.arraydef.align = "baseline -1"}
+ else if (align === "c") {array.arraydef.align = "center"}
+ else if (align) {array.arraydef.align = align} // FIXME: should be an error?
+ return array;
+ },
+
+ /************************************************************************/
+ /*
+ * String handling routines
+ */
+
+ /*
+ * Convert delimiter to character
+ */
+ convertDelimiter: function (c) {
+ if (c) {c = TEXDEF.delimiter[c]}
+ if (c == null) {return null}
+ if (c instanceof Array) {c = c[0]}
+ if (c.length === 4) {c = String.fromCharCode(parseInt(c,16))}
+ return c;
+ },
+
+ /*
+ * Trim spaces from a string
+ */
+ trimSpaces: function (text) {
+ if (typeof(text) != 'string') {return text}
+ return text.replace(/^\s+|\s+$/g,'');
+ },
+
+ /*
+ * Check if the next character is a space
+ */
+ nextIsSpace: function () {
+ return this.string.charAt(this.i).match(/\s/);
+ },
+
+ /*
+ * Get the next non-space character
+ */
+ GetNext: function () {
+ while (this.nextIsSpace()) {this.i++}
+ return this.string.charAt(this.i);
+ },
+
+ /*
+ * Get and return a control-sequence name
+ */
+ GetCS: function () {
+ var CS = this.string.slice(this.i).match(/^([a-z]+|.) ?/i);
+ if (CS) {this.i += CS[1].length; return CS[1]} else {this.i++; return " "}
+ },
+
+ /*
+ * Get and return a TeX argument (either a single character or control sequence,
+ * or the contents of the next set of braces).
+ */
+ GetArgument: function (name,noneOK) {
+ switch (this.GetNext()) {
+ case "":
+ if (!noneOK) {TEX.Error(["MissingArgFor","Missing argument for %1",name])}
+ return null;
+ case '}':
+ if (!noneOK) {
+ TEX.Error(["ExtraCloseMissingOpen",
+ "Extra close brace or missing open brace"]);
+ }
+ return null;
+ case '\\':
+ this.i++; return "\\"+this.GetCS();
+ case '{':
+ var j = ++this.i, parens = 1;
+ while (this.i < this.string.length) {
+ switch (this.string.charAt(this.i++)) {
+ case '\\': this.i++; break;
+ case '{': parens++; break;
+ case '}':
+ if (--parens == 0) {return this.string.slice(j,this.i-1)}
+ break;
+ }
+ }
+ TEX.Error(["MissingCloseBrace","Missing close brace"]);
+ break;
+ }
+ return this.string.charAt(this.i++);
+ },
+
+ /*
+ * Get an optional LaTeX argument in brackets
+ */
+ GetBrackets: function (name,def) {
+ if (this.GetNext() != '[') {return def};
+ var j = ++this.i, parens = 0;
+ while (this.i < this.string.length) {
+ switch (this.string.charAt(this.i++)) {
+ case '{': parens++; break;
+ case '\\': this.i++; break;
+ case '}':
+ if (parens-- <= 0) {
+ TEX.Error(["ExtraCloseLooking",
+ "Extra close brace while looking for %1","']'"]);
+ }
+ break;
+ case ']':
+ if (parens == 0) {return this.string.slice(j,this.i-1)}
+ break;
+ }
+ }
+ TEX.Error(["MissingCloseBracket",
+ "Couldn't find closing ']' for argument to %1",name]);
+ },
+
+ /*
+ * Get the name of a delimiter (check it in the delimiter list).
+ */
+ GetDelimiter: function (name,braceOK) {
+ while (this.nextIsSpace()) {this.i++}
+ var c = this.string.charAt(this.i); this.i++;
+ if (this.i <= this.string.length) {
+ if (c == "\\") {c += this.GetCS(name)}
+ else if (c === "{" && braceOK) {this.i--; c = this.GetArgument(name)}
+ if (TEXDEF.delimiter[c] != null) {return this.convertDelimiter(c)}
+ }
+ TEX.Error(["MissingOrUnrecognizedDelim",
+ "Missing or unrecognized delimiter for %1",name]);
+ },
+
+ /*
+ * Get a dimension (including its units).
+ */
+ GetDimen: function (name) {
+ var dimen;
+ if (this.nextIsSpace()) {this.i++}
+ if (this.string.charAt(this.i) == '{') {
+ dimen = this.GetArgument(name);
+ if (dimen.match(/^\s*([-+]?([.,]\d+|\d+([.,]\d*)?))\s*(pt|em|ex|mu|px|mm|cm|in|pc)\s*$/))
+ {return dimen.replace(/ /g,"").replace(/,/,".")}
+ } else {
+ dimen = this.string.slice(this.i);
+ var match = dimen.match(/^\s*(([-+]?([.,]\d+|\d+([.,]\d*)?))\s*(pt|em|ex|mu|px|mm|cm|in|pc)) ?/);
+ if (match) {
+ this.i += match[0].length;
+ return match[1].replace(/ /g,"").replace(/,/,".");
+ }
+ }
+ TEX.Error(["MissingDimOrUnits",
+ "Missing dimension or its units for %1",name]);
+ },
+
+ /*
+ * Get everything up to the given control sequence (token)
+ */
+ GetUpTo: function (name,token) {
+ while (this.nextIsSpace()) {this.i++}
+ var j = this.i, k, c, parens = 0;
+ while (this.i < this.string.length) {
+ k = this.i; c = this.string.charAt(this.i++);
+ switch (c) {
+ case '\\': c += this.GetCS(); break;
+ case '{': parens++; break;
+ case '}':
+ if (parens == 0) {
+ TEX.Error(["ExtraCloseLooking",
+ "Extra close brace while looking for %1",token])
+ }
+ parens--;
+ break;
+ }
+ if (parens == 0 && c == token) {return this.string.slice(j,k)}
+ }
+ TEX.Error(["TokenNotFoundForCommand",
+ "Couldn't find %1 for %2",token,name]);
+ },
+
+ /*
+ * Parse various substrings
+ */
+ ParseArg: function (name) {return TEX.Parse(this.GetArgument(name),this.stack.env).mml()},
+ ParseUpTo: function (name,token) {return TEX.Parse(this.GetUpTo(name,token),this.stack.env).mml()},
+
+ /*
+ * Break up a string into text and math blocks
+ */
+ InternalMath: function (text,level) {
+ var def = (this.stack.env.font ? {mathvariant: this.stack.env.font} : {});
+ var mml = [], i = 0, k = 0, c, match = '', braces = 0;
+ if (text.match(/\\?[${}\\]|\\\(|\\(eq)?ref\s*\{/)) {
+ while (i < text.length) {
+ c = text.charAt(i++);
+ if (c === '$') {
+ if (match === '$' && braces === 0) {
+ mml.push(MML.TeXAtom(TEX.Parse(text.slice(k,i-1),{}).mml()));
+ match = ''; k = i;
+ } else if (match === '') {
+ if (k < i-1) mml.push(this.InternalText(text.slice(k,i-1),def));
+ match = '$'; k = i;
+ }
+ } else if (c === '{' && match !== '') {
+ braces++;
+ } else if (c === '}') {
+ if (match === '}' && braces === 0) {
+ mml.push(MML.TeXAtom(TEX.Parse(text.slice(k,i),{}).mml().With(def)));
+ match = ''; k = i;
+ } else if (match !== '') {
+ if (braces) braces--;
+ }
+ } else if (c === '\\') {
+ if (match === '' && text.substr(i).match(/^(eq)?ref\s*\{/)) {
+ var len = RegExp["$&"].length;
+ if (k < i-1) mml.push(this.InternalText(text.slice(k,i-1),def));
+ match = '}'; k = i-1; i += len;
+ } else {
+ c = text.charAt(i++);
+ if (c === '(' && match === '') {
+ if (k < i-2) mml.push(this.InternalText(text.slice(k,i-2),def));
+ match = ')'; k = i;
+ } else if (c === ')' && match === ')' && braces === 0) {
+ mml.push(MML.TeXAtom(TEX.Parse(text.slice(k,i-2),{}).mml()));
+ match = ''; k = i;
+ } else if (c.match(/[${}\\]/) && match === '') {
+ i--; text = text.substr(0,i-1) + text.substr(i); // remove \ from \$, \{, \}, or \\
+ }
+ }
+ }
+ }
+ if (match !== '') TEX.Error(["MathNotTerminated","Math not terminated in text box"]);
+ }
+ if (k < text.length) mml.push(this.InternalText(text.slice(k),def));
+ if (level != null) {
+ mml = [MML.mstyle.apply(MML,mml).With({displaystyle:false,scriptlevel:level})];
+ } else if (mml.length > 1) {
+ mml = [MML.mrow.apply(MML,mml)];
+ }
+ return mml;
+ },
+ InternalText: function (text,def) {
+ text = text.replace(/^\s+/,NBSP).replace(/\s+$/,NBSP);
+ return MML.mtext(MML.chars(text)).With(def);
+ },
+
+ /*
+ * Replace macro paramters with their values
+ */
+ SubstituteArgs: function (args,string) {
+ var text = ''; var newstring = ''; var c; var i = 0;
+ while (i < string.length) {
+ c = string.charAt(i++);
+ if (c === "\\") {text += c + string.charAt(i++)}
+ else if (c === '#') {
+ c = string.charAt(i++);
+ if (c === '#') {text += c} else {
+ if (!c.match(/[1-9]/) || c > args.length) {
+ TEX.Error(["IllegalMacroParam",
+ "Illegal macro parameter reference"]);
+ }
+ newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]);
+ text = '';
+ }
+ } else {text += c}
+ }
+ return this.AddArgs(newstring,text);
+ },
+
+ /*
+ * Make sure that macros are followed by a space if their names
+ * could accidentally be continued into the following text.
+ */
+ AddArgs: function (s1,s2) {
+ if (s2.match(/^[a-z]/i) && s1.match(/(^|[^\\])(\\\\)*\\[a-z]+$/i)) {s1 += ' '}
+ if (s1.length + s2.length > TEX.config.MAXBUFFER) {
+ TEX.Error(["MaxBufferSize",
+ "MathJax internal buffer size exceeded; is there a recursive macro call?"]);
+ }
+ return s1+s2;
+ }
+
+ });
+
+ /************************************************************************/
+
+ TEX.Augment({
+ Stack: STACK, Parse: PARSE, Definitions: TEXDEF, Startup: STARTUP,
+
+ config: {
+ MAXMACROS: 10000, // maximum number of macro substitutions per equation
+ MAXBUFFER: 5*1024 // maximum size of TeX string to process
+ },
+
+ sourceMenuTitle: /*_(MathMenu)*/ ["TeXCommands","TeX Commands"],
+ annotationEncoding: "application/x-tex",
+
+ prefilterHooks: MathJax.Callback.Hooks(true), // hooks to run before processing TeX
+ postfilterHooks: MathJax.Callback.Hooks(true), // hooks to run after processing TeX
+
+ //
+ // Check if AMSmath extension must be loaded and push
+ // it on the extensions array, if needed
+ //
+ Config: function () {
+ this.SUPER(arguments).Config.apply(this,arguments);
+ if (this.config.equationNumbers.autoNumber !== "none") {
+ if (!this.config.extensions) {this.config.extensions = []}
+ this.config.extensions.push("AMSmath.js");
+ }
+ },
+
+ //
+ // Convert TeX to ElementJax
+ //
+ Translate: function (script) {
+ var mml, isError = false, math = MathJax.HTML.getScript(script);
+ var display = (script.type.replace(/\n/g," ").match(/(;|\s|\n)mode\s*=\s*display(;|\s|\n|$)/) != null);
+ var data = {math:math, display:display, script:script};
+ var callback = this.prefilterHooks.Execute(data); if (callback) return callback;
+ math = data.math;
+ try {
+ mml = TEX.Parse(math).mml();
+ } catch(err) {
+ if (!err.texError) {throw err}
+ mml = this.formatError(err,math,display,script);
+ isError = true;
+ }
+ if (mml.isa(MML.mtable) && mml.displaystyle === "inherit") mml.displaystyle = display; // for tagged equations
+ if (mml.inferred) {mml = MML.apply(MathJax.ElementJax,mml.data)} else {mml = MML(mml)}
+ if (display) {mml.root.display = "block"}
+ if (isError) {mml.texError = true}
+ data.math = mml;
+ return this.postfilterHooks.Execute(data) || data.math;
+ },
+ prefilterMath: function (math,displaystyle,script) {
+ return math;
+ },
+ postfilterMath: function (math,displaystyle,script) {
+ this.combineRelations(math.root);
+ return math;
+ },
+ formatError: function (err,math,display,script) {
+ var message = err.message.replace(/\n.*/,"");
+ HUB.signal.Post(["TeX Jax - parse error",message,math,display,script]);
+ return MML.Error(message);
+ },
+
+ //
+ // Produce an error and stop processing this equation
+ //
+ Error: function (message) {
+ //
+ // Translate message if it is ["id","message",args]
+ //
+ if (message instanceof Array) {message = _.apply(_,message)}
+ throw HUB.Insert(Error(message),{texError: true});
+ },
+
+ //
+ // Add a user-defined macro to the macro list
+ //
+ Macro: function (name,def,argn) {
+ TEXDEF.macros[name] = ['Macro'].concat([].slice.call(arguments,1));
+ TEXDEF.macros[name].isUser = true;
+ },
+
+ /*
+ * Create an mrow that has stretchy delimiters at either end, as needed
+ */
+ fenced: function (open,mml,close) {
+ var mrow = MML.mrow().With({open:open, close:close, texClass:MML.TEXCLASS.INNER});
+ mrow.Append(MML.mo(open).With({fence:true, stretchy:true, texClass:MML.TEXCLASS.OPEN}));
+ if (mml.type === "mrow") {mrow.Append.apply(mrow,mml.data)} else {mrow.Append(mml)}
+ mrow.Append(MML.mo(close).With({fence:true, stretchy:true, texClass:MML.TEXCLASS.CLOSE}));
+ return mrow;
+ },
+ /*
+ * Create an mrow that has \mathchoice using \bigg and \big for the delimiters
+ */
+ fixedFence: function (open,mml,close) {
+ var mrow = MML.mrow().With({open:open, close:close, texClass:MML.TEXCLASS.ORD});
+ if (open) {mrow.Append(this.mathPalette(open,"l"))}
+ if (mml.type === "mrow") {mrow.Append.apply(mrow,mml.data)} else {mrow.Append(mml)}
+ if (close) {mrow.Append(this.mathPalette(close,"r"))}
+ return mrow;
+ },
+ mathPalette: function (fence,side) {
+ if (fence === '{' || fence === '}') {fence = "\\"+fence}
+ var D = '{\\bigg'+side+' '+fence+'}', T = '{\\big'+side+' '+fence+'}';
+ return TEX.Parse('\\mathchoice'+D+T+T+T,{}).mml();
+ },
+
+ //
+ // Combine adjacent elements that are relations
+ // (since MathML treats the spacing very differently)
+ //
+ combineRelations: function (mml) {
+ var i, m, m1, m2;
+ for (i = 0, m = mml.data.length; i < m; i++) {
+ if (mml.data[i]) {
+ if (mml.isa(MML.mrow)) {
+ while (i+1 < m && (m1 = mml.data[i]) && (m2 = mml.data[i+1]) &&
+ m1.isa(MML.mo) && m2.isa(MML.mo) &&
+ m1.Get("texClass") === MML.TEXCLASS.REL &&
+ m2.Get("texClass") === MML.TEXCLASS.REL) {
+ if (m1.variantForm == m2.variantForm &&
+ m1.Get("mathvariant") == m2.Get("mathvariant") && m1.style == m2.style &&
+ m1["class"] == m2["class"] && !m1.id && !m2.id) {
+ m1.Append.apply(m1,m2.data);
+ mml.data.splice(i+1,1); m--;
+ } else {
+ m1.rspace = m2.lspace = "0pt"; i++;
+ }
+ }
+ }
+ if (!mml.data[i].isToken) {this.combineRelations(mml.data[i])}
+ }
+ }
+ }
+ });
+
+ //
+ // Add the default filters
+ //
+ TEX.prefilterHooks.Add(function (data) {
+ data.math = TEX.prefilterMath(data.math,data.display,data.script);
+ });
+ TEX.postfilterHooks.Add(function (data) {
+ data.math = TEX.postfilterMath(data.math,data.display,data.script);
+ });
+
+ TEX.loadComplete("jax.js");
+
+})(MathJax.InputJax.TeX,MathJax.Hub,MathJax.Ajax);
diff --git a/MarkDownEditor/MathJax/jax/output/PreviewHTML/config.js b/MarkDownEditor/MathJax/jax/output/PreviewHTML/config.js
new file mode 100644
index 0000000..b9a7aeb
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/output/PreviewHTML/config.js
@@ -0,0 +1,54 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/jax/output/PreviewHTML/config.js
+ *
+ * Initializes the PreviewHTML OutputJax (the main definition is in
+ * MathJax/jax/input/PreviewHTML/jax.js, which is loaded when needed).
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2015 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.OutputJax.PreviewHTML = MathJax.OutputJax({
+ id: "PreviewHTML",
+ version: "2.6.1",
+ directory: MathJax.OutputJax.directory + "/PreviewHTML",
+ extensionDir: MathJax.OutputJax.extensionDir + "/PreviewHTML",
+ noFastPreview: true, // don't do fast preview for this output jax
+
+ config: {
+ scale: 100, minScaleAdjust: 50, // global math scaling factor, and minimum adjusted scale factor
+ mtextFontInherit: false, // to make be in page font rather than MathJax font
+
+ linebreaks: {
+ automatic: false, // when false, only process linebreak="newline",
+ // when true, insert line breaks automatically in long expressions.
+
+ width: "container" // maximum width of a line for automatic line breaks (e.g. "30em").
+ // use "container" to compute size from containing element,
+ // use "nn% container" for a portion of the container,
+ // use "nn%" for a portion of the window size
+ }
+
+ }
+});
+
+if (!MathJax.Hub.config.delayJaxRegistration) {MathJax.OutputJax.PreviewHTML.Register("jax/mml")}
+
+MathJax.OutputJax.PreviewHTML.loadComplete("config.js");
diff --git a/MarkDownEditor/MathJax/jax/output/PreviewHTML/jax.js b/MarkDownEditor/MathJax/jax/output/PreviewHTML/jax.js
new file mode 100644
index 0000000..1ff2c6c
--- /dev/null
+++ b/MarkDownEditor/MathJax/jax/output/PreviewHTML/jax.js
@@ -0,0 +1,1092 @@
+/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/*************************************************************
+ *
+ * MathJax/jax/output/PreviewHTML/jax.js
+ *
+ * Implements the PreviewHTML OutputJax that displays mathematics
+ * using HTML to position the characters from math fonts
+ * in their proper locations.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2013-2015 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.
+ */
+
+
+(function (AJAX,HUB,HTML,PHTML) {
+ var MML;
+
+ var EVENT, TOUCH, HOVER; // filled in later
+
+ var FONTS = "'Times New Roman',Times,STIXGeneral,serif";
+ var STYLES = {
+ ".MJXp-script": {"font-size":".8em"},
+
+ ".MJXp-right": {
+ "-webkit-transform-origin":"right",
+ "-moz-transform-origin":"right",
+ "-ms-transform-origin":"right",
+ "-o-transform-origin":"right",
+ "transform-origin":"right"
+ },
+
+ ".MJXp-bold": {"font-weight":"bold"},
+ ".MJXp-italic": {"font-style":"italic"},
+ ".MJXp-scr": {"font-family":"MathJax_Script,"+FONTS},
+ ".MJXp-frak": {"font-family":"MathJax_Fraktur,"+FONTS},
+ ".MJXp-sf": {"font-family":"MathJax_SansSerif,"+FONTS},
+ ".MJXp-cal": {"font-family":"MathJax_Caligraphic,"+FONTS},
+ ".MJXp-mono": {"font-family":"MathJax_Typewriter,"+FONTS},
+ ".MJXp-largeop": {"font-size":"150%"},
+ ".MJXp-largeop.MJXp-int": {"vertical-align":"-.2em"},
+
+ ".MJXp-math": {
+ "display": "inline-block",
+ "line-height": "1.2",
+ "text-indent": "0",
+ "font-family": FONTS,
+ "white-space":"nowrap",
+ "border-collapse":"collapse"
+ },
+ ".MJXp-display": {
+ "display": "block",
+ "text-align": "center",
+ "margin": "1em 0"
+ },
+ ".MJXp-math span": {"display": "inline-block"},
+ ".MJXp-box": {"display":"block!important", "text-align": "center"},
+ ".MJXp-box:after": {"content": '" "'}, // needed for when there is no DOCTYPE
+ ".MJXp-rule": {"display":"block!important", "margin-top":".1em"},
+ ".MJXp-char": {"display":"block!important"},
+
+ ".MJXp-mo": {"margin": "0 .15em"},
+
+ ".MJXp-mfrac": {"margin": "0 .125em", "vertical-align":".25em"},
+ ".MJXp-denom": {"display": "inline-table!important", "width":"100%"},
+ ".MJXp-denom > *": {"display": "table-row!important"},
+
+ ".MJXp-surd": {"vertical-align":"top"},
+ ".MJXp-surd > *": {"display":"block!important"},
+
+ ".MJXp-script-box > * ": {"display":"table!important", "height":"50%"},
+ ".MJXp-script-box > * > *": {"display":"table-cell!important","vertical-align":"top"},
+ ".MJXp-script-box > *:last-child > *": {"vertical-align":"bottom"},
+ ".MJXp-script-box > * > * > *": {"display":"block!important"},
+
+ ".MJXp-mphantom": {"visibility": "hidden"},
+
+ ".MJXp-munderover": {"display":"inline-table!important"},
+ ".MJXp-over": {"display":"inline-block!important","text-align":"center"},
+ ".MJXp-over > *": {"display":"block!important"},
+ ".MJXp-munderover > *": {"display":"table-row!important"},
+
+ ".MJXp-mtable": {"vertical-align":".25em", "margin":"0 .125em"},
+ ".MJXp-mtable > *": {"display":"inline-table!important", "vertical-align":"middle"},
+ ".MJXp-mtr": {"display":"table-row!important"},
+ ".MJXp-mtd": {"display":"table-cell!important","text-align":"center","padding":".5em 0 0 .5em"},
+ ".MJXp-mtr > .MJXp-mtd:first-child": {"padding-left":0},
+ ".MJXp-mtr:first-child > .MJXp-mtd": {"padding-top":0},
+ ".MJXp-mlabeledtr": {"display":"table-row!important"},
+ ".MJXp-mlabeledtr > .MJXp-mtd:first-child": {"padding-left":0},
+ ".MJXp-mlabeledtr:first-child > .MJXp-mtd": {"padding-top":0},
+
+ ".MJXp-merror": {
+ "background-color": "#FFFF88",
+ color: "#CC0000",
+ border: "1px solid #CC0000",
+ padding: "1px 3px",
+ "font-style": "normal",
+ "font-size": "90%"
+ }
+ };
+
+ (function () {
+ for (var i = 0; i < 10; i++) {
+ var scale = "scaleX(."+i+")";
+ STYLES[".MJXp-scale"+i] = {
+ "-webkit-transform":scale,
+ "-moz-transform":scale,
+ "-ms-transform":scale,
+ "-o-transform":scale,
+ "transform":scale
+ }
+ }
+ })();
+
+ var BIGDIMEN = 1000000;
+ var V = "V", H = "H";
+
+ PHTML.Augment({
+ settings: HUB.config.menuSettings,
+ config: {styles: STYLES},
+
+ hideProcessedMath: false, // use display:none until all math is processed
+
+ maxStretchyParts: 1000, // limit the number of parts allowed for
+ // stretchy operators. See issue 366.
+
+ Config: function () {
+ if (!this.require) {this.require = []}
+ this.SUPER(arguments).Config.call(this); var settings = this.settings;
+ if (settings.scale) {this.config.scale = settings.scale}
+ this.require.push(MathJax.OutputJax.extensionDir+"/MathEvents.js");
+ },
+
+ Startup: function () {
+ //
+ // Set up event handling
+ //
+ EVENT = MathJax.Extension.MathEvents.Event;
+ TOUCH = MathJax.Extension.MathEvents.Touch;
+ HOVER = MathJax.Extension.MathEvents.Hover;
+ this.ContextMenu = EVENT.ContextMenu;
+ this.Mousedown = EVENT.AltContextMenu;
+ this.Mouseover = HOVER.Mouseover;
+ this.Mouseout = HOVER.Mouseout;
+ this.Mousemove = HOVER.Mousemove;
+
+ //
+ // Determine pixels per inch
+ //
+ var div = HTML.addElement(document.body,"div",{style:{width:"5in"}});
+ this.pxPerInch = div.offsetWidth/5; div.parentNode.removeChild(div);
+
+ //
+ // Set up styles and preload web fonts
+ //
+ return AJAX.Styles(this.config.styles,["InitializePHTML",this]);
+ },
+ InitializePHTML: function () {
+ },
+
+ preTranslate: function (state) {
+ var scripts = state.jax[this.id], i, m = scripts.length,
+ script, prev, span, div, jax;
+ //
+ // Loop through the scripts
+ //
+ for (i = 0; i < m; i++) {
+ script = scripts[i]; if (!script.parentNode) continue;
+ //
+ // Remove any existing output
+ //
+ prev = script.previousSibling;
+ if (prev && String(prev.className).match(/^MathJax_PHTML(_Display)?( MathJax_Processing)?$/))
+ {prev.parentNode.removeChild(prev)}
+ //
+ // Add the span, and a div if in display mode,
+ // then set the role and mark it as being processed
+ //
+ jax = script.MathJax.elementJax; if (!jax) continue;
+ jax.PHTML = {display: (jax.root.Get("display") === "block")}
+ span = div = HTML.Element("span",{
+ className:"MathJax_PHTML", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id,
+ oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown,
+ onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove,
+ onclick:EVENT.Click, ondblclick:EVENT.DblClick,
+ // Added for keyboard accessible menu.
+ onkeydown: EVENT.Keydown, tabIndex: HUB.getTabOrder(jax)
+ });
+ if (HUB.Browser.noContextMenu) {
+ span.ontouchstart = TOUCH.start;
+ span.ontouchend = TOUCH.end;
+ }
+ if (jax.PHTML.display) {
+ div = HTML.Element("div",{className:"MathJax_PHTML_Display"});
+ div.appendChild(span);
+ }
+ //
+ div.className += " MathJax_Processing";
+ script.parentNode.insertBefore(div,script);
+ }
+ },
+
+ Translate: function (script,state) {
+ if (!script.parentNode) return;
+
+ //
+ // Get the data about the math
+ //
+ var jax = script.MathJax.elementJax, math = jax.root,
+ span = document.getElementById(jax.inputID+"-Frame"),
+ div = (jax.PHTML.display ? span.parentNode : span);
+ //
+ // Typeset the math
+ //
+ this.initPHTML(math,span);
+// math.setTeXclass();
+ try {math.toPreviewHTML(span)} catch (err) {
+ if (err.restart) {while (span.firstChild) {span.removeChild(span.firstChild)}}
+ throw err;
+ }
+ //
+ // Put it in place, and remove the processing marker
+ //
+ div.className = div.className.split(/ /)[0];
+ //
+ // Check if we are hiding the math until more is processed
+ //
+ if (this.hideProcessedMath) {
+ //
+ // Hide the math and don't let its preview be removed
+ //
+ div.className += " MathJax_Processed";
+ if (script.MathJax.preview) {
+ jax.PHTML.preview = script.MathJax.preview;
+ delete script.MathJax.preview;
+ }
+ }
+ },
+
+ postTranslate: function (state) {
+ var scripts = state.jax[this.id];
+ if (!this.hideProcessedMath) return;
+ for (var i = 0, m = scripts.length; i < m; i++) {
+ var script = scripts[i];
+ if (script && script.MathJax.elementJax) {
+ //
+ // Remove the processed marker
+ //
+ script.previousSibling.className = script.previousSibling.className.split(/ /)[0];
+ var data = script.MathJax.elementJax.PHTML;
+ //
+ // Remove the preview, if any
+ //
+ if (data.preview) {
+ data.preview.innerHTML = "";
+ script.MathJax.preview = data.preview;
+ delete data.preview;
+ }
+ }
+ }
+ },
+
+ getJaxFromMath: function (math) {
+ if (math.parentNode.className === "MathJax_PHTML_Display") {math = math.parentNode}
+ do {math = math.nextSibling} while (math && math.nodeName.toLowerCase() !== "script");
+ return HUB.getJaxFor(math);
+ },
+ getHoverSpan: function (jax,math) {return jax.root.PHTMLspanElement()},
+ getHoverBBox: function (jax,span,math) {
+ var bbox = jax.root.PHTML, em = jax.PHTML.outerEm;
+ var BBOX = {w:bbox.w*em, h:bbox.h*em, d:bbox.d*em};
+ if (bbox.width) {BBOX.width = bbox.width}
+ return BBOX;
+ },
+
+ Zoom: function (jax,span,math,Mw,Mh) {
+ //
+ // Re-render at larger size
+ //
+ span.className = "MathJax";
+ this.idPostfix = "-zoom"; jax.root.toPHTML(span,span); this.idPostfix = "";
+ //
+ // Get height and width of zoomed math and original math
+ //
+ span.style.position = "absolute";
+ if (!width) {math.style.position = "absolute"}
+ var zW = span.offsetWidth, zH = span.offsetHeight,
+ mH = math.offsetHeight, mW = math.offsetWidth;
+ if (mW === 0) {mW = math.parentNode.offsetWidth}; // IE7 gets mW == 0?
+ span.style.position = math.style.position = "";
+ //
+ return {Y:-EVENT.getBBox(span).h, mW:mW, mH:mH, zW:zW, zH:zH};
+ },
+
+ initPHTML: function (math,span) {},
+
+ Remove: function (jax) {
+ var span = document.getElementById(jax.inputID+"-Frame");
+ if (span) {
+ if (jax.PHTML.display) {span = span.parentNode}
+ span.parentNode.removeChild(span);
+ }
+ delete jax.PHTML;
+ },
+
+ ID: 0, idPostfix: "",
+ GetID: function () {this.ID++; return this.ID},
+
+ VARIANT: {
+ "bold": "MJXp-bold",
+ "italic": "MJXp-italic",
+ "bold-italic": "MJXp-bold MJXp-italic",
+ "script": "MJXp-scr",
+ "bold-script": "MJXp-scr MJXp-bold",
+ "fraktur": "MJXp-frak",
+ "bold-fraktur": "MJXp-frak MJXp-bold",
+ "monospace": "MJXp-mono",
+ "sans-serif": "MJXp-sf",
+ "-tex-caligraphic": "MJXp-cal"
+ },
+ MATHSPACE: {
+ veryverythinmathspace: 1/18,
+ verythinmathspace: 2/18,
+ thinmathspace: 3/18,
+ mediummathspace: 4/18,
+ thickmathspace: 5/18,
+ verythickmathspace: 6/18,
+ veryverythickmathspace: 7/18,
+ negativeveryverythinmathspace: -1/18,
+ negativeverythinmathspace: -2/18,
+ negativethinmathspace: -3/18,
+ negativemediummathspace: -4/18,
+ negativethickmathspace: -5/18,
+ negativeverythickmathspace: -6/18,
+ negativeveryverythickmathspace: -7/18,
+
+ thin: .08,
+ medium: .1,
+ thick: .15,
+
+ infinity: BIGDIMEN
+ },
+ TeX: {
+ x_height: .430554
+ },
+ pxPerInch: 72,
+ em: 16,
+
+ // ### FIXME: add more here
+
+ DELIMITERS: {
+ "(": {dir:V},
+ "{": {dir:V, w:.58},
+ "[": {dir:V},
+ "|": {dir:V, w:.275},
+ ")": {dir:V},
+ "}": {dir:V, w:.58},
+ "]": {dir:V},
+ "/": {dir:V},
+ "\\": {dir:V},
+ "\u2223": {dir:V, w:.275},
+ "\u2225": {dir:V, w:.55},
+ "\u230A": {dir:V, w:.5},
+ "\u230B": {dir:V, w:.5},
+ "\u2308": {dir:V, w:.5},
+ "\u2309": {dir:V, w:.5},
+ "\u27E8": {dir:V, w:.5},
+ "\u27E9": {dir:V, w:.5},
+ "\u2191": {dir:V, w:.65},
+ "\u2193": {dir:V, w:.65},
+ "\u21D1": {dir:V, w:.75},
+ "\u21D3": {dir:V, w:.75},
+ "\u2195": {dir:V, w:.65},
+ "\u21D5": {dir:V, w:.75},
+ "\u27EE": {dir:V, w:.275},
+ "\u27EF": {dir:V, w:.275},
+ "\u23B0": {dir:V, w:.6},
+ "\u23B1": {dir:V, w:.6}
+ },
+
+ REMAPACCENT: {
+ "\u20D7":"\u2192", // vector arrow
+ "'": "\u02CB",
+ "`": "\u02CA",
+ ".": "\u02D9",
+ "^": "\u02C6",
+ "-": "\u02C9",
+ "~": "\u02DC",
+ "\u00AF": "\u02C9", // macron
+ "\u00B0": "\u02DA", // degree sign
+ "\u00B4": "\u02CA", // acute accent
+ "\u0300": "\u02CB", // combining grave
+ "\u0301": "\u02CA", // combining acute
+ "\u0302": "\u02C6", // combining circumflex
+ "\u0303": "\u02DC", // combinig tilde
+ "\u0304": "\u02C9", // combining macron
+ "\u0305": "\u02C9", // combining overline
+ "\u0306": "\u02D8", // combining breve
+ "\u0307": "\u02D9", // combining dot
+ "\u0308": "\u00A8", // combining double dot
+ "\u030C": "\u02C7" // combining caron
+ },
+ REMAPACCENTUNDER: {
+ },
+
+ length2em: function (length,size) {
+ if (typeof(length) !== "string") {length = length.toString()}
+ if (length === "") {return ""}
+ if (length === MML.SIZE.NORMAL) {return 1}
+ if (length === MML.SIZE.BIG) {return 2}
+ if (length === MML.SIZE.SMALL) {return .71}
+ if (this.MATHSPACE[length]) {return this.MATHSPACE[length]}
+ var match = length.match(/^\s*([-+]?(?:\.\d+|\d+(?:\.\d*)?))?(pt|em|ex|mu|px|pc|in|mm|cm|%)?/);
+ var m = parseFloat(match[1]||"1"), unit = match[2];
+ if (size == null) {size = 1}
+ if (unit === "em") {return m}
+ if (unit === "ex") {return m * this.TeX.x_height}
+ if (unit === "%") {return m / 100 * size}
+ if (unit === "px") {return m / this.em}
+ if (unit === "pt") {return m / 10} // 10 pt to an em
+ if (unit === "pc") {return m * 1.2} // 12 pt to a pc
+ if (unit === "in") {return m * this.pxPerInch / this.em}
+ if (unit === "cm") {return m * this.pxPerInch / this.em / 2.54} // 2.54 cm to an inch
+ if (unit === "mm") {return m * this.pxPerInch / this.em / 25.4} // 10 mm to a cm
+ if (unit === "mu") {return m / 18} // 18mu to an em for the scriptlevel
+ return m*size; // relative to given size (or 1em as default)
+ },
+
+ Em: function (m) {
+ if (Math.abs(m) < .001) return "0em";
+ return (m.toFixed(3).replace(/\.?0+$/,""))+"em";
+ },
+
+ arrayEntry: function (a,i) {return a[Math.max(0,Math.min(i,a.length-1))]}
+
+ });
+
+ MathJax.Hub.Register.StartupHook("mml Jax Ready",function () {
+ MML = MathJax.ElementJax.mml;
+
+ MML.mbase.Augment({
+ toPreviewHTML: function (span,options) {
+ return this.PHTMLdefaultSpan(span,options);
+ },
+
+ PHTMLdefaultSpan: function (span,options) {
+ if (!options) options = {};
+ span = this.PHTMLcreateSpan(span);
+ this.PHTMLhandleStyle(span);
+ this.PHTMLhandleColor(span);
+ if (this.isToken) this.PHTMLhandleToken(span);
+ for (var i = 0, m = this.data.length; i < m; i++) this.PHTMLaddChild(span,i,options);
+ return span;
+ },
+ PHTMLaddChild: function (span,i,options) {
+ var child = this.data[i];
+ if (child) {
+ if (options.childSpans)
+ span = HTML.addElement(span,"span",{className:options.className});
+ child.toPreviewHTML(span);
+ if (!options.noBBox) {
+ this.PHTML.w += child.PHTML.w + child.PHTML.l + child.PHTML.r;
+ if (child.PHTML.h > this.PHTML.h) this.PHTML.h = child.PHTML.h;
+ if (child.PHTML.d > this.PHTML.d) this.PHTML.d = child.PHTML.d;
+ if (child.PHTML.t > this.PHTML.t) this.PHTML.t = child.PHTML.t;
+ if (child.PHTML.b > this.PHTML.b) this.PHTML.b = child.PHTML.b;
+ }
+ } else if (options.forceChild) {HTML.addElement(span,"span")}
+ },
+ PHTMLstretchChild: function (i,H,D) {
+ var data = this.data[i];
+ if (data && data.PHTMLcanStretch("Vertical",H,D)) {
+ var bbox = this.PHTML, dbox = data.PHTML, w = dbox.w;
+ data.PHTMLstretchV(H,D);
+ bbox.w += dbox.w - w;
+ if (dbox.h > bbox.h) bbox.h = dbox.h;
+ if (dbox.d > bbox.d) bbox.d = dbox.d;
+ }
+ },
+
+ PHTMLcreateSpan: function (span) {
+ if (!this.PHTML) this.PHTML = {};
+ this.PHTML = {w:0, h:0, d:0, l:0, r:0, t:0, b:0};
+ if (this.inferred) return span;
+ // ### FIXME: This is a hack to handle the different spacing of the
+ // ### integral sign in Times compared to CM fonts
+ if (this.type === "mo" && this.data.join("") === "\u222B") {PHTML.lastIsInt = true}
+ else if (this.type !== "mspace" || this.width !== "negativethinmathspace") {PHTML.lastIsInt = false}
+ // ###
+ if (!this.PHTMLspanID) {this.PHTMLspanID = PHTML.GetID()};
+ var id = (this.id || "MJXp-Span-"+this.PHTMLspanID);
+ return HTML.addElement(span,"span",{className:"MJXp-"+this.type, id:id});
+ },
+ PHTMLspanElement: function () {
+ if (!this.PHTMLspanID) {return null}
+ return document.getElementById(this.id||"MJXp-Span-"+this.PHTMLspanID);
+ },
+
+ PHTMLhandleToken: function (span) {
+ var values = this.getValues("mathvariant");
+ if (values.mathvariant !== MML.VARIANT.NORMAL) {
+ span.className += " "+PHTML.VARIANT[values.mathvariant];
+ }
+ },
+
+ PHTMLhandleStyle: function (span) {
+ if (this.style) span.style.cssText = this.style;
+ },
+
+ PHTMLhandleColor: function (span) {
+ if (this.mathcolor) {span.style.color = this.mathcolor}
+ if (this.mathbackground) {span.style.backgroundColor = this.mathbackground}
+ },
+
+ PHTMLhandleScriptlevel: function (span) {
+ // ### FIXME: Need to prevent getting too small
+ // ### and should keep track of scaling so it can be compensated for
+ var level = this.Get("scriptlevel");
+ if (level) span.className += " MJXp-script";
+ },
+
+ PHTMLhandleText: function (span,text) {
+ var c, n;
+ var H = 0, D = 0, W = 0;
+ for (var i = 0, m = text.length; i < m; i++) {
+ n = text.charCodeAt(i); c = text.charAt(i);
+ if (n >= 0xD800 && n < 0xDBFF) {
+ i++; n = (((n-0xD800)<<10)+(text.charCodeAt(i)-0xDC00))+0x10000;
+ }
+ var h = .7, d = .22, w = .5;
+ if (n < 127) {
+ if (c.match(/[A-Za-ehik-or-xz0-9]/)) d = 0;
+ if (c.match(/[A-HK-Z]/)) {w = .67} else if (c.match(/[IJ]/)) {w = .36}
+ if (c.match(/[acegm-su-z]/)) {h = .45} else if (c.match(/[ij]/)) {h = .75}
+ if (c.match(/[ijlt]/)) w = .28;
+ }
+ if (PHTML.DELIMITERS[c]) {w = PHTML.DELIMITERS[c].w || .4}
+ // ### FIXME: handle Greek
+ // ### Combining diacriticals (all sets), spacing modifiers
+ // ### arrows (all sets), widths of braces
+ if (h > H) H = h; if (d > D) D = d; W += w;
+ }
+ if (!this.CHML) this.PHTML = {};
+ this.PHTML = {h:.9, d:.3, w:W, l:0, r:0, t:H, b:D};
+ HTML.addText(span,text);
+ },
+
+ PHTMLbboxFor: function (n) {
+ if (this.data[n] && this.data[n].PHTML) return this.data[n].PHTML;
+ return {w:0, h:0, d:0, l:0, r:0, t:0, b:0};
+ },
+
+ PHTMLcanStretch: function (direction,H,D) {
+ if (this.isEmbellished()) {
+ var core = this.Core();
+ if (core && core !== this) {return core.PHTMLcanStretch(direction,H,D)}
+ }
+ return false;
+ },
+ PHTMLstretchV: function (h,d) {},
+ PHTMLstretchH: function (w) {},
+
+ CoreParent: function () {
+ var parent = this;
+ while (parent && parent.isEmbellished() &&
+ parent.CoreMO() === this && !parent.isa(MML.math)) {parent = parent.Parent()}
+ return parent;
+ },
+ CoreText: function (parent) {
+ if (!parent) {return ""}
+ if (parent.isEmbellished()) {return parent.CoreMO().data.join("")}
+ while ((parent.isa(MML.mrow) || parent.isa(MML.TeXAtom) ||
+ parent.isa(MML.mstyle) || parent.isa(MML.mphantom)) &&
+ parent.data.length === 1 && parent.data[0]) {parent = parent.data[0]}
+ if (!parent.isToken) {return ""} else {return parent.data.join("")}
+ }
+
+ });
+
+ MML.chars.Augment({
+ toPreviewHTML: function (span) {
+ var text = this.toString().replace(/[\u2061-\u2064]/g,"");
+ this.PHTMLhandleText(span,text);
+ }
+ });
+ MML.entity.Augment({
+ toPreviewHTML: function (span) {
+ var text = this.toString().replace(/[\u2061-\u2064]/g,"");
+ this.PHTMLhandleText(span,text);
+ }
+ });
+
+ MML.math.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ if (this.Get("display") === "block") {span.className += " MJXp-display"}
+ return span;
+ }
+ });
+
+ MML.mo.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ this.PHTMLadjustAccent(span);
+ var values = this.getValues("lspace","rspace","scriptlevel","displaystyle","largeop");
+ if (values.scriptlevel === 0) {
+ this.PHTML.l = PHTML.length2em(values.lspace);
+ this.PHTML.r = PHTML.length2em(values.rspace);
+ span.style.marginLeft = PHTML.Em(this.PHTML.l);
+ span.style.marginRight = PHTML.Em(this.PHTML.r);
+ } else {
+ this.PHTML.l = .15;
+ this.PHTML.r = .1;
+ }
+ if (values.displaystyle && values.largeop) {
+ var box = HTML.Element("span",{className:"MJXp-largeop"});
+ box.appendChild(span.firstChild); span.appendChild(box);
+ this.PHTML.h *= 1.2; this.PHTML.d *= 1.2;
+ if (this.data.join("") === "\u222B") box.className += " MJXp-int";
+ }
+ // ### FIXME: Handle embellished op spacing
+ // ### FIXME: Remap minus signs
+ return span;
+ },
+ PHTMLadjustAccent: function (span) {
+ var parent = this.CoreParent();
+ if (parent && parent.isa(MML.munderover) &&
+ this.CoreText(parent.data[parent.base]).length === 1) {
+ var over = parent.data[parent.over], under = parent.data[parent.under];
+ var c = this.data.join(""), C;
+ if (over && this === over.CoreMO() && parent.Get("accent")) {C = PHTML.REMAPACCENT[c]}
+ else if (under && this === under.CoreMO() && parent.Get("accentunder")) {C = PHTML.REMAPACCENTUNDER[c]}
+ if (C) c = span.innerHTML = C;
+ if (c.match(/[\u02C6-\u02DC\u00A8]/)) {this.PHTML.acc = -.52}
+ else if (c === "\u2192") {this.PHTML.acc = -.15; this.PHTML.vec = true}
+ }
+ },
+ PHTMLcanStretch: function (direction,H,D) {
+ if (!this.Get("stretchy")) {return false}
+ var c = this.data.join("");
+ if (c.length > 1) {return false}
+ c = PHTML.DELIMITERS[c];
+ var stretch = (c && c.dir === direction.substr(0,1));
+ if (stretch) {
+ stretch = (this.PHTML.h !== H || this.PHTML.d !== D ||
+ (this.Get("minsize",true) || this.Get("maxsize",true)));
+ }
+ return stretch;
+ },
+ PHTMLstretchV: function (h,d) {
+ var span = this.PHTMLspanElement(), bbox = this.PHTML; //bbox.w = .4; // ## adjust width
+ var values = this.getValues("symmetric","maxsize","minsize");
+ if (values.symmetric) {H = 2*Math.max(h-.25,d+.25)} else {H = h + d}
+ values.maxsize = PHTML.length2em(values.maxsize,bbox.h+bbox.d);
+ values.minsize = PHTML.length2em(values.minsize,bbox.h+bbox.d);
+ H = Math.max(values.minsize,Math.min(values.maxsize,H));
+ var scale = H/(bbox.h+bbox.d-.3); // ### adjusted for extra tall bbox
+ var box = HTML.Element("span",{style:{"font-size":PHTML.Em(scale)}});
+ if (scale > 1.25) {
+ var sX = Math.ceil(1.25/scale * 10);
+ box.className = "MJXp-right MJXp-scale"+sX;
+ box.style.marginLeft = PHTML.Em(bbox.w*(sX/10-1)+.07);
+ bbox.w *= scale*sX/10;
+ }
+ box.appendChild(span.firstChild); span.appendChild(box);
+ if (values.symmetric) span.style.verticalAlign = PHTML.Em(.25*(1-scale));
+ }
+ });
+
+ MML.mspace.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ var values = this.getValues("height","depth","width");
+ var w = PHTML.length2em(values.width),
+ h = PHTML.length2em(values.height),
+ d = PHTML.length2em(values.depth);
+ var bbox = this.PHTML;
+ bbox.w = w; bbox.h = h; bbox.d = d;
+ if (w < 0) {
+ // ### FIXME: lastIsInt hack
+ if (!PHTML.lastIsInt) span.style.marginLeft = PHTML.Em(w);
+ w = 0;
+ }
+ span.style.width = PHTML.Em(w);
+ span.style.height = PHTML.Em(h+d);
+ if (d) span.style.verticalAlign = PHTML.Em(-d);
+ return span;
+ }
+ });
+
+ MML.mpadded.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{
+ childSpans:true, className:"MJXp-box", forceChild:true
+ });
+ var child = span.firstChild;
+ var values = this.getValues("width","height","depth","lspace","voffset");
+ var dimen = this.PHTMLdimen(values.lspace);
+ var T = 0, B = 0, L = dimen.len, R = -dimen.len, V = 0;
+ if (values.width !== "") {
+ dimen = this.PHTMLdimen(values.width,"w",0);
+ if (dimen.pm) {R += dimen.len} else {span.style.width = PHTML.Em(dimen.len)}
+ }
+ if (values.height !== "") {
+ dimen = this.PHTMLdimen(values.height,"h",0);
+ if (!dimen.pm) T += -this.PHTMLbboxFor(0).h;
+ T += dimen.len;
+ }
+ if (values.depth !== "") {
+ dimen = this.PHTMLdimen(values.depth,"d",0);
+ if (!dimen.pm) {B += -this.PHTMLbboxFor(0).d; V += -dimen.len}
+ B += dimen.len;
+ }
+ if (values.voffset !== "") {
+ dimen = this.PHTMLdimen(values.voffset);
+ T -= dimen.len; B += dimen.len;
+ V += dimen.len;
+ }
+ if (T) child.style.marginTop = PHTML.Em(T);
+ if (B) child.style.marginBottom = PHTML.Em(B);
+ if (L) child.style.marginLeft = PHTML.Em(L);
+ if (R) child.style.marginRight = PHTML.Em(R);
+ if (V) span.style.verticalAlign = PHTML.Em(V);
+ return span;
+ },
+ PHTMLdimen: function (length,d,m) {
+ if (m == null) {m = -BIGDIMEN}
+ length = String(length);
+ var match = length.match(/width|height|depth/);
+ var size = (match ? this.PHTML[match[0].charAt(0)] : (d ? this.PHTML[d] : 0));
+ return {len: PHTML.length2em(length,size)||0, pm: !!length.match(/^[-+]/)};
+ }
+ });
+
+ MML.munderover.Augment({
+ toPreviewHTML: function (span) {
+ var values = this.getValues("displaystyle","accent","accentunder","align");
+ var base = this.data[this.base];
+ if (!values.displaystyle && base != null &&
+ (base.movablelimits || base.CoreMO().Get("movablelimits"))) {
+ span = MML.msubsup.prototype.toPreviewHTML.call(this,span);
+ //
+ // Change class to msubsup for CSS rules.
+ // ### FIXME: should this be handled via adding another class instead?
+ //
+ span.className = span.className.replace(/munderover/,"msubsup");
+ return span;
+ }
+ span = this.PHTMLdefaultSpan(span,{childSpans:true, className:"", noBBox:true});
+ var obox = this.PHTMLbboxFor(this.over),
+ ubox = this.PHTMLbboxFor(this.under),
+ bbox = this.PHTMLbboxFor(this.base),
+ BBOX = this.PHTML, acc = obox.acc;
+ if (this.data[this.over]) {
+ span.lastChild.firstChild.style.marginLeft = obox.l =
+ span.lastChild.firstChild.style.marginRight = obox.r = 0;
+ var over = HTML.Element("span",{},[["span",{className:"MJXp-over"}]]);
+ over.firstChild.appendChild(span.lastChild);
+ if (span.childNodes.length > (this.data[this.under] ? 1 : 0))
+ over.firstChild.appendChild(span.firstChild);
+ this.data[this.over].PHTMLhandleScriptlevel(over.firstChild.firstChild);
+ if (acc != null) {
+ if (obox.vec) {
+ over.firstChild.firstChild.firstChild.style.fontSize = "60%";
+ obox.h *= .6; obox.d *= .6; obox.w *= .6;
+ }
+ acc = acc - obox.d + .1; if (bbox.t != null) {acc += bbox.t - bbox.h}
+ over.firstChild.firstChild.style.marginBottom = PHTML.Em(acc);
+ }
+ if (span.firstChild) {span.insertBefore(over,span.firstChild)}
+ else {span.appendChild(over)}
+ }
+ if (this.data[this.under]) {
+ span.lastChild.firstChild.style.marginLeft = ubox.l =
+ span.lastChild.firstChild.marginRight = ubox.r = 0;
+ this.data[this.under].PHTMLhandleScriptlevel(span.lastChild);
+ }
+ BBOX.w = Math.max(.8*obox.w,.8*ubox.w,bbox.w);
+ BBOX.h = .8*(obox.h+obox.d+(acc||0)) + bbox.h;
+ BBOX.d = bbox.d + .8*(ubox.h+ubox.d);
+ return span;
+ }
+ });
+
+ MML.msubsup.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{noBBox:true});
+ if (!this.data[this.base]) {
+ if (span.firstChild) {span.insertBefore(HTML.Element("span"),span.firstChild)}
+ else {span.appendChild(HTML.Element("span"))}
+ }
+ var base = this.data[this.base], sub = this.data[this.sub], sup = this.data[this.sup];
+ if (!base) base = {bbox: {h:.8, d:.2}};
+ span.firstChild.style.marginRight = ".05em";
+ var h = Math.max(.4,base.PHTML.h-.4),
+ d = Math.max(.2,base.PHTML.d+.1);
+ var bbox = this.PHTML;
+ if (sup && sub) {
+ var box = HTML.Element("span",{className:"MJXp-script-box", style:{
+ height: PHTML.Em(h+sup.PHTML.h*.8 + d+sub.PHTML.d*.8),
+ "vertical-align": PHTML.Em(-d-sub.PHTML.d*.8)
+ }},[
+ ["span",{},[["span",{},[["span",{
+ style:{"margin-bottom":PHTML.Em(-(sup.PHTML.d-.05))}
+ }]]]]],
+ ["span",{},[["span",{},[["span",{
+ style:{"margin-top":PHTML.Em(-(sup.PHTML.h-.05))}
+ }]]]]]
+ ]);
+ sub.PHTMLhandleScriptlevel(box.firstChild);
+ sup.PHTMLhandleScriptlevel(box.lastChild);
+ box.firstChild.firstChild.firstChild.appendChild(span.lastChild);
+ box.lastChild.firstChild.firstChild.appendChild(span.lastChild);
+ span.appendChild(box);
+ bbox.h = Math.max(base.PHTML.h,sup.PHTML.h*.8+h);
+ bbox.d = Math.max(base.PHTML.d,sub.PHTML.d*.8+d);
+ bbox.w = base.PHTML.w + Math.max(sup.PHTML.w,sub.PHTML.w) + .07;
+ } else if (sup) {
+ span.lastChild.style.verticalAlign = PHTML.Em(h);
+ sup.PHTMLhandleScriptlevel(span.lastChild);
+ bbox.h = Math.max(base.PHTML.h,sup.PHTML.h*.8+h);
+ bbox.d = Math.max(base.PHTML.d,sup.PHTML.d*.8-h);
+ bbox.w = base.PHTML.w + sup.PHTML.w + .07;
+ } else if (sub) {
+ span.lastChild.style.verticalAlign = PHTML.Em(-d);
+ sub.PHTMLhandleScriptlevel(span.lastChild);
+ bbox.h = Math.max(base.PHTML.h,sub.PHTML.h*.8-d);
+ bbox.d = Math.max(base.PHTML.d,sub.PHTML.d*.8+d);
+ bbox.w = base.PHTML.w + sub.PHTML.w + .07;
+ }
+ return span;
+ }
+ });
+
+ MML.mfrac.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{
+ childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
+ });
+ var values = this.getValues("linethickness","displaystyle");
+ if (!values.displaystyle) {
+ if (this.data[0]) this.data[0].PHTMLhandleScriptlevel(span.firstChild);
+ if (this.data[1]) this.data[1].PHTMLhandleScriptlevel(span.lastChild);
+ }
+ var denom = HTML.Element("span",{className:"MJXp-box"},[
+ ["span",{className:"MJXp-denom"},[ // inline-table
+ ["span",{},[["span",{className:"MJXp-rule",style:{height:"1em"}}]]],
+ ["span"] // spans are table-row
+ ]]
+ ]);
+ denom.firstChild.lastChild.appendChild(span.lastChild);
+ span.appendChild(denom);
+ var nbox = this.PHTMLbboxFor(0), dbox = this.PHTMLbboxFor(1), bbox = this.PHTML;
+ bbox.w = Math.max(nbox.w,dbox.w) * .8;
+ bbox.h = nbox.h+nbox.d + .1 + .25;
+ bbox.d = dbox.h+dbox.d - .25;
+ bbox.l = bbox.r = .125;
+ values.linethickness = Math.max(0,PHTML.length2em(values.linethickness||"0",0));
+ if (values.linethickness) {
+ var rule = denom.firstChild.firstChild.firstChild;
+ var t = PHTML.Em(values.linethickness);
+ rule.style.borderTop = "none";
+ rule.style.borderBottom = (values.linethickness < .15 ? "1px" : t)+" solid";
+ rule.style.margin = t+" 0";
+ t = values.linethickness;
+ denom.style.marginTop = PHTML.Em(3*t-1.2);
+ span.style.verticalAlign = PHTML.Em(1.5*t + .1);
+ bbox.h += 1.5*t - .1; bbox.d += 1.5*t;
+ } else {
+ denom.style.marginTop = "-.7em";
+ }
+ return span;
+ }
+ });
+
+ MML.msqrt.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{
+ childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
+ });
+ this.PHTMLlayoutRoot(span,span.firstChild);
+ return span;
+ },
+ PHTMLlayoutRoot: function (span,base) {
+ var bbox = this.PHTMLbboxFor(0);
+ var scale = Math.ceil((bbox.h+bbox.d+.14)*100), t = PHTML.Em(14/scale);
+ var surd = HTML.Element("span",{className:"MJXp-surd"},[
+ ["span",{style:{"font-size":scale+"%","margin-top":t}},["\u221A"]]
+ ]);
+ var root = HTML.Element("span",{className:"MJXp-root"},[
+ ["span",{className:"MJXp-rule",style:{"border-top":".08em solid"}}]
+ ]);
+ var W = (1.2/2.2)*scale/100; // width-of-surd = (height/H-to-W-ratio)
+ if (scale > 150) {
+ var sX = Math.ceil(150/scale * 10);
+ surd.firstChild.className = "MJXp-right MJXp-scale"+sX;
+ surd.firstChild.style.marginLeft = PHTML.Em(W*(sX/10-1)/scale*100);
+ W = W*sX/10;
+ root.firstChild.style.borderTopWidth = PHTML.Em(.08/Math.sqrt(sX/10));
+ }
+ root.appendChild(base);
+ span.appendChild(surd);
+ span.appendChild(root);
+ this.PHTML.h = bbox.h + .18; this.PHTML.d = bbox.d;
+ this.PHTML.w = bbox.w + W;
+ return span;
+ }
+ });
+
+ MML.mroot.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{
+ childSpans:true, className:"MJXp-box", forceChild:true, noBBox:true
+ });
+ var rbox = this.PHTMLbboxFor(1), root = span.removeChild(span.lastChild);
+ var sqrt = this.PHTMLlayoutRoot(HTML.Element("span"),span.firstChild);
+ root.className = "MJXp-script"; // ### FIXME: should be scriptscript
+ var scale = parseInt(sqrt.firstChild.firstChild.style.fontSize);
+ var v = .55*(scale/120) + rbox.d*.8, r = -.6*(scale/120);
+ if (scale > 150) {r *= .95*Math.ceil(150/scale*10)/10}
+ root.style.marginRight = PHTML.Em(r); root.style.verticalAlign = PHTML.Em(v);
+ if (-r > rbox.w*.8) root.style.marginLeft = PHTML.Em(-r-rbox.w*.8); // ### depends on rbox.w
+ span.appendChild(root); span.appendChild(sqrt);
+ this.PHTML.w += Math.max(0,rbox.w*.8+r);
+ this.PHTML.h = Math.max(this.PHTML.h,rbox.h*.8+v);
+ return span;
+ },
+ PHTMLlayoutRoot: MML.msqrt.prototype.PHTMLlayoutRoot
+ });
+
+ MML.mfenced.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLcreateSpan(span);
+ this.PHTMLhandleStyle(span);
+ this.PHTMLhandleColor(span);
+ //
+ // Make row of open, data, sep, ... data, close
+ //
+ this.addFakeNodes();
+ this.PHTMLaddChild(span,"open",{});
+ for (var i = 0, m = this.data.length; i < m; i++) {
+ this.PHTMLaddChild(span,"sep"+i,{});
+ this.PHTMLaddChild(span,i,{});
+ }
+ this.PHTMLaddChild(span,"close",{});
+ //
+ // Check for streching the elements
+ //
+ var H = this.PHTML.h, D = this.PHTML.d;
+ this.PHTMLstretchChild("open",H,D);
+ for (i = 0, m = this.data.length; i < m; i++) {
+ this.PHTMLstretchChild("sep"+i,H,D);
+ this.PHTMLstretchChild(i,H,D);
+ }
+ this.PHTMLstretchChild("close",H,D);
+ return span;
+ }
+ });
+
+ MML.mrow.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ var H = this.PHTML.h, D = this.PHTML.d;
+ for (var i = 0, m = this.data.length; i < m; i++) this.PHTMLstretchChild(i,H,D);
+ return span;
+ }
+ });
+
+ MML.mstyle.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ this.PHTMLhandleScriptlevel(span);
+ return span;
+ }
+ });
+
+ MML.TeXAtom.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span);
+ // ### FIXME: handle TeX class?
+ span.className = "MJXp-mrow";
+ return span;
+ }
+ });
+
+ MML.mtable.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLdefaultSpan(span,{noBBox:true});
+ var values = this.getValues("columnalign","rowalign","columnspacing","rowspacing",
+ "columnwidth","equalcolumns","equalrows",
+ "columnlines","rowlines","frame","framespacing",
+ "align","width");
+ var SPLIT = MathJax.Hub.SplitList, i, m, j, n;
+ var CSPACE = SPLIT(values.columnspacing),
+ RSPACE = SPLIT(values.rowspacing),
+ CALIGN = SPLIT(values.columnalign),
+ RALIGN = SPLIT(values.rowalign);
+ for (i = 0, m = CSPACE.length; i < m; i++) {CSPACE[i] = PHTML.length2em(CSPACE[i])}
+ for (i = 0, m = RSPACE.length; i < m; i++) {RSPACE[i] = PHTML.length2em(RSPACE[i])}
+
+ var table = HTML.Element("span");
+ while (span.firstChild) table.appendChild(span.firstChild);
+ span.appendChild(table);
+ var H = 0, W = 0;
+ for (i = 0, m = this.data.length; i < m; i++) {
+ var row = this.data[i];
+ if (row) {
+ var rspace = PHTML.arrayEntry(RSPACE,i-1), ralign = PHTML.arrayEntry(RALIGN,i);
+ var rbox = row.PHTML, rspan = row.PHTMLspanElement();
+ rspan.style.verticalAlign = ralign;
+ var k = (row.type === "mlabeledtr" ? 1 : 0);
+ for (j = 0, n = row.data.length; j < n-k; j++) {
+ var cell = row.data[j+k];
+ if (cell) {
+ var cspace = PHTML.arrayEntry(CSPACE,j-1), calign = PHTML.arrayEntry(CALIGN,j);
+ var cspan = cell.PHTMLspanElement();
+ if (j) {rbox.w += cspace; cspan.style.paddingLeft = PHTML.Em(cspace)}
+ if (i) cspan.style.paddingTop = PHTML.Em(rspace);
+ cspan.style.textAlign = calign;
+ }
+ }
+ H += rbox.h + rbox.d; if (i) {H += rspace}
+ if (rbox.w > W) W = rbox.w;
+ }
+ }
+ var bbox = this.PHTML;
+ bbox.w = W; bbox.h = H/2 + .25; bbox.d = H/2 - .25;
+ bbox.l = bbox.r = .125;
+ return span;
+ }
+ });
+ MML.mlabeledtr.Augment({
+ PHTMLdefaultSpan: function (span,options) {
+ if (!options) options = {};
+ span = this.PHTMLcreateSpan(span);
+ this.PHTMLhandleStyle(span);
+ this.PHTMLhandleColor(span);
+ if (this.isToken) this.PHTMLhandleToken(span);
+ // skip label for now
+ for (var i = 1, m = this.data.length; i < m; i++) this.PHTMLaddChild(span,i,options);
+ return span;
+ }
+ });
+
+ MML.semantics.Augment({
+ toPreviewHTML: function (span) {
+ span = this.PHTMLcreateSpan(span);
+ if (this.data[0]) {
+ this.data[0].toPreviewHTML(span);
+ MathJax.Hub.Insert(this.data[0].PHTML||{},this.PHTML);
+ }
+ return span;
+ }
+ });
+ MML.annotation.Augment({toPreviewHTML: function(span) {}});
+ MML["annotation-xml"].Augment({toPreviewHTML: function(span) {}});
+
+ //
+ // Loading isn't complete until the element jax is modified,
+ // but can't call loadComplete within the callback for "mml Jax Ready"
+ // (it would call PreviewHTML's Require routine, asking for the mml jax again)
+ // so wait until after the mml jax has finished processing.
+ //
+ // We also need to wait for the onload handler to run, since the loadComplete
+ // will call Config and Startup, which need to modify the body.
+ //
+ MathJax.Hub.Register.StartupHook("onLoad",function () {
+ setTimeout(MathJax.Callback(["loadComplete",PHTML,"jax.js"]),0);
+ });
+ });
+
+ MathJax.Hub.Register.StartupHook("End Cookie", function () {
+ if (HUB.config.menuSettings.zoom !== "None")
+ {AJAX.Require("[MathJax]/extensions/MathZoom.js")}
+ });
+
+})(MathJax.Ajax,MathJax.Hub,MathJax.HTML,MathJax.OutputJax.PreviewHTML);
diff --git a/MarkDownEditor/Model/DocumentExporter.cs b/MarkDownEditor/Model/DocumentExporter.cs
index dfc8892..8508a35 100644
--- a/MarkDownEditor/Model/DocumentExporter.cs
+++ b/MarkDownEditor/Model/DocumentExporter.cs
@@ -16,6 +16,7 @@ public class DocumentExporter
{
{ "Plain Html", new PlainHTMLExporter()},
{ "Html", new HTMLExporter()},
+ { "Html Local Mathjax", new HTMLWithLocalMathJaxExporter()},
{ "RTF", new RFTExporter()},
{ "Docx", new DocxExporter()},
{ "Epub", new EpubExporter()},
@@ -71,10 +72,44 @@ public void Export(string markdownType, string sourceCodePath, string cssFile, s
Process process = new Process();
process.StartInfo.FileName = "pandoc";
+ string mathjax = Properties.Settings.Default.ShowMathJax ? "--mathjax" : "";
process.StartInfo.Arguments =
cssFile == null
- ? $"\"{sourceCodePath}\" -f {markdownType} -t html --ascii -s -o \"{outputPath}\""
- : $"\"{sourceCodePath}\" -f {markdownType} -t html --ascii -s -H {tmpFile} -o \"{outputPath}\"";
+ ? $"\"{sourceCodePath}\" -f {markdownType} -t html {mathjax} --ascii -s -o \"{outputPath}\""
+ : $"\"{sourceCodePath}\" -f {markdownType} -t html {mathjax} --ascii -s -H {tmpFile} -o \"{outputPath}\"";
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.Start();
+ process.WaitForExit();
+
+ File.Delete(tmpFile);
+ }
+ }
+
+ public class HTMLWithLocalMathJaxExporter : IDocumentExporter
+ {
+ string mathjaxJsFilePath = new Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MathJax", "MathJax.js")).AbsoluteUri + "?config=TEX_CHTML";
+ public void Export(string markdownType, string sourceCodePath, string cssFile, string outputPath)
+ {
+ var tmpFile = Path.GetTempFileName();
+ if (cssFile != null)
+ {
+ StreamReader sr = new StreamReader(cssFile);
+ var cssContent = sr.ReadToEnd();
+ sr.Close();
+ StreamWriter sw = new StreamWriter(tmpFile);
+ sw.WriteLine("");
+ sw.Close();
+ }
+
+ Process process = new Process();
+ process.StartInfo.FileName = "pandoc";
+ string mathjax = Properties.Settings.Default.ShowMathJax ? $"--mathjax={mathjaxJsFilePath}" : "";
+ process.StartInfo.Arguments =
+ cssFile == null
+ ? $"\"{sourceCodePath}\" -f {markdownType} -t html {mathjax} --ascii -s -o \"{outputPath}\""
+ : $"\"{sourceCodePath}\" -f {markdownType} -t html {mathjax} --ascii -s -H {tmpFile} -o \"{outputPath}\"";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit();
@@ -143,15 +178,18 @@ public void Export(string markdownType, string sourceCodePath, string cssFile, s
DocumentExporter.Export("Html", markdownType, cssFile, sourceCodePath, tmpFilePath);
- File.WriteAllBytes(outputPath, HtmlToXConverter.ConvertToPdf(File.ReadAllText(tmpFilePath)));
- //Process process = new Process();
- //process.StartInfo.FileName = "wkhtmltopdf";
- //process.StartInfo.Arguments = $"\"{tmpFilePath}\" \"{outputPath}\"";
- //process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- //process.Start();
- //process.WaitForExit();
- //if (process.ExitCode != 0)
- // throw new Exception(Properties.Resources.FailedToExport + "\n" + "wkhtmltopdf error" + process.ExitCode);
+ if (File.Exists(outputPath))
+ File.Delete(outputPath);
+
+ //File.WriteAllBytes(outputPath, HtmlToXConverter.ConvertToPdf(File.ReadAllText(tmpFilePath)));
+ Process process = new Process();
+ process.StartInfo.FileName = "WkHtmlToPdfWrapper";
+ process.StartInfo.Arguments = $"\"{tmpFilePath}\" \"{outputPath}\"";
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.Start();
+ process.WaitForExit();
+ if (process.ExitCode != 0)
+ throw new Exception(Properties.Resources.FailedToExport + "\n" + "wkhtmltopdf error" + process.ExitCode);
File.Delete(tmpFilePath);
}
@@ -165,19 +203,22 @@ public void Export(string markdownType, string sourceCodePath, string cssFile, s
DocumentExporter.Export("Html", markdownType, cssFile, sourceCodePath, tmpFilePath);
- //Process process = new Process();
- //process.StartInfo.FileName = "wkhtmltoimage";
- //process.StartInfo.Arguments = $"--width 600 \"{tmpFilePath}\" \"{outputPath}\"";
- //process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- //process.Start();
- //process.WaitForExit();
- //if (process.ExitCode != 0)
- // throw new Exception(Properties.Resources.FailedToExport + "\n" + "wkhtmltoimage error" + process.ExitCode);
-
- var html = File.ReadAllText(tmpFilePath);
- var extension = Path.GetExtension(outputPath).Remove(0, 1).ToLower();
- var image = HtmlToXConverter.ConvertToImage(html, extension, 600, 0);
- File.WriteAllBytes(outputPath, image);
+ if (File.Exists(outputPath))
+ File.Delete(outputPath);
+
+ Process process = new Process();
+ process.StartInfo.FileName = "WkHtmlToImageWrapper";
+ process.StartInfo.Arguments = $"\"{tmpFilePath}\" \"{outputPath}\"";
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.Start();
+ process.WaitForExit();
+ if (process.ExitCode != 0)
+ throw new Exception(Properties.Resources.FailedToExport + "\n" + "wkhtmltoimage error" + process.ExitCode);
+
+ //var html = File.ReadAllText(tmpFilePath);
+ //var extension = Path.GetExtension(outputPath).Remove(0, 1).ToLower();
+ //var image = HtmlToXConverter.ConvertToImage(html, extension, 600, 0);
+ //File.WriteAllBytes(outputPath, image);
File.Delete(tmpFilePath);
}
diff --git a/MarkDownEditor/Properties/AssemblyInfo.cs b/MarkDownEditor/Properties/AssemblyInfo.cs
index 00ca4e4..c7b3162 100644
--- a/MarkDownEditor/Properties/AssemblyInfo.cs
+++ b/MarkDownEditor/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.3.7.0")]
-[assembly: AssemblyFileVersion("0.3.7.0")]
+[assembly: AssemblyVersion("0.3.8.0")]
+[assembly: AssemblyFileVersion("0.3.8.0")]
diff --git a/MarkDownEditor/Properties/Resources.Designer.cs b/MarkDownEditor/Properties/Resources.Designer.cs
index de53918..3856160 100644
--- a/MarkDownEditor/Properties/Resources.Designer.cs
+++ b/MarkDownEditor/Properties/Resources.Designer.cs
@@ -1050,6 +1050,15 @@ public static string ShowLineNumbers {
}
}
+ ///
+ /// Looks up a localized string similar to Show MathJax.
+ ///
+ public static string ShowMathJax {
+ get {
+ return ResourceManager.GetString("ShowMathJax", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Show Preview.
///
diff --git a/MarkDownEditor/Properties/Resources.resx b/MarkDownEditor/Properties/Resources.resx
index 40f7be4..df07ba6 100644
--- a/MarkDownEditor/Properties/Resources.resx
+++ b/MarkDownEditor/Properties/Resources.resx
@@ -570,4 +570,7 @@
Night Mode
+
+ Show MathJax
+
\ No newline at end of file
diff --git a/MarkDownEditor/Properties/Resources.zh-CN.resx b/MarkDownEditor/Properties/Resources.zh-CN.resx
index 2372e68..bb0cb94 100644
--- a/MarkDownEditor/Properties/Resources.zh-CN.resx
+++ b/MarkDownEditor/Properties/Resources.zh-CN.resx
@@ -570,4 +570,7 @@
夜间模式
+
+ 显示MathJax公式
+
\ No newline at end of file
diff --git a/MarkDownEditor/Properties/Settings.Designer.cs b/MarkDownEditor/Properties/Settings.Designer.cs
index 5a1b1c3..24fb9e5 100644
--- a/MarkDownEditor/Properties/Settings.Designer.cs
+++ b/MarkDownEditor/Properties/Settings.Designer.cs
@@ -268,5 +268,17 @@ public int CSSDark {
this["CSSDark"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool ShowMathJax {
+ get {
+ return ((bool)(this["ShowMathJax"]));
+ }
+ set {
+ this["ShowMathJax"] = value;
+ }
+ }
}
}
diff --git a/MarkDownEditor/Properties/Settings.settings b/MarkDownEditor/Properties/Settings.settings
index c00a379..b1b252e 100644
--- a/MarkDownEditor/Properties/Settings.settings
+++ b/MarkDownEditor/Properties/Settings.settings
@@ -65,5 +65,8 @@
1
+
+ False
+
\ No newline at end of file
diff --git a/MarkDownEditor/View/SettingsControl.xaml b/MarkDownEditor/View/SettingsControl.xaml
index 4d98f9a..0c56f29 100644
--- a/MarkDownEditor/View/SettingsControl.xaml
+++ b/MarkDownEditor/View/SettingsControl.xaml
@@ -112,6 +112,11 @@
+
+
+
+
+
diff --git a/MarkDownEditor/ViewModel/MainViewModel.cs b/MarkDownEditor/ViewModel/MainViewModel.cs
index 25ffe0d..57fd2aa 100644
--- a/MarkDownEditor/ViewModel/MainViewModel.cs
+++ b/MarkDownEditor/ViewModel/MainViewModel.cs
@@ -1262,7 +1262,7 @@ private void UpdatePreview()
bool isNightMode = SettingsViewModel.IsNightMode;
var cssFilePath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "css", isNightMode?"Dark":"Light", CurrentCssFiles[CurrentCssFileIndex]);
- DocumentExporter.Export("Html",
+ DocumentExporter.Export("Html Local Mathjax",
MarkDownType[CurrentMarkdownTypeText],
CurrentCssFileIndex==0|| CurrentCssFileIndex== CurrentCssFiles.Count-1? null: cssFilePath,
markdownSourceTempPath, previewSourceTempPath);
diff --git a/MarkDownEditor/ViewModel/SettingsViewModel.cs b/MarkDownEditor/ViewModel/SettingsViewModel.cs
index 4658f1a..cb14584 100644
--- a/MarkDownEditor/ViewModel/SettingsViewModel.cs
+++ b/MarkDownEditor/ViewModel/SettingsViewModel.cs
@@ -227,7 +227,6 @@ public bool ShowEndOfLine
RaisePropertyChanged("ShowEndOfLine");
}
}
-
private bool highlightCurrentLine = Properties.Settings.Default.HighlightCurrentLine;
public bool HighlightCurrentLine
{
@@ -243,6 +242,21 @@ public bool HighlightCurrentLine
}
}
+ private bool showMathJax = Properties.Settings.Default.ShowMathJax;
+ public bool ShowMathJax
+ {
+ get { return showMathJax; }
+ set
+ {
+ if (showMathJax == value)
+ return;
+ showMathJax = value;
+ Properties.Settings.Default.ShowMathJax = value;
+ Properties.Settings.Default.Save();
+ RaisePropertyChanged("ShowMathJax");
+ }
+ }
+
private bool showColumnRuler = Properties.Settings.Default.ShowColumnRuler;
public bool ShowColumnRuler
{
diff --git a/MarkDownEditor/pandoc.exe b/MarkDownEditor/pandoc.exe
index 84a0b4c..d866c71 100644
Binary files a/MarkDownEditor/pandoc.exe and b/MarkDownEditor/pandoc.exe differ
diff --git a/WkHtmlToImageWrapper/App.config b/WkHtmlToImageWrapper/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/WkHtmlToImageWrapper/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WkHtmlToImageWrapper/Program.cs b/WkHtmlToImageWrapper/Program.cs
new file mode 100644
index 0000000..19eab29
--- /dev/null
+++ b/WkHtmlToImageWrapper/Program.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WkHtmlToXDotNet;
+
+namespace WkHtmlToImageWrapper
+{
+ class Program
+ {
+ static int Main(string[] args)
+ {
+ try
+ {
+ string inputFilePath = args[0];
+ string outputFilePath = args[1];
+
+ var html = File.ReadAllText(inputFilePath);
+ var extension = Path.GetExtension(outputFilePath).Remove(0, 1).ToLower();
+ var image = HtmlToXConverter.ConvertToImage(html, extension, 600, 0);
+ File.WriteAllBytes(outputFilePath, image);
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ return 1;
+ }
+ }
+ }
+}
diff --git a/WkHtmlToImageWrapper/Properties/AssemblyInfo.cs b/WkHtmlToImageWrapper/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b8261ae
--- /dev/null
+++ b/WkHtmlToImageWrapper/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WkHtmlToImageWrapper")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WkHtmlToImageWrapper")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d01a2a12-54dd-4b88-a46a-926b4d0154de")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/WkHtmlToImageWrapper/WkHtmlToImageWrapper.csproj b/WkHtmlToImageWrapper/WkHtmlToImageWrapper.csproj
new file mode 100644
index 0000000..90ca7c7
--- /dev/null
+++ b/WkHtmlToImageWrapper/WkHtmlToImageWrapper.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {D01A2A12-54DD-4B88-A46A-926B4D0154DE}
+ Exe
+ Properties
+ WkHtmlToImageWrapper
+ WkHtmlToImageWrapper
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ ..\MarkDownEditor\WkHtmlToXDotNet.dll
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WkHtmlToPdfWrapper/App.config b/WkHtmlToPdfWrapper/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/WkHtmlToPdfWrapper/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WkHtmlToPdfWrapper/Program.cs b/WkHtmlToPdfWrapper/Program.cs
new file mode 100644
index 0000000..20828bd
--- /dev/null
+++ b/WkHtmlToPdfWrapper/Program.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WkHtmlToXDotNet;
+
+namespace WkHtmlToPdfWrapper
+{
+ class Program
+ {
+ static int Main(string[] args)
+ {
+ try
+ {
+ string inputFilePath = args[0];
+ string outputFilePath = args[1];
+ File.WriteAllBytes(outputFilePath, HtmlToXConverter.ConvertToPdf(File.ReadAllText(inputFilePath)));
+ return 0;
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ return 1;
+ }
+ }
+ }
+}
diff --git a/WkHtmlToPdfWrapper/Properties/AssemblyInfo.cs b/WkHtmlToPdfWrapper/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2be0741
--- /dev/null
+++ b/WkHtmlToPdfWrapper/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WkHtmlToPdfWrapper.exe")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WkHtmlToPdfWrapper.exe")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b0f82db9-f3ef-458e-8331-57563abb84a8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/WkHtmlToPdfWrapper/WkHtmlToPdfWrapper.csproj b/WkHtmlToPdfWrapper/WkHtmlToPdfWrapper.csproj
new file mode 100644
index 0000000..03e1d6d
--- /dev/null
+++ b/WkHtmlToPdfWrapper/WkHtmlToPdfWrapper.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B0F82DB9-F3EF-458E-8331-57563ABB84A8}
+ Exe
+ Properties
+ WkHtmlToPdfWrapper
+ WkHtmlToPdfWrapper
+ v4.5.2
+ 512
+ true
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ ..\MarkDownEditor\WkHtmlToXDotNet.dll
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file