//---------------------------------------------------------------------------- // Copyright (C) 2008-2012 The IPython Development Team // // Distributed under the terms of the BSD License. The full license is in // the file COPYING, distributed as part of this software. //---------------------------------------------------------------------------- //============================================================================ // MathJax utility functions //============================================================================ IPython.namespace('IPython.mathjaxutils'); IPython.mathjaxutils = (function (IPython) { var init = function () { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'left', // Change this to 'center' to center equations. "HTML-CSS": { styles: {'.MathJax_Display': {"margin": 0}} } }); MathJax.Hub.Configured(); } else if (window.mathjax_url != "") { // Don't have MathJax, but should. Show dialog. var message = $('
') .append( $("").addClass('dialog').html( "Math/LaTeX rendering will be disabled." ) ).append( $("").addClass('dialog').html( "If you have administrative access to the notebook server and" + " a working internet connection, you can install a local copy" + " of MathJax for offline use with the following command on the server" + " at a Python or IPython prompt:" ) ).append( $("").addClass('dialog').html( ">>> from IPython.external import mathjax; mathjax.install_mathjax()" ) ).append( $("").addClass('dialog').html( "This will try to install MathJax into the IPython source directory." ) ).append( $("").addClass('dialog').html( "If IPython is installed to a location that requires" + " administrative privileges to write, you will need to make this call as" + " an administrator, via 'sudo'." ) ).append( $("").addClass('dialog').html( "When you start the notebook server, you can instruct it to disable MathJax support altogether:" ) ).append( $("").addClass('dialog').html( "$ ipython notebook --no-mathjax" ) ).append( $("").addClass('dialog').html( "which will prevent this dialog from appearing." ) ) IPython.dialog.modal({ title : "Failed to retrieve MathJax from '" + window.mathjax_url + "'", body : message, buttons : { OK : {class: "btn-danger"} } }); } else { // No MathJax, but none expected. No dialog. }; }; // Some magic for deferring mathematical expressions to MathJax // by hiding them from the Markdown parser. // Some of the code here is adapted with permission from Davide Cervone // under the terms of the Apache2 license governing the MathJax project. // Other minor modifications are also due to StackExchange and are used with // permission. var inline = "$"; // the inline math delimiter var blocks, start, end, last, braces; // used in searching for math var math; // stores math until pagedown (Markdown parser) is done // MATHSPLIT contains the pattern for math delimiters and special symbols // needed for searching for math in the text input. var MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i; // 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$foo ` and `$bar
are variables.
var hasCodeSpans = /`/.test(text),
de_tilde;
if (hasCodeSpans) {
text = text.replace(/~/g, "~T").replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function (wholematch) {
return wholematch.replace(/\$/g, "~D");
});
de_tilde = function (text) { return text.replace(/~([TD])/g, function (wholematch, character) { return { T: "~", D: "$" }[character]; }) };
} else {
de_tilde = function (text) { return text; };
}
blocks = IPython.utils.regex_split(text.replace(/\r\n?/g, "\n"),MATHSPLIT);
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 (block === end) {
if (braces) {
last = i
}
else {
process_math(start, i, de_tilde)
}
}
else if (block.match(/\n.*\n/)) {
if (last) {
i = last;
process_math(start, i, de_tilde)
}
start = end = last = null;
braces = 0;
}
else if (block === "{") {
braces++
}
else if (block === "}" && braces) {
braces--
}
}
else {
//
// Look for math start delimiters and when
// found, set up the end delimiter.
//
if (block === inline || block === "$$") {
start = i;
end = block;
braces = 0;
}
else if (block.substr(1, 5) === "begin") {
start = i;
end = "\\end" + block.substr(6);
braces = 0;
}
}
}
if (last) {
process_math(start, last, de_tilde)
}
return de_tilde(blocks.join(""));
}
//
// Put back the math strings that were saved,
// and clear the math array (no need to keep it around).
//
var replace_math = function (text) {
if (!window.MathJax) {
return text;
}
text = text.replace(/@@(\d+)@@/g, function (match, n) {
return math[n]
});
math = null;
return text;
}
return {
init : init,
process_math : process_math,
remove_math : remove_math,
replace_math : replace_math
};
}(IPython));