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 @@ + + + + + + + + + + + + + + + + + + + + @@ -148,6 +181,7 @@ + @@ -163,6 +197,63 @@ Arguments="/x [ProductCode]"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -184,5 +275,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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("
"+text+"
"); + 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