From 612c0ccccba5f63399528125cb93335dbf996a9b Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Thu, 22 Aug 2013 18:03:01 -0400 Subject: [PATCH] FIX: Autolinking within a list --- .../discourse/dialects/autolink_dialect.js | 53 ++++++------------- .../discourse/dialects/mention_dialect.js | 16 ++++-- test/javascripts/components/markdown_test.js | 13 +++-- 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/discourse/dialects/autolink_dialect.js b/app/assets/javascripts/discourse/dialects/autolink_dialect.js index 086e41d67..4846abd68 100644 --- a/app/assets/javascripts/discourse/dialects/autolink_dialect.js +++ b/app/assets/javascripts/discourse/dialects/autolink_dialect.js @@ -14,51 +14,32 @@ Discourse.Dialect.on("register", function(event) { Parses out links from HTML. @method autoLink - @param {Markdown.Block} block the block to examine - @param {Array} next the next blocks in the sequence - @return {Array} the JsonML containing the markup or undefined if nothing changed. + @param {String} text the text match + @param {Array} match the match found + @param {Array} prev the previous jsonML + @return {Array} an array containing how many chars we've replaced and the jsonML content for it. @namespace Discourse.Dialect **/ - dialect.block['autolink'] = function autoLink(block, next) { + dialect.inline['http'] = dialect.inline['www'] = function autoLink(text, match, prev) { + + // We only care about links on boundaries + if (prev && (prev.length > 0)) { + var last = prev[prev.length - 1]; + if (typeof last === "string" && (!last.match(/\s$/))) { return; } + } + var pattern = /(^|\s)((?:https?:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.])(?:[^\s()<>]+|\([^\s()<>]+\))+(?:\([^\s()<>]+\)|[^`!()\[\]{};:'".,<>?«»“”‘’\s]))/gm, - result, - remaining = block, - m; - - var pushIt = function(p) { result.push(p) }; - - while (m = pattern.exec(remaining)) { - result = result || ['p']; + m = pattern.exec(text); + if (m) { var url = m[2], - urlIndex = remaining.indexOf(url), - before = remaining.slice(0, urlIndex); + displayUrl = m[2]; - if (before.match(/\[\d+\]/)) { return; } - - pattern.lastIndex = 0; - remaining = remaining.slice(urlIndex + url.length); - - if (before) { - this.processInline(before).forEach(pushIt); - } - - var displayUrl = url; if (url.match(/^www/)) { url = "http://" + url; } - result.push(['a', {href: url}, displayUrl]); - - if (remaining && remaining.match(/\n/)) { - next.unshift(MD.mk_block(remaining)); - remaining = []; - } + return [m[0].length, ['a', {href: url}, displayUrl]]; } - if (result) { - if (remaining.length) { - this.processInline(remaining).forEach(pushIt); - } - return [result]; - } }; + }); \ No newline at end of file diff --git a/app/assets/javascripts/discourse/dialects/mention_dialect.js b/app/assets/javascripts/discourse/dialects/mention_dialect.js index 29eef5f37..914e52dd7 100644 --- a/app/assets/javascripts/discourse/dialects/mention_dialect.js +++ b/app/assets/javascripts/discourse/dialects/mention_dialect.js @@ -11,8 +11,17 @@ Discourse.Dialect.on("register", function(event) { var dialect = event.dialect, MD = event.MD; - dialect.inline['@'] = function(text, match, prev) { - var args = Array.prototype.slice.call(arguments); + /** + Parses out @username mentions. + + @method parseMentions + @param {String} text the text match + @param {Array} match the match found + @param {Array} prev the previous jsonML + @return {Array} an array containing how many chars we've replaced and the jsonML content for it. + @namespace Discourse.Dialect + **/ + dialect.inline['@'] = function parseMentions(text, match, prev) { // We only care about mentions on word boundaries if (prev && (prev.length > 0)) { @@ -25,8 +34,7 @@ Discourse.Dialect.on("register", function(event) { if (m) { var username = m[1], - mentionLookup = dialect.options.mentionLookup || Discourse.Mention.lookupCache, - index = prev.indexOf(username); + mentionLookup = dialect.options.mentionLookup || Discourse.Mention.lookupCache; if (mentionLookup(username.substr(1))) { return [username.length, ['a', {'class': 'mention', href: Discourse.getURL("/users/") + username.substr(1).toLowerCase()}, username]]; diff --git a/test/javascripts/components/markdown_test.js b/test/javascripts/components/markdown_test.js index f60bc7b4c..ddaee7fa5 100644 --- a/test/javascripts/components/markdown_test.js +++ b/test/javascripts/components/markdown_test.js @@ -38,6 +38,10 @@ test("Line Breaks", function() { test("Links", function() { + cooked("EvilTrout: http://eviltrout.com", + '

EvilTrout: http://eviltrout.com

', + "autolinks a URL"); + cooked("Youtube: http://www.youtube.com/watch?v=1MrpeBRkM5A", '

Youtube: http://www.youtube.com/watch?v=1MrpeBRkM5A

', "allows links to contain query params"); @@ -58,10 +62,6 @@ test("Links", function() { '

Atwood: http://www.codinghorror.com

', "autolinks a URL with http://www"); - cooked("EvilTrout: http://eviltrout.com", - '

EvilTrout: http://eviltrout.com

', - "autolinks a URL"); - cooked("EvilTrout: http://eviltrout.com hello", '

EvilTrout: http://eviltrout.com hello

', "autolinks with trailing text"); @@ -78,6 +78,11 @@ test("Links", function() { "

Here's a tweet:
https://twitter.com/evil_trout/status/345954894420787200

", "It doesn't strip the new line."); + cooked("1. View @eviltrout's profile here: http://meta.discourse.org/users/eviltrout/activity\nnext line.", + "
  1. View @eviltrout's profile here: http://meta.discourse.org/users/eviltrout/activity
    next line.
", + "allows autolinking within a list without inserting a paragraph."); + + cooked("[3]: http://eviltrout.com", "", "It doesn't autolink markdown link references"); cooked("http://discourse.org and http://discourse.org/another_url and http://www.imdb.com/name/nm2225369",