diff --git a/lib/common/utils.js b/lib/common/utils.js index 2faa6a1..0e05b14 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -41,15 +41,6 @@ function arrayReplaceAt(src, pos, newElements) { //////////////////////////////////////////////////////////////////////////////// -var UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g; - -function unescapeMd(str) { - if (str.indexOf('\\') < 0) { return str; } - return str.replace(UNESCAPE_MD_RE, '$1'); -} - -//////////////////////////////////////////////////////////////////////////////// - function isValidEntityCode(c) { /*eslint no-bitwise:0*/ // broken sequence @@ -79,8 +70,11 @@ function fromCodePoint(c) { return String.fromCharCode(c); } -var NAMED_ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi; + +var UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g; +var NAMED_ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi; var DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i; +var UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + NAMED_ENTITY_RE.source, 'gi'); var entities = require('./entities'); function replaceEntityPattern(match, name) { @@ -106,6 +100,20 @@ function replaceEntities(str) { return str.replace(NAMED_ENTITY_RE, replaceEntityPattern); } +function unescapeMd(str) { + if (str.indexOf('\\') < 0) { return str; } + return str.replace(UNESCAPE_MD_RE, '$1'); +} + +function unescapeAll(str) { + if (str.indexOf('\\') < 0 && str.indexOf('&') < 0) { return str; } + + return str.replace(UNESCAPE_ALL_RE, function(match, escaped, entity) { + if (escaped) { return escaped; } + return replaceEntityPattern(match, entity); + }); +} + //////////////////////////////////////////////////////////////////////////////// var HTML_ESCAPE_TEST_RE = /[&<>"]/; @@ -142,7 +150,7 @@ var encode = require('mdurl/encode'); // - (?) punicode for domain mame (but encodeURI seems to work in real world) // function normalizeLink(url) { - return encode(replaceEntities(url)); + return encode(url); } //////////////////////////////////////////////////////////////////////////////// @@ -248,6 +256,7 @@ exports.assign = assign; exports.isString = isString; exports.has = has; exports.unescapeMd = unescapeMd; +exports.unescapeAll = unescapeAll; exports.isValidEntityCode = isValidEntityCode; exports.fromCodePoint = fromCodePoint; exports.replaceEntities = replaceEntities; diff --git a/lib/helpers/parse_link_destination.js b/lib/helpers/parse_link_destination.js index 57a75fb..91a6821 100644 --- a/lib/helpers/parse_link_destination.js +++ b/lib/helpers/parse_link_destination.js @@ -4,7 +4,7 @@ var normalizeLink = require('../common/utils').normalizeLink; -var unescapeMd = require('../common/utils').unescapeMd; +var unescapeAll = require('../common/utils').unescapeAll; module.exports = function parseLinkDestination(str, pos, max) { @@ -25,7 +25,7 @@ module.exports = function parseLinkDestination(str, pos, max) { if (code === 0x0A /* \n */) { return result; } if (code === 0x3E /* > */) { result.pos = pos + 1; - result.str = normalizeLink(unescapeMd(str.slice(start + 1, pos))); + result.str = normalizeLink(unescapeAll(str.slice(start + 1, pos))); result.ok = true; return result; } @@ -72,7 +72,7 @@ module.exports = function parseLinkDestination(str, pos, max) { if (start === pos) { return result; } - result.str = normalizeLink(unescapeMd(str.slice(start, pos))); + result.str = normalizeLink(unescapeAll(str.slice(start, pos))); result.lines = lines; result.pos = pos; result.ok = true; diff --git a/test/fixtures/markdown-it/commonmark_extras.txt b/test/fixtures/markdown-it/commonmark_extras.txt index 192b6a3..515922f 100644 --- a/test/fixtures/markdown-it/commonmark_extras.txt +++ b/test/fixtures/markdown-it/commonmark_extras.txt @@ -124,6 +124,21 @@ Multiline title in definitions: . +Escaping entities in links: + +. +[](<">) + +[](<\">) + +[](<\\">) +. +

+

+

+. + + Coverage. Directive can terminate paragraph. . a