From 483597c82a90c4b860bef8ec977b75d20f3564e9 Mon Sep 17 00:00:00 2001 From: David Anson Date: Tue, 16 Jun 2015 17:50:55 -0700 Subject: [PATCH] Cache result of forEachLine for ~4% time reduction. --- .eslintrc | 2 +- lib/rules.js | 53 +++++++++++++++++++++++++++++----------------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/.eslintrc b/.eslintrc index 753ca56d..4fcecdaf 100644 --- a/.eslintrc +++ b/.eslintrc @@ -12,7 +12,7 @@ "rules": { "no-alert": 2, "no-array-constructor": 2, - "no-bitwise": 2, + "no-bitwise": 0, "no-caller": 2, "no-catch-shadow": 2, "no-comma-dangle": 2, diff --git a/lib/rules.js b/lib/rules.js index bdff6a1e..14ee4c87 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -38,22 +38,32 @@ function filterTokens(params, type, callback) { // Calls the provided function for each line (with context) function forEachLine(params, callback) { - // Identify lines in code blocks - var codeLines = []; - filterTokens(params, "code_block", function forToken(token) { - for (var i = token.map[0]; i < token.map[1]; i++) { - codeLines.push(i); - } - }); - // Identify lines in code fences (with info about transitions) - var inFence = false; + if (!params.forEachLine) { + var lineMetadata = new Array(params.lines.length); + var inFence = false; + // Find fenced code by pattern (parser ignores "``` close fence") + params.lines.forEach(function forLine(line, lineIndex) { + var metadata = 0; + if (/^(```|~~~)/.test(line)) { + metadata = inFence ? -2 : 2; + inFence = !inFence; + } else if (inFence) { + metadata = 1; + } + lineMetadata[lineIndex] = metadata; + }); + // Find code blocks normally + filterTokens(params, "code_block", function forToken(token) { + for (var i = token.map[0]; i < token.map[1]; i++) { + lineMetadata[i] = 1; + } + }); + params.forEachLine = lineMetadata; + } + // Invoke callback params.lines.forEach(function forLine(line, lineIndex) { - var onFence = /^(```|~~~)/.test(line); - if (onFence) { - inFence = !inFence; - } - var inCodeBlock = (codeLines.indexOf(lineIndex) !== -1); - callback(line, lineIndex, inFence || inCodeBlock, onFence); + var metadata = params.forEachLine[lineIndex]; + callback(line, lineIndex, !!metadata, (metadata >> 1)); }); } @@ -581,13 +591,11 @@ module.exports = [ "desc": "Fenced code blocks should be surrounded by blank lines", "tags": [ "code", "blank_lines" ], "func": function MD031(params, errors) { - forEachLine(params, function forLine(line, lineIndex, inCode, onFence) { - if (onFence && - ((inCode && (lineIndex - 1 >= 0) && - params.lines[lineIndex - 1].length) || - (!inCode && (lineIndex + 1 < params.lines.length) && - params.lines[lineIndex + 1].length))) { - errors.push(lineIndex + 1); + var lines = params.lines; + forEachLine(params, function forLine(line, i, inCode, onFence) { + if (((onFence > 0) && (i - 1 >= 0) && lines[i - 1].length) || + ((onFence < 0) && (i + 1 < lines.length) && lines[i + 1].length)) { + errors.push(i + 1); } }); } @@ -610,7 +618,6 @@ module.exports = [ } inList = listMarker; } - inList = inList && !onFence; prevLine = line; }); }