diff --git a/IPython/html/nbconvert/handlers.py b/IPython/html/nbconvert/handlers.py index 749cd9d..63ba266 100644 --- a/IPython/html/nbconvert/handlers.py +++ b/IPython/html/nbconvert/handlers.py @@ -43,7 +43,7 @@ def respond_zip(handler, name, output, resources): # Prepare the zip file buffer = io.BytesIO() zipf = zipfile.ZipFile(buffer, mode='w', compression=zipfile.ZIP_DEFLATED) - output_filename = os.path.splitext(name)[0] + '.' + resources['output_extension'] + output_filename = os.path.splitext(name)[0] + resources['output_extension'] zipf.writestr(output_filename, cast_bytes(output, 'utf-8')) for filename, data in output_files.items(): zipf.writestr(os.path.basename(filename), data) @@ -96,7 +96,7 @@ class NbconvertFileHandler(IPythonHandler): # Force download if requested if self.get_argument('download', 'false').lower() == 'true': - filename = os.path.splitext(name)[0] + '.' + resources['output_extension'] + filename = os.path.splitext(name)[0] + resources['output_extension'] self.set_header('Content-Disposition', 'attachment; filename="%s"' % filename) diff --git a/IPython/html/static/notebook/js/menubar.js b/IPython/html/static/notebook/js/menubar.js index 5992e0f..9a2814b 100644 --- a/IPython/html/static/notebook/js/menubar.js +++ b/IPython/html/static/notebook/js/menubar.js @@ -69,17 +69,21 @@ define([ MenuBar.prototype._nbconvert = function (format, download) { download = download || false; var notebook_path = this.notebook.notebook_path; - if (this.notebook.dirty) { - this.notebook.save_notebook({async : false}); - } var url = utils.url_join_encode( this.base_url, 'nbconvert', format, notebook_path ) + "?download=" + download.toString(); - - window.open(url); + + var w = window.open() + if (this.notebook.dirty) { + this.notebook.save_notebook().then(function() { + w.location = url; + }); + } else { + w.location = url; + } }; MenuBar.prototype.bind_events = function () { @@ -129,10 +133,6 @@ define([ that._nbconvert('html', false); }); - this.element.find('#download_py').click(function () { - that._nbconvert('python', true); - }); - this.element.find('#download_html').click(function () { that._nbconvert('html', true); }); @@ -308,6 +308,16 @@ define([ this.events.on('checkpoint_created.Notebook', function (event, data) { that.update_restore_checkpoint(that.notebook.checkpoints); }); + + this.events.on('notebook_loaded.Notebook', function() { + var langinfo = that.notebook.metadata.language_info || {}; + that.update_nbconvert_script(langinfo); + }); + + this.events.on('kernel_ready.Kernel', function(event, data) { + var langinfo = data.kernel.info_reply.language_info || {}; + that.update_nbconvert_script(langinfo); + }); }; MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { @@ -340,6 +350,31 @@ define([ ); }); }; + + MenuBar.prototype.update_nbconvert_script = function(langinfo) { + // Set the 'Download as foo' menu option for the relevant language. + var el = this.element.find('#download_script'); + var that = this; + + // Set menu entry text to e.g. "Python (.py)" + var langname = (langinfo.name || 'Script') + langname = langname.charAt(0).toUpperCase()+langname.substr(1) // Capitalise + el.find('a').text(langname + ' ('+(langinfo.file_extension || 'txt')+')'); + + // Unregister any previously registered handlers + el.off('click'); + if (langinfo.nbconvert_exporter) { + // Metadata specifies a specific exporter, e.g. 'python' + el.click(function() { + that._nbconvert(langinfo.nbconvert_exporter, true); + }); + } else { + // Use generic 'script' exporter + el.click(function() { + that._nbconvert('script', true); + }); + } + }; // Backwards compatability. IPython.MenuBar = MenuBar; diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index b2f56b7..e1db7ad 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -1944,7 +1944,7 @@ define([ var start = new Date().getTime(); var that = this; - this.contents.save(this.notebook_path, model).then( + return this.contents.save(this.notebook_path, model).then( $.proxy(this.save_notebook_success, this, start), function (error) { that.events.trigger('notebook_save_failed.Notebook', error); diff --git a/IPython/html/templates/notebook.html b/IPython/html/templates/notebook.html index 4a9a890..1f8b554 100644 --- a/IPython/html/templates/notebook.html +++ b/IPython/html/templates/notebook.html @@ -105,7 +105,7 @@ class="notebook_app"