##// END OF EJS Templates
Backport PR #2212: catch errors in markdown javascript...
MinRK -
Show More
@@ -1,390 +1,394 b''
1 1 /**
2 2 * Primary styles
3 3 *
4 4 * Author: IPython Development Team
5 5 */
6 6
7 7
8 8 body {
9 9 overflow: hidden;
10 10 }
11 11
12 12 span#save_widget {
13 13 padding: 5px;
14 14 margin: 0px 0px 0px 300px;
15 15 display:inline-block;
16 16 }
17 17
18 18 span#notebook_name {
19 19 height: 1em;
20 20 line-height: 1em;
21 21 padding: 3px;
22 22 border: none;
23 23 font-size: 146.5%;
24 24 }
25 25
26 26 .ui-menubar-item .ui-button .ui-button-text {
27 27 padding: 0.4em 1.0em;
28 28 font-size: 100%;
29 29 }
30 30
31 31 .ui-menu {
32 32 -moz-box-shadow: 0px 6px 10px -1px #adadad;
33 33 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
34 34 box-shadow: 0px 6px 10px -1px #adadad;
35 35 }
36 36
37 37 .ui-menu .ui-menu-item a {
38 38 border: 1px solid transparent;
39 39 padding: 2px 1.6em;
40 40 }
41 41
42 42 .ui-menu .ui-menu-item a.ui-state-focus {
43 43 margin: 0;
44 44 }
45 45
46 46 .ui-menu hr {
47 47 margin: 0.3em 0;
48 48 }
49 49
50 50 #menubar_container {
51 51 position: relative;
52 52 }
53 53
54 54 #notification {
55 55 position: absolute;
56 56 right: 3px;
57 57 top: 3px;
58 58 height: 25px;
59 59 padding: 3px 6px;
60 60 z-index: 10;
61 61 }
62 62
63 63 #toolbar {
64 64 padding: 3px 15px;
65 65 }
66 66
67 67 #cell_type {
68 68 font-size: 85%;
69 69 }
70 70
71 71
72 72 div#main_app {
73 73 width: 100%;
74 74 position: relative;
75 75 }
76 76
77 77 span#quick_help_area {
78 78 position: static;
79 79 padding: 5px 0px;
80 80 margin: 0px 0px 0px 0px;
81 81 }
82 82
83 83 .help_string {
84 84 float: right;
85 85 width: 170px;
86 86 padding: 0px 5px;
87 87 text-align: left;
88 88 font-size: 85%;
89 89 }
90 90
91 91 .help_string_label {
92 92 float: right;
93 93 font-size: 85%;
94 94 }
95 95
96 96 div#notebook_panel {
97 97 margin: 0px 0px 0px 0px;
98 98 padding: 0px;
99 99 }
100 100
101 101 div#notebook {
102 102 overflow-y: scroll;
103 103 overflow-x: auto;
104 104 width: 100%;
105 105 /* This spaces the cell away from the edge of the notebook area */
106 106 padding: 5px 5px 15px 5px;
107 107 margin: 0px;
108 108 background-color: white;
109 109 }
110 110
111 111 div#pager_splitter {
112 112 height: 8px;
113 113 }
114 114
115 115 div#pager {
116 116 padding: 15px;
117 117 overflow: auto;
118 118 display: none;
119 119 }
120 120
121 121 div.ui-widget-content {
122 122 border: 1px solid #aaa;
123 123 outline: none;
124 124 }
125 125
126 126 .cell {
127 127 border: 1px solid transparent;
128 128 }
129 129
130 130 div.cell {
131 131 width: 100%;
132 132 padding: 5px 5px 5px 0px;
133 133 /* This acts as a spacer between cells, that is outside the border */
134 134 margin: 2px 0px 2px 0px;
135 135 }
136 136
137 137 div.code_cell {
138 138 background-color: white;
139 139 }
140 140
141 141 /* any special styling for code cells that are currently running goes here */
142 142 div.code_cell.running {
143 143 }
144 144
145 145 div.prompt {
146 146 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
147 147 width: 11ex;
148 148 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
149 149 padding: 0.4em;
150 150 margin: 0px;
151 151 font-family: monospace;
152 152 text-align:right;
153 153 }
154 154
155 155 div.input {
156 156 page-break-inside: avoid;
157 157 }
158 158
159 159 /* input_area and input_prompt must match in top border and margin for alignment */
160 160 div.input_area {
161 161 color: black;
162 162 border: 1px solid #ddd;
163 163 border-radius: 3px;
164 164 background: #f7f7f7;
165 165 }
166 166
167 167 div.input_prompt {
168 168 color: navy;
169 169 border-top: 1px solid transparent;
170 170 }
171 171
172 172 div.output_wrapper {
173 173 /* This is a spacer between the input and output of each cell */
174 174 margin-top: 5px;
175 175 margin-left: 5px;
176 176 /* FF needs explicit width to stretch */
177 177 width: 100%;
178 178 /* this position must be relative to enable descendents to be absolute within it */
179 179 position: relative;
180 180 }
181 181
182 182 /* class for the output area when it should be height-limited */
183 183 div.output_scroll {
184 184 /* ideally, this would be max-height, but FF barfs all over that */
185 185 height: 24em;
186 186 /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
187 187 width: 100%;
188 188
189 189 overflow: auto;
190 190 border-radius: 3px;
191 191 box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
192 192 }
193 193
194 194 /* output div while it is collapsed */
195 195 div.output_collapsed {
196 196 margin-right: 5px;
197 197 }
198 198
199 199 div.out_prompt_overlay {
200 200 height: 100%;
201 201 padding: 0px;
202 202 position: absolute;
203 203 border-radius: 3px;
204 204 }
205 205
206 206 div.out_prompt_overlay:hover {
207 207 /* use inner shadow to get border that is computed the same on WebKit/FF */
208 208 box-shadow: inset 0 0 1px #000;
209 209 background: rgba(240, 240, 240, 0.5);
210 210 }
211 211
212 212 div.output_prompt {
213 213 color: darkred;
214 214 /* 5px right shift to account for margin in parent container */
215 215 margin: 0 5px 0 -5px;
216 216 }
217 217
218 218 /* This class is the outer container of all output sections. */
219 219 div.output_area {
220 220 padding: 0px;
221 221 page-break-inside: avoid;
222 222 }
223 223
224 224 /* This class is for the output subarea inside the output_area and after
225 225 the prompt div. */
226 226 div.output_subarea {
227 227 padding: 0.4em 0.4em 0.4em 0.4em;
228 228 }
229 229
230 230 /* The rest of the output_* classes are for special styling of the different
231 231 output types */
232 232
233 233 /* all text output has this class: */
234 234 div.output_text {
235 235 text-align: left;
236 236 color: black;
237 237 font-family: monospace;
238 238 }
239 239
240 240 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
241 241 div.output_stream {
242 242 padding-top: 0.0em;
243 243 padding-bottom: 0.0em;
244 244 }
245 245 div.output_stdout {
246 246 }
247 247 div.output_stderr {
248 248 background: #fdd; /* very light red background for stderr */
249 249 }
250 250
251 251 div.output_latex {
252 252 text-align: left;
253 253 color: black;
254 254 }
255 255
256 256 div.output_html {
257 257 }
258 258
259 259 div.output_png {
260 260 }
261 261
262 262 div.output_jpeg {
263 263 }
264 264
265 265 div.text_cell {
266 266 background-color: white;
267 267 padding: 5px 5px 5px 5px;
268 268 }
269 269
270 270 div.text_cell_input {
271 271 color: black;
272 272 border: 1px solid #ddd;
273 273 border-radius: 3px;
274 274 background: #f7f7f7;
275 275 }
276 276
277 277 div.text_cell_render {
278 278 font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
279 279 outline: none;
280 280 resize: none;
281 281 width: inherit;
282 282 border-style: none;
283 283 padding: 5px;
284 284 color: black;
285 285 }
286 286
287 287 /* The following gets added to the <head> if it is detected that the user has a
288 288 * monospace font with inconsistent normal/bold/italic height. See
289 289 * notebookmain.js. Such fonts will have keywords vertically offset with
290 290 * respect to the rest of the text. The user should select a better font.
291 291 * See: https://github.com/ipython/ipython/issues/1503
292 292 *
293 293 * .CodeMirror span {
294 294 * vertical-align: bottom;
295 295 * }
296 296 */
297 297
298 298 .CodeMirror {
299 299 line-height: 1.231; /* Changed from 1em to our global default */
300 300 }
301 301
302 302 .CodeMirror-scroll {
303 303 height: auto; /* Changed to auto to autogrow */
304 304 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
305 305 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
306 306 overflow-y: hidden;
307 307 overflow-x: auto; /* Changed from auto to remove scrollbar */
308 308 }
309 309
310 310 /* CSS font colors for translated ANSI colors. */
311 311
312 312
313 313 .ansiblack {color: black;}
314 314 .ansired {color: darkred;}
315 315 .ansigreen {color: darkgreen;}
316 316 .ansiyellow {color: brown;}
317 317 .ansiblue {color: darkblue;}
318 318 .ansipurple {color: darkviolet;}
319 319 .ansicyan {color: steelblue;}
320 320 .ansigrey {color: grey;}
321 321 .ansibold {font-weight: bold;}
322 322
323 323 .completions {
324 324 position: absolute;
325 325 z-index: 10;
326 326 overflow: hidden;
327 327 border: 1px solid grey;
328 328 }
329 329
330 330 .completions select {
331 331 background: white;
332 332 outline: none;
333 333 border: none;
334 334 padding: 0px;
335 335 margin: 0px;
336 336 overflow: auto;
337 337 font-family: monospace;
338 338 }
339 339
340 340 option.context {
341 341 background-color: #DEF7FF;
342 342 }
343 343 option.introspection {
344 344 background-color: #EBF4EB;
345 345 }
346 346
347 347 /*fixed part of the completion*/
348 348 .completions p b {
349 349 font-weight:bold;
350 350 }
351 351
352 352 .completions p {
353 353 background: #DDF;
354 354 /*outline: none;
355 355 padding: 0px;*/
356 356 border-bottom: black solid 1px;
357 357 padding: 1px;
358 358 font-family: monospace;
359 359 }
360 360
361 361 pre.dialog {
362 362 background-color: #f7f7f7;
363 363 border: 1px solid #ddd;
364 364 border-radius: 3px;
365 365 padding: 0.4em;
366 366 padding-left: 2em;
367 367 }
368 368
369 369 p.dialog {
370 370 padding : 0.2em;
371 371 }
372 372
373 373 .shortcut_key {
374 374 display: inline-block;
375 375 width: 15ex;
376 376 text-align: right;
377 377 font-family: monospace;
378 378 }
379 379
380 380 .shortcut_descr {
381 381 }
382 382
383 383 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
384 384 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
385 385 */
386 386 pre, code, kbd, samp { white-space: pre-wrap; }
387 387
388 388 #fonttest {
389 389 font-family: monospace;
390 390 }
391
392 .js-error {
393 color: darkred;
394 } No newline at end of file
@@ -1,367 +1,375 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // TextCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 // TextCell base class
15 15
16 16 var TextCell = function () {
17 17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 18 IPython.Cell.apply(this, arguments);
19 19 this.rendered = false;
20 20 this.cell_type = this.cell_type || 'text';
21 21 };
22 22
23 23
24 24 TextCell.prototype = new IPython.Cell();
25 25
26 26
27 27 TextCell.prototype.create_element = function () {
28 28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 29 cell.attr('tabindex','2');
30 30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31 31 this.code_mirror = CodeMirror(input_area.get(0), {
32 32 indentUnit : 4,
33 33 mode: this.code_mirror_mode,
34 34 theme: 'default',
35 35 value: this.placeholder,
36 36 readOnly: this.read_only,
37 37 lineWrapping : true,
38 38 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
39 39 });
40 40 // The tabindex=-1 makes this div focusable.
41 41 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
42 42 addClass('rendered_html').attr('tabindex','-1');
43 43 cell.append(input_area).append(render_area);
44 44 this.element = cell;
45 45 };
46 46
47 47
48 48 TextCell.prototype.bind_events = function () {
49 49 IPython.Cell.prototype.bind_events.apply(this);
50 50 var that = this;
51 51 this.element.keydown(function (event) {
52 52 if (event.which === 13 && !event.shiftKey) {
53 53 if (that.rendered) {
54 54 that.edit();
55 55 return false;
56 56 };
57 57 };
58 58 });
59 59 this.element.dblclick(function () {
60 60 that.edit();
61 61 });
62 62 };
63 63
64 64
65 65 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
66 66 // This method gets called in CodeMirror's onKeyDown/onKeyPress
67 67 // handlers and is used to provide custom key handling. Its return
68 68 // value is used to determine if CodeMirror should ignore the event:
69 69 // true = ignore, false = don't ignore.
70 70
71 71 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
72 72 // Always ignore shift-enter in CodeMirror as we handle it.
73 73 return true;
74 74 }
75 75 return false;
76 76 };
77 77
78 78
79 79 TextCell.prototype.select = function () {
80 80 IPython.Cell.prototype.select.apply(this);
81 81 var output = this.element.find("div.text_cell_render");
82 82 output.trigger('focus');
83 83 };
84 84
85 85
86 86 TextCell.prototype.unselect = function() {
87 87 // render on selection of another cell
88 88 this.render();
89 89 IPython.Cell.prototype.unselect.apply(this);
90 90 };
91 91
92 92
93 93 TextCell.prototype.edit = function () {
94 94 if ( this.read_only ) return;
95 95 if (this.rendered === true) {
96 96 var text_cell = this.element;
97 97 var output = text_cell.find("div.text_cell_render");
98 98 output.hide();
99 99 text_cell.find('div.text_cell_input').show();
100 100 this.code_mirror.refresh();
101 101 this.code_mirror.focus();
102 102 // We used to need an additional refresh() after the focus, but
103 103 // it appears that this has been fixed in CM. This bug would show
104 104 // up on FF when a newly loaded markdown cell was edited.
105 105 this.rendered = false;
106 106 if (this.get_text() === this.placeholder) {
107 107 this.set_text('');
108 108 this.refresh();
109 109 }
110 110 }
111 111 };
112 112
113 113
114 114 // Subclasses must define render.
115 115 TextCell.prototype.render = function () {};
116 116
117 117
118 118 TextCell.prototype.get_text = function() {
119 119 return this.code_mirror.getValue();
120 120 };
121 121
122 122
123 123 TextCell.prototype.set_text = function(text) {
124 124 this.code_mirror.setValue(text);
125 125 this.code_mirror.refresh();
126 126 };
127 127
128 128
129 129 TextCell.prototype.get_rendered = function() {
130 130 return this.element.find('div.text_cell_render').html();
131 131 };
132 132
133 133
134 134 TextCell.prototype.set_rendered = function(text) {
135 135 this.element.find('div.text_cell_render').html(text);
136 136 };
137 137
138 138
139 139 TextCell.prototype.at_top = function () {
140 140 if (this.rendered) {
141 141 return true;
142 142 } else {
143 143 return false;
144 144 }
145 145 };
146 146
147 147
148 148 TextCell.prototype.at_bottom = function () {
149 149 if (this.rendered) {
150 150 return true;
151 151 } else {
152 152 return false;
153 153 }
154 154 };
155 155
156 156
157 157 TextCell.prototype.fromJSON = function (data) {
158 158 IPython.Cell.prototype.fromJSON.apply(this, arguments);
159 159 if (data.cell_type === this.cell_type) {
160 160 if (data.source !== undefined) {
161 161 this.set_text(data.source);
162 162 // make this value the starting point, so that we can only undo
163 163 // to this state, instead of a blank cell
164 164 this.code_mirror.clearHistory();
165 165 this.set_rendered(data.rendered || '');
166 166 this.rendered = false;
167 167 this.render();
168 168 }
169 169 }
170 170 };
171 171
172 172
173 173 TextCell.prototype.toJSON = function () {
174 174 var data = IPython.Cell.prototype.toJSON.apply(this);
175 175 data.cell_type = this.cell_type;
176 176 data.source = this.get_text();
177 177 return data;
178 178 };
179 179
180 180
181 181 // HTMLCell
182 182
183 183 var HTMLCell = function () {
184 184 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
185 185 IPython.TextCell.apply(this, arguments);
186 186 this.cell_type = 'html';
187 187 };
188 188
189 189
190 190 HTMLCell.prototype = new TextCell();
191 191
192 192
193 193 HTMLCell.prototype.render = function () {
194 194 if (this.rendered === false) {
195 195 var text = this.get_text();
196 196 if (text === "") { text = this.placeholder; }
197 197 this.set_rendered(text);
198 198 this.typeset();
199 199 this.element.find('div.text_cell_input').hide();
200 200 this.element.find("div.text_cell_render").show();
201 201 this.rendered = true;
202 202 }
203 203 };
204 204
205 205
206 206 // MarkdownCell
207 207
208 208 var MarkdownCell = function () {
209 209 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
210 210 IPython.TextCell.apply(this, arguments);
211 211 this.cell_type = 'markdown';
212 212 };
213 213
214 214
215 215 MarkdownCell.prototype = new TextCell();
216 216
217 217
218 218 MarkdownCell.prototype.render = function () {
219 219 if (this.rendered === false) {
220 220 var text = this.get_text();
221 221 if (text === "") { text = this.placeholder; }
222 222 var html = IPython.markdown_converter.makeHtml(text);
223 this.set_rendered(html);
223 try {
224 this.set_rendered(html);
225 } catch (e) {
226 console.log("Error running Javascript in Markdown:");
227 console.log(e);
228 this.set_rendered($("<div/>").addClass("js-error").html(
229 "Error rendering Markdown!<br/>" + e.toString())
230 );
231 }
224 232 this.typeset()
225 233 this.element.find('div.text_cell_input').hide();
226 234 this.element.find("div.text_cell_render").show();
227 235 var code_snippets = this.element.find("pre > code");
228 236 code_snippets.replaceWith(function () {
229 237 var code = $(this).html();
230 238 /* Substitute br for newlines and &nbsp; for spaces
231 239 before highlighting, since prettify doesn't
232 240 preserve those on all browsers */
233 241 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
234 242 code = code.replace(/ /gm, '&nbsp;');
235 243 code = prettyPrintOne(code);
236 244
237 245 return '<code class="prettyprint">' + code + '</code>';
238 246 });
239 247 this.rendered = true;
240 248 }
241 249 };
242 250
243 251
244 252 // RawCell
245 253
246 254 var RawCell = function () {
247 255 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
248 256 this.code_mirror_mode = 'rst';
249 257 IPython.TextCell.apply(this, arguments);
250 258 this.cell_type = 'raw';
251 259 };
252 260
253 261
254 262 RawCell.prototype = new TextCell();
255 263
256 264
257 265 RawCell.prototype.render = function () {
258 266 this.rendered = true;
259 267 this.edit();
260 268 };
261 269
262 270
263 271 RawCell.prototype.select = function () {
264 272 IPython.Cell.prototype.select.apply(this);
265 273 this.code_mirror.refresh();
266 274 this.code_mirror.focus();
267 275 };
268 276
269 277
270 278 RawCell.prototype.at_top = function () {
271 279 var cursor = this.code_mirror.getCursor();
272 280 if (cursor.line === 0) {
273 281 return true;
274 282 } else {
275 283 return false;
276 284 }
277 285 };
278 286
279 287
280 288 RawCell.prototype.at_bottom = function () {
281 289 var cursor = this.code_mirror.getCursor();
282 290 if (cursor.line === (this.code_mirror.lineCount()-1)) {
283 291 return true;
284 292 } else {
285 293 return false;
286 294 }
287 295 };
288 296
289 297
290 298 // HTMLCell
291 299
292 300 var HeadingCell = function () {
293 301 this.placeholder = "Type Heading Here";
294 302 IPython.TextCell.apply(this, arguments);
295 303 this.cell_type = 'heading';
296 304 this.level = 1;
297 305 };
298 306
299 307
300 308 HeadingCell.prototype = new TextCell();
301 309
302 310
303 311 HeadingCell.prototype.fromJSON = function (data) {
304 312 if (data.level != undefined){
305 313 this.level = data.level;
306 314 }
307 315 IPython.TextCell.prototype.fromJSON.apply(this, arguments);
308 316 };
309 317
310 318
311 319 HeadingCell.prototype.toJSON = function () {
312 320 var data = IPython.TextCell.prototype.toJSON.apply(this);
313 321 data.level = this.get_level();
314 322 return data;
315 323 };
316 324
317 325
318 326 HeadingCell.prototype.set_level = function (level) {
319 327 this.level = level;
320 328 if (this.rendered) {
321 329 this.rendered = false;
322 330 this.render();
323 331 };
324 332 };
325 333
326 334
327 335 HeadingCell.prototype.get_level = function () {
328 336 return this.level;
329 337 };
330 338
331 339
332 340 HeadingCell.prototype.set_rendered = function (text) {
333 341 var r = this.element.find("div.text_cell_render");
334 342 r.empty();
335 343 r.append($('<h'+this.level+'/>').html(text));
336 344 };
337 345
338 346
339 347 HeadingCell.prototype.get_rendered = function () {
340 348 var r = this.element.find("div.text_cell_render");
341 349 return r.children().first().html();
342 350 };
343 351
344 352
345 353 HeadingCell.prototype.render = function () {
346 354 if (this.rendered === false) {
347 355 var text = this.get_text();
348 356 if (text === "") { text = this.placeholder; }
349 357 this.set_rendered(text);
350 358 this.typeset();
351 359 this.element.find('div.text_cell_input').hide();
352 360 this.element.find("div.text_cell_render").show();
353 361 this.rendered = true;
354 362 };
355 363 };
356 364
357 365 IPython.TextCell = TextCell;
358 366 IPython.HTMLCell = HTMLCell;
359 367 IPython.MarkdownCell = MarkdownCell;
360 368 IPython.RawCell = RawCell;
361 369 IPython.HeadingCell = HeadingCell;
362 370
363 371
364 372 return IPython;
365 373
366 374 }(IPython));
367 375
General Comments 0
You need to be logged in to leave comments. Login now