Stackedit/public/res/extensions/mathJax.js

277 lines
7.7 KiB
JavaScript
Raw Normal View History

2013-11-07 23:10:38 +00:00
/*defines MathJax */
2013-05-27 19:45:33 +00:00
define([
2014-04-29 20:23:22 +00:00
"utils",
"classes/Extension",
"text!html/mathJaxSettingsBlock.html",
"mathjax"
2013-10-06 14:34:40 +00:00
], function(utils, Extension, mathJaxSettingsBlockHTML) {
2014-04-29 20:23:22 +00:00
2013-06-22 23:48:57 +00:00
var mathJax = new Extension("mathJax", "MathJax", true);
mathJax.settingsBlock = mathJaxSettingsBlockHTML;
2014-04-29 20:23:22 +00:00
mathJax.defaultConfig = {
tex : "{}",
tex2jax: '{ inlineMath: [["$","$"],["\\\\\\\\(","\\\\\\\\)"]], displayMath: [["$$","$$"],["\\\\[","\\\\]"]], processEscapes: true }'
};
mathJax.onLoadSettings = function() {
utils.setInputValue("#input-mathjax-config-tex", mathJax.config.tex);
utils.setInputValue("#input-mathjax-config-tex2jax", mathJax.config.tex2jax);
};
mathJax.onSaveSettings = function(newConfig, event) {
newConfig.tex = utils.getInputJsValue("#input-mathjax-config-tex", event);
newConfig.tex2jax = utils.getInputJsValue("#input-mathjax-config-tex2jax", event);
};
/*jshint ignore:start */
mathJax.onPagedownConfigure = function(editorObject) {
preview = document.getElementById("preview-contents");
var converter = editorObject.getConverter();
converter.hooks.chain("preConversion", removeMath);
converter.hooks.chain("postConversion", replaceMath);
};
var afterRefreshCallback;
mathJax.onAsyncPreview = function(callback) {
afterRefreshCallback = callback;
UpdateMJ();
};
// From math.stackexchange.com...
//
// The math is in blocks i through j, so
// collect it into one block and clear the others.
// Replace &, <, and > by named entities.
// For IE, put <br> at the ends of comments since IE removes \n.
// Clear the current math positions and store the index of the
// math, then push the math string onto the storage array.
//
function processMath(i, j, unescape) {
var block = blocks.slice(i, j + 1).join("")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
for(HUB.Browser.isMSIE && (block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n")); j > i;)
blocks[j] = "", j--;
blocks[i] = "@@" + math.length + "@@";
unescape && (block = unescape(block));
math.push(block);
start = end = last = null;
}
function removeMath(text) {
start = end = last = null;
math = [];
var unescape;
if(/`/.test(text)) {
text = text.replace(/~/g, "~T").replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function(text) {
return text.replace(/\$/g, "~D")
});
unescape = function(text) {
return text.replace(/~([TD])/g,
function(match, n) {
return {T: "~", D: "$"}[n]
})
};
} else {
unescape = function(text) {
return text
};
}
blocks = split(text.replace(/\r\n?/g, "\n"), splitDelimiter);
for(var i = 1, m = blocks.length; i < m; i += 2) {
var block = blocks[i];
if("@" === block.charAt(0)) {
//
// Things that look like our math markers will get
// stored and then retrieved along with the math.
//
blocks[i] = "@@" + math.length + "@@";
math.push(block)
} else if(start) {
//
// If we are in math, look for the end delimiter,
// but don't go past double line breaks, and
// and balance braces within the math.
//
if(end == inline && block.charAt(0) == '\n') {
// This should fix #136 by ignoring inline maths that are actually multiline
start = end = last = null;
} else if(block === end) {
if(braces) {
last = i
} else {
processMath(start, i, unescape)
}
} else {
if(block.match(/\n.*\n/)) {
last && (i = last, processMath(start, i, unescape)), start = end = last = null, braces = 0
} else {
if("{" === block) {
braces++
} else {
"}" === block && braces && braces--
}
}
}
} else {
if(block === inline || "$$" === block) {
start = i;
end = block;
braces = 0;
} else {
if("begin" === block.substr(1, 5)) {
start = i;
end = "\\end" + block.substr(6);
braces = 0;
}
}
}
}
last && processMath(start, last, unescape);
return unescape(blocks.join(""))
}
//
// Put back the math strings that were saved,
// and clear the math array (no need to keep it around).
//
function replaceMath(text) {
text = text.replace(/@@(\d+)@@/g, function(match, n) {
return math[n]
});
math = null;
return text
}
//
// This is run to restart MathJax after it has finished
// the previous run (that may have been canceled)
//
function RestartMJ() {
pending = false;
HUB.cancelTypeset = false;
HUB.Queue([
"Typeset",
HUB,
preview
]);
HUB.Queue(afterRefreshCallback); //benweet
}
//
// When the preview changes, cancel MathJax and restart,
// if we haven't done that already.
//
function UpdateMJ() {
if(!pending /*benweet (we need to call our afterRefreshCallback) && ready */) {
pending = true;
HUB.Cancel();
HUB.Queue(RestartMJ);
}
}
var ready = false, pending = false, preview = null, inline = "$", blocks, start, end, last, braces, math, HUB = MathJax.Hub;
//
// Runs after initial typeset
//
HUB.Queue(function() {
ready = true;
HUB.processUpdateTime = 50;
HUB.Config({"HTML-CSS": {EqnChunk: 10, EqnChunkFactor: 1}, SVG: {EqnChunk: 10, EqnChunkFactor: 1}})
});
/*benweet
Don't hash inline math $...$ (see https://github.com/benweet/stackedit/issues/136)
var u = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i, r;
*/
//
// The pattern for math delimiters and special symbols
// needed for searching for math in the page.
//
var splitDelimiter = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i;
var split;
if(3 === "aba".split(/(b)/).length) {
split = function(text, delimiter) {
return text.split(delimiter)
};
} else {
split = function(text, delimiter) {
var b = [], c;
if(!delimiter.global) {
c = delimiter.toString();
var d = "";
c = c.replace(/^\/(.*)\/([im]*)$/, function(a, c, b) {
d = b;
return c
});
delimiter = RegExp(c, d + "g")
}
for(var e = delimiter.lastIndex = 0; c = delimiter.exec(text);) {
b.push(text.substring(e, c.index));
b.push.apply(b, c.slice(1));
e = c.index + c[0].length;
}
b.push(text.substring(e));
return b
};
}
(function() {
var HUB = MathJax.Hub;
if(!HUB.Cancel) {
HUB.cancelTypeset = !1;
HUB.Register.StartupHook("HTML-CSS Jax Config", function() {
var HTMLCSS = MathJax.OutputJax["HTML-CSS"], TRANSLATE = HTMLCSS.Translate;
HTMLCSS.Augment({Translate: function(script, state) {
if(HUB.cancelTypeset || state.cancelled)
throw Error("MathJax Canceled");
return TRANSLATE.call(HTMLCSS, script, state)
}})
});
HUB.Register.StartupHook("SVG Jax Config", function() {
var SVG = MathJax.OutputJax.SVG, TRANSLATE = SVG.Translate;
SVG.Augment({Translate: function(script, state) {
if(HUB.cancelTypeset || state.cancelled)
throw Error("MathJax Canceled");
return TRANSLATE.call(SVG,
script, state)
}})
});
HUB.Register.StartupHook("TeX Jax Config", function() {
var TEX = MathJax.InputJax.TeX, TRANSLATE = TEX.Translate;
TEX.Augment({Translate: function(script, state) {
if(HUB.cancelTypeset || state.cancelled)
throw Error("MathJax Canceled");
return TRANSLATE.call(TEX, script, state)
}})
});
var PROCESSERROR = HUB.processError;
HUB.processError = function(error, state, type) {
if("MathJax Canceled" !== error.message)
return PROCESSERROR.call(HUB, error, state, type);
MathJax.Message.Clear(0, 0);
state.jaxIDs = [];
state.jax = {};
state.scripts = [];
state.i = state.j = 0;
state.cancelled = true;
return null
};
HUB.Cancel = function() {
this.cancelTypeset = true
}
}
})();
/*jshint ignore:end */
2013-05-25 00:34:04 +00:00
return mathJax;
});