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