From 8d512c22ac740c3955654ba7b3dd7b3316055a54 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Tue, 7 Aug 2012 23:53:24 +0200 Subject: [PATCH 1/2] fix markdown linking of images, also improve tests grammatically + 1 js syntax error --- .../javascripts/app/helpers/text_formatter.js | 3 ++- .../app/helpers/text_formatter_spec.js | 22 ++++++++++++++----- spec/javascripts/bookmarklet-spec.js | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js index 0759a6665..5bd45b932 100644 --- a/app/assets/javascripts/app/helpers/text_formatter.js +++ b/app/assets/javascripts/app/helpers/text_formatter.js @@ -20,12 +20,13 @@ // regex copied from: http://daringfireball.net/2010/07/improved_regex_for_matching_urls (slightly modified) var urlRegex = /(^|\s)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/gi; text = text.replace(urlRegex, function(wholematch, space, url) { + if( url.match(/^[^\w]/) ) return wholematch; // evil witchcraft, noop return space+"<"+url+">"; }); // process links // regex copied from: https://code.google.com/p/pagedown/source/browse/Markdown.Converter.js#1198 (and slightly expanded) - var linkRegex = /(\[.*\]:\s)?(<|\()((https?|ftp):\/\/[^\/'">\s][^'">\s]+)(>|\))/gi; + var linkRegex = /(\[.*\]:\s)?(<|\()((https?|ftp):\/\/[^\/'">\s][^'">\s]+?)(>|\))/gi; text = text.replace(linkRegex, function() { var unicodeUrl = arguments[3]; var addr = parse_url(unicodeUrl); diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js index aa1da7e31..d5f9b1f18 100644 --- a/spec/javascripts/app/helpers/text_formatter_spec.js +++ b/spec/javascripts/app/helpers/text_formatter_spec.js @@ -46,10 +46,10 @@ describe("app.helpers.textFormatter", function(){ }) }); - context("non-ascii urls", function() { + context("non-ascii url", function() { beforeEach(function() { this.evilUrls = [ - "http://www.bürgerentscheid-krankenhäuser.de", // example from issue #2665 + "http://www.bürgerentscheid-krankenhäuser.de", // example from issue #2665 "http://bündnis-für-krankenhäuser.de/wp-content/uploads/2011/11/cropped-logohp.jpg", "http://موقع.وزارة-الاتصالات.مصر/", // example from #3082 "http:///scholar.google.com/citations?view_op=top_venues", @@ -64,14 +64,14 @@ describe("app.helpers.textFormatter", function(){ ]; }); - it("correctly encode to punycode", function() { + it("correctly encodes to punycode", function() { _.each(this.evilUrls, function(url, num) { var text = this.formatter.markdownify( "<" + url + ">" ); expect(text).toContain(this.asciiUrls[num]); }, this); }); - it("don't break link texts", function() { + it("doesn't break link texts", function() { var linkText = "check out this awesome link!"; var text = this.formatter.markdownify( "["+linkText+"]("+this.evilUrls[0]+")" ); @@ -79,7 +79,7 @@ describe("app.helpers.textFormatter", function(){ expect(text).toContain(linkText); }); - it("don't break reference style links", function() { + it("doesn't break reference style links", function() { var postContent = "blabla blab [my special link][1] bla blabla\n\n[1]: "+this.evilUrls[0]+" and an optional title)"; var text = this.formatter.markdownify(postContent); @@ -89,12 +89,22 @@ describe("app.helpers.textFormatter", function(){ it("can be used as img src", function() { var postContent = "![logo]("+ this.evilUrls[1] +")"; - var niceImg = '"'+ this.asciiUrls[1] +'"'; // the "" are from src="" + var niceImg = 'src="'+ this.asciiUrls[1] +'"'; // the "" are from src="" var text = this.formatter.markdownify(postContent); expect(text).toContain(niceImg); }); + it("doesn't break linked images", function() { + var postContent = "I am linking an image here [![some-alt-text]("+this.evilUrls[1]+")]("+this.evilUrls[3]+")"; + var text = this.formatter.markdownify(postContent); + var linked_image = 'src="'+this.asciiUrls[1]+'"'; + var image_link = 'href="'+this.asciiUrls[3]+'"'; + + expect(text).toContain(linked_image); + expect(text).toContain(image_link); + }); + }); }) diff --git a/spec/javascripts/bookmarklet-spec.js b/spec/javascripts/bookmarklet-spec.js index 10a32dd6d..c776b9e1a 100644 --- a/spec/javascripts/bookmarklet-spec.js +++ b/spec/javascripts/bookmarklet-spec.js @@ -33,7 +33,7 @@ describe("bookmarklet", function() { _.defer(function() { expect($("#publisher #status_message_fake_text").val() == "").toBeFalsy(); expect($("#publisher #status_message_text").val() == "").toBeFalsy(); - }; + }); }); }); From 6613522097a841922b80c0efd1cdc3da6cf85633 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Wed, 8 Aug 2012 00:20:21 +0200 Subject: [PATCH 2/2] implement "special symbols" (switch certain strings for utf-8 symbols), fixes #3140 --- .../javascripts/app/helpers/text_formatter.js | 24 +++++++++++++++ .../app/helpers/text_formatter_spec.js | 29 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js index 5bd45b932..12d140c33 100644 --- a/app/assets/javascripts/app/helpers/text_formatter.js +++ b/app/assets/javascripts/app/helpers/text_formatter.js @@ -53,6 +53,30 @@ return text; }); + // make nice little utf-8 symbols + converter.hooks.chain("preConversion", function(text) { + var input_strings = [ + "<->", "->", "<-", + "(c)", "(r)", "(tm)", + "<3" + ]; + var output_symbols = [ + "↔", "→", "←", + "©", "®", "™", + "♥" + ]; + // quote function from: http://stackoverflow.com/a/494122 + var quote = function(str) { + return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); + }; + + _.each(input_strings, function(str, idx) { + var r = new RegExp(quote(str), "gi"); + text = text.replace(r, output_symbols[idx]); + }); + return text; + }); + converter.hooks.chain("postConversion", function (text) { return text.replace(/(\"(?:(?:http|https):\/\/)?[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?\")(\>)/g, '$1 target="_blank">') }); diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js index d5f9b1f18..1d41d3aa9 100644 --- a/spec/javascripts/app/helpers/text_formatter_spec.js +++ b/spec/javascripts/app/helpers/text_formatter_spec.js @@ -46,6 +46,35 @@ describe("app.helpers.textFormatter", function(){ }) }); + context("symbol conversion", function() { + beforeEach(function() { + this.input_strings = [ + "->", "<-", "<->", + "(c)", "(r)", "(tm)", + "<3" + ]; + this.output_symbols = [ + "→", "←", "↔", + "©", "®", "™", + "♥" + ]; + }); + + it("correctly converts the input strings to their corresponding output symbol", function() { + _.each(this.input_strings, function(str, idx) { + var text = this.formatter.markdownify(str); + expect(text).toContain(this.output_symbols[idx]); + }, this); + }); + + it("converts all symbols at once", function() { + var text = this.formatter.markdownify(this.input_strings.join(" ")); + _.each(this.output_symbols, function(sym) { + expect(text).toContain(sym); + }); + }); + }); + context("non-ascii url", function() { beforeEach(function() { this.evilUrls = [