From 72f81fc3cab1634d735ce6705dce118ad9861583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Bercher?= Date: Sun, 15 Jan 2017 15:45:41 +0100 Subject: [PATCH 1/4] [code_prettify] add JSON conversion of results from the R kernel --- code_prettify.js | 4 ++-- code_prettify.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code_prettify.js b/code_prettify.js index 7a1f8ef67..fb32cc68a 100644 --- a/code_prettify.js +++ b/code_prettify.js @@ -31,8 +31,8 @@ define(function(require, exports, module) { }, "r": { "library": "library(formatR)\nlibrary(jsonlite)", - "prefix": "cat(paste(tidy_source(text=", - "postfix": ")[['text.tidy']], collapse='\n'))" + "prefix": "cat(toJSON(paste(tidy_source(text=", + "postfix": ", output=FALSE)[['text.tidy']], collapse='\n')))" }, "javascript": { "library": "jsbeautify = require(" + "'js-beautify')", diff --git a/code_prettify.yaml b/code_prettify.yaml index 442fc60a1..31acbfac9 100644 --- a/code_prettify.yaml +++ b/code_prettify.yaml @@ -61,8 +61,8 @@ Parameters: }, "r": { "library": "library(formatR)\nlibrary(jsonlite)", - "prefix": "cat(paste(tidy_source(text=", - "postfix": ")[['text.tidy']], collapse='\n'))" + "prefix": "cat(toJSON(paste(tidy_source(text=", + "postfix": ", output=FALSE)[['text.tidy']], collapse='\n')))" }, "javascript": { "library": "jsbeautify = require('js-beautify')", From 73118dff3ea8659dd2e229385b4ff70f3ba730f4 Mon Sep 17 00:00:00 2001 From: Josh Barnes Date: Tue, 9 May 2017 11:33:14 +0100 Subject: [PATCH 2/4] [lib] whitespace --- kernel_exec_on_cell.js | 479 +++++++++++++++++++++-------------------- 1 file changed, 240 insertions(+), 239 deletions(-) diff --git a/kernel_exec_on_cell.js b/kernel_exec_on_cell.js index 09d255b46..5e54e406d 100755 --- a/kernel_exec_on_cell.js +++ b/kernel_exec_on_cell.js @@ -15,7 +15,7 @@ define(function(require, exports, module) { function KernelExecOnCells(mod_name, cfg) { this.mod_name = mod_name; - this.cfg = cfg; + this.cfg = cfg; this.mod_log_prefix = '[' + this.mod_name + ']'; this.mod_edit_shortcuts = {}; this.mod_cmd_shortcuts = {}; @@ -29,17 +29,17 @@ define(function(require, exports, module) { // gives default settings var default_cfg = { add_toolbar_button: true, - hotkeys: { - process_selected: 'Ctrl-L', - process_all: 'Ctrl-Shift-L', - }, + hotkeys: { + process_selected: 'Ctrl-L', + process_all: 'Ctrl-Shift-L', + }, register_hotkey: true, show_alerts_for_errors: true, button_icon: 'fa-legal', button_label: mod_name, kbd_shortcut_text: mod_name, kernel_config_map: {}, - actions: null, // to be filled by register_actions + actions: null, // to be filled by register_actions }; // apply defaults to cfg. Don't use jquery extend, as we want cfg to still // be same object, in case plugin alters it later @@ -50,117 +50,117 @@ define(function(require, exports, module) { } // set default json string, will later be updated from config // before it is parsed into an object - this.cfg.kernel_config_map_json = JSON.stringify(this.cfg.kernel_config_map); - + this.cfg.kernel_config_map_json = JSON.stringify(this.cfg.kernel_config_map); + } // end per-plugin wrapper define_plugin_functions // Prototypes // ---------- - /** - * return a Promise which will resolve/reject based on the kernel message - * type. - * The returned promise will be - * - resolved if the message was not an error - * - rejected using the message's error text if msg.msg_type is "error" - */ - KernelExecOnCells.prototype.convert_error_msg_to_broken_promise = function(msg) { - var that = this; - return new Promise(function(resolve, reject) { - if (msg.msg_type == 'error') { - return reject(that.mod_log_prefix + '\n Error: ' + msg.content.ename + '\n' + msg.content.evalue); - } - return resolve(msg); - }); - } + /** + * return a Promise which will resolve/reject based on the kernel message + * type. + * The returned promise will be + * - resolved if the message was not an error + * - rejected using the message's error text if msg.msg_type is "error" + */ + KernelExecOnCells.prototype.convert_error_msg_to_broken_promise = function(msg) { + var that = this; + return new Promise(function(resolve, reject) { + if (msg.msg_type == 'error') { + return reject(that.mod_log_prefix + '\n Error: ' + msg.content.ename + '\n' + msg.content.evalue); + } + return resolve(msg); + }); + } - KernelExecOnCells.prototype.convert_loading_library_error_msg_to_broken_promise = function(msg) { - var that = this; - return new Promise(function(resolve, reject) { - if (msg.msg_type == 'error') { - return reject(that.mod_log_prefix + '\n Error loading library for ' + - Jupyter.notebook.metadata.kernelspec.language + ':\n' + - msg.content.ename + msg.content.evalue + - '\n\nCheck that the appropriate library/module is correctly installed (read ' + - that.mod_name + '\'s documentation for details)'); - } - return resolve(msg); - }); - } + KernelExecOnCells.prototype.convert_loading_library_error_msg_to_broken_promise = function(msg) { + var that = this; + return new Promise(function(resolve, reject) { + if (msg.msg_type == 'error') { + return reject(that.mod_log_prefix + '\n Error loading library for ' + + Jupyter.notebook.metadata.kernelspec.language + ':\n' + + msg.content.ename + msg.content.evalue + + '\n\nCheck that the appropriate library/module is correctly installed (read ' + + that.mod_name + '\'s documentation for details)'); + } + return resolve(msg); + }); + } - KernelExecOnCells.prototype.get_kernel_config = function() { - var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase(); - var kernel_config = this.cfg.kernel_config_map[kernelLanguage]; - // true => deep - return $.extend(true, {}, this.default_kernel_config, kernel_config); - } + KernelExecOnCells.prototype.get_kernel_config = function() { + var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase(); + var kernel_config = this.cfg.kernel_config_map[kernelLanguage]; + // true => deep + return $.extend(true, {}, this.default_kernel_config, kernel_config); + } - KernelExecOnCells.prototype.transform_json_string_to_kernel_string = function(str, kernel_config) { - for (var ii = 0; ii < kernel_config.replacements_json_to_kernel.length; ii++) { - var from = kernel_config.replacements_json_to_kernel[ii][0]; - var to = kernel_config.replacements_json_to_kernel[ii][1]; - str = str.replace(from, to); - } - return str; + KernelExecOnCells.prototype.transform_json_string_to_kernel_string = function(str, kernel_config) { + for (var ii = 0; ii < kernel_config.replacements_json_to_kernel.length; ii++) { + var from = kernel_config.replacements_json_to_kernel[ii][0]; + var to = kernel_config.replacements_json_to_kernel[ii][1]; + str = str.replace(from, to); } + return str; + } - /** - * construct functions as callbacks for the autoformat cell promise. This - * is necessary because javascript lacks loop scoping, so if we don't use - * this IIFE pattern, cell_index & cell are passed by reference, and every - * callback ends up using the same value - */ - KernelExecOnCells.prototype.construct_cell_callbacks = function(cell_index, cell) { - var that = this; - var on_success = function(formatted_text) { - cell.set_text(formatted_text); - }; - var on_failure = function(reason) { - console.warn( - that.mod_log_prefix, - 'error processing cell', cell_index + ':\n', - reason - ); - if (that.cfg.show_alerts_for_errors) { - alert(reason); - } - }; - return [on_success, on_failure]; - } + /** + * construct functions as callbacks for the autoformat cell promise. This + * is necessary because javascript lacks loop scoping, so if we don't use + * this IIFE pattern, cell_index & cell are passed by reference, and every + * callback ends up using the same value + */ + KernelExecOnCells.prototype.construct_cell_callbacks = function(cell_index, cell) { + var that = this; + var on_success = function(formatted_text) { + cell.set_text(formatted_text); + }; + var on_failure = function(reason) { + console.warn( + that.mod_log_prefix, + 'error processing cell', cell_index + ':\n', + reason + ); + if (that.cfg.show_alerts_for_errors) { + alert(reason); + } + }; + return [on_success, on_failure]; + } - KernelExecOnCells.prototype.autoformat_cells = function(indices) { + KernelExecOnCells.prototype.autoformat_cells = function(indices) { - if (indices === undefined) { - indices = Jupyter.notebook.get_selected_cells_indices(); - } - var kernel_config = this.get_kernel_config(); - for (var ii = 0; ii < indices.length; ii++) { - var cell_index = indices[ii]; - var cell = Jupyter.notebook.get_cell(cell_index); - if (!(cell instanceof CodeCell)) { - continue; - } - // IIFE because otherwise cell_index & cell are passed by reference - var callbacks = this.construct_cell_callbacks(cell_index, cell); - this.autoformat_text(cell.get_text(), kernel_config).then(callbacks[0], callbacks[1]); + if (indices === undefined) { + indices = Jupyter.notebook.get_selected_cells_indices(); + } + var kernel_config = this.get_kernel_config(); + for (var ii = 0; ii < indices.length; ii++) { + var cell_index = indices[ii]; + var cell = Jupyter.notebook.get_cell(cell_index); + if (!(cell instanceof CodeCell)) { + continue; } + // IIFE because otherwise cell_index & cell are passed by reference + var callbacks = this.construct_cell_callbacks(cell_index, cell); + this.autoformat_text(cell.get_text(), kernel_config).then(callbacks[0], callbacks[1]); } + } - KernelExecOnCells.prototype.autoformat_text = function(text, kernel_config) { - var that = this; - return new Promise(function(resolve, reject) { - kernel_config = kernel_config || that.get_kernel_config(); - var kernel_str = that.transform_json_string_to_kernel_string( - JSON.stringify(text), kernel_config); - Jupyter.notebook.kernel.execute( - kernel_config.prefix + kernel_str + kernel_config.postfix, { - iopub: { - output: function(msg) { - return resolve(that.convert_error_msg_to_broken_promise(msg).then( - function on_success(msg) { - // print goes to stream text => msg.content.text - // but for some kernels (eg nodejs) can be called as result of exec - if (msg.content.text !== undefined){ + KernelExecOnCells.prototype.autoformat_text = function(text, kernel_config) { + var that = this; + return new Promise(function(resolve, reject) { + kernel_config = kernel_config || that.get_kernel_config(); + var kernel_str = that.transform_json_string_to_kernel_string( + JSON.stringify(text), kernel_config); + Jupyter.notebook.kernel.execute( + kernel_config.prefix + kernel_str + kernel_config.postfix, { + iopub: { + output: function(msg) { + return resolve(that.convert_error_msg_to_broken_promise(msg).then( + function on_success(msg) { + // print goes to stream text => msg.content.text + // but for some kernels (eg nodejs) can be called as result of exec + if (msg.content.text !== undefined) { var formatted_text; try { formatted_text = String(JSON.parse(msg.content.text)); @@ -171,83 +171,84 @@ define(function(require, exports, module) { formatted_text = formatted_text.trim(); } return formatted_text; - }} - )); - } + } + } + )); } - }, { silent: false } - ); - }); - } + } + }, { silent: false } + ); + }); + } - KernelExecOnCells.prototype.add_toolbar_button = function() { - var that = this; - if ($('#' + this.mod_name + '_button').length < 1) { - var button_group_id = this.mod_name + '_button'; - Jupyter.toolbar.add_buttons_group( - [this.cfg.actions.process_selected.name], button_group_id); - } + KernelExecOnCells.prototype.add_toolbar_button = function() { + var that = this; + if ($('#' + this.mod_name + '_button').length < 1) { + var button_group_id = this.mod_name + '_button'; + Jupyter.toolbar.add_buttons_group( + [this.cfg.actions.process_selected.name], button_group_id); } + } - KernelExecOnCells.prototype.add_keyboard_shortcuts = function() { - var new_shortcuts = {}; - new_shortcuts[this.cfg.hotkeys.process_selected] = this.cfg.actions.process_selected.name; - new_shortcuts[this.cfg.hotkeys.process_all] = this.cfg.actions.process_all.name; - Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(new_shortcuts); - Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(new_shortcuts); - } + KernelExecOnCells.prototype.add_keyboard_shortcuts = function() { + var new_shortcuts = {}; + new_shortcuts[this.cfg.hotkeys.process_selected] = this.cfg.actions.process_selected.name; + new_shortcuts[this.cfg.hotkeys.process_all] = this.cfg.actions.process_all.name; + Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(new_shortcuts); + Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(new_shortcuts); + } - KernelExecOnCells.prototype.register_actions = function() { - /** - * it's important that the actions created by registering keyboard - * shortcuts get different names, as otherwise a default action is - * created, whose name is a string representation of the handler - * function. - * Since this library uses the same handler function for all plugins, - * just with different contexts (different values of cfg), their - * string representations are the same, and the last one to be - * registered overwrites all previous versions. - * This is essentially an issue with notebook, but it encourages us to - * use actions, which is where notebook is going anyway. - */ - var actions = this.cfg.actions = {}; - var that = this; - actions.process_selected = { - help: that.cfg.kbd_shortcut_text + ' selected cell(s)', - help_index: 'yf', - icon: that.cfg.button_icon, - handler: function(evt) { that.autoformat_cells(); }, - }; - actions.process_all = { - help: that.cfg.kbd_shortcut_text + " the whole notebook", - help_index: 'yf', - icon: that.cfg.button_icon, - handler: function(evt) { - var indices = [], - N = Jupyter.notebook.ncells(); - for (var i = 0; i < N; i++) { - indices.push(i); - } - that.autoformat_cells(indices); - }, - }; + KernelExecOnCells.prototype.register_actions = function() { + /** + * it's important that the actions created by registering keyboard + * shortcuts get different names, as otherwise a default action is + * created, whose name is a string representation of the handler + * function. + * Since this library uses the same handler function for all plugins, + * just with different contexts (different values of cfg), their + * string representations are the same, and the last one to be + * registered overwrites all previous versions. + * This is essentially an issue with notebook, but it encourages us to + * use actions, which is where notebook is going anyway. + */ + var actions = this.cfg.actions = {}; + var that = this; + actions.process_selected = { + help: that.cfg.kbd_shortcut_text + ' selected cell(s)', + help_index: 'yf', + icon: that.cfg.button_icon, + handler: function(evt) { that.autoformat_cells(); }, + }; + actions.process_all = { + help: that.cfg.kbd_shortcut_text + " the whole notebook", + help_index: 'yf', + icon: that.cfg.button_icon, + handler: function(evt) { + var indices = [], + N = Jupyter.notebook.ncells(); + for (var i = 0; i < N; i++) { + indices.push(i); + } + that.autoformat_cells(indices); + }, + }; - actions.process_selected.name = Jupyter.keyboard_manager.actions.register( - actions.process_selected, 'process_selected_cells', that.mod_name); - actions.process_all.name = Jupyter.keyboard_manager.actions.register( - actions.process_all, 'process_all_cells', that.mod_name); - } + actions.process_selected.name = Jupyter.keyboard_manager.actions.register( + actions.process_selected, 'process_selected_cells', that.mod_name); + actions.process_all.name = Jupyter.keyboard_manager.actions.register( + actions.process_all, 'process_all_cells', that.mod_name); + } - KernelExecOnCells.prototype.setup_for_new_kernel = function() { - var that = this; - var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase(); - var kernel_config = this.cfg.kernel_config_map[kernelLanguage]; - if (kernel_config === undefined) { - $('#' + this.mod_name + '_button').remove(); - alert(this.mod_log_prefix + " Sorry, can't use kernel language " + kernelLanguage + ".\n" + - "Configurations are currently only defined for the following languages:\n" + - Object.keys(this.cfg.kernel_config_map).join(', ') + "\n" + - "See readme for more details."); + KernelExecOnCells.prototype.setup_for_new_kernel = function() { + var that = this; + var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase(); + var kernel_config = this.cfg.kernel_config_map[kernelLanguage]; + if (kernel_config === undefined) { + $('#' + this.mod_name + '_button').remove(); + alert(this.mod_log_prefix + " Sorry, can't use kernel language " + kernelLanguage + ".\n" + + "Configurations are currently only defined for the following languages:\n" + + Object.keys(this.cfg.kernel_config_map).join(', ') + "\n" + + "See readme for more details."); // also remove keyboard shortcuts if (this.cfg.register_hotkey) { try { @@ -257,81 +258,81 @@ define(function(require, exports, module) { } catch (err) {} } - } else { // kernel language is supported - if (this.cfg.add_toolbar_button) { - this.add_toolbar_button(); - } - if (this.cfg.register_hotkey) { - this.add_keyboard_shortcuts(); - } - Jupyter.notebook.kernel.execute( - kernel_config.library, { - iopub: { - output: function(msg) { - return that.convert_loading_library_error_msg_to_broken_promise(msg) - .catch( - function on_failure(err) { - if (that.cfg.show_alerts_for_errors) { - alert(err); - } - else{ - console.error(err) - } + } else { // kernel language is supported + if (this.cfg.add_toolbar_button) { + this.add_toolbar_button(); + } + if (this.cfg.register_hotkey) { + this.add_keyboard_shortcuts(); + } + Jupyter.notebook.kernel.execute( + kernel_config.library, { + iopub: { + output: function(msg) { + return that.convert_loading_library_error_msg_to_broken_promise(msg) + .catch( + function on_failure(err) { + if (that.cfg.show_alerts_for_errors) { + alert(err); + } + else { + console.error(err) } + } - ); - } + ); } - }, { silent: false } - ); + } + }, { silent: false } + ); - } } + } - KernelExecOnCells.prototype.initialize_plugin = function() { - var that = this; - var base_url = utils.get_body_data("baseUrl"); - var conf_section = new ConfigSection('notebook', { base_url: base_url }); - // first, load config - conf_section.load() - // now update default config with that loaded from server - .then(function on_success(config_data) { - $.extend(true, that.cfg, config_data[that.mod_name]); - }, function on_error(err) { - console.warn(that.mod_log_prefix, 'error loading config:', err); - }) - // next parse json config values - .then(function on_success() { - var parsed_kernel_cfg = JSON.parse(that.cfg.kernel_config_map_json); - $.extend(that.cfg.kernel_config_map, parsed_kernel_cfg); - }) - // if we failed to parse the json values in the config - // using catch pattern, we attempt to continue anyway using defaults - .catch(function on_error(err) { - console.warn( - that.mod_log_prefix, 'error parsing config variable', - that.mod_name + '.kernel_config_map_json to a json object:', - err - ); - }) - // now do things which required the config to be loaded - .then(function on_success() { - that.register_actions(); // register actions - // kernel may already have been loaded before we get here, in which - // case we've missed the kernel_ready.Kernel event, so try ctx - if (typeof Jupyter.notebook.kernel !== "undefined" && Jupyter.notebook.kernel !== null) { - that.setup_for_new_kernel(); - } + KernelExecOnCells.prototype.initialize_plugin = function() { + var that = this; + var base_url = utils.get_body_data("baseUrl"); + var conf_section = new ConfigSection('notebook', { base_url: base_url }); + // first, load config + conf_section.load() + // now update default config with that loaded from server + .then(function on_success(config_data) { + $.extend(true, that.cfg, config_data[that.mod_name]); + }, function on_error(err) { + console.warn(that.mod_log_prefix, 'error loading config:', err); + }) + // next parse json config values + .then(function on_success() { + var parsed_kernel_cfg = JSON.parse(that.cfg.kernel_config_map_json); + $.extend(that.cfg.kernel_config_map, parsed_kernel_cfg); + }) + // if we failed to parse the json values in the config + // using catch pattern, we attempt to continue anyway using defaults + .catch(function on_error(err) { + console.warn( + that.mod_log_prefix, 'error parsing config variable', + that.mod_name + '.kernel_config_map_json to a json object:', + err + ); + }) + // now do things which required the config to be loaded + .then(function on_success() { + that.register_actions(); // register actions + // kernel may already have been loaded before we get here, in which + // case we've missed the kernel_ready.Kernel event, so try ctx + if (typeof Jupyter.notebook.kernel !== "undefined" && Jupyter.notebook.kernel !== null) { + that.setup_for_new_kernel(); + } - // on kernel_ready.Kernel, a new kernel has been started - events.on("kernel_ready.Kernel", function(evt, data) { - console.log(that.mod_log_prefix, 'restarting for new kernel_ready.Kernel event'); - that.setup_for_new_kernel(); - }); - }).catch(function on_error(err) { - console.error(that.mod_log_prefix, 'error loading:', err); + // on kernel_ready.Kernel, a new kernel has been started + events.on("kernel_ready.Kernel", function(evt, data) { + console.log(that.mod_log_prefix, 'restarting for new kernel_ready.Kernel event'); + that.setup_for_new_kernel(); }); - } + }).catch(function on_error(err) { + console.error(that.mod_log_prefix, 'error loading:', err); + }); + } exports.define_plugin = KernelExecOnCells; return {define_plugin: KernelExecOnCells} From cd44e758f6de2542718635b44a346c815c2b203d Mon Sep 17 00:00:00 2001 From: Josh Barnes Date: Tue, 9 May 2017 11:36:08 +0100 Subject: [PATCH 3/4] [lib] linting --- kernel_exec_on_cell.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/kernel_exec_on_cell.js b/kernel_exec_on_cell.js index 5e54e406d..1d86372a7 100755 --- a/kernel_exec_on_cell.js +++ b/kernel_exec_on_cell.js @@ -72,7 +72,7 @@ define(function(require, exports, module) { } return resolve(msg); }); - } + }; KernelExecOnCells.prototype.convert_loading_library_error_msg_to_broken_promise = function(msg) { var that = this; @@ -86,14 +86,14 @@ define(function(require, exports, module) { } return resolve(msg); }); - } + }; KernelExecOnCells.prototype.get_kernel_config = function() { var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase(); var kernel_config = this.cfg.kernel_config_map[kernelLanguage]; // true => deep return $.extend(true, {}, this.default_kernel_config, kernel_config); - } + }; KernelExecOnCells.prototype.transform_json_string_to_kernel_string = function(str, kernel_config) { for (var ii = 0; ii < kernel_config.replacements_json_to_kernel.length; ii++) { @@ -102,7 +102,7 @@ define(function(require, exports, module) { str = str.replace(from, to); } return str; - } + }; /** * construct functions as callbacks for the autoformat cell promise. This @@ -126,7 +126,7 @@ define(function(require, exports, module) { } }; return [on_success, on_failure]; - } + }; KernelExecOnCells.prototype.autoformat_cells = function(indices) { @@ -144,7 +144,7 @@ define(function(require, exports, module) { var callbacks = this.construct_cell_callbacks(cell_index, cell); this.autoformat_text(cell.get_text(), kernel_config).then(callbacks[0], callbacks[1]); } - } + }; KernelExecOnCells.prototype.autoformat_text = function(text, kernel_config) { var that = this; @@ -164,7 +164,8 @@ define(function(require, exports, module) { var formatted_text; try { formatted_text = String(JSON.parse(msg.content.text)); - } catch (err) { + } + catch (err) { return Promise.reject(err); } if (kernel_config.trim_formatted_text) { @@ -179,16 +180,15 @@ define(function(require, exports, module) { }, { silent: false } ); }); - } + }; KernelExecOnCells.prototype.add_toolbar_button = function() { - var that = this; if ($('#' + this.mod_name + '_button').length < 1) { var button_group_id = this.mod_name + '_button'; Jupyter.toolbar.add_buttons_group( [this.cfg.actions.process_selected.name], button_group_id); } - } + }; KernelExecOnCells.prototype.add_keyboard_shortcuts = function() { var new_shortcuts = {}; @@ -196,7 +196,7 @@ define(function(require, exports, module) { new_shortcuts[this.cfg.hotkeys.process_all] = this.cfg.actions.process_all.name; Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(new_shortcuts); Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(new_shortcuts); - } + }; KernelExecOnCells.prototype.register_actions = function() { /** @@ -237,7 +237,7 @@ define(function(require, exports, module) { actions.process_selected, 'process_selected_cells', that.mod_name); actions.process_all.name = Jupyter.keyboard_manager.actions.register( actions.process_all, 'process_all_cells', that.mod_name); - } + }; KernelExecOnCells.prototype.setup_for_new_kernel = function() { var that = this; @@ -276,7 +276,7 @@ define(function(require, exports, module) { alert(err); } else { - console.error(err) + console.error(err); } } @@ -287,7 +287,7 @@ define(function(require, exports, module) { ); } - } + }; KernelExecOnCells.prototype.initialize_plugin = function() { var that = this; @@ -332,8 +332,8 @@ define(function(require, exports, module) { }).catch(function on_error(err) { console.error(that.mod_log_prefix, 'error loading:', err); }); - } + }; exports.define_plugin = KernelExecOnCells; - return {define_plugin: KernelExecOnCells} + return {define_plugin: KernelExecOnCells}; }); From d4e1ffe13fdff9f87ad2ff2b9a3202db3a9cfea8 Mon Sep 17 00:00:00 2001 From: Josh Barnes Date: Tue, 9 May 2017 11:37:44 +0100 Subject: [PATCH 4/4] [lib] ensure each library object has its own config object this effectively prevents other nbextensions from modifying the default config, which for some reason I previously thought might be useful, rather than just potentially dangerous. --- kernel_exec_on_cell.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/kernel_exec_on_cell.js b/kernel_exec_on_cell.js index 1d86372a7..87de93889 100755 --- a/kernel_exec_on_cell.js +++ b/kernel_exec_on_cell.js @@ -15,7 +15,6 @@ define(function(require, exports, module) { function KernelExecOnCells(mod_name, cfg) { this.mod_name = mod_name; - this.cfg = cfg; this.mod_log_prefix = '[' + this.mod_name + ']'; this.mod_edit_shortcuts = {}; this.mod_cmd_shortcuts = {}; @@ -41,13 +40,9 @@ define(function(require, exports, module) { kernel_config_map: {}, actions: null, // to be filled by register_actions }; - // apply defaults to cfg. Don't use jquery extend, as we want cfg to still - // be same object, in case plugin alters it later - for (var key in default_cfg) { - if (!this.cfg.hasOwnProperty(key)) { - this.cfg[key] = default_cfg[key]; - } - } + // extend a new object, to avoid interference with other nbextensions + // derived from the same base class + this.cfg = $.extend(true, {}, cfg, default_cfg); // set default json string, will later be updated from config // before it is parsed into an object this.cfg.kernel_config_map_json = JSON.stringify(this.cfg.kernel_config_map);