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