From 26a22b182a492c6ec5012a03a5362d6c97e054b0 Mon Sep 17 00:00:00 2001
From: Vitaly Puzrin
Date: Sat, 8 Nov 2014 18:52:23 +0300
Subject: [PATCH] Fixed replaceEntities, default preset, improved coverage
---
lib/common/utils.js | 43 ++++++++++++-------
lib/configs/default.js | 1 +
lib/rules_core/replacements.js | 5 +--
.../fixtures/remarkable/commonmark_extras.txt | 11 +++++
test/fixtures/remarkable/typographer.txt | 7 +++
test/fixtures/remarkable/xss.txt | 2 +-
test/misc.js | 12 ++++++
7 files changed, 60 insertions(+), 21 deletions(-)
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>)
.
-xss link
+xss link
.
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;