##// END OF EJS Templates
Markdown cells are now saved and restored in notebooks.
Brian E. Granger -
Show More
@@ -1,718 +1,721 b''
1 1
2 2 //============================================================================
3 3 // Notebook
4 4 //============================================================================
5 5
6 6 var IPython = (function (IPython) {
7 7
8 8 var utils = IPython.utils;
9 9
10 10 var Notebook = function (selector) {
11 11 this.element = $(selector);
12 12 this.element.scroll();
13 13 this.element.data("notebook", this);
14 14 this.next_prompt_number = 1;
15 15 this.kernel = null;
16 16 this.msg_cell_map = {};
17 17 this.style();
18 18 this.create_elements();
19 19 this.bind_events();
20 20 };
21 21
22 22
23 23 Notebook.prototype.style = function () {
24 24 $('div#notebook').addClass('border-box-sizing');
25 25 };
26 26
27 27
28 28 Notebook.prototype.create_elements = function () {
29 29 // We add this end_space div to the end of the notebook div to:
30 30 // i) provide a margin between the last cell and the end of the notebook
31 31 // ii) to prevent the div from scrolling up when the last cell is being
32 32 // edited, but is too low on the page, which browsers will do automatically.
33 33 this.element.append($('<div class="end_space"></div>').height(50));
34 34 $('div#notebook').addClass('border-box-sizing');
35 35 };
36 36
37 37
38 38 Notebook.prototype.bind_events = function () {
39 39 var that = this;
40 40 $(document).keydown(function (event) {
41 41 // console.log(event);
42 42 if (event.which === 38) {
43 43 var cell = that.selected_cell();
44 44 if (cell.at_top()) {
45 45 event.preventDefault();
46 46 that.select_prev();
47 47 };
48 48 } else if (event.which === 40) {
49 49 var cell = that.selected_cell();
50 50 if (cell.at_bottom()) {
51 51 event.preventDefault();
52 52 that.select_next();
53 53 };
54 54 } else if (event.which === 13 && event.shiftKey) {
55 55 that.execute_selected_cell();
56 56 return false;
57 57 } else if (event.which === 13 && event.ctrlKey) {
58 58 that.execute_selected_cell({terminal:true});
59 59 return false;
60 60 };
61 61 });
62 62
63 63 this.element.bind('collapse_pager', function () {
64 64 var app_height = $('div#main_app').height(); // content height
65 65 var splitter_height = $('div#pager_splitter').outerHeight(true);
66 66 var new_height = app_height - splitter_height;
67 67 that.element.animate({height : new_height + 'px'}, 'fast');
68 68 });
69 69
70 70 this.element.bind('expand_pager', function () {
71 71 var app_height = $('div#main_app').height(); // content height
72 72 var splitter_height = $('div#pager_splitter').outerHeight(true);
73 73 var pager_height = $('div#pager').outerHeight(true);
74 74 var new_height = app_height - pager_height - splitter_height;
75 75 that.element.animate({height : new_height + 'px'}, 'fast');
76 76 });
77 77
78 78 this.element.bind('collapse_left_panel', function () {
79 79 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
80 80 var new_margin = splitter_width;
81 81 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
82 82 });
83 83
84 84 this.element.bind('expand_left_panel', function () {
85 85 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
86 86 var left_panel_width = IPython.left_panel.width;
87 87 var new_margin = splitter_width + left_panel_width;
88 88 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
89 89 });
90 90 };
91 91
92 92
93 93 Notebook.prototype.scroll_to_bottom = function () {
94 94 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
95 95 };
96 96
97 97
98 98 Notebook.prototype.scroll_to_top = function () {
99 99 this.element.animate({scrollTop:0}, 0);
100 100 };
101 101
102 102
103 103 // Cell indexing, retrieval, etc.
104 104
105 105
106 106 Notebook.prototype.cell_elements = function () {
107 107 return this.element.children("div.cell");
108 108 }
109 109
110 110
111 111 Notebook.prototype.ncells = function (cell) {
112 112 return this.cell_elements().length;
113 113 }
114 114
115 115
116 116 // TODO: we are often calling cells as cells()[i], which we should optimize
117 117 // to cells(i) or a new method.
118 118 Notebook.prototype.cells = function () {
119 119 return this.cell_elements().toArray().map(function (e) {
120 120 return $(e).data("cell");
121 121 });
122 122 }
123 123
124 124
125 125 Notebook.prototype.find_cell_index = function (cell) {
126 126 var result = null;
127 127 this.cell_elements().filter(function (index) {
128 128 if ($(this).data("cell") === cell) {
129 129 result = index;
130 130 };
131 131 });
132 132 return result;
133 133 };
134 134
135 135
136 136 Notebook.prototype.index_or_selected = function (index) {
137 137 return index || this.selected_index() || 0;
138 138 }
139 139
140 140
141 141 Notebook.prototype.select = function (index) {
142 142 if (index !== undefined && index >= 0 && index < this.ncells()) {
143 143 if (this.selected_index() !== null) {
144 144 this.selected_cell().unselect();
145 145 };
146 146 this.cells()[index].select();
147 147 if (index === (this.ncells()-1)) {
148 148 this.scroll_to_bottom();
149 149 };
150 150 };
151 151 return this;
152 152 };
153 153
154 154
155 155 Notebook.prototype.select_next = function () {
156 156 var index = this.selected_index();
157 157 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
158 158 this.select(index+1);
159 159 };
160 160 return this;
161 161 };
162 162
163 163
164 164 Notebook.prototype.select_prev = function () {
165 165 var index = this.selected_index();
166 166 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
167 167 this.select(index-1);
168 168 };
169 169 return this;
170 170 };
171 171
172 172
173 173 Notebook.prototype.selected_index = function () {
174 174 var result = null;
175 175 this.cell_elements().filter(function (index) {
176 176 if ($(this).data("cell").selected === true) {
177 177 result = index;
178 178 };
179 179 });
180 180 return result;
181 181 };
182 182
183 183
184 184 Notebook.prototype.cell_for_msg = function (msg_id) {
185 185 var cell_id = this.msg_cell_map[msg_id];
186 186 var result = null;
187 187 this.cell_elements().filter(function (index) {
188 188 cell = $(this).data("cell");
189 189 if (cell.cell_id === cell_id) {
190 190 result = cell;
191 191 };
192 192 });
193 193 return result;
194 194 };
195 195
196 196
197 197 Notebook.prototype.selected_cell = function () {
198 198 return this.cell_elements().eq(this.selected_index()).data("cell");
199 199 }
200 200
201 201
202 202 // Cell insertion, deletion and moving.
203 203
204 204
205 205 Notebook.prototype.delete_cell = function (index) {
206 206 var i = index || this.selected_index();
207 207 if (i !== null && i >= 0 && i < this.ncells()) {
208 208 this.cell_elements().eq(i).remove();
209 209 if (i === (this.ncells())) {
210 210 this.select(i-1);
211 211 } else {
212 212 this.select(i);
213 213 };
214 214 };
215 215 return this;
216 216 };
217 217
218 218
219 219 Notebook.prototype.append_cell = function (cell) {
220 220 this.element.find('div.end_space').before(cell.element);
221 221 return this;
222 222 };
223 223
224 224
225 225 Notebook.prototype.insert_cell_after = function (cell, index) {
226 226 var ncells = this.ncells();
227 227 if (ncells === 0) {
228 228 this.append_cell(cell);
229 229 return this;
230 230 };
231 231 if (index >= 0 && index < ncells) {
232 232 this.cell_elements().eq(index).after(cell.element);
233 233 };
234 234 return this
235 235 };
236 236
237 237
238 238 Notebook.prototype.insert_cell_before = function (cell, index) {
239 239 var ncells = this.ncells();
240 240 if (ncells === 0) {
241 241 this.append_cell(cell);
242 242 return this;
243 243 };
244 244 if (index >= 0 && index < ncells) {
245 245 this.cell_elements().eq(index).before(cell.element);
246 246 };
247 247 return this;
248 248 };
249 249
250 250
251 251 Notebook.prototype.move_cell_up = function (index) {
252 252 var i = index || this.selected_index();
253 253 if (i !== null && i < this.ncells() && i > 0) {
254 254 var pivot = this.cell_elements().eq(i-1);
255 255 var tomove = this.cell_elements().eq(i);
256 256 if (pivot !== null && tomove !== null) {
257 257 tomove.detach();
258 258 pivot.before(tomove);
259 259 this.select(i-1);
260 260 };
261 261 };
262 262 return this;
263 263 }
264 264
265 265
266 266 Notebook.prototype.move_cell_down = function (index) {
267 267 var i = index || this.selected_index();
268 268 if (i !== null && i < (this.ncells()-1) && i >= 0) {
269 269 var pivot = this.cell_elements().eq(i+1)
270 270 var tomove = this.cell_elements().eq(i)
271 271 if (pivot !== null && tomove !== null) {
272 272 tomove.detach();
273 273 pivot.after(tomove);
274 274 this.select(i+1);
275 275 };
276 276 };
277 277 return this;
278 278 }
279 279
280 280
281 281 Notebook.prototype.sort_cells = function () {
282 282 var ncells = this.ncells();
283 283 var sindex = this.selected_index();
284 284 var swapped;
285 285 do {
286 286 swapped = false
287 287 for (var i=1; i<ncells; i++) {
288 288 current = this.cell_elements().eq(i).data("cell");
289 289 previous = this.cell_elements().eq(i-1).data("cell");
290 290 if (previous.input_prompt_number > current.input_prompt_number) {
291 291 this.move_cell_up(i);
292 292 swapped = true;
293 293 };
294 294 };
295 295 } while (swapped);
296 296 this.select(sindex);
297 297 return this;
298 298 };
299 299
300 300
301 301 Notebook.prototype.insert_code_cell_before = function (index) {
302 302 // TODO: Bounds check for i
303 303 var i = this.index_or_selected(index);
304 304 var cell = new IPython.CodeCell(this);
305 305 cell.set_input_prompt();
306 306 this.insert_cell_before(cell, i);
307 307 this.select(this.find_cell_index(cell));
308 308 return cell;
309 309 }
310 310
311 311
312 312 Notebook.prototype.insert_code_cell_after = function (index) {
313 313 // TODO: Bounds check for i
314 314 var i = this.index_or_selected(index);
315 315 var cell = new IPython.CodeCell(this);
316 316 cell.set_input_prompt();
317 317 this.insert_cell_after(cell, i);
318 318 this.select(this.find_cell_index(cell));
319 319 return cell;
320 320 }
321 321
322 322
323 323 Notebook.prototype.insert_html_cell_before = function (index) {
324 324 // TODO: Bounds check for i
325 325 var i = this.index_or_selected(index);
326 326 var cell = new IPython.HTMLCell(this);
327 327 cell.config_mathjax();
328 328 this.insert_cell_before(cell, i);
329 329 this.select(this.find_cell_index(cell));
330 330 return cell;
331 331 }
332 332
333 333
334 334 Notebook.prototype.insert_html_cell_after = function (index) {
335 335 // TODO: Bounds check for i
336 336 var i = this.index_or_selected(index);
337 337 var cell = new IPython.HTMLCell(this);
338 338 cell.config_mathjax();
339 339 this.insert_cell_after(cell, i);
340 340 this.select(this.find_cell_index(cell));
341 341 return cell;
342 342 }
343 343
344 344
345 345 Notebook.prototype.insert_markdown_cell_before = function (index) {
346 346 // TODO: Bounds check for i
347 347 var i = this.index_or_selected(index);
348 348 var cell = new IPython.MarkdownCell(this);
349 349 cell.config_mathjax();
350 350 this.insert_cell_before(cell, i);
351 351 this.select(this.find_cell_index(cell));
352 352 return cell;
353 353 }
354 354
355 355
356 356 Notebook.prototype.insert_markdown_cell_after = function (index) {
357 357 // TODO: Bounds check for i
358 358 var i = this.index_or_selected(index);
359 359 var cell = new IPython.MarkdownCell(this);
360 360 cell.config_mathjax();
361 361 this.insert_cell_after(cell, i);
362 362 this.select(this.find_cell_index(cell));
363 363 return cell;
364 364 }
365 365
366 366
367 367 Notebook.prototype.to_code = function (index) {
368 368 // TODO: Bounds check for i
369 369 var i = this.index_or_selected(index);
370 370 var source_element = this.cell_elements().eq(i);
371 371 var source_cell = source_element.data("cell");
372 372 if (source_cell instanceof IPython.HTMLCell ||
373 373 source_cell instanceof IPython.MarkdownCell) {
374 374 this.insert_code_cell_after(i);
375 375 var target_cell = this.cells()[i+1];
376 376 target_cell.set_code(source_cell.get_source());
377 377 source_element.remove();
378 378 };
379 379 };
380 380
381 381
382 382 Notebook.prototype.to_markdown = function (index) {
383 383 // TODO: Bounds check for i
384 384 var i = this.index_or_selected(index);
385 385 var source_element = this.cell_elements().eq(i);
386 386 var source_cell = source_element.data("cell");
387 387 var target_cell = null;
388 388 if (source_cell instanceof IPython.CodeCell) {
389 389 this.insert_markdown_cell_after(i);
390 390 var target_cell = this.cells()[i+1];
391 391 var text = source_cell.get_code();
392 392 } else if (source_cell instanceof IPython.HTMLCell) {
393 393 this.insert_markdown_cell_after(i);
394 394 var target_cell = this.cells()[i+1];
395 395 var text = source_cell.get_source();
396 396 if (text === source_cell.placeholder) {
397 397 text = target_cell.placeholder;
398 398 }
399 399 }
400 400 if (target_cell !== null) {
401 401 if (text === "") {text = target_cell.placeholder;};
402 402 target_cell.set_source(text);
403 403 source_element.remove();
404 404 target_cell.edit();
405 405 }
406 406 };
407 407
408 408
409 409 Notebook.prototype.to_html = function (index) {
410 410 // TODO: Bounds check for i
411 411 var i = this.index_or_selected(index);
412 412 var source_element = this.cell_elements().eq(i);
413 413 var source_cell = source_element.data("cell");
414 414 var target_cell = null;
415 415 if (source_cell instanceof IPython.CodeCell) {
416 416 this.insert_html_cell_after(i);
417 417 var target_cell = this.cells()[i+1];
418 418 var text = source_cell.get_code();
419 419 } else if (source_cell instanceof IPython.MarkdownCell) {
420 420 this.insert_html_cell_after(i);
421 421 var target_cell = this.cells()[i+1];
422 422 var text = source_cell.get_source();
423 423 if (text === source_cell.placeholder) {
424 424 text = target_cell.placeholder;
425 425 }
426 426 }
427 427 if (target_cell !== null) {
428 428 if (text === "") {text = target_cell.placeholder;};
429 429 target_cell.set_source(text);
430 430 source_element.remove();
431 431 target_cell.edit();
432 432 }
433 433 };
434 434
435 435
436 436 // Cell collapsing
437 437
438 438 Notebook.prototype.collapse = function (index) {
439 439 var i = this.index_or_selected(index);
440 440 this.cells()[i].collapse();
441 441 };
442 442
443 443
444 444 Notebook.prototype.expand = function (index) {
445 445 var i = this.index_or_selected(index);
446 446 this.cells()[i].expand();
447 447 };
448 448
449 449
450 450 // Kernel related things
451 451
452 452 Notebook.prototype.start_kernel = function () {
453 453 this.kernel = new IPython.Kernel();
454 454 var notebook_id = IPython.save_widget.get_notebook_id();
455 455 this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this));
456 456 };
457 457
458 458
459 459 Notebook.prototype.handle_shell_reply = function (e) {
460 460 reply = $.parseJSON(e.data);
461 461 var header = reply.header;
462 462 var content = reply.content;
463 463 var msg_type = header.msg_type;
464 464 // console.log(reply);
465 465 var cell = this.cell_for_msg(reply.parent_header.msg_id);
466 466 if (msg_type === "execute_reply") {
467 467 cell.set_input_prompt(content.execution_count);
468 468 } else if (msg_type === "complete_reply") {
469 469 cell.finish_completing(content.matched_text, content.matches);
470 470 };
471 471 var payload = content.payload || [];
472 472 this.handle_payload(payload);
473 473 };
474 474
475 475
476 476 Notebook.prototype.handle_payload = function (payload) {
477 477 var l = payload.length;
478 478 if (l > 0) {
479 479 IPython.pager.clear();
480 480 IPython.pager.expand();
481 481 };
482 482 for (var i=0; i<l; i++) {
483 483 IPython.pager.append_text(payload[i].text);
484 484 };
485 485 };
486 486
487 487
488 488 Notebook.prototype.handle_iopub_reply = function (e) {
489 489 reply = $.parseJSON(e.data);
490 490 var content = reply.content;
491 491 // console.log(reply);
492 492 var msg_type = reply.header.msg_type;
493 493 var cell = this.cell_for_msg(reply.parent_header.msg_id);
494 494 var output_types = ['stream','display_data','pyout','pyerr'];
495 495 if (output_types.indexOf(msg_type) >= 0) {
496 496 this.handle_output(cell, msg_type, content);
497 497 } else if (msg_type === "status") {
498 498 if (content.execution_state === "busy") {
499 499 IPython.kernel_status_widget.status_busy();
500 500 } else if (content.execution_state === "idle") {
501 501 IPython.kernel_status_widget.status_idle();
502 502 };
503 503 }
504 504 };
505 505
506 506
507 507 Notebook.prototype.handle_output = function (cell, msg_type, content) {
508 508 var json = {};
509 509 json.output_type = msg_type;
510 510 if (msg_type === "stream") {
511 511 json.text = content.data + '\n';
512 512 } else if (msg_type === "display_data") {
513 513 json = this.convert_mime_types(json, content.data);
514 514 } else if (msg_type === "pyout") {
515 515 json.prompt_number = content.execution_count;
516 516 json = this.convert_mime_types(json, content.data);
517 517 } else if (msg_type === "pyerr") {
518 518 json.ename = content.ename;
519 519 json.evalue = content.evalue;
520 520 json.traceback = content.traceback;
521 521 };
522 522 cell.append_output(json);
523 523 };
524 524
525 525
526 526 Notebook.prototype.convert_mime_types = function (json, data) {
527 527 if (data['text/plain'] !== undefined) {
528 528 json.text = data['text/plain'];
529 529 };
530 530 if (data['text/html'] !== undefined) {
531 531 json.html = data['text/html'];
532 532 };
533 533 if (data['image/svg+xml'] !== undefined) {
534 534 json.svg = data['image/svg+xml'];
535 535 };
536 536 if (data['image/png'] !== undefined) {
537 537 json.png = data['image/png'];
538 538 };
539 539 if (data['text/latex'] !== undefined) {
540 540 json.latex = data['text/latex'];
541 541 };
542 542 if (data['application/json'] !== undefined) {
543 543 json.json = data['application/json'];
544 544 };
545 545 if (data['application/javascript'] !== undefined) {
546 546 json.javascript = data['application/javascript'];
547 547 }
548 548 return json;
549 549 };
550 550
551 551 Notebook.prototype.kernel_started = function () {
552 552 console.log("Kernel started: ", this.kernel.kernel_id);
553 553 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
554 554 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
555 555 };
556 556
557 557
558 558 Notebook.prototype.execute_selected_cell = function (options) {
559 559 // add_new: should a new cell be added if we are at the end of the nb
560 560 // terminal: execute in terminal mode, which stays in the current cell
561 561 default_options = {terminal: false, add_new: true}
562 562 $.extend(default_options, options)
563 563 var that = this;
564 564 var cell = that.selected_cell();
565 565 var cell_index = that.find_cell_index(cell);
566 566 if (cell instanceof IPython.CodeCell) {
567 567 cell.clear_output();
568 568 var code = cell.get_code();
569 569 var msg_id = that.kernel.execute(cell.get_code());
570 570 that.msg_cell_map[msg_id] = cell.cell_id;
571 571 } else if (cell instanceof IPython.HTMLCell) {
572 572 cell.render();
573 573 }
574 574 if (default_options.terminal) {
575 575 cell.clear_input();
576 576 } else {
577 577 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
578 578 that.insert_code_cell_after();
579 579 // If we are adding a new cell at the end, scroll down to show it.
580 580 that.scroll_to_bottom();
581 581 } else {
582 582 that.select(cell_index+1);
583 583 };
584 584 };
585 585 };
586 586
587 587
588 588 Notebook.prototype.execute_all_cells = function () {
589 589 var ncells = this.ncells();
590 590 for (var i=0; i<ncells; i++) {
591 591 this.select(i);
592 592 this.execute_selected_cell({add_new:false});
593 593 };
594 594 this.scroll_to_bottom();
595 595 };
596 596
597 597
598 598 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
599 599 var msg_id = this.kernel.complete(line, cursor_pos);
600 600 this.msg_cell_map[msg_id] = cell.cell_id;
601 601 };
602 602
603 603 // Persistance and loading
604 604
605 605
606 606 Notebook.prototype.fromJSON = function (data) {
607 607 var ncells = this.ncells();
608 608 for (var i=0; i<ncells; i++) {
609 609 // Always delete cell 0 as they get renumbered as they are deleted.
610 610 this.delete_cell(0);
611 611 };
612 612 // Only handle 1 worksheet for now.
613 613 var worksheet = data.worksheets[0];
614 614 if (worksheet !== undefined) {
615 615 var new_cells = worksheet.cells;
616 616 ncells = new_cells.length;
617 617 var cell_data = null;
618 618 var new_cell = null;
619 619 for (var i=0; i<ncells; i++) {
620 620 cell_data = new_cells[i];
621 621 if (cell_data.cell_type == 'code') {
622 622 new_cell = this.insert_code_cell_after();
623 623 new_cell.fromJSON(cell_data);
624 624 } else if (cell_data.cell_type === 'html') {
625 625 new_cell = this.insert_html_cell_after();
626 626 new_cell.fromJSON(cell_data);
627 } else if (cell_data.cell_type === 'markdown') {
628 new_cell = this.insert_markdown_cell_after();
629 new_cell.fromJSON(cell_data);
627 630 };
628 631 };
629 632 };
630 633 };
631 634
632 635
633 636 Notebook.prototype.toJSON = function () {
634 637 var cells = this.cells();
635 638 var ncells = cells.length;
636 639 cell_array = new Array(ncells);
637 640 for (var i=0; i<ncells; i++) {
638 641 cell_array[i] = cells[i].toJSON();
639 642 };
640 643 data = {
641 644 // Only handle 1 worksheet for now.
642 645 worksheets : [{cells:cell_array}]
643 646 }
644 647 return data
645 648 };
646 649
647 650 Notebook.prototype.save_notebook = function () {
648 651 if (IPython.save_widget.test_notebook_name()) {
649 652 var notebook_id = IPython.save_widget.get_notebook_id();
650 653 var nbname = IPython.save_widget.get_notebook_name();
651 654 // We may want to move the name/id/nbformat logic inside toJSON?
652 655 var data = this.toJSON();
653 656 data.name = nbname;
654 657 data.nbformat = 2;
655 658 data.id = notebook_id
656 659 // We do the call with settings so we can set cache to false.
657 660 var settings = {
658 661 processData : false,
659 662 cache : false,
660 663 type : "PUT",
661 664 data : JSON.stringify(data),
662 665 headers : {'Content-Type': 'application/json'},
663 666 success : $.proxy(this.notebook_saved,this)
664 667 };
665 668 IPython.save_widget.status_saving();
666 669 $.ajax("/notebooks/" + notebook_id, settings);
667 670 };
668 671 };
669 672
670 673
671 674 Notebook.prototype.notebook_saved = function (data, status, xhr) {
672 675 IPython.save_widget.status_save();
673 676 }
674 677
675 678
676 679 Notebook.prototype.load_notebook = function (callback) {
677 680 var that = this;
678 681 var notebook_id = IPython.save_widget.get_notebook_id();
679 682 // We do the call with settings so we can set cache to false.
680 683 var settings = {
681 684 processData : false,
682 685 cache : false,
683 686 type : "GET",
684 687 dataType : "json",
685 688 success : function (data, status, xhr) {
686 689 that.notebook_loaded(data, status, xhr);
687 690 if (callback !== undefined) {
688 691 callback();
689 692 };
690 693 }
691 694 };
692 695 IPython.save_widget.status_loading();
693 696 $.ajax("/notebooks/" + notebook_id, settings);
694 697 }
695 698
696 699
697 700 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
698 701 this.fromJSON(data);
699 702 if (this.ncells() === 0) {
700 703 this.insert_code_cell_after();
701 704 };
702 705 IPython.save_widget.status_save();
703 706 IPython.save_widget.set_notebook_name(data.name);
704 707 this.start_kernel();
705 708 // fromJSON always selects the last cell inserted. We need to wait
706 709 // until that is done before scrolling to the top.
707 710 setTimeout(function () {
708 711 IPython.notebook.select(0);
709 712 IPython.notebook.scroll_to_top();
710 713 }, 50);
711 714 };
712 715
713 716 IPython.Notebook = Notebook;
714 717
715 718 return IPython;
716 719
717 720 }(IPython));
718 721
@@ -1,249 +1,249 b''
1 1
2 2 //============================================================================
3 3 // TextCell
4 4 //============================================================================
5 5
6 6 var IPython = (function (IPython) {
7 7
8 8 // TextCell base class
9 9
10 10 var TextCell = function (notebook) {
11 11 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
12 12 this.placeholder = this.placeholder || '';
13 13 IPython.Cell.apply(this, arguments);
14 14 this.rendered = false;
15 15 this.cell_type = this.cell_type || 'text';
16 16 };
17 17
18 18
19 19 TextCell.prototype = new IPython.Cell();
20 20
21 21
22 22 TextCell.prototype.create_element = function () {
23 23 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
24 24 var input_area = $('<div/>').addClass('text_cell_input');
25 25 this.code_mirror = CodeMirror(input_area.get(0), {
26 26 indentUnit : 4,
27 27 enterMode : 'flat',
28 28 tabMode: 'shift',
29 29 mode: this.code_mirror_mode,
30 30 theme: 'default',
31 31 value: this.placeholder
32 32 });
33 33 // The tabindex=-1 makes this div focusable.
34 34 var render_area = $('<div/>').addClass('text_cell_render').
35 35 addClass('rendered_html').attr('tabindex','-1');
36 36 cell.append(input_area).append(render_area);
37 37 this.element = cell;
38 38 };
39 39
40 40
41 41 TextCell.prototype.bind_events = function () {
42 42 IPython.Cell.prototype.bind_events.apply(this);
43 43 var that = this;
44 44 this.element.keydown(function (event) {
45 45 if (event.which === 13) {
46 46 if (that.rendered) {
47 47 that.edit();
48 48 event.preventDefault();
49 49 };
50 50 };
51 51 });
52 52 };
53 53
54 54
55 55 TextCell.prototype.select = function () {
56 56 IPython.Cell.prototype.select.apply(this);
57 57 var output = this.element.find("div.text_cell_render");
58 58 output.trigger('focus');
59 59 };
60 60
61 61
62 62 TextCell.prototype.edit = function () {
63 63 if (this.rendered === true) {
64 64 var text_cell = this.element;
65 65 var output = text_cell.find("div.text_cell_render");
66 66 output.hide();
67 67 text_cell.find('div.text_cell_input').show();
68 68 this.code_mirror.focus();
69 69 this.code_mirror.refresh();
70 70 this.rendered = false;
71 71 };
72 72 };
73 73
74 74
75 75 // Subclasses must define render.
76 76 TextCell.prototype.render = function () {};
77 77
78 78
79 79 TextCell.prototype.config_mathjax = function () {
80 80 var text_cell = this.element;
81 81 var that = this;
82 82 text_cell.click(function () {
83 83 that.edit();
84 84 }).focusout(function () {
85 85 that.render();
86 86 });
87 87
88 88 text_cell.trigger("focusout");
89 89 };
90 90
91 91
92 92 TextCell.prototype.get_source = function() {
93 93 return this.code_mirror.getValue();
94 94 };
95 95
96 96
97 97 TextCell.prototype.set_source = function(text) {
98 98 this.code_mirror.setValue(text);
99 99 this.code_mirror.refresh();
100 100 };
101 101
102 102
103 103 TextCell.prototype.get_rendered = function(text) {
104 104 return this.element.find('div.text_cell_render').html();
105 105 };
106 106
107 107
108 108 TextCell.prototype.set_rendered = function(text) {
109 109 this.element.find('div.text_cell_render').html(text);
110 110 };
111 111
112 112
113 113 TextCell.prototype.at_top = function () {
114 114 if (this.rendered) {
115 115 return true;
116 116 } else {
117 117 return false;
118 118 }
119 119 };
120 120
121 121
122 122 TextCell.prototype.at_bottom = function () {
123 123 if (this.rendered) {
124 124 return true;
125 125 } else {
126 126 return false;
127 127 }
128 128 };
129 129
130 130
131 131 TextCell.prototype.fromJSON = function (data) {
132 132 if (data.cell_type === this.cell_type) {
133 133 if (data.source !== undefined) {
134 134 this.set_source(data.source);
135 this.set_rendered(data.source);
135 this.set_rendered(data.rendered);
136 136 };
137 137 };
138 138 }
139 139
140 140
141 141 TextCell.prototype.toJSON = function () {
142 142 var data = {}
143 143 data.cell_type = this.cell_type;
144 144 data.source = this.get_source();
145 145 data.rendered = this.get_rendered();
146 146 return data;
147 147 };
148 148
149 149
150 150 // HTMLCell
151 151
152 152 var HTMLCell = function (notebook) {
153 153 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
154 154 IPython.TextCell.apply(this, arguments);
155 155 this.cell_type = 'html';
156 156 };
157 157
158 158
159 159 HTMLCell.prototype = new TextCell();
160 160
161 161
162 162 HTMLCell.prototype.render = function () {
163 163 if (this.rendered === false) {
164 164 var text = this.get_source();
165 165 if (text === "") {text = this.placeholder;};
166 166 this.set_rendered(text);
167 167 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
168 168 this.element.find('div.text_cell_input').hide();
169 169 this.element.find("div.text_cell_render").show();
170 170 this.rendered = true;
171 171 };
172 172 };
173 173
174 174
175 175 // MarkdownCell
176 176
177 177 var MarkdownCell = function (notebook) {
178 178 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
179 179 IPython.TextCell.apply(this, arguments);
180 180 this.cell_type = 'markdown';
181 181 };
182 182
183 183
184 184 MarkdownCell.prototype = new TextCell();
185 185
186 186
187 187 MarkdownCell.prototype.render = function () {
188 188 if (this.rendered === false) {
189 189 var text = this.get_source();
190 190 if (text === "") {text = this.placeholder;};
191 191 var html = IPython.markdown_converter.makeHtml(text);
192 192 this.set_rendered(html);
193 193 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
194 194 this.element.find('div.text_cell_input').hide();
195 195 this.element.find("div.text_cell_render").show();
196 196 this.rendered = true;
197 197 };
198 198 };
199 199
200 200
201 201 // RSTCell
202 202
203 203 var RSTCell = function (notebook) {
204 204 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
205 205 IPython.TextCell.apply(this, arguments);
206 206 this.cell_type = 'rst';
207 207 };
208 208
209 209
210 210 RSTCell.prototype = new TextCell();
211 211
212 212
213 213 RSTCell.prototype.render = function () {
214 214 if (this.rendered === false) {
215 215 var text = this.get_source();
216 216 if (text === "") {text = this.placeholder;};
217 217 var settings = {
218 218 processData : false,
219 219 cache : false,
220 220 type : "POST",
221 221 data : text,
222 222 headers : {'Content-Type': 'application/x-rst'},
223 223 success : $.proxy(this.handle_render,this)
224 224 };
225 225 $.ajax("/rstservice/render", settings);
226 226 this.element.find('div.text_cell_input').hide();
227 227 this.element.find("div.text_cell_render").show();
228 228 this.set_rendered("Rendering...");
229 229 };
230 230 };
231 231
232 232
233 233 RSTCell.prototype.handle_render = function (data, status, xhr) {
234 234 this.set_rendered(data);
235 235 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
236 236 this.rendered = true;
237 237 };
238 238
239 239
240 240 IPython.TextCell = TextCell;
241 241 IPython.HTMLCell = HTMLCell;
242 242 IPython.MarkdownCell = MarkdownCell;
243 243 IPython.RSTCell = RSTCell;
244 244
245 245
246 246 return IPython;
247 247
248 248 }(IPython));
249 249
@@ -1,195 +1,195 b''
1 1 import json
2 2 from xml.etree import ElementTree as ET
3 3 import re
4 4
5 5 from IPython.nbformat import v2
6 6 from IPython.nbformat import v1
7 7
8 8 from IPython.nbformat.v2 import (
9 9 NotebookNode,
10 new_code_cell, new_html_cell, new_notebook, new_output, new_worksheet
10 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet
11 11 )
12 12
13 13
14 14 current_nbformat = 2
15 15
16 16
17 17 class NBFormatError(Exception):
18 18 pass
19 19
20 20
21 21 def parse_json(s, **kwargs):
22 22 """Parse a string into a (nbformat, dict) tuple."""
23 23 d = json.loads(s, **kwargs)
24 24 nbformat = d.get('nbformat',1)
25 25 return nbformat, d
26 26
27 27
28 28 def parse_xml(s, **kwargs):
29 29 """Parse a string into a (nbformat, etree) tuple."""
30 30 root = ET.fromstring(s)
31 31 nbformat_e = root.find('nbformat')
32 32 if nbformat_e is not None:
33 33 nbformat = int(nbformat_e.text)
34 34 else:
35 35 raise NBFormatError('No nbformat version found')
36 36 return nbformat, root
37 37
38 38
39 39 def parse_py(s, **kwargs):
40 40 """Parse a string into a (nbformat, string) tuple."""
41 41 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
42 42 m = re.search(pattern,s)
43 43 if m is not None:
44 44 nbformat = int(m.group('nbformat'))
45 45 else:
46 46 nbformat = 2
47 47 return nbformat, s
48 48
49 49
50 50 def reads_json(s, **kwargs):
51 51 """Read a JSON notebook from a string and return the NotebookNode object."""
52 52 nbformat, d = parse_json(s, **kwargs)
53 53 if nbformat == 1:
54 54 nb = v1.to_notebook_json(d, **kwargs)
55 55 nb = v2.convert_to_this_nbformat(nb, orig_version=1)
56 56 elif nbformat == 2:
57 57 nb = v2.to_notebook_json(d, **kwargs)
58 58 else:
59 59 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
60 60 return nb
61 61
62 62
63 63 def writes_json(nb, **kwargs):
64 64 return v2.writes_json(nb, **kwargs)
65 65
66 66
67 67 def reads_xml(s, **kwargs):
68 68 """Read an XML notebook from a string and return the NotebookNode object."""
69 69 nbformat, root = parse_xml(s, **kwargs)
70 70 if nbformat == 2:
71 71 nb = v2.to_notebook_xml(root, **kwargs)
72 72 else:
73 73 raise NBFormatError('Unsupported XML nbformat version: %i' % nbformat)
74 74 return nb
75 75
76 76
77 77 def writes_xml(nb, **kwargs):
78 78 return v2.writes_xml(nb, **kwargs)
79 79
80 80
81 81 def reads_py(s, **kwargs):
82 82 """Read a .py notebook from a string and return the NotebookNode object."""
83 83 nbformat, s = parse_py(s, **kwargs)
84 84 if nbformat == 2:
85 85 nb = v2.to_notebook_py(s, **kwargs)
86 86 else:
87 87 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
88 88 return nb
89 89
90 90
91 91 def writes_py(nb, **kwargs):
92 92 return v2.writes_py(nb, **kwargs)
93 93
94 94
95 95 # High level API
96 96
97 97
98 98 def reads(s, format, **kwargs):
99 99 """Read a notebook from a string and return the NotebookNode object.
100 100
101 101 This function properly handles notebooks of any version. The notebook
102 102 returned will always be in the current version's format.
103 103
104 104 Parameters
105 105 ----------
106 106 s : str
107 107 The raw string to read the notebook from.
108 108 format : ('xml','json','py')
109 109 The format that the string is in.
110 110
111 111 Returns
112 112 -------
113 113 nb : NotebookNode
114 114 The notebook that was read.
115 115 """
116 116 if format == 'xml':
117 117 return reads_xml(s, **kwargs)
118 118 elif format == 'json':
119 119 return reads_json(s, **kwargs)
120 120 elif format == 'py':
121 121 return reads_py(s, **kwargs)
122 122 else:
123 123 raise NBFormatError('Unsupported format: %s' % format)
124 124
125 125
126 126 def writes(nb, format, **kwargs):
127 127 """Write a notebook to a string in a given format in the current nbformat version.
128 128
129 129 This function always writes the notebook in the current nbformat version.
130 130
131 131 Parameters
132 132 ----------
133 133 nb : NotebookNode
134 134 The notebook to write.
135 135 format : ('xml','json','py')
136 136 The format to write the notebook in.
137 137
138 138 Returns
139 139 -------
140 140 s : str
141 141 The notebook string.
142 142 """
143 143 if format == 'xml':
144 144 return writes_xml(nb, **kwargs)
145 145 elif format == 'json':
146 146 return writes_json(nb, **kwargs)
147 147 elif format == 'py':
148 148 return writes_py(nb, **kwargs)
149 149 else:
150 150 raise NBFormatError('Unsupported format: %s' % format)
151 151
152 152
153 153 def read(fp, format, **kwargs):
154 154 """Read a notebook from a file and return the NotebookNode object.
155 155
156 156 This function properly handles notebooks of any version. The notebook
157 157 returned will always be in the current version's format.
158 158
159 159 Parameters
160 160 ----------
161 161 fp : file
162 162 Any file-like object with a read method.
163 163 format : ('xml','json','py')
164 164 The format that the string is in.
165 165
166 166 Returns
167 167 -------
168 168 nb : NotebookNode
169 169 The notebook that was read.
170 170 """
171 171 return reads(fp.read(), format, **kwargs)
172 172
173 173
174 174 def write(nb, fp, format, **kwargs):
175 175 """Write a notebook to a file in a given format in the current nbformat version.
176 176
177 177 This function always writes the notebook in the current nbformat version.
178 178
179 179 Parameters
180 180 ----------
181 181 nb : NotebookNode
182 182 The notebook to write.
183 183 fp : file
184 184 Any file-like object with a write method.
185 185 format : ('xml','json','py')
186 186 The format to write the notebook in.
187 187
188 188 Returns
189 189 -------
190 190 s : str
191 191 The notebook string.
192 192 """
193 193 return fp.write(writes(nb, format, **kwargs))
194 194
195 195
@@ -1,21 +1,21 b''
1 1
2 2 from .nbbase import (
3 3 NotebookNode,
4 new_code_cell, new_html_cell, new_notebook, new_output, new_worksheet
4 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet
5 5 )
6 6
7 7 from .nbjson import reads as reads_json, writes as writes_json
8 8 from .nbjson import reads as read_json, writes as write_json
9 9 from .nbjson import to_notebook as to_notebook_json
10 10
11 11 from .nbxml import reads as reads_xml, writes as writes_xml
12 12 from .nbxml import reads as read_xml, writes as write_xml
13 13 from .nbxml import to_notebook as to_notebook_xml
14 14
15 15 from .nbpy import reads as reads_py, writes as writes_py
16 16 from .nbpy import reads as read_py, writes as write_py
17 17 from .nbpy import to_notebook as to_notebook_py
18 18
19 19 from .convert import convert_to_this_nbformat
20 20
21 21
@@ -1,20 +1,20 b''
1 1 from .nbbase import (
2 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
2 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
3 3 )
4 4
5 5 def convert_to_this_nbformat(nb, orig_version=1):
6 6 if orig_version == 1:
7 7 newnb = new_notebook()
8 8 ws = new_worksheet()
9 9 for cell in nb.cells:
10 if cell.cell_type == 'code':
10 if cell.cell_type == u'code':
11 11 newcell = new_code_cell(input=cell.get('code'),prompt_number=cell.get('prompt_number'))
12 elif cell.cell_type == 'text':
13 newcell = new_html_cell(source=cell.get('text'))
12 elif cell.cell_type == u'text':
13 newcell = new_text_cell(u'markdown',source=cell.get('text'))
14 14 ws.cells.append(newcell)
15 15 newnb.worksheets.append(ws)
16 16 return newnb
17 17 else:
18 18 raise ValueError('Cannot convert a notebook from v%s to v2' % orig_version)
19 19
20 20
@@ -1,104 +1,106 b''
1 1 """The basic dict based notebook format."""
2 2
3 3 import pprint
4 4 import uuid
5 5
6 6 from IPython.utils.ipstruct import Struct
7 7
8 8
9 9 class NotebookNode(Struct):
10 10 pass
11 11
12 12
13 13 def from_dict(d):
14 14 if isinstance(d, dict):
15 15 newd = NotebookNode()
16 16 for k,v in d.items():
17 17 newd[k] = from_dict(v)
18 18 return newd
19 19 elif isinstance(d, (tuple, list)):
20 20 return [from_dict(i) for i in d]
21 21 else:
22 22 return d
23 23
24 24
25 25 def new_output(output_type=None, output_text=None, output_png=None,
26 26 output_html=None, output_svg=None, output_latex=None, output_json=None,
27 27 output_javascript=None, prompt_number=None):
28 28 """Create a new code cell with input and output"""
29 29 output = NotebookNode()
30 30 if output_type is not None:
31 31 output.output_type = unicode(output_type)
32 32 if output_text is not None:
33 33 output.text = unicode(output_text)
34 34 if output_png is not None:
35 35 output.png = bytes(output_png)
36 36 if output_html is not None:
37 37 output.html = unicode(output_html)
38 38 if output_svg is not None:
39 39 output.svg = unicode(output_svg)
40 40 if output_latex is not None:
41 41 output.latex = unicode(output_latex)
42 42 if output_json is not None:
43 43 output.json = unicode(output_json)
44 44 if output_javascript is not None:
45 45 output.javascript = unicode(output_javascript)
46 46 if prompt_number is not None:
47 47 output.prompt_number = int(prompt_number)
48 48 return output
49 49
50 50
51 51 def new_code_cell(input=None, prompt_number=None, outputs=None, language=u'python'):
52 52 """Create a new code cell with input and output"""
53 53 cell = NotebookNode()
54 54 cell.cell_type = u'code'
55 55 if language is not None:
56 56 cell.language = unicode(language)
57 57 if input is not None:
58 58 cell.input = unicode(input)
59 59 if prompt_number is not None:
60 60 cell.prompt_number = int(prompt_number)
61 61 if outputs is None:
62 62 cell.outputs = []
63 63 else:
64 64 cell.outputs = outputs
65 65
66 66 return cell
67 67
68 def new_html_cell(source=None):
68 def new_text_cell(cell_type, source=None, rendered=None):
69 69 """Create a new text cell."""
70 70 cell = NotebookNode()
71 71 if source is not None:
72 72 cell.source = unicode(source)
73 cell.cell_type = u'html'
73 if rendered is not None:
74 cell.rendered = unicode(rendered)
75 cell.cell_type = cell_type
74 76 return cell
75 77
76 78
77 79 def new_worksheet(name=None, cells=None):
78 80 """Create a worksheet by name with with a list of cells."""
79 81 ws = NotebookNode()
80 82 if name is not None:
81 83 ws.name = unicode(name)
82 84 if cells is None:
83 85 ws.cells = []
84 86 else:
85 87 ws.cells = list(cells)
86 88 return ws
87 89
88 90
89 91 def new_notebook(name=None, id=None, worksheets=None):
90 92 """Create a notebook by name, id and a list of worksheets."""
91 93 nb = NotebookNode()
92 94 nb.nbformat = 2
93 95 if name is not None:
94 96 nb.name = unicode(name)
95 97 if id is None:
96 98 nb.id = unicode(uuid.uuid4())
97 99 else:
98 100 nb.id = unicode(id)
99 101 if worksheets is None:
100 102 nb.worksheets = []
101 103 else:
102 104 nb.worksheets = list(worksheets)
103 105 return nb
104 106
@@ -1,168 +1,178 b''
1 1 """Read and write notebook files as XML."""
2 2
3 3 from base64 import encodestring, decodestring
4 4 from xml.etree import ElementTree as ET
5 5
6 6 from .rwbase import NotebookReader, NotebookWriter
7 7 from .nbbase import (
8 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
9 9 )
10 10
11 11 def indent(elem, level=0):
12 12 i = "\n" + level*" "
13 13 if len(elem):
14 14 if not elem.text or not elem.text.strip():
15 15 elem.text = i + " "
16 16 if not elem.tail or not elem.tail.strip():
17 17 elem.tail = i
18 18 for elem in elem:
19 19 indent(elem, level+1)
20 20 if not elem.tail or not elem.tail.strip():
21 21 elem.tail = i
22 22 else:
23 23 if level and (not elem.tail or not elem.tail.strip()):
24 24 elem.tail = i
25 25
26 26
27 27 def _get_text(e, tag):
28 28 sub_e = e.find(tag)
29 29 if sub_e is None:
30 30 return None
31 31 else:
32 32 return sub_e.text
33 33
34 34
35 35 def _set_text(nbnode, attr, parent, tag):
36 36 if attr in nbnode:
37 37 e = ET.SubElement(parent, tag)
38 38 e.text = nbnode[attr]
39 39
40 40
41 41 def _get_int(e, tag):
42 42 sub_e = e.find(tag)
43 43 if sub_e is None:
44 44 return None
45 45 else:
46 46 return int(sub_e.text)
47 47
48 48
49 49 def _set_int(nbnode, attr, parent, tag):
50 50 if attr in nbnode:
51 51 e = ET.SubElement(parent, tag)
52 52 e.text = unicode(nbnode[attr])
53 53
54 54
55 55 def _get_binary(e, tag):
56 56 sub_e = e.find(tag)
57 57 if sub_e is None:
58 58 return None
59 59 else:
60 60 return decodestring(sub_e.text)
61 61
62 62
63 63 def _set_binary(nbnode, attr, parent, tag):
64 64 if attr in nbnode:
65 65 e = ET.SubElement(parent, tag)
66 66 e.text = encodestring(nbnode[attr])
67 67
68 68
69 69 class XMLReader(NotebookReader):
70 70
71 71 def reads(self, s, **kwargs):
72 72 root = ET.fromstring(s)
73 73 return self.to_notebook(root, **kwargs)
74 74
75 75 def to_notebook(self, root, **kwargs):
76 76 nbname = _get_text(root,'name')
77 77 nbid = _get_text(root,'id')
78 78
79 79 worksheets = []
80 80 for ws_e in root.find('worksheets').getiterator('worksheet'):
81 81 wsname = _get_text(ws_e,'name')
82 82 cells = []
83 83 for cell_e in ws_e.find('cells').getiterator():
84 84 if cell_e.tag == 'codecell':
85 85 input = _get_text(cell_e,'input')
86 86 prompt_number = _get_int(cell_e,'prompt_number')
87 87 language = _get_text(cell_e,'language')
88 88 outputs = []
89 89 for output_e in cell_e.find('outputs').getiterator('output'):
90 90 out_prompt_number = _get_int(output_e,'prompt_number')
91 91 output_type = _get_text(output_e,'output_type')
92 92 output_text = _get_text(output_e,'text')
93 93 output_png = _get_binary(output_e,'png')
94 94 output_svg = _get_text(output_e,'svg')
95 95 output_html = _get_text(output_e,'html')
96 96 output_latex = _get_text(output_e,'latex')
97 97 output_json = _get_text(output_e,'json')
98 98 output_javascript = _get_text(output_e,'javascript')
99 99 output = new_output(output_type=output_type,output_png=output_png,
100 100 output_text=output_text,output_svg=output_svg,
101 101 output_html=output_html,output_latex=output_latex,
102 102 output_json=output_json,output_javascript=output_javascript,
103 103 prompt_number=out_prompt_number
104 104 )
105 105 outputs.append(output)
106 106 cc = new_code_cell(input=input,prompt_number=prompt_number,
107 107 language=language,outputs=outputs)
108 108 cells.append(cc)
109 109 if cell_e.tag == 'htmlcell':
110 110 source = _get_text(cell_e,'source')
111 cells.append(new_html_cell(source=source))
111 rendered = _get_text(cell_e,'rendered')
112 cells.append(new_text_cell(u'html', source=source, rendered=rendered))
113 if cell_e.tag == 'markdowncell':
114 source = _get_text(cell_e,'source')
115 rendered = _get_text(cell_e,'rendered')
116 cells.append(new_text_cell(u'markdown', source=source, rendered=rendered))
112 117 ws = new_worksheet(name=wsname,cells=cells)
113 118 worksheets.append(ws)
114 119
115 120 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
116 121 return nb
117 122
118 123
119 124 class XMLWriter(NotebookWriter):
120 125
121 126 def writes(self, nb, **kwargs):
122 127 nb_e = ET.Element('notebook')
123 128 _set_text(nb,'name',nb_e,'name')
124 129 _set_text(nb,'id',nb_e,'id')
125 130 _set_int(nb,'nbformat',nb_e,'nbformat')
126 131 wss_e = ET.SubElement(nb_e,'worksheets')
127 132 for ws in nb.worksheets:
128 133 ws_e = ET.SubElement(wss_e, 'worksheet')
129 134 _set_text(ws,'name',ws_e,'name')
130 135 cells_e = ET.SubElement(ws_e,'cells')
131 136 for cell in ws.cells:
132 137 cell_type = cell.cell_type
133 138 if cell_type == 'code':
134 139 cell_e = ET.SubElement(cells_e, 'codecell')
135 140 _set_text(cell,'input',cell_e,'input')
136 141 _set_text(cell,'language',cell_e,'language')
137 142 _set_int(cell,'prompt_number',cell_e,'prompt_number')
138 143 outputs_e = ET.SubElement(cell_e, 'outputs')
139 144 for output in cell.outputs:
140 145 output_e = ET.SubElement(outputs_e, 'output')
141 146 _set_int(output,'prompt_number',output_e,'prompt_number')
142 147 _set_text(output,'output_type',output_e,'output_type')
143 148 _set_text(output,'text',output_e,'text')
144 149 _set_binary(output,'png',output_e,'png')
145 150 _set_text(output,'html',output_e,'html')
146 151 _set_text(output,'svg',output_e,'svg')
147 152 _set_text(output,'latex',output_e,'latex')
148 153 _set_text(output,'json',output_e,'json')
149 154 _set_text(output,'javascript',output_e,'javascript')
150 155 elif cell_type == 'html':
151 156 cell_e = ET.SubElement(cells_e, 'htmlcell')
152 157 _set_text(cell,'source',cell_e,'source')
158 _set_text(cell,'rendered',cell_e,'rendered')
159 elif cell_type == 'markdown':
160 cell_e = ET.SubElement(cells_e, 'markdowncell')
161 _set_text(cell,'source',cell_e,'source')
162 _set_text(cell,'rendered',cell_e,'rendered')
153 163
154 164 indent(nb_e)
155 165 txt = ET.tostring(nb_e, encoding="utf-8")
156 166 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
157 167 return txt
158 168
159 169
160 170 _reader = XMLReader()
161 171 _writer = XMLWriter()
162 172
163 173 reads = _reader.reads
164 174 read = _reader.read
165 175 to_notebook = _reader.to_notebook
166 176 write = _writer.write
167 177 writes = _writer.writes
168 178
@@ -1,75 +1,83 b''
1 1 from ..nbbase import (
2 2 NotebookNode,
3 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
3 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
4 4 )
5 5
6 6
7 7
8 8 ws = new_worksheet(name='worksheet1')
9 9
10 ws.cells.append(new_html_cell(
11 source='Some NumPy Examples'
10 ws.cells.append(new_text_cell(
11 u'html',
12 source='Some NumPy Examples',
13 rendered='Some NumPy Examples'
12 14 ))
13 15
14 16
15 17 ws.cells.append(new_code_cell(
16 18 input='import numpy',
17 19 prompt_number=1
18 20 ))
19 21
22 ws.cells.append(new_text_cell(
23 u'markdown',
24 source='Some NumPy Examples',
25 rendered='Some NumPy Examples'
26 ))
27
20 28 ws.cells.append(new_code_cell(
21 29 input='a = numpy.random.rand(100)',
22 30 prompt_number=2
23 31 ))
24 32
25 33 ws.cells.append(new_code_cell(
26 34 input='print a',
27 35 prompt_number=3,
28 36 outputs=[new_output(
29 37 output_type=u'pyout',
30 38 output_text=u'<array a>',
31 39 output_html=u'The HTML rep',
32 40 output_latex=u'$a$',
33 41 output_png=b'data',
34 42 output_svg=u'<svg>',
35 43 output_json=u'json data',
36 44 output_javascript=u'var i=0;',
37 45 prompt_number=3
38 46 ),new_output(
39 47 output_type=u'display_data',
40 48 output_text=u'<array a>',
41 49 output_html=u'The HTML rep',
42 50 output_latex=u'$a$',
43 51 output_png=b'data',
44 52 output_svg=u'<svg>',
45 53 output_json=u'json data',
46 54 output_javascript=u'var i=0;',
47 55 prompt_number=4
48 56 )]
49 57 ))
50 58
51 59 nb0 = new_notebook(
52 60 name='nb0',
53 61 worksheets=[ws, new_worksheet(name='worksheet2')]
54 62 )
55 63
56 64 nb0_py = """# <nbformat>2</nbformat>
57 65
58 66 # <codecell>
59 67
60 68 import numpy
61 69
62 70 # </codecell>
63 71 # <codecell>
64 72
65 73 a = numpy.random.rand(100)
66 74
67 75 # </codecell>
68 76 # <codecell>
69 77
70 78 print a
71 79
72 80 # </codecell>
73 81 """
74 82
75 83
@@ -1,66 +1,79 b''
1 1 from unittest import TestCase
2 2
3 3 from ..nbbase import (
4 4 NotebookNode,
5 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
6 6 )
7 7
8 8 class TestCell(TestCase):
9 9
10 10 def test_empty_code_cell(self):
11 11 cc = new_code_cell()
12 12 self.assertEquals(cc.cell_type,'code')
13 13 self.assertEquals('input' not in cc, True)
14 14 self.assertEquals('prompt_number' not in cc, True)
15 15 self.assertEquals(cc.outputs, [])
16 16
17 17 def test_code_cell(self):
18 18 cc = new_code_cell(input='a=10', prompt_number=0)
19 19 cc.outputs = [new_output(output_type='pyout',
20 20 output_svg='foo',output_text='10',prompt_number=0)]
21 21 self.assertEquals(cc.input, u'a=10')
22 22 self.assertEquals(cc.prompt_number, 0)
23 23 self.assertEquals(cc.language, u'python')
24 24 self.assertEquals(cc.outputs[0].svg, u'foo')
25 25 self.assertEquals(cc.outputs[0].text, u'10')
26 26 self.assertEquals(cc.outputs[0].prompt_number, 0)
27 27
28 28 def test_empty_html_cell(self):
29 tc = new_html_cell()
30 self.assertEquals(tc.cell_type, 'html')
29 tc = new_text_cell(u'html')
30 self.assertEquals(tc.cell_type, u'html')
31 31 self.assertEquals('source' not in tc, True)
32 self.assertEquals('rendered' not in tc, True)
32 33
33 34 def test_html_cell(self):
34 tc = new_html_cell('hi')
35 tc = new_text_cell(u'html', 'hi', 'hi')
35 36 self.assertEquals(tc.source, u'hi')
37 self.assertEquals(tc.rendered, u'hi')
38
39 def test_empty_markdown_cell(self):
40 tc = new_text_cell(u'markdown')
41 self.assertEquals(tc.cell_type, u'markdown')
42 self.assertEquals('source' not in tc, True)
43 self.assertEquals('rendered' not in tc, True)
44
45 def test_markdown_cell(self):
46 tc = new_text_cell(u'markdown', 'hi', 'hi')
47 self.assertEquals(tc.source, u'hi')
48 self.assertEquals(tc.rendered, u'hi')
36 49
37 50
38 51 class TestWorksheet(TestCase):
39 52
40 53 def test_empty_worksheet(self):
41 54 ws = new_worksheet()
42 55 self.assertEquals(ws.cells,[])
43 56 self.assertEquals('name' not in ws, True)
44 57
45 58 def test_worksheet(self):
46 cells = [new_code_cell(), new_html_cell()]
59 cells = [new_code_cell(), new_text_cell(u'html')]
47 60 ws = new_worksheet(cells=cells,name='foo')
48 61 self.assertEquals(ws.cells,cells)
49 62 self.assertEquals(ws.name,u'foo')
50 63
51 64 class TestNotebook(TestCase):
52 65
53 66 def test_empty_notebook(self):
54 67 nb = new_notebook()
55 68 self.assertEquals('id' in nb, True)
56 69 self.assertEquals(nb.worksheets, [])
57 70 self.assertEquals('name' not in nb, True)
58 71 self.assertEquals(nb.nbformat,2)
59 72
60 73 def test_notebook(self):
61 74 worksheets = [new_worksheet(),new_worksheet()]
62 75 nb = new_notebook(name='foo',worksheets=worksheets)
63 76 self.assertEquals(nb.name,u'foo')
64 77 self.assertEquals(nb.worksheets,worksheets)
65 78 self.assertEquals(nb.nbformat,2)
66 79
@@ -1,17 +1,17 b''
1 1 from unittest import TestCase
2 2
3 3 from ..nbbase import (
4 4 NotebookNode,
5 new_code_cell, new_html_cell, new_worksheet, new_notebook
5 new_code_cell, new_text_cell, new_worksheet, new_notebook
6 6 )
7 7
8 8 from ..nbpy import reads, writes
9 9 from .nbexamples import nb0, nb0_py
10 10
11 11
12 12 class TestPy(TestCase):
13 13
14 14 def test_write(self):
15 15 s = writes(nb0)
16 16 self.assertEquals(s,nb0_py)
17 17
General Comments 0
You need to be logged in to leave comments. Login now