Browse Source

Assorted fixes & speed opts

pull/14/head
Vitaly Puzrin 10 years ago
parent
commit
d87eeb2ab0
  1. 19
      lib/helpers.js
  2. 2
      lib/lexer_block/fences.js
  3. 2
      lib/lexer_block/heading.js
  4. 2
      lib/lexer_block/lheading.js
  5. 2
      lib/lexer_block/paragraph.js
  6. 13
      lib/lexer_inline.js
  7. 11
      lib/lexer_inline/autolink.js
  8. 2
      lib/lexer_inline/escape.js
  9. 2
      lib/lexer_inline/newline.js
  10. 10
      lib/renderer.js
  11. 6
      lib/state_inline.js
  12. 36
      test/fixtures/stmd/bad.txt
  13. 24
      test/fixtures/stmd/good.txt

19
lib/helpers.js

@ -91,6 +91,23 @@ function escapeHtml(str) {
return str; return str;
} }
function escapeHtmlKeepEntities(str) {
if (str.indexOf('&') >= 0) {
str = str.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&');
}
if (str.indexOf('<') >= 0) { str = str.replace(/</g, '&lt;'); }
if (str.indexOf('>') >= 0) { str = str.replace(/>/g, '&gt;'); }
if (str.indexOf('"') >= 0) { str = str.replace(/"/g, '&quot;'); }
return str;
}
var UNESCAPE_MD_RE = /\\([\\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;
function unescapeMd(str) {
if (str.indexOf('\\') < 0) { return str; }
return str.replace(UNESCAPE_MD_RE, '$1');
}
exports.isWhiteSpace = isWhiteSpace; exports.isWhiteSpace = isWhiteSpace;
exports.isEmpty = isEmpty; exports.isEmpty = isEmpty;
@ -100,3 +117,5 @@ exports.skipChars = skipChars;
exports.getLines = getLines; exports.getLines = getLines;
exports.skipCharsBack = skipCharsBack; exports.skipCharsBack = skipCharsBack;
exports.escapeHtml = escapeHtml; exports.escapeHtml = escapeHtml;
exports.unescapeMd = unescapeMd;
exports.escapeHtmlKeepEntities = escapeHtmlKeepEntities;

2
lib/lexer_block/fences.js

@ -85,7 +85,7 @@ module.exports = function fences(state, startLine, endLine, silent) {
state.tokens.push({ state.tokens.push({
type: 'fence', type: 'fence',
params: params ? params.split(/\s+/g) : [], params: params,
content: getLines(state, startLine + 1, nextLine, len, true) content: getLines(state, startLine + 1, nextLine, len, true)
}); });

2
lib/lexer_block/heading.js

@ -55,7 +55,7 @@ module.exports = function heading(state, startLine, endLine, silent) {
if (pos < max) { if (pos < max) {
state.tokens.push({ state.tokens.push({
type: 'inline', type: 'inline',
content: state.src.slice(pos, max) content: state.src.slice(pos, max).trim()
}); });
} }
state.tokens.push({ type: 'heading_close', level: level }); state.tokens.push({ type: 'heading_close', level: level });

2
lib/lexer_block/lheading.js

@ -40,7 +40,7 @@ module.exports = function lheading(state, startLine, endLine, silent) {
state.tokens.push({ type: 'heading_open', level: marker === 0x3D/* = */ ? 1 : 2 }); state.tokens.push({ type: 'heading_open', level: marker === 0x3D/* = */ ? 1 : 2 });
state.tokens.push({ state.tokens.push({
type: 'inline', type: 'inline',
content: state.src.slice(pos, max) content: state.src.slice(pos, max).trim()
}); });
state.tokens.push({ type: 'heading_close', level: marker === 0x3D/* = */ ? 1 : 2 }); state.tokens.push({ type: 'heading_close', level: marker === 0x3D/* = */ ? 1 : 2 });

2
lib/lexer_block/paragraph.js

@ -37,7 +37,7 @@ module.exports = function paragraph(state, startLine/*, endLine*/) {
state.tokens.push({ type: 'paragraph_open' }); state.tokens.push({ type: 'paragraph_open' });
state.tokens.push({ state.tokens.push({
type: 'inline', type: 'inline',
content: getLines(state, startLine, nextLine, state.blkIndent, false) content: getLines(state, startLine, nextLine, state.blkIndent, false).trim()
}); });
state.tokens.push({ type: 'paragraph_close' }); state.tokens.push({ type: 'paragraph_close' });

13
lib/lexer_inline.js

@ -152,21 +152,10 @@ LexerInline.prototype.tokenize = function (state) {
// Parse input string. // Parse input string.
// //
LexerInline.prototype.parse = function (str, options) { LexerInline.prototype.parse = function (str, options) {
var state = new StateInline(str, this, options), var state = new StateInline(str, this, options);
tokens = state.tokens,
len, tok;
this.tokenize(state); this.tokenize(state);
// If last token is text - strip tailing spaces
len = tokens.length;
if (len) {
tok = tokens[len - 1];
if (tok.type === 'text' && tok.content.charCodeAt(tok.content.length - 1) === 0x20) {
tok.content = tok.content.replace(/ +$/, '');
}
}
return state.tokens; return state.tokens;
}; };

11
lib/lexer_inline/autolink.js

@ -1,7 +1,8 @@
// Process autolinks '<protocol:...>' // Process autolinks '<protocol:...>'
var escape = require('../helpers').escapeHtml; var escapeHtml = require('../helpers').escapeHtml;
/*eslint max-len:0*/ /*eslint max-len:0*/
var EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/; var EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;
@ -24,11 +25,11 @@ module.exports = function autolink(state) {
state.push({ state.push({
type: 'link_open', type: 'link_open',
href: escape(linkMatch[0].slice(1, -1)) href: linkMatch[0].slice(1, -1)
}); });
state.push({ state.push({
type: 'text', type: 'text',
content: escape(linkMatch[0].slice(1, -1)) content: escapeHtml(linkMatch[0].slice(1, -1))
}); });
state.push({ type: 'link_close' }); state.push({ type: 'link_close' });
@ -41,11 +42,11 @@ module.exports = function autolink(state) {
if (emailMatch) { if (emailMatch) {
state.tokens.push({ state.tokens.push({
type: 'link_open', type: 'link_open',
href: 'mailto:' + escape(emailMatch[0].slice(1, -1)) href: 'mailto:' + emailMatch[0].slice(1, -1)
}); });
state.tokens.push({ state.tokens.push({
type: 'text', type: 'text',
content: escape(emailMatch[0].slice(1, -1)) content: escapeHtml(emailMatch[0].slice(1, -1))
}); });
state.tokens.push({ type: 'link_close' }); state.tokens.push({ type: 'link_close' });

2
lib/lexer_inline/escape.js

@ -1,6 +1,6 @@
// Proceess escaped chars and hardbreaks // Proceess escaped chars and hardbreaks
var ESCAPED = '\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-]' var ESCAPED = '\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-'
.split('') .split('')
.map(function(ch) { return ch.charCodeAt(0); }); .map(function(ch) { return ch.charCodeAt(0); });

2
lib/lexer_inline/newline.js

@ -26,7 +26,7 @@ module.exports = function escape(state) {
} }
if (pmax > 0 && state.pending.charCodeAt(pmax) === 0x20) { if (pmax > 0 && state.pending.charCodeAt(pmax) === 0x20) {
state.pending = state.pending.slice(0, -1); state.pending = state.pending.replace(/ +$/, '');
} }
state.pending += '\n'; state.pending += '\n';

10
lib/renderer.js

@ -3,6 +3,8 @@
var assign = require('object-assign'); var assign = require('object-assign');
var escapeHtml = require('./helpers').escapeHtml; var escapeHtml = require('./helpers').escapeHtml;
var escapeHtmlKeepEntities = require('./helpers').escapeHtmlKeepEntities;
var unescapeMd = require('./helpers').unescapeMd;
// check if we need to hide '\n' before next token // check if we need to hide '\n' before next token
@ -40,9 +42,11 @@ rules.fence = function (tokens, idx, options) {
var token = tokens[idx]; var token = tokens[idx];
var langMark = ''; var langMark = '';
var langPrefix = options.codeLangPrefix || ''; var langPrefix = options.codeLangPrefix || '';
var params;
if (token.params.length) { if (token.params) {
langMark = ' class="' + langPrefix + escapeHtml(token.params[0]) + '"'; params = token.params.split(/ +/g);
langMark = ' class="' + langPrefix + escapeHtmlKeepEntities(unescapeMd(params[0])) + '"';
} }
return '<pre><code' + langMark + '>' return '<pre><code' + langMark + '>'
@ -96,7 +100,7 @@ rules.paragraph_close = function (tokens, idx /*, options*/) {
rules.link_open = function (tokens, idx /*, options*/) { rules.link_open = function (tokens, idx /*, options*/) {
return '<a href="' + tokens[idx].href + '">'; return '<a href="' + escapeHtmlKeepEntities(tokens[idx].href) + '">';
}; };
rules.link_close = function (/*tokens, idx, options*/) { rules.link_close = function (/*tokens, idx, options*/) {
return '</a>'; return '</a>';

6
lib/state_inline.js

@ -16,11 +16,7 @@ function StateInline(src, lexer, options) {
StateInline.prototype.pushText = function () { StateInline.prototype.pushText = function () {
var pending = this.pending; var pending = this.pending;
// strip leading spaces from the first token.
// others will be stripped by logic in `newline` rule
if (this.tokens.length === 0 && pending.charCodeAt(0) === 0x20) {
pending = pending.replace(/^ +/, '');
}
this.tokens.push({ this.tokens.push({
type: 'text', type: 'text',
content: pending content: pending

36
test/fixtures/stmd/bad.txt

@ -718,24 +718,6 @@ error:
<p>[foo]: /bar* &quot;ti*tle&quot;</p> <p>[foo]: /bar* &quot;ti*tle&quot;</p>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3718
.
``` foo\+bar
foo
```
.
<pre><code class="language-foo+bar">foo
</code></pre>
.
error:
<pre><code class="language-foo\+bar">foo
</code></pre>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3791 src line: 3791
@ -781,24 +763,6 @@ error:
<p>[foo]: /f&ouml;&ouml; &quot;f&ouml;&ouml;&quot;</p> <p>[foo]: /f&ouml;&ouml; &quot;f&ouml;&ouml;&quot;</p>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3811
.
``` f&ouml;&ouml;
foo
```
.
<pre><code class="language-f&ouml;&ouml;">foo
</code></pre>
.
error:
<pre><code class="language-f&amp;ouml;&amp;ouml;">foo
</code></pre>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3954 src line: 3954

24
test/fixtures/stmd/good.txt

@ -2668,6 +2668,18 @@ src line: 3688
<p><a href="http://google.com?find=\*">http://google.com?find=\*</a></p> <p><a href="http://google.com?find=\*">http://google.com?find=\*</a></p>
. .
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3718
.
``` foo\+bar
foo
```
.
<pre><code class="language-foo+bar">foo
</code></pre>
.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3736 src line: 3736
@ -2722,6 +2734,18 @@ src line: 3781
<p>&MadeUpEntity;</p> <p>&MadeUpEntity;</p>
. .
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3811
.
``` f&ouml;&ouml;
foo
```
.
<pre><code class="language-f&ouml;&ouml;">foo
</code></pre>
.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src line: 3822 src line: 3822

Loading…
Cancel
Save