Skip to content

Commit

Permalink
Normalize links before they hit renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
rlidwka committed Nov 13, 2014
1 parent b884828 commit d54ed88
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 13 deletions.
9 changes: 9 additions & 0 deletions lib/helpers/normalize_link.js
@@ -0,0 +1,9 @@
'use strict';


var replaceEntities = require('../common/utils').replaceEntities;


module.exports = function normalizeLink(url) {
return encodeURI(decodeURI(replaceEntities(url)));
};
14 changes: 9 additions & 5 deletions lib/helpers/parse_link_destination.js
Expand Up @@ -6,11 +6,12 @@
'use strict';


var unescapeMd = require('../common/utils').unescapeMd;
var normalizeLink = require('./normalize_link');
var unescapeMd = require('../common/utils').unescapeMd;


module.exports = function parseLinkDestination(state, pos) {
var code, level,
var code, level, link,
start = pos,
max = state.posMax;

Expand All @@ -20,8 +21,10 @@ module.exports = function parseLinkDestination(state, pos) {
code = state.src.charCodeAt(pos);
if (code === 0x0A /* \n */) { return false; }
if (code === 0x3E /* > */) {
link = normalizeLink(unescapeMd(state.src.slice(start + 1, pos)));
if (!state.parser.validateLink(link)) { return false; }
state.pos = pos + 1;
state.linkContent = unescapeMd(state.src.slice(start + 1, pos));
state.linkContent = link;
return true;
}
if (code === 0x5C /* \ */ && pos + 1 < max) {
Expand Down Expand Up @@ -67,9 +70,10 @@ module.exports = function parseLinkDestination(state, pos) {

if (start === pos) { return false; }

state.linkContent = unescapeMd(state.src.slice(start, pos));
if (!state.parser.validateLink(state.linkContent)) { return false; }
link = normalizeLink(unescapeMd(state.src.slice(start, pos)));
if (!state.parser.validateLink(link)) { return false; }

state.linkContent = link;
state.pos = pos;
return true;
};
4 changes: 2 additions & 2 deletions lib/renderer.js
Expand Up @@ -147,15 +147,15 @@ rules.paragraph_close = function (tokens, idx /*, options, env */) {

rules.link_open = function (tokens, idx /*, options, env */) {
var title = tokens[idx].title ? (' title="' + escapeHtml(replaceEntities(tokens[idx].title)) + '"') : '';
return '<a href="' + escapeHtml(encodeURI(decodeURI(replaceEntities(tokens[idx].href)))) + '"' + title + '>';
return '<a href="' + escapeHtml(tokens[idx].href) + '"' + title + '>';
};
rules.link_close = function (/* tokens, idx, options, env */) {
return '</a>';
};


rules.image = function (tokens, idx, options /*, env */) {
var src = ' src="' + escapeHtml(encodeURI(tokens[idx].src)) + '"';
var src = ' src="' + escapeHtml(tokens[idx].src) + '"';
var title = tokens[idx].title ? (' title="' + escapeHtml(replaceEntities(tokens[idx].title)) + '"') : '';
var alt = ' alt="' + (tokens[idx].alt ? escapeHtml(replaceEntities(tokens[idx].alt)) : '') + '"';
var suffix = options.xhtmlOut ? ' /' : '';
Expand Down
14 changes: 8 additions & 6 deletions lib/rules_inline/autolink.js
Expand Up @@ -2,7 +2,8 @@

'use strict';

var url_schemas = require('../common/url_schemas');
var url_schemas = require('../common/url_schemas');
var normalizeLink = require('../helpers/normalize_link');


/*eslint max-len:0*/
Expand All @@ -11,7 +12,7 @@ var AUTOLINK_RE = /^<([a-zA-Z.\-]{1,25}):([^<>\x00-\x20]*)>/;


module.exports = function autolink(state, silent) {
var tail, linkMatch, emailMatch, url, pos = state.pos;
var tail, linkMatch, emailMatch, url, fullUrl, pos = state.pos;

if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }

Expand All @@ -25,13 +26,13 @@ module.exports = function autolink(state, silent) {
if (url_schemas.indexOf(linkMatch[1].toLowerCase()) < 0) { return false; }

url = linkMatch[0].slice(1, -1);

fullUrl = normalizeLink(url);
if (!state.parser.validateLink(url)) { return false; }

if (!silent) {
state.push({
type: 'link_open',
href: url,
href: fullUrl,
level: state.level
});
state.push({
Expand All @@ -52,12 +53,13 @@ module.exports = function autolink(state, silent) {

url = emailMatch[0].slice(1, -1);

if (!state.parser.validateLink('mailto:' + url)) { return false; }
fullUrl = normalizeLink('mailto:' + url);
if (!state.parser.validateLink(fullUrl)) { return false; }

if (!silent) {
state.push({
type: 'link_open',
href: 'mailto:' + url,
href: fullUrl,
level: state.level
});
state.push({
Expand Down
16 changes: 16 additions & 0 deletions test/fixtures/remarkable/commonmark_extras.txt
Expand Up @@ -107,3 +107,19 @@ a
<p>a</p>
<?php
.

Normalize link destination, but not text inside it:

.
<http://example.com/α%CE%B2γ%CE%B4>
.
<p><a href="http://example.com/%CE%B1%CE%B2%CE%B3%CE%B4">http://example.com/α%CE%B2γ%CE%B4</a></p>
.

Autolinks do not allow escaping:

.
<http://example.com/\[\>
.
<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
.

0 comments on commit d54ed88

Please sign in to comment.