Browse Source

Fixed entities in text for new spec

pull/14/head
Vitaly Puzrin 10 years ago
parent
commit
e44a781160
  1. 2134
      lib/common/entities.js
  2. 30
      lib/helpers.js
  3. 25
      lib/lexer_inline/entity.js
  4. 12
      lib/renderer.js

2134
lib/common/entities.js

File diff suppressed because it is too large

30
lib/helpers.js

@ -108,6 +108,34 @@ function unescapeMd(str) {
return str.replace(UNESCAPE_MD_RE, '$1');
}
function isValidEntityCode(c) {
/*eslint no-bitwise:0*/
// broken sequence
if (c >= 0xD800 && c <= 0xDFFF) { return false; }
if (c >= 0xF5 && c <= 0xFF) { return false; }
if (c === 0xC0 || c === 0xC1) { return false; }
// never used
if (c >= 0xFDD0 && c <= 0xFDEF) { return false; }
if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false; }
// control codes
if (c <= 0x1F) { return false; }
if (c >= 0x7F && c <= 0x9F) { return false; }
// out of range
if (c > 0x10FFFF) { return false; }
return true;
}
function fromCodePoint(c) {
/*eslint no-bitwise:0*/
if (c > 0xffff) {
c -= 0x10000;
var surrogate1 = 0xd800 + (c >> 10),
surrogate2 = 0xdc00 + (c & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
}
return String.fromCharCode(c);
}
exports.isWhiteSpace = isWhiteSpace;
exports.isEmpty = isEmpty;
@ -119,3 +147,5 @@ exports.skipCharsBack = skipCharsBack;
exports.escapeHtml = escapeHtml;
exports.unescapeMd = unescapeMd;
exports.escapeHtmlKeepEntities = escapeHtmlKeepEntities;
exports.isValidEntityCode = isValidEntityCode;
exports.fromCodePoint = fromCodePoint;

25
lib/lexer_inline/entity.js

@ -1,13 +1,19 @@
// Proceess html entity - &#123, &#xAF, &quot
// Proceess html entity - &#123;, &#xAF;, &quot;, ...
'use strict';
var entities = require('../common/entities');
var escapeHtml = require('../helpers').escapeHtml;
var isValidEntityCode = require('../helpers').isValidEntityCode;
var fromCodePoint = require('../helpers').fromCodePoint;
var DIGITAL_RE = /^(?:x[a-f0-9]{1,8}|[0-9]{1,8});/i;
var NAMED_RE = /^[a-z][a-z0-9]{1,31};/i;
var NAMED_RE = /^([a-z][a-z0-9]{1,31});/i;
module.exports = function entity(state) {
var ch, match, pos = state.pos, max = state.posMax;
var ch, code, match, pos = state.pos, max = state.posMax;
if (state.src.charCodeAt(pos) !== 0x26/* & */) { return false; }
@ -24,16 +30,19 @@ module.exports = function entity(state) {
if (ch === 0x23 /* # */) {
match = state.src.slice(pos + 1).match(DIGITAL_RE);
if (match) {
state.pending += '&#' + match[0];
code = match[0][0].toLowerCase() === 'x' ? parseInt(match[0].slice(1), 16) : parseInt(match[0], 10);
state.pending += isValidEntityCode(code) ? escapeHtml(fromCodePoint(code)) : fromCodePoint(0xFFFD);
state.pos += match[0].length + 2;
return true;
}
} else {
match = state.src.slice(pos).match(NAMED_RE);
if (match) {
state.pending += '&' + match[0];
state.pos += match[0].length + 1;
return true;
if (entities.hasOwnProperty(match[1])) {
state.pending += escapeHtml(entities[match[1]]);
state.pos += match[0].length + 1;
return true;
}
}
}

12
lib/renderer.js

@ -7,6 +7,13 @@ var escapeHtmlKeepEntities = require('./helpers').escapeHtmlKeepEntities;
var unescapeMd = require('./helpers').unescapeMd;
function escapeUrl(str) {
try {
return encodeURI(str);
} catch (__) {}
return '';
}
// check if we need to hide '\n' before next token
function getBreak(tokens, idx) {
if (++idx < tokens.length &&
@ -17,7 +24,6 @@ function getBreak(tokens, idx) {
return '\n';
}
var rules = {};
@ -101,7 +107,7 @@ rules.paragraph_close = function (tokens, idx /*, options*/) {
rules.link_open = function (tokens, idx /*, options*/) {
var title = tokens[idx].title ? (' title="' + escapeHtmlKeepEntities(tokens[idx].title) + '"') : '';
return '<a href="' + escapeHtmlKeepEntities(tokens[idx].href) + '"' + title + '>';
return '<a href="' + escapeHtml(escapeUrl(tokens[idx].href)) + '"' + title + '>';
};
rules.link_close = function (/*tokens, idx, options*/) {
return '</a>';
@ -109,7 +115,7 @@ rules.link_close = function (/*tokens, idx, options*/) {
rules.image = function (tokens, idx, options) {
var src = ' src="' + escapeHtmlKeepEntities(tokens[idx].src) + '"';
var src = ' src="' + escapeHtml(escapeUrl(tokens[idx].src)) + '"';
var title = tokens[idx].title ? (' title="' + escapeHtmlKeepEntities(tokens[idx].title) + '"') : '';
var alt = ' alt="' + (tokens[idx].alt ? escapeHtmlKeepEntities(tokens[idx].alt) : '') + '"';
var suffix = options.xhtml ? ' /' : '';

Loading…
Cancel
Save