diff --git a/benchmark/benchloop.js b/benchmark/benchloop.js new file mode 100644 index 0000000..b4f5fe2 --- /dev/null +++ b/benchmark/benchloop.js @@ -0,0 +1,37 @@ + +'use strict'; + +/* IMPORT */ + +var fs = require ('fs'), + path = require ('path'), + benchmark = require ('benchloop'), + mit = require ('..'); + +/* HELPERS */ + +var SAMPLES_PATH = path.join (__dirname, 'samples'); +var md = mit ('commonmark'); + +/* BENCHMARK */ + +benchmark.defaultOptions = Object.assign (benchmark.defaultOptions, { + iterations: 50, + log: 'compact' +}); + +fs.readdirSync (SAMPLES_PATH).forEach (function (sample) { + + var samplePath = path.join (SAMPLES_PATH, sample), + content = fs.readFileSync (samplePath, 'utf-8'); + + benchmark ({ + name: sample, + fn: function () { + md.render (content); + } + }); + +}); + +benchmark.summary (); diff --git a/benchmark/profile.js b/benchmark/profile.js index ddc378b..1cd44ac 100755 --- a/benchmark/profile.js +++ b/benchmark/profile.js @@ -14,6 +14,8 @@ var md = require('../')({ // var data = fs.readFileSync(path.join(__dirname, '/samples/lorem1.txt'), 'utf8'); var data = fs.readFileSync(path.join(__dirname, '../test/fixtures/commonmark/spec.txt'), 'utf8'); -for (var i = 0; i < 20; i++) { +console.time('profile'); +for (var i = 0; i < 200; i++) { md.render(data); } +console.timeEnd('profile'); diff --git a/lib/common/utils.js b/lib/common/utils.js index 712cd29..15f0207 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -13,6 +13,14 @@ function has(object, key) { return _hasOwnProperty.call(object, key); } +var _repeat = String.prototype.repeat || function (count) { + return new Array(count + 1).join (this); +}; + +function repeat(str, count) { + return _repeat.call (str, count); +} + // Merge objects // function assign(obj /*from1, from2, from3, ...*/) { @@ -237,7 +245,7 @@ function isMdAsciiPunct(ch) { } } -// Hepler to unify [reference labels]. +// Helper to unify [reference labels]. // function normalizeReference(str) { // Trim and collapse whitespace @@ -302,6 +310,7 @@ exports.lib.ucmicro = require('uc.micro'); exports.assign = assign; exports.isString = isString; exports.has = has; +exports.repeat = repeat; exports.unescapeMd = unescapeMd; exports.unescapeAll = unescapeAll; exports.isValidEntityCode = isValidEntityCode; diff --git a/lib/renderer.js b/lib/renderer.js index 5a173fe..0b1f700 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -44,9 +44,14 @@ default_rules.fence = function (tokens, idx, options, env, slf) { highlighted, i, arr, tmpAttrs, tmpToken; if (info) { - arr = info.split(/(\s+)/g); - langName = arr[0]; - langAttrs = arr.slice(2).join(''); + if (!/\s/.test (info)) { + langName = info; + langAttrs = ''; + } else { + arr = info.split(/(\s+)/g); + langName = arr[0]; + langAttrs = arr.slice(2).join(''); + } } if (options.highlight) { @@ -55,7 +60,7 @@ default_rules.fence = function (tokens, idx, options, env, slf) { highlighted = escapeHtml(token.content); } - if (highlighted.indexOf('
'
+ + highlighted
+ + '
\n';
+ }
+
return ''
+ highlighted
+ '
\n';
@@ -293,13 +304,17 @@ Renderer.prototype.renderInline = function (tokens, options, env) {
* instead of simple escaping.
**/
Renderer.prototype.renderInlineAsText = function (tokens, options, env) {
- var result = '';
+ var type, token,
+ result = '';
for (var i = 0, len = tokens.length; i < len; i++) {
- if (tokens[i].type === 'text') {
- result += tokens[i].content;
- } else if (tokens[i].type === 'image') {
- result += this.renderInlineAsText(tokens[i].children, options, env);
+ token = tokens[i];
+ type = token.type;
+
+ if (type === 'text') {
+ result += token.content;
+ } else if (type === 'image') {
+ result += this.renderInlineAsText(token.children, options, env);
}
}
@@ -317,17 +332,18 @@ Renderer.prototype.renderInlineAsText = function (tokens, options, env) {
* this method directly.
**/
Renderer.prototype.render = function (tokens, options, env) {
- var i, len, type,
+ var i, len, type, token,
result = '',
rules = this.rules;
for (i = 0, len = tokens.length; i < len; i++) {
- type = tokens[i].type;
+ token = tokens[i];
+ type = token.type;
if (type === 'inline') {
- result += this.renderInline(tokens[i].children, options, env);
+ result += this.renderInline(token.children, options, env);
} else if (typeof rules[type] !== 'undefined') {
- result += rules[tokens[i].type](tokens, i, options, env, this);
+ result += rules[type](tokens, i, options, env, this);
} else {
result += this.renderToken(tokens, i, options, env);
}
diff --git a/lib/rules_block/blockquote.js b/lib/rules_block/blockquote.js
index a02699a..2cb13fc 100644
--- a/lib/rules_block/blockquote.js
+++ b/lib/rules_block/blockquote.js
@@ -6,6 +6,9 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function blockquote(state, startLine, endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var adjustTab,
ch,
i,
@@ -30,9 +33,6 @@ module.exports = function blockquote(state, startLine, endLine, silent) {
pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
// check the block quote marker
if (state.src.charCodeAt(pos++) !== 0x3E/* > */) { return false; }
diff --git a/lib/rules_block/code.js b/lib/rules_block/code.js
index a83db11..92ab183 100644
--- a/lib/rules_block/code.js
+++ b/lib/rules_block/code.js
@@ -4,10 +4,10 @@
module.exports = function code(state, startLine, endLine/*, silent*/) {
- var nextLine, last, token;
-
if (state.sCount[startLine] - state.blkIndent < 4) { return false; }
+ var nextLine, last, token;
+
last = nextLine = startLine + 1;
while (nextLine < endLine) {
diff --git a/lib/rules_block/fence.js b/lib/rules_block/fence.js
index 44f1538..9d31e6a 100644
--- a/lib/rules_block/fence.js
+++ b/lib/rules_block/fence.js
@@ -4,14 +4,14 @@
module.exports = function fence(state, startLine, endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var marker, len, params, nextLine, mem, token, markup,
haveEndMarker = false,
pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
if (pos + 3 > max) { return false; }
marker = state.src.charCodeAt(pos);
diff --git a/lib/rules_block/heading.js b/lib/rules_block/heading.js
index 9863f48..38c1ae5 100644
--- a/lib/rules_block/heading.js
+++ b/lib/rules_block/heading.js
@@ -6,13 +6,13 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function heading(state, startLine, endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var ch, level, tmp, token,
pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
ch = state.src.charCodeAt(pos);
if (ch !== 0x23/* # */ || pos >= max) { return false; }
diff --git a/lib/rules_block/hr.js b/lib/rules_block/hr.js
index a3bb14e..c5f005f 100644
--- a/lib/rules_block/hr.js
+++ b/lib/rules_block/hr.js
@@ -3,16 +3,17 @@
'use strict';
var isSpace = require('../common/utils').isSpace;
+var repeat = require('../common/utils').repeat;
module.exports = function hr(state, startLine, endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var marker, cnt, ch, token,
pos = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
marker = state.src.charCodeAt(pos++);
// Check hr marker
@@ -39,7 +40,7 @@ module.exports = function hr(state, startLine, endLine, silent) {
token = state.push('hr', 'hr', 0);
token.map = [ startLine, state.line ];
- token.markup = Array(cnt + 1).join(String.fromCharCode(marker));
+ token.markup = repeat (String.fromCharCode(marker), cnt);
return true;
};
diff --git a/lib/rules_block/html_block.js b/lib/rules_block/html_block.js
index 256b595..cf63b82 100644
--- a/lib/rules_block/html_block.js
+++ b/lib/rules_block/html_block.js
@@ -21,14 +21,14 @@ var HTML_SEQUENCES = [
module.exports = function html_block(state, startLine, endLine, silent) {
- var i, nextLine, token, lineText,
- pos = state.bMarks[startLine] + state.tShift[startLine],
- max = state.eMarks[startLine];
+ if (!state.md.options.html) { return false; }
// if it's indented more than 3 spaces, it should be a code block
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
- if (!state.md.options.html) { return false; }
+ var i, nextLine, token, lineText,
+ pos = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine];
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
diff --git a/lib/rules_block/lheading.js b/lib/rules_block/lheading.js
index 19bdc39..4d51b48 100644
--- a/lib/rules_block/lheading.js
+++ b/lib/rules_block/lheading.js
@@ -4,13 +4,13 @@
module.exports = function lheading(state, startLine, endLine/*, silent*/) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var content, terminate, i, l, token, pos, max, level, marker,
nextLine = startLine + 1, oldParentType,
terminatorRules = state.md.block.ruler.getRules('paragraph');
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
oldParentType = state.parentType;
state.parentType = 'paragraph'; // use paragraph to match terminatorRules
diff --git a/lib/rules_block/list.js b/lib/rules_block/list.js
index f6d7c8d..1f21ea1 100644
--- a/lib/rules_block/list.js
+++ b/lib/rules_block/list.js
@@ -11,7 +11,6 @@ function skipBulletListMarker(state, startLine) {
var marker, pos, max, ch;
pos = state.bMarks[startLine] + state.tShift[startLine];
- max = state.eMarks[startLine];
marker = state.src.charCodeAt(pos++);
// Check bullet
@@ -21,6 +20,8 @@ function skipBulletListMarker(state, startLine) {
return -1;
}
+ max = state.eMarks[startLine];
+
if (pos < max) {
ch = state.src.charCodeAt(pos);
@@ -84,13 +85,14 @@ function skipOrderedListMarker(state, startLine) {
}
function markTightParagraphs(state, idx) {
- var i, l,
+ var i, l, token,
level = state.level + 2;
for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
- if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
+ token = state.tokens[i];
+ if (token.level === level && token.type === 'paragraph_open') {
state.tokens[i + 2].hidden = true;
- state.tokens[i].hidden = true;
+ token.hidden = true;
i += 2;
}
}
@@ -98,6 +100,21 @@ function markTightParagraphs(state, idx) {
module.exports = function list(state, startLine, endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
+ // Special case:
+ // - item 1
+ // - item 2
+ // - item 3
+ // - item 4
+ // - this one is a paragraph continuation
+ if (state.listIndent >= 0 &&
+ state.sCount[startLine] - state.listIndent >= 4 &&
+ state.sCount[startLine] < state.blkIndent) {
+ return false;
+ }
+
var ch,
contentStart,
i,
@@ -129,21 +146,6 @@ module.exports = function list(state, startLine, endLine, silent) {
isTerminatingParagraph = false,
tight = true;
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
- // Special case:
- // - item 1
- // - item 2
- // - item 3
- // - item 4
- // - this one is a paragraph continuation
- if (state.listIndent >= 0 &&
- state.sCount[startLine] - state.listIndent >= 4 &&
- state.sCount[startLine] < state.blkIndent) {
- return false;
- }
-
// limit conditions when list can interrupt
// a paragraph (validation mode only)
if (silent && state.parentType === 'paragraph') {
diff --git a/lib/rules_block/reference.js b/lib/rules_block/reference.js
index 78daa26..285d75e 100644
--- a/lib/rules_block/reference.js
+++ b/lib/rules_block/reference.js
@@ -6,6 +6,9 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function reference(state, startLine, _endLine, silent) {
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
+
var ch,
destEndPos,
destEndLineNo,
@@ -27,9 +30,6 @@ module.exports = function reference(state, startLine, _endLine, silent) {
max = state.eMarks[startLine],
nextLine = startLine + 1;
- // if it's indented more than 3 spaces, it should be a code block
- if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
-
if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false; }
// Simple check to quickly interrupt scan on [link](url) at the start of line.
diff --git a/lib/rules_block/state_block.js b/lib/rules_block/state_block.js
index e42cb4b..51e555b 100644
--- a/lib/rules_block/state_block.js
+++ b/lib/rules_block/state_block.js
@@ -4,6 +4,7 @@
var Token = require('../token');
var isSpace = require('../common/utils').isSpace;
+var repeat = require('../common/utils').repeat;
function StateBlock(src, md, env, tokens) {
@@ -173,15 +174,14 @@ StateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {
// cut lines range from source.
StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {
- var i, lineIndent, ch, first, last, queue, lineStart,
+ var i, lineIndent, ch, first, last, lineStart,
+ lines = '',
line = begin;
if (begin >= end) {
- return '';
+ return lines;
}
- queue = new Array(end - begin);
-
for (i = 0; line < end; line++, i++) {
lineIndent = 0;
lineStart = first = this.bMarks[line];
@@ -215,13 +215,13 @@ StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF
if (lineIndent > indent) {
// partially expanding tabs in code blocks, e.g '\t\tfoobar'
// with indent=2 becomes ' \tfoobar'
- queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);
+ lines += repeat (' ', lineIndent - indent) + this.src.slice(first, last);
} else {
- queue[i] = this.src.slice(first, last);
+ lines += this.src.slice(first, last);
}
}
- return queue.join('');
+ return lines;
};
// re-export Token class to use in block rules
diff --git a/lib/rules_block/table.js b/lib/rules_block/table.js
index 89ed65c..e59cd9b 100644
--- a/lib/rules_block/table.js
+++ b/lib/rules_block/table.js
@@ -50,20 +50,20 @@ function escapedSplit(str) {
module.exports = function table(state, startLine, endLine, silent) {
- var ch, lineText, pos, i, l, nextLine, columns, columnCount, token,
- aligns, t, tableLines, tbodyLines, oldParentType, terminate,
- terminatorRules;
-
// should have at least two lines
if (startLine + 2 > endLine) { return false; }
- nextLine = startLine + 1;
+ var nextLine = startLine + 1;
if (state.sCount[nextLine] < state.blkIndent) { return false; }
// if it's indented more than 3 spaces, it should be a code block
if (state.sCount[nextLine] - state.blkIndent >= 4) { return false; }
+ var ch, lineText, pos, i, l, columns, columnCount, token,
+ aligns, t, tableLines, tbodyLines, oldParentType, terminate,
+ terminatorRules;
+
// first character of the second line should be '|', '-', ':',
// and no other characters are allowed but spaces;
// basically, this is the equivalent of /^[-:|][-:|\s]*$/ regexp
diff --git a/lib/rules_core/linkify.js b/lib/rules_core/linkify.js
index 7c3ffc8..405b4a0 100644
--- a/lib/rules_core/linkify.js
+++ b/lib/rules_core/linkify.js
@@ -17,13 +17,13 @@ function isLinkClose(str) {
module.exports = function linkify(state) {
+ if (!state.md.options.linkify) { return; }
+
var i, j, l, tokens, token, currentToken, nodes, ln, text, pos, lastPos,
level, htmlLinkLevel, url, fullUrl, urlText,
blockTokens = state.tokens,
links;
- if (!state.md.options.linkify) { return; }
-
for (j = 0, l = blockTokens.length; j < l; j++) {
if (blockTokens[j].type !== 'inline' ||
!state.md.linkify.pretest(blockTokens[j].content)) {
diff --git a/lib/rules_core/normalize.js b/lib/rules_core/normalize.js
index ad196cd..b1e3dee 100644
--- a/lib/rules_core/normalize.js
+++ b/lib/rules_core/normalize.js
@@ -4,18 +4,21 @@
// https://spec.commonmark.org/0.29/#line-ending
-var NEWLINES_RE = /\r\n?|\n/g;
-var NULL_RE = /\0/g;
+var CRLF_RE = /\r\n?/g;
module.exports = function normalize(state) {
- var str;
+ var src = state.src;
- // Normalize newlines
- str = state.src.replace(NEWLINES_RE, '\n');
+ // Normalize CRLF newlines
+ src = src.replace(CRLF_RE, '\n');
// Replace NULL characters
- str = str.replace(NULL_RE, '\uFFFD');
+ for (var i = 0, l = src.length; i < l; i++) {
+ if (!src.charCodeAt(i)) {
+ src = src.slice (0, i) + '\uFFFD' + src.slice (i + 1);
+ }
+ }
- state.src = str;
+ state.src = src;
};
diff --git a/lib/rules_core/smartquotes.js b/lib/rules_core/smartquotes.js
index e96fc71..4ec2dd9 100644
--- a/lib/rules_core/smartquotes.js
+++ b/lib/rules_core/smartquotes.js
@@ -26,7 +26,7 @@ function process_inlines(tokens, state) {
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
- thisLevel = tokens[i].level;
+ thisLevel = token.level;
for (j = stack.length - 1; j >= 0; j--) {
if (stack[j].level <= thisLevel) { break; }
diff --git a/lib/rules_inline/autolink.js b/lib/rules_inline/autolink.js
index 66deb90..cd8c6f9 100644
--- a/lib/rules_inline/autolink.js
+++ b/lib/rules_inline/autolink.js
@@ -9,11 +9,11 @@ var AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$/;
module.exports = function autolink(state, silent) {
+ if (state.src.charCodeAt(state.pos) !== 0x3C/* < */) { return false; }
+
var url, fullUrl, token, ch, start, max,
pos = state.pos;
- if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
-
start = state.pos;
max = state.posMax;
diff --git a/lib/rules_inline/backticks.js b/lib/rules_inline/backticks.js
index b9c9ddb..bd122fc 100644
--- a/lib/rules_inline/backticks.js
+++ b/lib/rules_inline/backticks.js
@@ -4,12 +4,13 @@
module.exports = function backtick(state, silent) {
- var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,
- pos = state.pos,
- ch = state.src.charCodeAt(pos);
+ var ch = state.src.charCodeAt(state.pos);
if (ch !== 0x60/* ` */) { return false; }
+ var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,
+ pos = state.pos;
+
start = pos;
pos++;
max = state.posMax;
diff --git a/lib/rules_inline/emphasis.js b/lib/rules_inline/emphasis.js
index c140d2c..7f8bc3d 100644
--- a/lib/rules_inline/emphasis.js
+++ b/lib/rules_inline/emphasis.js
@@ -6,14 +6,14 @@
// Insert each marker as a separate text token, and add it to delimiter list
//
module.exports.tokenize = function emphasis(state, silent) {
- var i, scanned, token,
- start = state.pos,
- marker = state.src.charCodeAt(start);
-
if (silent) { return false; }
+ var marker = state.src.charCodeAt(state.pos);
+
if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false; }
+ var i, scanned, token;
+
scanned = state.scanDelims(state.pos, marker === 0x2A);
for (i = 0; i < scanned.length; i++) {
diff --git a/lib/rules_inline/entity.js b/lib/rules_inline/entity.js
index 6fcc889..ee0beb0 100644
--- a/lib/rules_inline/entity.js
+++ b/lib/rules_inline/entity.js
@@ -13,9 +13,9 @@ var NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
module.exports = function entity(state, silent) {
- var ch, code, match, pos = state.pos, max = state.posMax;
+ if (state.src.charCodeAt(state.pos) !== 0x26/* & */) { return false; }
- if (state.src.charCodeAt(pos) !== 0x26/* & */) { return false; }
+ var ch, code, match, pos = state.pos, max = state.posMax;
if (pos + 1 < max) {
ch = state.src.charCodeAt(pos + 1);
diff --git a/lib/rules_inline/escape.js b/lib/rules_inline/escape.js
index 229ead0..d0e38ab 100644
--- a/lib/rules_inline/escape.js
+++ b/lib/rules_inline/escape.js
@@ -13,9 +13,9 @@ for (var i = 0; i < 256; i++) { ESCAPED.push(0); }
module.exports = function escape(state, silent) {
- var ch, pos = state.pos, max = state.posMax;
+ if (state.src.charCodeAt(state.pos) !== 0x5C/* \ */) { return false; }
- if (state.src.charCodeAt(pos) !== 0x5C/* \ */) { return false; }
+ var ch, pos = state.pos, max = state.posMax;
pos++;
diff --git a/lib/rules_inline/html_inline.js b/lib/rules_inline/html_inline.js
index 28c7980..67e206f 100644
--- a/lib/rules_inline/html_inline.js
+++ b/lib/rules_inline/html_inline.js
@@ -14,18 +14,18 @@ function isLetter(ch) {
module.exports = function html_inline(state, silent) {
- var ch, match, max, token,
- pos = state.pos;
-
if (!state.md.options.html) { return false; }
// Check start
- max = state.posMax;
- if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||
- pos + 2 >= max) {
+ var max = state.posMax;
+ if (state.src.charCodeAt(state.pos) !== 0x3C/* < */ ||
+ state.pos + 2 >= max) {
return false;
}
+ var ch, match, token,
+ pos = state.pos;
+
// Quick fail on second char
ch = state.src.charCodeAt(pos + 1);
if (ch !== 0x21/* ! */ &&
diff --git a/lib/rules_inline/image.js b/lib/rules_inline/image.js
index 53edd32..9075033 100644
--- a/lib/rules_inline/image.js
+++ b/lib/rules_inline/image.js
@@ -7,6 +7,9 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function image(state, silent) {
+ if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }
+ if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }
+
var attrs,
code,
content,
@@ -24,9 +27,6 @@ module.exports = function image(state, silent) {
oldPos = state.pos,
max = state.posMax;
- if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }
- if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }
-
labelStart = state.pos + 2;
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false);
diff --git a/lib/rules_inline/link.js b/lib/rules_inline/link.js
index 1d242bf..1183e1b 100644
--- a/lib/rules_inline/link.js
+++ b/lib/rules_inline/link.js
@@ -7,6 +7,8 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function link(state, silent) {
+ if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false; }
+
var attrs,
code,
label,
@@ -23,8 +25,6 @@ module.exports = function link(state, silent) {
start = state.pos,
parseReference = true;
- if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false; }
-
labelStart = state.pos + 1;
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true);
diff --git a/lib/rules_inline/newline.js b/lib/rules_inline/newline.js
index 14aa42d..f756337 100644
--- a/lib/rules_inline/newline.js
+++ b/lib/rules_inline/newline.js
@@ -6,11 +6,13 @@ var isSpace = require('../common/utils').isSpace;
module.exports = function newline(state, silent) {
- var pmax, max, pos = state.pos;
+ if (state.src.charCodeAt(state.pos) !== 0x0A/* \n */) { return false; }
- if (state.src.charCodeAt(pos) !== 0x0A/* \n */) { return false; }
+ var pmax, max,
+ pending = state.pending,
+ pos = state.pos;
- pmax = state.pending.length - 1;
+ pmax = pending.length - 1;
max = state.posMax;
// ' \n' -> hardbreak
@@ -18,12 +20,12 @@ module.exports = function newline(state, silent) {
// Pending string is stored in concat mode, indexed lookups will cause
// convertion to flat mode.
if (!silent) {
- if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {
- if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {
- state.pending = state.pending.replace(/ +$/, '');
+ if (pmax >= 0 && pending.charCodeAt(pmax) === 0x20) {
+ if (pmax >= 1 && pending.charCodeAt(pmax - 1) === 0x20) {
+ state.pending = pending.replace(/ +$/, '');
state.push('hardbreak', 'br', 0);
} else {
- state.pending = state.pending.slice(0, -1);
+ state.pending = pending.slice(0, -1);
state.push('softbreak', 'br', 0);
}
diff --git a/lib/rules_inline/strikethrough.js b/lib/rules_inline/strikethrough.js
index cb8944f..7d45e82 100644
--- a/lib/rules_inline/strikethrough.js
+++ b/lib/rules_inline/strikethrough.js
@@ -6,14 +6,14 @@
// Insert each marker as a separate text token, and add it to delimiter list
//
module.exports.tokenize = function strikethrough(state, silent) {
- var i, scanned, token, len, ch,
- start = state.pos,
- marker = state.src.charCodeAt(start);
-
if (silent) { return false; }
+ var marker = state.src.charCodeAt(state.pos);
+
if (marker !== 0x7E/* ~ */) { return false; }
+ var i, scanned, token, len, ch;
+
scanned = state.scanDelims(state.pos, true);
len = scanned.length;
ch = String.fromCharCode(marker);
diff --git a/lib/rules_inline/text_collapse.js b/lib/rules_inline/text_collapse.js
index 390b0fe..44f5615 100644
--- a/lib/rules_inline/text_collapse.js
+++ b/lib/rules_inline/text_collapse.js
@@ -10,26 +10,27 @@
module.exports = function text_collapse(state) {
- var curr, last,
+ var curr, last, token,
level = 0,
tokens = state.tokens,
- max = state.tokens.length;
+ max = tokens.length;
for (curr = last = 0; curr < max; curr++) {
+ token = tokens[curr];
// re-calculate levels after emphasis/strikethrough turns some text nodes
// into opening/closing tags
- if (tokens[curr].nesting < 0) level--; // closing tag
- tokens[curr].level = level;
- if (tokens[curr].nesting > 0) level++; // opening tag
+ if (token.nesting < 0) level--; // closing tag
+ token.level = level;
+ if (token.nesting > 0) level++; // opening tag
- if (tokens[curr].type === 'text' &&
+ if (token.type === 'text' &&
curr + 1 < max &&
tokens[curr + 1].type === 'text') {
// collapse two adjacent text nodes
- tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;
+ tokens[curr + 1].content = token.content + tokens[curr + 1].content;
} else {
- if (curr !== last) { tokens[last] = tokens[curr]; }
+ if (curr !== last) { tokens[last] = token; }
last++;
}
diff --git a/package.json b/package.json
index 22ee3de..28bf2fc 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"@rollup/plugin-node-resolve": "^10.0.0",
"ansi": "^0.3.0",
"autoprefixer-stylus": "^1.0.0",
+ "benchloop": "^1.3.2",
"benchmark": "~2.1.0",
"chai": "^4.2.0",
"coveralls": "^3.0.4",