Show More
@@ -1,23 +1,28 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 |
// Copyright (C) 2008-201 |
|
2 | // Copyright (C) 2008-2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 |
// MathJax |
|
9 | // MathJax utility functions | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | IPython.namespace('IPython.mathjaxutils'); | |
13 |
|
13 | |||
14 |
|
|
14 | IPython.mathjaxutils = (function (IPython) { | |
|
15 | ||||
|
16 | var init = function () { | |||
15 | if (window.MathJax) { |
|
17 | if (window.MathJax) { | |
16 | // MathJax loaded |
|
18 | // MathJax loaded | |
17 | MathJax.Hub.Config({ |
|
19 | MathJax.Hub.Config({ | |
|
20 | TeX: { equationNumbers: { autoNumber: "AMS", useLabelIds: true }, | |||
|
21 | extensions: ["autoload-all.js"] }, | |||
18 | tex2jax: { |
|
22 | tex2jax: { | |
19 | inlineMath: [ ['$','$'], ["\\(","\\)"] ], |
|
23 | inlineMath: [ ['$','$'], ["\\(","\\)"] ], | |
20 | displayMath: [ ['$$','$$'], ["\\[","\\]"] ] |
|
24 | displayMath: [ ['$$','$$'], ["\\[","\\]"] ], | |
|
25 | processEnvironments: true | |||
21 | }, |
|
26 | }, | |
22 | displayAlign: 'left', // Change this to 'center' to center equations. |
|
27 | displayAlign: 'left', // Change this to 'center' to center equations. | |
23 | "HTML-CSS": { |
|
28 | "HTML-CSS": { | |
@@ -74,10 +79,152 b' var IPython = (function (IPython) {' | |||||
74 | }; |
|
79 | }; | |
75 | }; |
|
80 | }; | |
76 |
|
81 | |||
|
82 | // Some magic for deferring mathematical expressions to MathJaX | |||
|
83 | // Some of the code here is adapted with permission from Stack Exchange Inc. | |||
|
84 | ||||
|
85 | var inline = "$"; // the inline math delimiter | |||
|
86 | var blocks, start, end, last, braces; // used in searching for math | |||
|
87 | var math; // stores math until pagedown (Markdown parser) is done | |||
|
88 | var HUB = MathJax.Hub; | |||
|
89 | ||||
|
90 | // MATHSPLIT contains the pattern for math delimiters and special symbols | |||
|
91 | // needed for searching for math in the text input. | |||
|
92 | var MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i; | |||
|
93 | ||||
|
94 | // The math is in blocks i through j, so | |||
|
95 | // collect it into one block and clear the others. | |||
|
96 | // Replace &, <, and > by named entities. | |||
|
97 | // For IE, put <br> at the ends of comments since IE removes \n. | |||
|
98 | // Clear the current math positions and store the index of the | |||
|
99 | // math, then push the math string onto the storage array. | |||
|
100 | // The preProcess function is called on all blocks if it has been passed in | |||
|
101 | function processMath(i, j, preProcess) { | |||
|
102 | var block = blocks.slice(i, j + 1).join("").replace(/&/g, "&") // use HTML entity for & | |||
|
103 | .replace(/</g, "<") // use HTML entity for < | |||
|
104 | .replace(/>/g, ">") // use HTML entity for > | |||
|
105 | ; | |||
|
106 | if (HUB.Browser.isMSIE) { | |||
|
107 | block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n") | |||
|
108 | } | |||
|
109 | while (j > i) { | |||
|
110 | blocks[j] = ""; | |||
|
111 | j--; | |||
|
112 | } | |||
|
113 | blocks[i] = "@@" + math.length + "@@"; // replace the current block text with a unique tag to find later | |||
|
114 | if (preProcess) | |||
|
115 | block = preProcess(block); | |||
|
116 | math.push(block); | |||
|
117 | start = end = last = null; | |||
|
118 | } | |||
|
119 | ||||
|
120 | // Break up the text into its component parts and search | |||
|
121 | // through them for math delimiters, braces, linebreaks, etc. | |||
|
122 | // Math delimiters must match and braces must balance. | |||
|
123 | // Don't allow math to pass through a double linebreak | |||
|
124 | // (which will be a paragraph). | |||
|
125 | // | |||
|
126 | function removeMath(text) { | |||
|
127 | start = end = last = null; // for tracking math delimiters | |||
|
128 | math = []; // stores math strings for later | |||
|
129 | ||||
|
130 | // Except for extreme edge cases, this should catch precisely those pieces of the markdown | |||
|
131 | // source that will later be turned into code spans. While MathJax will not TeXify code spans, | |||
|
132 | // we still have to consider them at this point; the following issue has happened several times: | |||
|
133 | // | |||
|
134 | // `$foo` and `$bar` are varibales. --> <code>$foo ` and `$bar</code> are variables. | |||
|
135 | ||||
|
136 | var hasCodeSpans = /`/.test(text), | |||
|
137 | deTilde; | |||
|
138 | if (hasCodeSpans) { | |||
|
139 | text = text.replace(/~/g, "~T").replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function (wholematch) { | |||
|
140 | return wholematch.replace(/\$/g, "~D"); | |||
|
141 | }); | |||
|
142 | deTilde = function (text) { return text.replace(/~([TD])/g, function (wholematch, character) { return { T: "~", D: "$" }[character]; }) }; | |||
|
143 | } else { | |||
|
144 | deTilde = function (text) { return text; }; | |||
|
145 | } | |||
|
146 | ||||
|
147 | blocks = IPython.utils.regex_split(text.replace(/\r\n?/g, "\n"),MATHSPLIT); | |||
|
148 | ||||
|
149 | for (var i = 1, m = blocks.length; i < m; i += 2) { | |||
|
150 | var block = blocks[i]; | |||
|
151 | if (block.charAt(0) === "@") { | |||
|
152 | // | |||
|
153 | // Things that look like our math markers will get | |||
|
154 | // stored and then retrieved along with the math. | |||
|
155 | // | |||
|
156 | blocks[i] = "@@" + math.length + "@@"; | |||
|
157 | math.push(block); | |||
|
158 | } | |||
|
159 | else if (start) { | |||
|
160 | // | |||
|
161 | // If we are in math, look for the end delimiter, | |||
|
162 | // but don't go past double line breaks, and | |||
|
163 | // and balance braces within the math. | |||
|
164 | // | |||
|
165 | if (block === end) { | |||
|
166 | if (braces) { | |||
|
167 | last = i | |||
|
168 | } | |||
|
169 | else { | |||
|
170 | processMath(start, i, deTilde) | |||
|
171 | } | |||
|
172 | } | |||
|
173 | else if (block.match(/\n.*\n/)) { | |||
|
174 | if (last) { | |||
|
175 | i = last; | |||
|
176 | processMath(start, i, deTilde) | |||
|
177 | } | |||
|
178 | start = end = last = null; | |||
|
179 | braces = 0; | |||
|
180 | } | |||
|
181 | else if (block === "{") { | |||
|
182 | braces++ | |||
|
183 | } | |||
|
184 | else if (block === "}" && braces) { | |||
|
185 | braces-- | |||
|
186 | } | |||
|
187 | } | |||
|
188 | else { | |||
|
189 | // | |||
|
190 | // Look for math start delimiters and when | |||
|
191 | // found, set up the end delimiter. | |||
|
192 | // | |||
|
193 | if (block === inline || block === "$$") { | |||
|
194 | start = i; | |||
|
195 | end = block; | |||
|
196 | braces = 0; | |||
|
197 | } | |||
|
198 | else if (block.substr(1, 5) === "begin") { | |||
|
199 | start = i; | |||
|
200 | end = "\\end" + block.substr(6); | |||
|
201 | braces = 0; | |||
|
202 | } | |||
|
203 | } | |||
|
204 | } | |||
|
205 | if (last) { | |||
|
206 | processMath(start, last, deTilde) | |||
|
207 | } | |||
|
208 | return deTilde(blocks.join("")); | |||
|
209 | } | |||
77 |
|
210 | |||
78 | // Set module variables |
|
211 | // | |
79 | IPython.init_mathjax = init_mathjax; |
|
212 | // Put back the math strings that were saved, | |
|
213 | // and clear the math array (no need to keep it around). | |||
|
214 | // | |||
|
215 | function replaceMath(text) { | |||
|
216 | text = text.replace(/@@(\d+)@@/g, function (match, n) { | |||
|
217 | return math[n] | |||
|
218 | }); | |||
|
219 | math = null; | |||
|
220 | return text; | |||
|
221 | } | |||
80 |
|
222 | |||
81 |
return |
|
223 | return { | |
|
224 | init : init, | |||
|
225 | processMath : processMath, | |||
|
226 | removeMath : removeMath, | |||
|
227 | replaceMath : replaceMath, | |||
|
228 | }; | |||
82 |
|
229 | |||
83 | }(IPython)); No newline at end of file |
|
230 | }(IPython)); |
@@ -31,7 +31,7 b' $(document).ready(function () {' | |||||
31 | } |
|
31 | } | |
32 | // end monkey patching CodeMirror |
|
32 | // end monkey patching CodeMirror | |
33 |
|
33 | |||
34 |
IPython. |
|
34 | IPython.mathjaxutils.init(); | |
35 |
|
35 | |||
36 | IPython.read_only = $('body').data('readOnly') === 'True'; |
|
36 | IPython.read_only = $('body').data('readOnly') === 'True'; | |
37 | $('div#main_app').addClass('border-box-sizing ui-widget'); |
|
37 | $('div#main_app').addClass('border-box-sizing ui-widget'); |
@@ -12,7 +12,7 b'' | |||||
12 |
|
12 | |||
13 | $(document).ready(function () { |
|
13 | $(document).ready(function () { | |
14 |
|
14 | |||
15 |
IPython. |
|
15 | IPython.mathjaxutils.init(); | |
16 |
|
16 | |||
17 | IPython.read_only = $('body').data('readOnly') === 'True'; |
|
17 | IPython.read_only = $('body').data('readOnly') === 'True'; | |
18 | $('div#main_app').addClass('border-box-sizing ui-widget'); |
|
18 | $('div#main_app').addClass('border-box-sizing ui-widget'); |
@@ -1,5 +1,5 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 |
// Copyright (C) 2008-201 |
|
2 | // Copyright (C) 2008-2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
@@ -221,7 +221,11 b' var IPython = (function (IPython) {' | |||||
221 | if (this.rendered === false) { |
|
221 | if (this.rendered === false) { | |
222 | var text = this.get_text(); |
|
222 | var text = this.get_text(); | |
223 | if (text === "") { text = this.placeholder; } |
|
223 | if (text === "") { text = this.placeholder; } | |
|
224 | ||||
|
225 | text = IPython.mathjaxutils.removeMath(text) | |||
224 | var html = IPython.markdown_converter.makeHtml(text); |
|
226 | var html = IPython.markdown_converter.makeHtml(text); | |
|
227 | html = IPython.mathjaxutils.replaceMath(html) | |||
|
228 | ||||
225 | try { |
|
229 | try { | |
226 | this.set_rendered(html); |
|
230 | this.set_rendered(html); | |
227 | } catch (e) { |
|
231 | } catch (e) { |
@@ -1,5 +1,5 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 |
// Copyright (C) 2008-201 |
|
2 | // Copyright (C) 2008-2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
@@ -13,6 +13,123 b" IPython.namespace('IPython.utils');" | |||||
13 |
|
13 | |||
14 | IPython.utils = (function (IPython) { |
|
14 | IPython.utils = (function (IPython) { | |
15 |
|
15 | |||
|
16 | //============================================================================ | |||
|
17 | // Cross-browser RegEx Split | |||
|
18 | //============================================================================ | |||
|
19 | ||||
|
20 | // This code has been MODIFIED from the code licensed below to not replace the | |||
|
21 | // default browser split. The license is reproduced here. | |||
|
22 | ||||
|
23 | // see http://blog.stevenlevithan.com/archives/cross-browser-split for more info: | |||
|
24 | /*! | |||
|
25 | * Cross-Browser Split 1.1.1 | |||
|
26 | * Copyright 2007-2012 Steven Levithan <stevenlevithan.com> | |||
|
27 | * Available under the MIT License | |||
|
28 | * ECMAScript compliant, uniform cross-browser split method | |||
|
29 | */ | |||
|
30 | ||||
|
31 | /** | |||
|
32 | * Splits a string into an array of strings using a regex or string | |||
|
33 | * separator. Matches of the separator are not included in the result array. | |||
|
34 | * However, if `separator` is a regex that contains capturing groups, | |||
|
35 | * backreferences are spliced into the result each time `separator` is | |||
|
36 | * matched. Fixes browser bugs compared to the native | |||
|
37 | * `String.prototype.split` and can be used reliably cross-browser. | |||
|
38 | * @param {String} str String to split. | |||
|
39 | * @param {RegExp|String} separator Regex or string to use for separating | |||
|
40 | * the string. | |||
|
41 | * @param {Number} [limit] Maximum number of items to include in the result | |||
|
42 | * array. | |||
|
43 | * @returns {Array} Array of substrings. | |||
|
44 | * @example | |||
|
45 | * | |||
|
46 | * // Basic use | |||
|
47 | * regex_split('a b c d', ' '); | |||
|
48 | * // -> ['a', 'b', 'c', 'd'] | |||
|
49 | * | |||
|
50 | * // With limit | |||
|
51 | * regex_split('a b c d', ' ', 2); | |||
|
52 | * // -> ['a', 'b'] | |||
|
53 | * | |||
|
54 | * // Backreferences in result array | |||
|
55 | * regex_split('..word1 word2..', /([a-z]+)(\d+)/i); | |||
|
56 | * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] | |||
|
57 | */ | |||
|
58 | var regex_split = function (str, separator, limit) { | |||
|
59 | // If `separator` is not a regex, use `split` | |||
|
60 | if (Object.prototype.toString.call(separator) !== "[object RegExp]") { | |||
|
61 | return split.call(str, separator, limit); | |||
|
62 | } | |||
|
63 | var output = [], | |||
|
64 | flags = (separator.ignoreCase ? "i" : "") + | |||
|
65 | (separator.multiline ? "m" : "") + | |||
|
66 | (separator.extended ? "x" : "") + // Proposed for ES6 | |||
|
67 | (separator.sticky ? "y" : ""), // Firefox 3+ | |||
|
68 | lastLastIndex = 0, | |||
|
69 | // Make `global` and avoid `lastIndex` issues by working with a copy | |||
|
70 | separator = new RegExp(separator.source, flags + "g"), | |||
|
71 | separator2, match, lastIndex, lastLength; | |||
|
72 | str += ""; // Type-convert | |||
|
73 | ||||
|
74 | compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined" | |||
|
75 | if (!compliantExecNpcg) { | |||
|
76 | // Doesn't need flags gy, but they don't hurt | |||
|
77 | separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); | |||
|
78 | } | |||
|
79 | /* Values for `limit`, per the spec: | |||
|
80 | * If undefined: 4294967295 // Math.pow(2, 32) - 1 | |||
|
81 | * If 0, Infinity, or NaN: 0 | |||
|
82 | * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; | |||
|
83 | * If negative number: 4294967296 - Math.floor(Math.abs(limit)) | |||
|
84 | * If other: Type-convert, then use the above rules | |||
|
85 | */ | |||
|
86 | limit = typeof(limit) === "undefined" ? | |||
|
87 | -1 >>> 0 : // Math.pow(2, 32) - 1 | |||
|
88 | limit >>> 0; // ToUint32(limit) | |||
|
89 | while (match = separator.exec(str)) { | |||
|
90 | // `separator.lastIndex` is not reliable cross-browser | |||
|
91 | lastIndex = match.index + match[0].length; | |||
|
92 | if (lastIndex > lastLastIndex) { | |||
|
93 | output.push(str.slice(lastLastIndex, match.index)); | |||
|
94 | // Fix browsers whose `exec` methods don't consistently return `undefined` for | |||
|
95 | // nonparticipating capturing groups | |||
|
96 | if (!compliantExecNpcg && match.length > 1) { | |||
|
97 | match[0].replace(separator2, function () { | |||
|
98 | for (var i = 1; i < arguments.length - 2; i++) { | |||
|
99 | if (typeof(arguments[i]) === "undefined") { | |||
|
100 | match[i] = undefined; | |||
|
101 | } | |||
|
102 | } | |||
|
103 | }); | |||
|
104 | } | |||
|
105 | if (match.length > 1 && match.index < str.length) { | |||
|
106 | Array.prototype.push.apply(output, match.slice(1)); | |||
|
107 | } | |||
|
108 | lastLength = match[0].length; | |||
|
109 | lastLastIndex = lastIndex; | |||
|
110 | if (output.length >= limit) { | |||
|
111 | break; | |||
|
112 | } | |||
|
113 | } | |||
|
114 | if (separator.lastIndex === match.index) { | |||
|
115 | separator.lastIndex++; // Avoid an infinite loop | |||
|
116 | } | |||
|
117 | } | |||
|
118 | if (lastLastIndex === str.length) { | |||
|
119 | if (lastLength || !separator.test("")) { | |||
|
120 | output.push(""); | |||
|
121 | } | |||
|
122 | } else { | |||
|
123 | output.push(str.slice(lastLastIndex)); | |||
|
124 | } | |||
|
125 | return output.length > limit ? output.slice(0, limit) : output; | |||
|
126 | }; | |||
|
127 | ||||
|
128 | //============================================================================ | |||
|
129 | // End contributed Cross-browser RegEx Split | |||
|
130 | //============================================================================ | |||
|
131 | ||||
|
132 | ||||
16 | var uuid = function () { |
|
133 | var uuid = function () { | |
17 | // http://www.ietf.org/rfc/rfc4122.txt |
|
134 | // http://www.ietf.org/rfc/rfc4122.txt | |
18 | var s = []; |
|
135 | var s = []; | |
@@ -138,6 +255,7 b' IPython.utils = (function (IPython) {' | |||||
138 |
|
255 | |||
139 |
|
256 | |||
140 | return { |
|
257 | return { | |
|
258 | regex_split : regex_split, | |||
141 | uuid : uuid, |
|
259 | uuid : uuid, | |
142 | fixConsole : fixConsole, |
|
260 | fixConsole : fixConsole, | |
143 | keycodes : keycodes, |
|
261 | keycodes : keycodes, |
@@ -199,7 +199,7 b' data-notebook-id={{notebook_id}}' | |||||
199 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> |
|
199 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> | |
200 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
200 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> | |
201 | <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> |
|
201 | <script src="{{ static_url("js/layoutmanager.js") }}" type="text/javascript" charset="utf-8"></script> | |
202 |
<script src="{{ static_url("js/ |
|
202 | <script src="{{ static_url("js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script> | |
203 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
203 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> | |
204 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
204 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> | |
205 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
205 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
@@ -69,7 +69,7 b' data-notebook-id={{notebook_id}}' | |||||
69 |
|
69 | |||
70 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> |
|
70 | <script src="{{ static_url("js/events.js") }}" type="text/javascript" charset="utf-8"></script> | |
71 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> |
|
71 | <script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script> | |
72 |
<script src="{{ static_url("js/ |
|
72 | <script src="{{ static_url("js/mathjaxutils.js") }}" type="text/javascript" charset="utf-8"></script> | |
73 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> |
|
73 | <script src="{{ static_url("js/outputarea.js") }}" type="text/javascript" charset="utf-8"></script> | |
74 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
74 | <script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script> | |
75 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
|
75 | <script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script> |
General Comments 0
You need to be logged in to leave comments.
Login now