diff --git a/notebook/static/base/js/utils.js b/notebook/static/base/js/utils.js index cf9ed588a..f693056ea 100644 --- a/notebook/static/base/js/utils.js +++ b/notebook/static/base/js/utils.js @@ -453,6 +453,22 @@ define([ return txt; } + // Remove characters that are overridden by backspace characters + function fixBackspace(txt) { + var tmp = txt; + do { + txt = tmp; + // Cancel out anything-but-newline followed by backspace + tmp = txt.replace(/[^\n]\x08/gm, ''); + } while (tmp.length < txt.length); + return txt; + } + + // Remove characters overridden by backspace and carriage return + function fixOverwrittenChars(txt) { + return fixCarriageReturn(fixBackspace(txt)); + } + // Locate any URLs and convert them to a anchor tag function autoLinkUrls(txt) { return txt.replace(/(^|\s)(https?|ftp)(:[^'"<>\s]+)/gi, @@ -972,6 +988,8 @@ define([ uuid : uuid, fixConsole : fixConsole, fixCarriageReturn : fixCarriageReturn, + fixBackspace : fixBackspace, + fixOverwrittenChars: fixOverwrittenChars, autoLinkUrls : autoLinkUrls, points_to_pixels : points_to_pixels, get_body_data : get_body_data, diff --git a/notebook/static/notebook/js/outputarea.js b/notebook/static/notebook/js/outputarea.js index cea3b8b65..51375c189 100644 --- a/notebook/static/notebook/js/outputarea.js +++ b/notebook/static/notebook/js/outputarea.js @@ -504,7 +504,7 @@ define([ // latest output was in the same stream, // so append to it instead of making a new output. // escape ANSI & HTML specials: - last.text = utils.fixCarriageReturn(last.text + json.text); + last.text = utils.fixOverwrittenChars(last.text + json.text); var pre = this.element.find('div.'+subclass).last().find('pre'); var html = utils.fixConsole(last.text); html = utils.autoLinkUrls(html); @@ -659,7 +659,7 @@ define([ var append_text = function (data, md, element) { var type = 'text/plain'; var toinsert = this.create_output_subarea(md, "output_text", type); - data = utils.fixCarriageReturn(data); + data = utils.fixOverwrittenChars(data); // escape ANSI & HTML specials in plaintext: data = utils.fixConsole(data); data = utils.autoLinkUrls(data); diff --git a/notebook/static/notebook/js/pager.js b/notebook/static/notebook/js/pager.js index f292a8a98..3d63baed8 100644 --- a/notebook/static/notebook/js/pager.js +++ b/notebook/static/notebook/js/pager.js @@ -157,7 +157,7 @@ define([ * The only user content injected with this HTML call is escaped by * the fixConsole() method. */ - this.pager_element.find(".container").append($('
').html(utils.fixConsole(utils.fixCarriageReturn(text)))); + this.pager_element.find(".container").append($('').html(utils.fixConsole(utils.fixOverwrittenChars(text)))); }; Pager.prototype.append = function (htm) { diff --git a/notebook/tests/base/utils.js b/notebook/tests/base/utils.js index e772e5eb7..0038e58cd 100644 --- a/notebook/tests/base/utils.js +++ b/notebook/tests/base/utils.js @@ -1,4 +1,5 @@ casper.notebook_test(function () { + // Test fixConsole // Note, \u001b is the unicode notation of octal \033 which is not officially in js var input = [ "\u001b[0m[\u001b[0minfo\u001b[0m] \u001b[0mtext\u001b[0m", @@ -29,7 +30,25 @@ casper.notebook_test(function () { }, input); this.test.assertEquals(result, output, "IPython.utils.fixConsole() handles [0m correctly"); - + + // Test fixOverwrittenChars + var overwriting_test_cases = [ + {input: "ABC\rDEF", result: "DEF"}, + {input: "ABC\r\nDEF", result: "ABC\nDEF"}, + {input: "123\b456", result: "12456"}, + {input: "123\n\b456", result: "123\n\b456"}, + {input: "\b456", result: "\b456"} + ]; + + var that = this; + overwriting_test_cases.forEach(function(testcase){ + var result = that.evaluate(function (input) { + return IPython.utils.fixOverwrittenChars(input); + }, testcase.input); + that.test.assertEquals(result, testcase.result, "Overwriting characters processed"); + }); + + // Test load_extensions this.thenEvaluate(function() { define('nbextensions/a', [], function() { window.a = true; }); define('nbextensions/c', [], function() { window.c = true; });