Add tokenLists and use in filterTokens for ~10% time reduction.

This commit is contained in:
David Anson 2015-06-12 09:37:11 -07:00
parent 096f4d7afd
commit 3e208b7bc5
2 changed files with 26 additions and 22 deletions

View file

@ -58,6 +58,7 @@ function lintContent(content, config) {
// Parse content into tokens and lines
var tokens = md.parse(content, {});
var lines = content.split(shared.newLineRe);
var tokenLists = {};
// Annotate tokens with line/lineNumber
tokens.forEach(function forToken(token) {
if (token.map) {
@ -76,10 +77,15 @@ function lintContent(content, config) {
}
});
}
if (!tokenLists[token.type]) {
tokenLists[token.type] = [];
}
tokenLists[token.type].push(token);
});
// Create parameters for rules
var params = {
"tokens": tokens,
"tokenLists": tokenLists,
"lines": lines
};
// Merge rules/tags and sanitize config

View file

@ -32,19 +32,15 @@ function unorderedListStyleFor(token) {
}
// Calls the provided function for each matching token
function filterTokens(tokens, type, callback) {
tokens.forEach(function forToken(token) {
if (token.type === type) {
callback(token);
}
});
function filterTokens(params, type, callback) {
(params.tokenLists[type] || []).forEach(callback);
}
// Calls the provided function for each line (with context)
function forEachLine(params, callback) {
// Identify lines in code blocks
var codeLines = [];
filterTokens(params.tokens, "code_block", function forToken(token) {
filterTokens(params, "code_block", function forToken(token) {
for (var i = token.map[0]; i < token.map[1]; i++) {
codeLines.push(i);
}
@ -63,9 +59,11 @@ function forEachLine(params, callback) {
// Calls the provided function for each specified inline child token
function forEachInlineChild(params, type, callback) {
filterTokens(params.tokens, "inline", function forToken(token) {
filterTokens(token.children, type, function forChild(child) {
callback(child, token);
filterTokens(params, "inline", function forToken(token) {
token.children.forEach(function forChild(child) {
if (child.type === type) {
callback(child, token);
}
});
});
}
@ -131,7 +129,7 @@ module.exports = [
"tags": [ "headers" ],
"func": function MD001(params, errors) {
var prevLevel = 0;
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
var level = parseInt(token.tag.slice(1), 10);
if (prevLevel && (level > prevLevel + 1)) {
errors.push(token.lineNumber);
@ -164,7 +162,7 @@ module.exports = [
"tags": [ "headers" ],
"func": function MD003(params, errors) {
var style = params.options.style || "consistent";
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
if (style === "consistent") {
style = headingStyleFor(token);
}
@ -324,7 +322,7 @@ module.exports = [
"tags": [ "code" ],
"func": function MD014(params, errors) {
[ "code_block", "fence" ].forEach(function forType(type) {
filterTokens(params.tokens, type, function forToken(token) {
filterTokens(params, type, function forToken(token) {
if (token.content && token.content.split(shared.newLineRe)
.every(function forLine(line) {
return !line || /^\$\s/.test(line);
@ -354,7 +352,7 @@ module.exports = [
"desc": "Multiple spaces after hash on atx style header",
"tags": [ "headers", "atx", "spaces" ],
"func": function MD019(params, errors) {
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
if ((headingStyleFor(token) === "atx") &&
/^#+\s\s/.test(token.line)) {
errors.push(token.lineNumber);
@ -382,7 +380,7 @@ module.exports = [
"desc": "Multiple spaces inside hashes on closed atx style header",
"tags": [ "headers", "atx_closed", "spaces" ],
"func": function MD021(params, errors) {
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
if ((headingStyleFor(token) === "atx_closed") &&
(/^#+\s\s/.test(token.line) || /\s\s#+$/.test(token.line))) {
errors.push(token.lineNumber);
@ -433,7 +431,7 @@ module.exports = [
"desc": "Headers must start at the beginning of the line",
"tags": [ "headers", "spaces" ],
"func": function MD023(params, errors) {
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
if (/^\s/.test(token.line)) {
errors.push(token.lineNumber);
}
@ -463,7 +461,7 @@ module.exports = [
"tags": [ "headers" ],
"func": function MD025(params, errors) {
var hasTopLevelHeading = false;
filterTokens(params.tokens, "heading_open", function forToken(token) {
filterTokens(params, "heading_open", function forToken(token) {
if (token.tag === "h1") {
if (hasTopLevelHeading) {
errors.push(token.lineNumber);
@ -623,7 +621,7 @@ module.exports = [
"desc": "Inline HTML",
"tags": [ "html" ],
"func": function MD033(params, errors) {
filterTokens(params.tokens, "html_block", function forToken(token) {
filterTokens(params, "html_block", function forToken(token) {
errors.push(token.lineNumber);
});
forEachInlineChild(params, "html_inline", function forToken(token) {
@ -637,7 +635,7 @@ module.exports = [
"desc": "Bare URL used",
"tags": [ "links", "url" ],
"func": function MD034(params, errors) {
filterTokens(params.tokens, "inline", function forToken(token) {
filterTokens(params, "inline", function forToken(token) {
var inLink = false;
token.children.forEach(function forChild(child) {
if (child.type === "link_open") {
@ -660,7 +658,7 @@ module.exports = [
"tags": [ "hr" ],
"func": function MD035(params, errors) {
var style = params.options.style || "consistent";
filterTokens(params.tokens, "hr", function forToken(token) {
filterTokens(params, "hr", function forToken(token) {
if (style === "consistent") {
style = token.line;
}
@ -735,7 +733,7 @@ module.exports = [
"desc": "Spaces inside link text",
"tags": [ "whitespace", "links" ],
"func": function MD039(params, errors) {
filterTokens(params.tokens, "inline", function forToken(token) {
filterTokens(params, "inline", function forToken(token) {
var inLink = false;
var index = 0;
var lastChildRightSpaceLineNumber = 0;
@ -768,7 +766,7 @@ module.exports = [
"desc": "Fenced code blocks should have a language specified",
"tags": [ "code", "language" ],
"func": function MD040(params, errors) {
filterTokens(params.tokens, "fence", function forToken(token) {
filterTokens(params, "fence", function forToken(token) {
if (!token.info.trim()) {
errors.push(token.lineNumber);
}