##// END OF EJS Templates
nbconvert api tests fixes
Jonathan Frederic -
Show More
@@ -1,26 +1,27 b''
1 # http://travis-ci.org/#!/ipython/ipython
1 # http://travis-ci.org/#!/ipython/ipython
2 language: python
2 language: python
3 python:
3 python:
4 - 3.4
4 - 3.4
5 - 2.7
5 - 2.7
6 - 3.3
6 - 3.3
7 env:
7 env:
8 - GROUP=js
8 - GROUP=js
9 - GROUP=
9 - GROUP=
10 before_install:
10 before_install:
11 # workaround for https://github.com/travis-ci/travis-cookbooks/issues/155
11 # workaround for https://github.com/travis-ci/travis-cookbooks/issues/155
12 - sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
12 - sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
13 # Pierre Carrier's PPA for PhantomJS and CasperJS
13 # Pierre Carrier's PPA for PhantomJS and CasperJS
14 - time sudo add-apt-repository -y ppa:pcarrier/ppa
14 - time sudo add-apt-repository -y ppa:pcarrier/ppa
15 - time sudo apt-get update
15 - time sudo apt-get update
16 - time sudo apt-get install pandoc casperjs nodejs libzmq3-dev
16 - time sudo apt-get install pandoc casperjs nodejs libzmq3-dev
17 - time pip install -f https://nipy.bic.berkeley.edu/wheelhouse/travis jinja2 sphinx pygments tornado requests mock pyzmq jsonschema jsonpointer
17 - time pip install -f https://nipy.bic.berkeley.edu/wheelhouse/travis jinja2 sphinx pygments tornado requests mock pyzmq jsonschema jsonpointer
18 - time npm install requirejs r.js jquery
18 install:
19 install:
19 - time python setup.py install -q
20 - time python setup.py install -q
20 script:
21 script:
21 - cd /tmp && iptest $GROUP
22 - cd /tmp && iptest $GROUP
22
23
23 matrix:
24 matrix:
24 exclude:
25 exclude:
25 - python: 3.3
26 - python: 3.3
26 env: GROUP=js
27 env: GROUP=js
@@ -1,453 +1,454 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'notebook/js/cell',
7 'notebook/js/cell',
8 'base/js/security',
8 'base/js/security',
9 'notebook/js/mathjaxutils',
9 'notebook/js/mathjaxutils',
10 'notebook/js/celltoolbar',
10 'notebook/js/celltoolbar',
11 ], function(IPython, $, cell, security, mathjaxutils, celltoolbar) {
11 'components/marked/lib/marked',
12 ], function(IPython, $, cell, security, mathjaxutils, celltoolbar, marked) {
12 "use strict";
13 "use strict";
13 var Cell = cell.Cell;
14 var Cell = cell.Cell;
14
15
15 /**
16 /**
16 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
17 * Construct a new TextCell, codemirror mode is by default 'htmlmixed', and cell type is 'text'
17 * cell start as not redered.
18 * cell start as not redered.
18 *
19 *
19 * @class TextCell
20 * @class TextCell
20 * @constructor TextCell
21 * @constructor TextCell
21 * @extend Cell
22 * @extend Cell
22 * @param {object|undefined} [options]
23 * @param {object|undefined} [options]
23 * @param [options.cm_config] {object} config to pass to CodeMirror, will extend/overwrite default config
24 * @param [options.cm_config] {object} config to pass to CodeMirror, will extend/overwrite default config
24 * @param [options.placeholder] {string} default string to use when souce in empty for rendering (only use in some TextCell subclass)
25 * @param [options.placeholder] {string} default string to use when souce in empty for rendering (only use in some TextCell subclass)
25 */
26 */
26 var TextCell = function (options, events, config, keyboard_manager, notebook) {
27 var TextCell = function (options, events, config, keyboard_manager, notebook) {
27 // in all TextCell/Cell subclasses
28 // in all TextCell/Cell subclasses
28 // do not assign most of members here, just pass it down
29 // do not assign most of members here, just pass it down
29 // in the options dict potentially overwriting what you wish.
30 // in the options dict potentially overwriting what you wish.
30 // they will be assigned in the base class.
31 // they will be assigned in the base class.
31 this.notebook = notebook;
32 this.notebook = notebook;
32 this.events = events;
33 this.events = events;
33 this.config = config;
34 this.config = config;
34
35
35 // we cannot put this as a class key as it has handle to "this".
36 // we cannot put this as a class key as it has handle to "this".
36 var cm_overwrite_options = {
37 var cm_overwrite_options = {
37 onKeyEvent: $.proxy(this.handle_keyevent,this)
38 onKeyEvent: $.proxy(this.handle_keyevent,this)
38 };
39 };
39
40
40 options = this.mergeopt(TextCell,options,{cm_config:cm_overwrite_options});
41 options = this.mergeopt(TextCell,options,{cm_config:cm_overwrite_options});
41
42
42 this.cell_type = this.cell_type || 'text';
43 this.cell_type = this.cell_type || 'text';
43 mathjaxutils = mathjaxutils;
44 mathjaxutils = mathjaxutils;
44
45
45 Cell.apply(this, [options, keyboard_manager, events]);
46 Cell.apply(this, [options, keyboard_manager, events]);
46
47
47 this.rendered = false;
48 this.rendered = false;
48 };
49 };
49
50
50 TextCell.prototype = new Cell();
51 TextCell.prototype = new Cell();
51
52
52 TextCell.options_default = {
53 TextCell.options_default = {
53 cm_config : {
54 cm_config : {
54 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
55 extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess"},
55 mode: 'htmlmixed',
56 mode: 'htmlmixed',
56 lineWrapping : true,
57 lineWrapping : true,
57 }
58 }
58 };
59 };
59
60
60
61
61 /**
62 /**
62 * Create the DOM element of the TextCell
63 * Create the DOM element of the TextCell
63 * @method create_element
64 * @method create_element
64 * @private
65 * @private
65 */
66 */
66 TextCell.prototype.create_element = function () {
67 TextCell.prototype.create_element = function () {
67 Cell.prototype.create_element.apply(this, arguments);
68 Cell.prototype.create_element.apply(this, arguments);
68
69
69 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
70 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
70 cell.attr('tabindex','2');
71 cell.attr('tabindex','2');
71
72
72 var prompt = $('<div/>').addClass('prompt input_prompt');
73 var prompt = $('<div/>').addClass('prompt input_prompt');
73 cell.append(prompt);
74 cell.append(prompt);
74 var inner_cell = $('<div/>').addClass('inner_cell');
75 var inner_cell = $('<div/>').addClass('inner_cell');
75 this.celltoolbar = new celltoolbar.CellToolbar(this, this.events, this.notebook);
76 this.celltoolbar = new celltoolbar.CellToolbar(this, this.events, this.notebook);
76 inner_cell.append(this.celltoolbar.element);
77 inner_cell.append(this.celltoolbar.element);
77 var input_area = $('<div/>').addClass('input_area');
78 var input_area = $('<div/>').addClass('input_area');
78 this.code_mirror = new CodeMirror(input_area.get(0), this.cm_config);
79 this.code_mirror = new CodeMirror(input_area.get(0), this.cm_config);
79 // The tabindex=-1 makes this div focusable.
80 // The tabindex=-1 makes this div focusable.
80 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
81 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
81 addClass('rendered_html').attr('tabindex','-1');
82 addClass('rendered_html').attr('tabindex','-1');
82 inner_cell.append(input_area).append(render_area);
83 inner_cell.append(input_area).append(render_area);
83 cell.append(inner_cell);
84 cell.append(inner_cell);
84 this.element = cell;
85 this.element = cell;
85 };
86 };
86
87
87
88
88 /**
89 /**
89 * Bind the DOM evet to cell actions
90 * Bind the DOM evet to cell actions
90 * Need to be called after TextCell.create_element
91 * Need to be called after TextCell.create_element
91 * @private
92 * @private
92 * @method bind_event
93 * @method bind_event
93 */
94 */
94 TextCell.prototype.bind_events = function () {
95 TextCell.prototype.bind_events = function () {
95 Cell.prototype.bind_events.apply(this);
96 Cell.prototype.bind_events.apply(this);
96 var that = this;
97 var that = this;
97
98
98 this.element.dblclick(function () {
99 this.element.dblclick(function () {
99 if (that.selected === false) {
100 if (that.selected === false) {
100 this.events.trigger('select.Cell', {'cell':that});
101 this.events.trigger('select.Cell', {'cell':that});
101 }
102 }
102 var cont = that.unrender();
103 var cont = that.unrender();
103 if (cont) {
104 if (cont) {
104 that.focus_editor();
105 that.focus_editor();
105 }
106 }
106 });
107 });
107 };
108 };
108
109
109 // Cell level actions
110 // Cell level actions
110
111
111 TextCell.prototype.select = function () {
112 TextCell.prototype.select = function () {
112 var cont = Cell.prototype.select.apply(this);
113 var cont = Cell.prototype.select.apply(this);
113 if (cont) {
114 if (cont) {
114 if (this.mode === 'edit') {
115 if (this.mode === 'edit') {
115 this.code_mirror.refresh();
116 this.code_mirror.refresh();
116 }
117 }
117 }
118 }
118 return cont;
119 return cont;
119 };
120 };
120
121
121 TextCell.prototype.unrender = function () {
122 TextCell.prototype.unrender = function () {
122 if (this.read_only) return;
123 if (this.read_only) return;
123 var cont = Cell.prototype.unrender.apply(this);
124 var cont = Cell.prototype.unrender.apply(this);
124 if (cont) {
125 if (cont) {
125 var text_cell = this.element;
126 var text_cell = this.element;
126 var output = text_cell.find("div.text_cell_render");
127 var output = text_cell.find("div.text_cell_render");
127 output.hide();
128 output.hide();
128 text_cell.find('div.input_area').show();
129 text_cell.find('div.input_area').show();
129 if (this.get_text() === this.placeholder) {
130 if (this.get_text() === this.placeholder) {
130 this.set_text('');
131 this.set_text('');
131 }
132 }
132 this.refresh();
133 this.refresh();
133 }
134 }
134 if (this.celltoolbar.ui_controls_list.length) {
135 if (this.celltoolbar.ui_controls_list.length) {
135 this.celltoolbar.show();
136 this.celltoolbar.show();
136 }
137 }
137 return cont;
138 return cont;
138 };
139 };
139
140
140 TextCell.prototype.execute = function () {
141 TextCell.prototype.execute = function () {
141 this.render();
142 this.render();
142 };
143 };
143
144
144 /**
145 /**
145 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
146 * setter: {{#crossLink "TextCell/set_text"}}{{/crossLink}}
146 * @method get_text
147 * @method get_text
147 * @retrun {string} CodeMirror current text value
148 * @retrun {string} CodeMirror current text value
148 */
149 */
149 TextCell.prototype.get_text = function() {
150 TextCell.prototype.get_text = function() {
150 return this.code_mirror.getValue();
151 return this.code_mirror.getValue();
151 };
152 };
152
153
153 /**
154 /**
154 * @param {string} text - Codemiror text value
155 * @param {string} text - Codemiror text value
155 * @see TextCell#get_text
156 * @see TextCell#get_text
156 * @method set_text
157 * @method set_text
157 * */
158 * */
158 TextCell.prototype.set_text = function(text) {
159 TextCell.prototype.set_text = function(text) {
159 this.code_mirror.setValue(text);
160 this.code_mirror.setValue(text);
160 this.code_mirror.refresh();
161 this.code_mirror.refresh();
161 };
162 };
162
163
163 /**
164 /**
164 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
165 * setter :{{#crossLink "TextCell/set_rendered"}}{{/crossLink}}
165 * @method get_rendered
166 * @method get_rendered
166 * */
167 * */
167 TextCell.prototype.get_rendered = function() {
168 TextCell.prototype.get_rendered = function() {
168 return this.element.find('div.text_cell_render').html();
169 return this.element.find('div.text_cell_render').html();
169 };
170 };
170
171
171 /**
172 /**
172 * @method set_rendered
173 * @method set_rendered
173 */
174 */
174 TextCell.prototype.set_rendered = function(text) {
175 TextCell.prototype.set_rendered = function(text) {
175 this.element.find('div.text_cell_render').html(text);
176 this.element.find('div.text_cell_render').html(text);
176 this.celltoolbar.hide();
177 this.celltoolbar.hide();
177 };
178 };
178
179
179
180
180 /**
181 /**
181 * Create Text cell from JSON
182 * Create Text cell from JSON
182 * @param {json} data - JSON serialized text-cell
183 * @param {json} data - JSON serialized text-cell
183 * @method fromJSON
184 * @method fromJSON
184 */
185 */
185 TextCell.prototype.fromJSON = function (data) {
186 TextCell.prototype.fromJSON = function (data) {
186 Cell.prototype.fromJSON.apply(this, arguments);
187 Cell.prototype.fromJSON.apply(this, arguments);
187 if (data.cell_type === this.cell_type) {
188 if (data.cell_type === this.cell_type) {
188 if (data.source !== undefined) {
189 if (data.source !== undefined) {
189 this.set_text(data.source);
190 this.set_text(data.source);
190 // make this value the starting point, so that we can only undo
191 // make this value the starting point, so that we can only undo
191 // to this state, instead of a blank cell
192 // to this state, instead of a blank cell
192 this.code_mirror.clearHistory();
193 this.code_mirror.clearHistory();
193 // TODO: This HTML needs to be treated as potentially dangerous
194 // TODO: This HTML needs to be treated as potentially dangerous
194 // user input and should be handled before set_rendered.
195 // user input and should be handled before set_rendered.
195 this.set_rendered(data.rendered || '');
196 this.set_rendered(data.rendered || '');
196 this.rendered = false;
197 this.rendered = false;
197 this.render();
198 this.render();
198 }
199 }
199 }
200 }
200 };
201 };
201
202
202 /** Generate JSON from cell
203 /** Generate JSON from cell
203 * @return {object} cell data serialised to json
204 * @return {object} cell data serialised to json
204 */
205 */
205 TextCell.prototype.toJSON = function () {
206 TextCell.prototype.toJSON = function () {
206 var data = Cell.prototype.toJSON.apply(this);
207 var data = Cell.prototype.toJSON.apply(this);
207 data.source = this.get_text();
208 data.source = this.get_text();
208 if (data.source == this.placeholder) {
209 if (data.source == this.placeholder) {
209 data.source = "";
210 data.source = "";
210 }
211 }
211 return data;
212 return data;
212 };
213 };
213
214
214
215
215 /**
216 /**
216 * @class MarkdownCell
217 * @class MarkdownCell
217 * @constructor MarkdownCell
218 * @constructor MarkdownCell
218 * @extends IPython.HTMLCell
219 * @extends IPython.HTMLCell
219 */
220 */
220 var MarkdownCell = function (options, events, config, keyboard_manager) {
221 var MarkdownCell = function (options, events, config, keyboard_manager) {
221 options = this.mergeopt(MarkdownCell, options);
222 options = this.mergeopt(MarkdownCell, options);
222
223
223 this.cell_type = 'markdown';
224 this.cell_type = 'markdown';
224 TextCell.apply(this, [options, events, config, keyboard_manager]);
225 TextCell.apply(this, [options, events, config, keyboard_manager]);
225 };
226 };
226
227
227 MarkdownCell.options_default = {
228 MarkdownCell.options_default = {
228 cm_config: {
229 cm_config: {
229 mode: 'ipythongfm'
230 mode: 'ipythongfm'
230 },
231 },
231 placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$"
232 placeholder: "Type *Markdown* and LaTeX: $\\alpha^2$"
232 };
233 };
233
234
234 MarkdownCell.prototype = new TextCell();
235 MarkdownCell.prototype = new TextCell();
235
236
236 /**
237 /**
237 * @method render
238 * @method render
238 */
239 */
239 MarkdownCell.prototype.render = function () {
240 MarkdownCell.prototype.render = function () {
240 var cont = TextCell.prototype.render.apply(this);
241 var cont = TextCell.prototype.render.apply(this);
241 if (cont) {
242 if (cont) {
242 var text = this.get_text();
243 var text = this.get_text();
243 var math = null;
244 var math = null;
244 if (text === "") { text = this.placeholder; }
245 if (text === "") { text = this.placeholder; }
245 var text_and_math = mathjaxutils.remove_math(text);
246 var text_and_math = mathjaxutils.remove_math(text);
246 text = text_and_math[0];
247 text = text_and_math[0];
247 math = text_and_math[1];
248 math = text_and_math[1];
248 var html = marked.parser(marked.lexer(text));
249 var html = marked.parser(marked.lexer(text));
249 html = mathjaxutils.replace_math(html, math);
250 html = mathjaxutils.replace_math(html, math);
250 html = security.sanitize_html(html);
251 html = security.sanitize_html(html);
251 html = $($.parseHTML(html));
252 html = $($.parseHTML(html));
252 // links in markdown cells should open in new tabs
253 // links in markdown cells should open in new tabs
253 html.find("a[href]").not('[href^="#"]').attr("target", "_blank");
254 html.find("a[href]").not('[href^="#"]').attr("target", "_blank");
254 this.set_rendered(html);
255 this.set_rendered(html);
255 this.element.find('div.input_area').hide();
256 this.element.find('div.input_area').hide();
256 this.element.find("div.text_cell_render").show();
257 this.element.find("div.text_cell_render").show();
257 this.typeset();
258 this.typeset();
258 }
259 }
259 return cont;
260 return cont;
260 };
261 };
261
262
262
263
263 // RawCell
264 // RawCell
264
265
265 /**
266 /**
266 * @class RawCell
267 * @class RawCell
267 * @constructor RawCell
268 * @constructor RawCell
268 * @extends TextCell
269 * @extends TextCell
269 */
270 */
270 var RawCell = function (options, events, config, keyboard_manager) {
271 var RawCell = function (options, events, config, keyboard_manager) {
271
272
272 options = this.mergeopt(RawCell,options);
273 options = this.mergeopt(RawCell,options);
273 TextCell.apply(this, [options, events, config, keyboard_manager]);
274 TextCell.apply(this, [options, events, config, keyboard_manager]);
274 this.cell_type = 'raw';
275 this.cell_type = 'raw';
275 // RawCell should always hide its rendered div
276 // RawCell should always hide its rendered div
276 this.element.find('div.text_cell_render').hide();
277 this.element.find('div.text_cell_render').hide();
277 };
278 };
278
279
279 RawCell.options_default = {
280 RawCell.options_default = {
280 placeholder : "Write raw LaTeX or other formats here, for use with nbconvert. " +
281 placeholder : "Write raw LaTeX or other formats here, for use with nbconvert. " +
281 "It will not be rendered in the notebook. " +
282 "It will not be rendered in the notebook. " +
282 "When passing through nbconvert, a Raw Cell's content is added to the output unmodified."
283 "When passing through nbconvert, a Raw Cell's content is added to the output unmodified."
283 };
284 };
284
285
285 RawCell.prototype = new TextCell();
286 RawCell.prototype = new TextCell();
286
287
287 /** @method bind_events **/
288 /** @method bind_events **/
288 RawCell.prototype.bind_events = function () {
289 RawCell.prototype.bind_events = function () {
289 TextCell.prototype.bind_events.apply(this);
290 TextCell.prototype.bind_events.apply(this);
290 var that = this;
291 var that = this;
291 this.element.focusout(function() {
292 this.element.focusout(function() {
292 that.auto_highlight();
293 that.auto_highlight();
293 that.render();
294 that.render();
294 });
295 });
295
296
296 this.code_mirror.on('focus', function() { that.unrender(); });
297 this.code_mirror.on('focus', function() { that.unrender(); });
297 };
298 };
298
299
299 /**
300 /**
300 * Trigger autodetection of highlight scheme for current cell
301 * Trigger autodetection of highlight scheme for current cell
301 * @method auto_highlight
302 * @method auto_highlight
302 */
303 */
303 RawCell.prototype.auto_highlight = function () {
304 RawCell.prototype.auto_highlight = function () {
304 this._auto_highlight(this.config.raw_cell_highlight);
305 this._auto_highlight(this.config.raw_cell_highlight);
305 };
306 };
306
307
307 /** @method render **/
308 /** @method render **/
308 RawCell.prototype.render = function () {
309 RawCell.prototype.render = function () {
309 var cont = TextCell.prototype.render.apply(this);
310 var cont = TextCell.prototype.render.apply(this);
310 if (cont){
311 if (cont){
311 var text = this.get_text();
312 var text = this.get_text();
312 if (text === "") { text = this.placeholder; }
313 if (text === "") { text = this.placeholder; }
313 this.set_text(text);
314 this.set_text(text);
314 this.element.removeClass('rendered');
315 this.element.removeClass('rendered');
315 }
316 }
316 return cont;
317 return cont;
317 };
318 };
318
319
319
320
320 /**
321 /**
321 * @class HeadingCell
322 * @class HeadingCell
322 * @extends TextCell
323 * @extends TextCell
323 */
324 */
324
325
325 /**
326 /**
326 * @constructor HeadingCell
327 * @constructor HeadingCell
327 * @extends TextCell
328 * @extends TextCell
328 */
329 */
329 var HeadingCell = function (options, events, config, keyboard_manager) {
330 var HeadingCell = function (options, events, config, keyboard_manager) {
330 options = this.mergeopt(HeadingCell, options);
331 options = this.mergeopt(HeadingCell, options);
331
332
332 this.level = 1;
333 this.level = 1;
333 this.cell_type = 'heading';
334 this.cell_type = 'heading';
334 TextCell.apply(this, [options, events, config, keyboard_manager]);
335 TextCell.apply(this, [options, events, config, keyboard_manager]);
335
336
336 /**
337 /**
337 * heading level of the cell, use getter and setter to access
338 * heading level of the cell, use getter and setter to access
338 * @property level
339 * @property level
339 */
340 */
340 };
341 };
341
342
342 HeadingCell.options_default = {
343 HeadingCell.options_default = {
343 placeholder: "Type Heading Here"
344 placeholder: "Type Heading Here"
344 };
345 };
345
346
346 HeadingCell.prototype = new TextCell();
347 HeadingCell.prototype = new TextCell();
347
348
348 /** @method fromJSON */
349 /** @method fromJSON */
349 HeadingCell.prototype.fromJSON = function (data) {
350 HeadingCell.prototype.fromJSON = function (data) {
350 if (data.level !== undefined){
351 if (data.level !== undefined){
351 this.level = data.level;
352 this.level = data.level;
352 }
353 }
353 TextCell.prototype.fromJSON.apply(this, arguments);
354 TextCell.prototype.fromJSON.apply(this, arguments);
354 };
355 };
355
356
356
357
357 /** @method toJSON */
358 /** @method toJSON */
358 HeadingCell.prototype.toJSON = function () {
359 HeadingCell.prototype.toJSON = function () {
359 var data = TextCell.prototype.toJSON.apply(this);
360 var data = TextCell.prototype.toJSON.apply(this);
360 data.level = this.get_level();
361 data.level = this.get_level();
361 return data;
362 return data;
362 };
363 };
363
364
364 /**
365 /**
365 * can the cell be split into two cells
366 * can the cell be split into two cells
366 * @method is_splittable
367 * @method is_splittable
367 **/
368 **/
368 HeadingCell.prototype.is_splittable = function () {
369 HeadingCell.prototype.is_splittable = function () {
369 return false;
370 return false;
370 };
371 };
371
372
372
373
373 /**
374 /**
374 * can the cell be merged with other cells
375 * can the cell be merged with other cells
375 * @method is_mergeable
376 * @method is_mergeable
376 **/
377 **/
377 HeadingCell.prototype.is_mergeable = function () {
378 HeadingCell.prototype.is_mergeable = function () {
378 return false;
379 return false;
379 };
380 };
380
381
381 /**
382 /**
382 * Change heading level of cell, and re-render
383 * Change heading level of cell, and re-render
383 * @method set_level
384 * @method set_level
384 */
385 */
385 HeadingCell.prototype.set_level = function (level) {
386 HeadingCell.prototype.set_level = function (level) {
386 this.level = level;
387 this.level = level;
387 if (this.rendered) {
388 if (this.rendered) {
388 this.rendered = false;
389 this.rendered = false;
389 this.render();
390 this.render();
390 }
391 }
391 };
392 };
392
393
393 /** The depth of header cell, based on html (h1 to h6)
394 /** The depth of header cell, based on html (h1 to h6)
394 * @method get_level
395 * @method get_level
395 * @return {integer} level - for 1 to 6
396 * @return {integer} level - for 1 to 6
396 */
397 */
397 HeadingCell.prototype.get_level = function () {
398 HeadingCell.prototype.get_level = function () {
398 return this.level;
399 return this.level;
399 };
400 };
400
401
401
402
402 HeadingCell.prototype.get_rendered = function () {
403 HeadingCell.prototype.get_rendered = function () {
403 var r = this.element.find("div.text_cell_render");
404 var r = this.element.find("div.text_cell_render");
404 return r.children().first().html();
405 return r.children().first().html();
405 };
406 };
406
407
407 HeadingCell.prototype.render = function () {
408 HeadingCell.prototype.render = function () {
408 var cont = TextCell.prototype.render.apply(this);
409 var cont = TextCell.prototype.render.apply(this);
409 if (cont) {
410 if (cont) {
410 var text = this.get_text();
411 var text = this.get_text();
411 var math = null;
412 var math = null;
412 // Markdown headings must be a single line
413 // Markdown headings must be a single line
413 text = text.replace(/\n/g, ' ');
414 text = text.replace(/\n/g, ' ');
414 if (text === "") { text = this.placeholder; }
415 if (text === "") { text = this.placeholder; }
415 text = new Array(this.level + 1).join("#") + " " + text;
416 text = new Array(this.level + 1).join("#") + " " + text;
416 var text_and_math = mathjaxutils.remove_math(text);
417 var text_and_math = mathjaxutils.remove_math(text);
417 text = text_and_math[0];
418 text = text_and_math[0];
418 math = text_and_math[1];
419 math = text_and_math[1];
419 var html = marked.parser(marked.lexer(text));
420 var html = marked.parser(marked.lexer(text));
420 html = mathjaxutils.replace_math(html, math);
421 html = mathjaxutils.replace_math(html, math);
421 html = security.sanitize_html(html);
422 html = security.sanitize_html(html);
422 var h = $($.parseHTML(html));
423 var h = $($.parseHTML(html));
423 // add id and linkback anchor
424 // add id and linkback anchor
424 var hash = h.text().replace(/ /g, '-');
425 var hash = h.text().replace(/ /g, '-');
425 h.attr('id', hash);
426 h.attr('id', hash);
426 h.append(
427 h.append(
427 $('<a/>')
428 $('<a/>')
428 .addClass('anchor-link')
429 .addClass('anchor-link')
429 .attr('href', '#' + hash)
430 .attr('href', '#' + hash)
430 .text('ΒΆ')
431 .text('ΒΆ')
431 );
432 );
432 this.set_rendered(h);
433 this.set_rendered(h);
433 this.element.find('div.input_area').hide();
434 this.element.find('div.input_area').hide();
434 this.element.find("div.text_cell_render").show();
435 this.element.find("div.text_cell_render").show();
435 this.typeset();
436 this.typeset();
436 }
437 }
437 return cont;
438 return cont;
438 };
439 };
439
440
440 // Backwards compatability.
441 // Backwards compatability.
441 IPython.TextCell = TextCell;
442 IPython.TextCell = TextCell;
442 IPython.MarkdownCell = MarkdownCell;
443 IPython.MarkdownCell = MarkdownCell;
443 IPython.RawCell = RawCell;
444 IPython.RawCell = RawCell;
444 IPython.HeadingCell = HeadingCell;
445 IPython.HeadingCell = HeadingCell;
445
446
446 var Cells = {
447 var Cells = {
447 'TextCell': TextCell,
448 'TextCell': TextCell,
448 'MarkdownCell': MarkdownCell,
449 'MarkdownCell': MarkdownCell,
449 'RawCell': RawCell,
450 'RawCell': RawCell,
450 'HeadingCell': HeadingCell,
451 'HeadingCell': HeadingCell,
451 };
452 };
452 return Cells;
453 return Cells;
453 });
454 });
@@ -1,54 +1,63 b''
1 // Node.js script for markdown to html conversion
1 // Node.js script for markdown to html conversion
2 // This applies the same math extraction and marked settings
2 // This applies the same math extraction and marked settings
3 // that we use in the live notebook.
3 // that we use in the live notebook.
4
4
5 // IPython static_path dir relative to here:
5 // IPython static_path dir relative to here:
6 var static_path = __dirname + "/../../html/static/";
6 var static_path = __dirname + "/../../html/static/";
7
7
8 var fs = require('fs');
8 // Excerpt from the example in require.js docs
9 var IPython;
9 // http://requirejs.org/docs/node.html
10 // marked can be loaded with require,
10 var requirejs = require('requirejs');
11 // the others must be execfiled
11 requirejs.config({
12 var marked = require(static_path + 'components/marked/lib/marked.js');
12 //Pass the top-level main.js/index.js require
13
13 //function to requirejs so that node modules
14 eval(fs.readFileSync(static_path + "components/highlight.js/build/highlight.pack.js", 'utf8'));
14 //are loaded relative to the top-level JS file.
15 eval(fs.readFileSync(static_path + "base/js/namespace.js", 'utf8'));
15 nodeRequire: require,
16 baseUrl: static_path,
17 });
16
18
17 eval(fs.readFileSync(static_path + "base/js/utils.js", 'utf8'));
19 requirejs([
18 eval(fs.readFileSync(static_path + "notebook/js/mathjaxutils.js", 'utf8'));
20 'fs',
21 'components/marked/lib/marked',
22 'components/highlight.js/build/highlight.pack',
23 'base/js/utils',
24 'notebook/js/mathjaxutils',
25 ], function(fs, marked, hljs, utils, mathjaxutils) {
19
26
20 // this is copied from notebook.main. Should it be moved somewhere we can reuse it?
27 // this is copied from notebook.main. Should it be moved somewhere we can reuse it?
21 marked.setOptions({
28 marked.setOptions({
22 gfm : true,
29 gfm : true,
23 tables: true,
30 tables: true,
24 langPrefix: "language-",
31 langPrefix: "language-",
25 highlight: function(code, lang) {
32 highlight: function(code, lang) {
26 if (!lang) {
33 if (!lang) {
27 // no language, no highlight
34 // no language, no highlight
28 return code;
35 return code;
29 }
36 }
30 var highlighted;
37 var highlighted;
31 try {
38 try {
32 highlighted = hljs.highlight(lang, code, false);
39 highlighted = hljs.highlight(lang, code, false);
33 } catch(err) {
40 } catch(err) {
34 highlighted = hljs.highlightAuto(code);
41 highlighted = hljs.highlightAuto(code);
42 }
43 return highlighted.value;
35 }
44 }
36 return highlighted.value;
45 });
37 }
38 });
39
46
40 // read the markdown from stdin
47 // read the markdown from stdin
41 var md='';
48 var md='';
42 process.stdin.on("data", function (data) {
49 process.stdin.on("data", function (data) {
43 md += data;
50 md += data;
44 });
51 });
52
53 // perform the md2html transform once stdin is complete
54 process.stdin.on("end", function () {
55 var text_and_math = mathjaxutils.remove_math(md);
56 var text = text_and_math[0];
57 var math = text_and_math[1];
58 var html = marked.parser(marked.lexer(text));
59 html = mathjaxutils.replace_math(html, math);
60 process.stdout.write(html);
61 });
45
62
46 // perform the md2html transform once stdin is complete
47 process.stdin.on("end", function () {
48 var text_and_math = IPython.mathjaxutils.remove_math(md);
49 var text = text_and_math[0];
50 var math = text_and_math[1];
51 var html = marked.parser(marked.lexer(text));
52 html = IPython.mathjaxutils.replace_math(html, math);
53 process.stdout.write(html);
54 });
63 });
General Comments 0
You need to be logged in to leave comments. Login now