diff --git a/lib/common/utils.js b/lib/common/utils.js index a230260..855fe2b 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -11,20 +11,18 @@ function isString(obj) { return _class(obj) === '[object String]'; } // function assign(obj /*from1, from2, from3, ...*/) { var sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - var source = sources.shift(); - if (!source) { continue; } + + sources.forEach(function (source) { + if (!source) { return; } if (typeof source !== 'object') { throw new TypeError(source + 'must be object'); } - for (var p in source) { - if (source.hasOwnProperty(p)) { - obj[p] = source[p]; - } - } - } + Object.keys(source).forEach(function (key) { + obj[key] = source[key]; + }); + }); return obj; } @@ -66,18 +64,31 @@ function fromCodePoint(c) { return String.fromCharCode(c); } -var NAMED_ENTITY_RE = /&([a-z][a-z0-9]{1,31});/gi; +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 entities = require('./entities'); +function replaceEntityPattern(match, name) { + var code = 0; + + if (entities.hasOwnProperty(name)) { + return entities[name]; + } else if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) { + code = name[1].toLowerCase() === 'x' ? + parseInt(name.slice(2), 16) + : + parseInt(name.slice(1), 10); + if (isValidEntityCode(code)) { + return fromCodePoint(code); + } + } + return match; +} + function replaceEntities(str) { if (str.indexOf('&') < 0) { return str; } - return str.replace(NAMED_ENTITY_RE, function(match, name) { - if (entities.hasOwnProperty(name)) { - return entities[name]; - } - return match; - }); + return str.replace(NAMED_ENTITY_RE, replaceEntityPattern); } diff --git a/lib/configs/default.js b/lib/configs/default.js index 8081fbd..5c2aa8b 100644 --- a/lib/configs/default.js +++ b/lib/configs/default.js @@ -36,6 +36,7 @@ module.exports = { 'inline', 'references', 'replacements', + 'linkify', 'smartquotes', 'references', 'abbr2' diff --git a/lib/rules_core/replacements.js b/lib/rules_core/replacements.js index 640ecf5..875e902 100644 --- a/lib/rules_core/replacements.js +++ b/lib/rules_core/replacements.js @@ -20,10 +20,7 @@ function replaceScopedAbbr(str) { if (str.indexOf('(') < 0) { return str; } return str.replace(SCOPED_ABBR_RE, function(match, name) { - if (SCOPED_ABBR.hasOwnProperty(name.toLowerCase())) { - return SCOPED_ABBR[name.toLowerCase()]; - } - return match; + return SCOPED_ABBR[name.toLowerCase()]; }); } diff --git a/test/fixtures/remarkable/commonmark_extras.txt b/test/fixtures/remarkable/commonmark_extras.txt index 73eb6af..14ea06d 100644 --- a/test/fixtures/remarkable/commonmark_extras.txt +++ b/test/fixtures/remarkable/commonmark_extras.txt @@ -96,3 +96,14 @@ Not a list item .
1.list
. + + +Coverage. Direcctive can terminate paragraph. + +. +a +a +(bad) +. + + copyright . (c) (C) diff --git a/test/fixtures/remarkable/xss.txt b/test/fixtures/remarkable/xss.txt index c39455e..db98624 100644 --- a/test/fixtures/remarkable/xss.txt +++ b/test/fixtures/remarkable/xss.txt @@ -42,7 +42,7 @@ Should not allow some protocols in links and images . [xss link]("><script>alert("xss")</script>) . - + . diff --git a/test/misc.js b/test/misc.js index fb0598f..deacd3c 100644 --- a/test/misc.js +++ b/test/misc.js @@ -29,6 +29,18 @@ describe('Utils', function () { assert.strictEqual(isValidEntityCode(0x7F), false); }); + it('replaceEntities', function () { + var replaceEntities = require('../lib/common/utils').replaceEntities; + + assert.strictEqual(replaceEntities('&'), '&'); + assert.strictEqual(replaceEntities(' '), ' '); + assert.strictEqual(replaceEntities(' '), ' '); + assert.strictEqual(replaceEntities('&&'), '&&'); + + assert.strictEqual(replaceEntities('&am;'), '&am;'); + assert.strictEqual(replaceEntities(''), ''); + }); + it('assign', function () { var assign = require('../lib/common/utils').assign;