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; });