diff --git a/lib/marked.js b/lib/marked.js index 1ecfc3ee8d..1fe8ba45ac 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -554,68 +554,9 @@ inline.normal = merge({}, inline); inline.pedantic = merge({}, inline.normal, { strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/, - /* Original link re: /^!?\[(label)\]\(\s*?(?:\s+(['"][\s\S]*?['"]))?\s*\)/ - * This captures the spec reasonably well but is vulnerable to REDOS. - * Instead we use a custom parser that follows the RegExp.exec semantics. */ - link: { - exec: function (s) { - // [TEXT](DESTINATION) - var generalLinkRe = edit(/^!?\[(label)\]\((.*?)\)/) - .replace('label', inline._label) - .getRegex(); - - // destination: DESTINATION from generalLinkRe - // returns [destination, title]: no angle-brackets on destination, no quotes on title - function splitIntoDestinationAndTitle (destination) { - function unwrapAngleBrackets (str) { - if (str.match(/^<.*>$/)) { - str = str.slice(1, -1); - } - return str; - } - - // Valid DESTINATIONs, in decreasing specificity. - var destinationAndTitleRe = /^([^'"(]*[^\s])\s+(['"(].*['")])/; - var destinationRe = /^(?)/; - var parsingRegexes = [destinationAndTitleRe, destinationRe]; - - var match = false; - for (var i = 0; i < parsingRegexes.length; i++) { - match = parsingRegexes[i].exec(destination); - if (match) { - break; - } - } - - if (!match) { - return null; - } - - var dest = match[1]; - var title = match[2] || ''; // Not all parsingRegexes have 2 groups. - - // Format dest. - dest = dest.trim(); - dest = unwrapAngleBrackets(dest); - - return [dest, title]; - } - - var fullMatch = generalLinkRe.exec(s); - if (!fullMatch) { - return null; - } - - var text = fullMatch[1]; - var destination = fullMatch[2]; - - var destinationAndTitle = splitIntoDestinationAndTitle(destination); - if (!destinationAndTitle) { - return null; - } - return [fullMatch[0], text, destinationAndTitle[0], destinationAndTitle[1]]; - } - }, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', inline._label) + .getRegex(), reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) .replace('label', inline._label) .getRegex() @@ -762,8 +703,19 @@ InlineLexer.prototype.output = function(src) { src = src.substring(cap[0].length); this.inLink = true; href = cap[2]; - href = href[0] === '<' ? href.substring(1, href.length - 1) : href; - title = cap[3] ? cap[3].substring(1, cap[3].length - 1) : cap[3]; + if (this.options.pedantic) { + link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + + if (link) { + href = link[1]; + title = link[3]; + } else { + title = ''; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim().replace(/^<([\s\S]*)>$/, '$1'); out += this.outputLink(cap, { href: InlineLexer.escapes(href), title: InlineLexer.escapes(title) diff --git a/test/new/link_lt.html b/test/new/link_lt.html new file mode 100644 index 0000000000..ea48caa950 --- /dev/null +++ b/test/new/link_lt.html @@ -0,0 +1 @@ +

URL

diff --git a/test/new/link_lt.md b/test/new/link_lt.md new file mode 100644 index 0000000000..f4f9adddc9 --- /dev/null +++ b/test/new/link_lt.md @@ -0,0 +1 @@ +[URL](