diff --git a/notebook/static/notebook/js/cell.js b/notebook/static/notebook/js/cell.js index 9b6379a687..eceda62a10 100644 --- a/notebook/static/notebook/js/cell.js +++ b/notebook/static/notebook/js/cell.js @@ -49,10 +49,9 @@ define([ options = options || {}; this.keyboard_manager = options.keyboard_manager; this.events = options.events; - var config = utils.mergeopt(Cell, options.config); + var config = options.config; // superclass default overwrite our default - this.placeholder = config.placeholder || ''; this.selected = false; this.anchor = false; this.rendered = false; @@ -83,19 +82,21 @@ define([ // load this from metadata later ? this.user_highlight = 'auto'; - - var _local_cm_config = {}; - if(this.class_config){ - _local_cm_config = this.class_config.get_sync('cm_config'); + // merge my class-specific config data with general cell-level config + var class_config_data = {}; + if (this.class_config) { + class_config_data = this.class_config.get_sync(); } - - var local = new configmod.ConfigWithDefaults(options.config, - {}, 'Cell'); - var llcm = local.get_sync('cm_config'); - config.cm_config = utils.mergeopt({}, config.cm_config, utils.mergeopt({}, llcm, _local_cm_config)); + var cell_config = new configmod.ConfigWithDefaults(options.config, + Cell.options_default, 'Cell'); + var cell_config_data = cell_config.get_sync(); + + // this._options is a merge of SomeCell and Cell config data: + this._options = utils.mergeopt({}, cell_config_data, class_config_data); + this.placeholder = this._options.placeholder || ''; + this.cell_id = utils.uuid(); - this._options = config; // For JS VM engines optimization, attributes should be all set (even // to null) in the constructor, and if possible, if different subclass diff --git a/notebook/static/notebook/js/codecell.js b/notebook/static/notebook/js/codecell.js index ef69791c1c..11e6a087e2 100644 --- a/notebook/static/notebook/js/codecell.js +++ b/notebook/static/notebook/js/codecell.js @@ -96,7 +96,7 @@ define([ this.tooltip = options.tooltip; this.config = options.config; this.class_config = new configmod.ConfigWithDefaults(this.config, - CodeCell.config_defaults, 'CodeCell'); + CodeCell.options_default, 'CodeCell'); // create all attributed in constructor function // even if null for V8 VM optimisation @@ -141,8 +141,6 @@ define([ }, }; - CodeCell.config_defaults = CodeCell.options_default; - CodeCell.msg_cells = {}; CodeCell.prototype = Object.create(Cell.prototype); diff --git a/notebook/static/notebook/js/codemirror-ipythongfm.js b/notebook/static/notebook/js/codemirror-ipythongfm.js index 293d17dca7..f840964e2f 100644 --- a/notebook/static/notebook/js/codemirror-ipythongfm.js +++ b/notebook/static/notebook/js/codemirror-ipythongfm.js @@ -55,5 +55,16 @@ }, 'gfm'); CodeMirror.defineMIME("text/x-ipythongfm", "ipythongfm"); + + // async workaround: + // Cells may be loaded before this mode is defined. + // If that happens, trigger re-load of the mode: + if (Jupyter && Jupyter.notebook) { + Jupyter.notebook.get_cells().map(function (cell) { + if (cell.code_mirror && cell.code_mirror.getOption('mode') === 'ipythongfm') { + cell.code_mirror.setOption('mode', 'ipythongfm'); + } + }); + } }); -}) +}); diff --git a/notebook/static/notebook/js/textcell.js b/notebook/static/notebook/js/textcell.js index 9ba54b4aed..fdb7e48ceb 100644 --- a/notebook/static/notebook/js/textcell.js +++ b/notebook/static/notebook/js/textcell.js @@ -56,7 +56,6 @@ define([ this.notebook = options.notebook; // we cannot put this as a class key as it has handle to "this". - var config = utils.mergeopt(TextCell, this.config); Cell.apply(this, [{ config: options.config, keyboard_manager: options.keyboard_manager, @@ -279,9 +278,9 @@ define([ * notebook: Notebook instance */ options = options || {}; - var config = utils.mergeopt(MarkdownCell, {}); + var config_default = utils.mergeopt(TextCell, MarkdownCell.options_default); this.class_config = new configmod.ConfigWithDefaults(options.config, - {}, 'MarkdownCell'); + config_default, 'MarkdownCell'); TextCell.apply(this, [$.extend({}, options, {config: options.config})]); this.cell_type = 'markdown'; @@ -527,24 +526,20 @@ define([ * notebook: Notebook instance */ options = options || {}; - var config = utils.mergeopt(RawCell, {}); - TextCell.apply(this, [$.extend({}, options, {config: options.config})]); - + var config_default = utils.mergeopt(TextCell, RawCell.options_default); this.class_config = new configmod.ConfigWithDefaults(options.config, - RawCell.config_defaults, 'RawCell'); + config_default, 'RawCell'); + TextCell.apply(this, [$.extend({}, options, {config: options.config})]); this.cell_type = 'raw'; }; RawCell.options_default = { - placeholder : "Write raw LaTeX or other formats here, for use with nbconvert. " + - "It will not be rendered in the notebook. " + - "When passing through nbconvert, a Raw Cell's content is added to the output unmodified." - }; - - RawCell.config_defaults = { highlight_modes : { 'diff' :{'reg':[/^diff/]} }, + placeholder : "Write raw LaTeX or other formats here, for use with nbconvert. " + + "It will not be rendered in the notebook. " + + "When passing through nbconvert, a Raw Cell's content is added to the output unmodified.", }; RawCell.prototype = Object.create(TextCell.prototype); diff --git a/notebook/static/services/config.js b/notebook/static/services/config.js index 9c5d7dda8e..822306d9f6 100644 --- a/notebook/static/services/config.js +++ b/notebook/static/services/config.js @@ -102,7 +102,21 @@ function(utils) { */ ConfigWithDefaults.prototype.get_sync = function(key) { var data = this._class_data(); - return key in data ? data[key] : this.defaults[key]; + if (key === undefined) { + // no key specified, return full config data + return $.extend(true, {}, this.defaults, data); + } + + var value = data[key]; + if (value !== undefined) { + if (typeof value == 'object') { + // merge with defaults if it's an object + return $.extend(true, {}, this.defaults[key], value); + } else { + return value; + } + } + return this.defaults[key]; }; /** diff --git a/notebook/tests/notebook/dualmode_cellmode.js b/notebook/tests/notebook/dualmode_cellmode.js index 3701792d30..459d18a743 100644 --- a/notebook/tests/notebook/dualmode_cellmode.js +++ b/notebook/tests/notebook/dualmode_cellmode.js @@ -2,17 +2,26 @@ // Test casper.notebook_test(function () { + function get_cell_cm_mode(index) { + return casper.evaluate(function (index) { + return Jupyter.notebook.get_cell(index).code_mirror.getMode().name; + }, {index: index}); + } + this.then(function () { // Cell mode change + var that = this; var index = 0; this.select_cell(index); var a = 'hello\nmulti\nline'; this.set_cell_text(index, a); this.trigger_keydown('esc','r'); this.test.assertEquals(this.get_cell(index).cell_type, 'raw', 'r; cell is raw'); + this.test.assertEquals(get_cell_cm_mode(index), 'null', 'raw cell codemirror mode is null'); this.trigger_keydown('1'); this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '1; cell is markdown'); this.test.assertEquals(this.get_cell_text(index), '# ' + a, '1; markdown heading'); + this.test.assertEquals(get_cell_cm_mode(index), 'ipythongfm', 'codemirror cell mode is ipythongfm'); this.trigger_keydown('2'); this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '2; cell is markdown'); this.test.assertEquals(this.get_cell_text(index), '## ' + a, '2; markdown heading'); @@ -34,6 +43,7 @@ casper.notebook_test(function () { this.trigger_keydown('y'); this.test.assertEquals(this.get_cell(index).cell_type, 'code', 'y; cell is code'); this.test.assertEquals(this.get_cell_text(index), '###### ' + a, 'y; still has hashes'); + this.test.assertEquals(get_cell_cm_mode(index), 'ipython', 'code cell mode is ipython'); this.trigger_keydown('1'); this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', '1; cell is markdown'); this.test.assertEquals(this.get_cell_text(index), '# ' + a, '1; markdown heading');