mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 06:20:12 +01:00
Remove state from shared.js, move to cache.js.
This commit is contained in:
parent
827e1acb56
commit
f614f3e1ce
17 changed files with 124 additions and 98 deletions
24
lib/cache.js
Normal file
24
lib/cache.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let lineMetadata = null;
|
||||||
|
module.exports.lineMetadata = (value) => {
|
||||||
|
if (value) {
|
||||||
|
lineMetadata = value;
|
||||||
|
}
|
||||||
|
return lineMetadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
let flattenedLists = null;
|
||||||
|
module.exports.flattenedLists = (value) => {
|
||||||
|
if (value) {
|
||||||
|
flattenedLists = value;
|
||||||
|
}
|
||||||
|
return flattenedLists;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.clear = () => {
|
||||||
|
lineMetadata = null;
|
||||||
|
flattenedLists = null;
|
||||||
|
};
|
||||||
|
|
@ -8,6 +8,7 @@ const { URL } = require("url");
|
||||||
const markdownIt = require("markdown-it");
|
const markdownIt = require("markdown-it");
|
||||||
const rules = require("./rules");
|
const rules = require("./rules");
|
||||||
const shared = require("./shared");
|
const shared = require("./shared");
|
||||||
|
const cache = require("./cache");
|
||||||
|
|
||||||
const deprecatedRuleNames = [ "MD002" ];
|
const deprecatedRuleNames = [ "MD002" ];
|
||||||
|
|
||||||
|
|
@ -327,7 +328,8 @@ function lintContent(
|
||||||
lines,
|
lines,
|
||||||
frontMatterLines
|
frontMatterLines
|
||||||
};
|
};
|
||||||
shared.makeTokenCache(params);
|
cache.lineMetadata(shared.getLineMetadata(params));
|
||||||
|
cache.flattenedLists(shared.flattenLists(params));
|
||||||
// Function to run for each rule
|
// Function to run for each rule
|
||||||
const result = (resultVersion === 0) ? {} : [];
|
const result = (resultVersion === 0) ? {} : [];
|
||||||
function forRule(rule) {
|
function forRule(rule) {
|
||||||
|
|
@ -411,10 +413,10 @@ function lintContent(
|
||||||
try {
|
try {
|
||||||
ruleList.forEach(forRule);
|
ruleList.forEach(forRule);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
shared.makeTokenCache(null);
|
cache.clear();
|
||||||
return callback(ex);
|
return callback(ex);
|
||||||
}
|
}
|
||||||
shared.makeTokenCache(null);
|
cache.clear();
|
||||||
return callback(null, result);
|
return callback(null, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
lib/md004.js
16
lib/md004.js
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, listItemMarkerRe,
|
||||||
|
rangeFromRegExp } = require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
// Returns the unordered list style for a list item token
|
// Returns the unordered list style for a list item token
|
||||||
function unorderedListStyleFor(token) {
|
function unorderedListStyleFor(token) {
|
||||||
|
|
@ -25,12 +27,12 @@ module.exports = {
|
||||||
const style = params.config.style || "consistent";
|
const style = params.config.style || "consistent";
|
||||||
let expectedStyle = style;
|
let expectedStyle = style;
|
||||||
const nestingStyles = [];
|
const nestingStyles = [];
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
if (list.unordered) {
|
if (list.unordered) {
|
||||||
if (expectedStyle === "consistent") {
|
if (expectedStyle === "consistent") {
|
||||||
expectedStyle = unorderedListStyleFor(list.items[0]);
|
expectedStyle = unorderedListStyleFor(list.items[0]);
|
||||||
}
|
}
|
||||||
list.items.forEach(function forItem(item) {
|
list.items.forEach((item) => {
|
||||||
const itemStyle = unorderedListStyleFor(item);
|
const itemStyle = unorderedListStyleFor(item);
|
||||||
if (style === "sublist") {
|
if (style === "sublist") {
|
||||||
const nesting = list.nesting;
|
const nesting = list.nesting;
|
||||||
|
|
@ -38,14 +40,14 @@ module.exports = {
|
||||||
(itemStyle !== nestingStyles[nesting - 1])) {
|
(itemStyle !== nestingStyles[nesting - 1])) {
|
||||||
nestingStyles[nesting] = itemStyle;
|
nestingStyles[nesting] = itemStyle;
|
||||||
} else {
|
} else {
|
||||||
shared.addErrorDetailIf(onError, item.lineNumber,
|
addErrorDetailIf(onError, item.lineNumber,
|
||||||
nestingStyles[nesting], itemStyle, null, null,
|
nestingStyles[nesting], itemStyle, null, null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shared.addErrorDetailIf(onError, item.lineNumber,
|
addErrorDetailIf(onError, item.lineNumber,
|
||||||
expectedStyle, itemStyle, null, null,
|
expectedStyle, itemStyle, null, null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
lib/md005.js
20
lib/md005.js
|
|
@ -2,26 +2,28 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addError, addErrorDetailIf, indentFor, listItemMarkerRe,
|
||||||
|
orderedListItemMarkerRe, rangeFromRegExp } = require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD005", "list-indent" ],
|
"names": [ "MD005", "list-indent" ],
|
||||||
"description": "Inconsistent indentation for list items at the same level",
|
"description": "Inconsistent indentation for list items at the same level",
|
||||||
"tags": [ "bullet", "ul", "indentation" ],
|
"tags": [ "bullet", "ul", "indentation" ],
|
||||||
"function": function MD005(params, onError) {
|
"function": function MD005(params, onError) {
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
const expectedIndent = list.indent;
|
const expectedIndent = list.indent;
|
||||||
let expectedEnd = 0;
|
let expectedEnd = 0;
|
||||||
let actualEnd = -1;
|
let actualEnd = -1;
|
||||||
let endMatching = false;
|
let endMatching = false;
|
||||||
list.items.forEach(function forItem(item) {
|
list.items.forEach((item) => {
|
||||||
const actualIndent = shared.indentFor(item);
|
const actualIndent = indentFor(item);
|
||||||
if (list.unordered) {
|
if (list.unordered) {
|
||||||
shared.addErrorDetailIf(onError, item.lineNumber,
|
addErrorDetailIf(onError, item.lineNumber,
|
||||||
expectedIndent, actualIndent, null, null,
|
expectedIndent, actualIndent, null, null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
} else {
|
} else {
|
||||||
const match = shared.orderedListItemMarkerRe.exec(item.line);
|
const match = orderedListItemMarkerRe.exec(item.line);
|
||||||
actualEnd = match && match[0].length;
|
actualEnd = match && match[0].length;
|
||||||
expectedEnd = expectedEnd || actualEnd;
|
expectedEnd = expectedEnd || actualEnd;
|
||||||
if ((expectedIndent !== actualIndent) || endMatching) {
|
if ((expectedIndent !== actualIndent) || endMatching) {
|
||||||
|
|
@ -31,8 +33,8 @@ module.exports = {
|
||||||
const detail = endMatching ?
|
const detail = endMatching ?
|
||||||
`Expected: (${expectedEnd}); Actual: (${actualEnd})` :
|
`Expected: (${expectedEnd}); Actual: (${actualEnd})` :
|
||||||
`Expected: ${expectedIndent}; Actual: ${actualIndent}`;
|
`Expected: ${expectedIndent}; Actual: ${actualIndent}`;
|
||||||
shared.addError(onError, item.lineNumber, detail, null,
|
addError(onError, item.lineNumber, detail, null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
lib/md006.js
10
lib/md006.js
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, listItemMarkerRe, rangeFromRegExp } =
|
||||||
|
require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD006", "ul-start-left" ],
|
"names": [ "MD006", "ul-start-left" ],
|
||||||
|
|
@ -10,11 +12,11 @@ module.exports = {
|
||||||
"Consider starting bulleted lists at the beginning of the line",
|
"Consider starting bulleted lists at the beginning of the line",
|
||||||
"tags": [ "bullet", "ul", "indentation" ],
|
"tags": [ "bullet", "ul", "indentation" ],
|
||||||
"function": function MD006(params, onError) {
|
"function": function MD006(params, onError) {
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
if (list.unordered && !list.nesting) {
|
if (list.unordered && !list.nesting) {
|
||||||
shared.addErrorDetailIf(onError, list.open.lineNumber,
|
addErrorDetailIf(onError, list.open.lineNumber,
|
||||||
0, list.indent, null, null,
|
0, list.indent, null, null,
|
||||||
shared.rangeFromRegExp(list.open.line, shared.listItemMarkerRe));
|
rangeFromRegExp(list.open.line, listItemMarkerRe));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
lib/md007.js
10
lib/md007.js
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, listItemMarkerRe, rangeFromRegExp } =
|
||||||
|
require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD007", "ul-indent" ],
|
"names": [ "MD007", "ul-indent" ],
|
||||||
|
|
@ -10,11 +12,11 @@ module.exports = {
|
||||||
"tags": [ "bullet", "ul", "indentation" ],
|
"tags": [ "bullet", "ul", "indentation" ],
|
||||||
"function": function MD007(params, onError) {
|
"function": function MD007(params, onError) {
|
||||||
const optionsIndent = params.config.indent || 2;
|
const optionsIndent = params.config.indent || 2;
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
if (list.unordered && list.parentsUnordered && list.indent) {
|
if (list.unordered && list.parentsUnordered && list.indent) {
|
||||||
shared.addErrorDetailIf(onError, list.open.lineNumber,
|
addErrorDetailIf(onError, list.open.lineNumber,
|
||||||
list.parentIndent + optionsIndent, list.indent, null, null,
|
list.parentIndent + optionsIndent, list.indent, null, null,
|
||||||
shared.rangeFromRegExp(list.open.line, shared.listItemMarkerRe));
|
rangeFromRegExp(list.open.line, listItemMarkerRe));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
|
||||||
const { addError, filterTokens, forEachLine, includesSorted, rangeFromRegExp,
|
const { addError, filterTokens, forEachLine, includesSorted, rangeFromRegExp,
|
||||||
trimRight } = shared;
|
trimRight } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
const trailingSpaceRe = /\s+$/;
|
const trailingSpaceRe = /\s+$/;
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ module.exports = {
|
||||||
listItemLineNumbers.sort((a, b) => a - b);
|
listItemLineNumbers.sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
const expected = (brSpaces < 2) ? 0 : brSpaces;
|
||||||
forEachLine((line, lineIndex) => {
|
forEachLine(lineMetadata(), (line, lineIndex) => {
|
||||||
const lineNumber = lineIndex + 1;
|
const lineNumber = lineIndex + 1;
|
||||||
if (trailingSpaceRe.test(line) &&
|
if (trailingSpaceRe.test(line) &&
|
||||||
!includesSorted(listItemLineNumbers, lineNumber)) {
|
!includesSorted(listItemLineNumbers, lineNumber)) {
|
||||||
|
|
|
||||||
10
lib/md010.js
10
lib/md010.js
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addError, forEachLine, rangeFromRegExp } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
const tabRe = /\t+/;
|
const tabRe = /\t+/;
|
||||||
|
|
||||||
|
|
@ -13,11 +14,10 @@ module.exports = {
|
||||||
"function": function MD010(params, onError) {
|
"function": function MD010(params, onError) {
|
||||||
const codeBlocks = params.config.code_blocks;
|
const codeBlocks = params.config.code_blocks;
|
||||||
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
||||||
shared.forEachLine(function forLine(line, lineIndex, inCode) {
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
||||||
if (tabRe.test(line) && (!inCode || includeCodeBlocks)) {
|
if (tabRe.test(line) && (!inCode || includeCodeBlocks)) {
|
||||||
shared.addError(onError, lineIndex + 1,
|
addError(onError, lineIndex + 1, "Column: " + (line.indexOf("\t") + 1),
|
||||||
"Column: " + (line.indexOf("\t") + 1), null,
|
null, rangeFromRegExp(line, tabRe));
|
||||||
shared.rangeFromRegExp(line, tabRe));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, forEachLine } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD012", "no-multiple-blanks" ],
|
"names": [ "MD012", "no-multiple-blanks" ],
|
||||||
|
|
@ -11,10 +12,10 @@ module.exports = {
|
||||||
"function": function MD012(params, onError) {
|
"function": function MD012(params, onError) {
|
||||||
const maximum = params.config.maximum || 1;
|
const maximum = params.config.maximum || 1;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
shared.forEachLine(function forLine(line, lineIndex, inCode) {
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
||||||
count = (inCode || line.trim().length) ? 0 : count + 1;
|
count = (inCode || line.trim().length) ? 0 : count + 1;
|
||||||
if (maximum < count) {
|
if (maximum < count) {
|
||||||
shared.addErrorDetailIf(onError, lineIndex + 1, maximum, count);
|
addErrorDetailIf(onError, lineIndex + 1, maximum, count);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
|
||||||
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
||||||
includesSorted, rangeFromRegExp } = shared;
|
includesSorted, rangeFromRegExp } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
const longLineRePrefix = "^(.{";
|
const longLineRePrefix = "^(.{";
|
||||||
const longLineRePostfix = "})(.*\\s.*)$";
|
const longLineRePostfix = "})(.*\\s.*)$";
|
||||||
|
|
@ -56,7 +56,7 @@ module.exports = {
|
||||||
linkOnlyLineNumbers.push(token.lineNumber);
|
linkOnlyLineNumbers.push(token.lineNumber);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
forEachLine((line, lineIndex, inCode, onFence, inTable) => {
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
|
||||||
const lineNumber = lineIndex + 1;
|
const lineNumber = lineIndex + 1;
|
||||||
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
||||||
const length = isHeading ? headingLineLength : lineLength;
|
const length = isHeading ? headingLineLength : lineLength;
|
||||||
|
|
|
||||||
10
lib/md018.js
10
lib/md018.js
|
|
@ -2,17 +2,19 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorContext, atxHeadingSpaceRe, forEachLine,
|
||||||
|
rangeFromRegExp } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD018", "no-missing-space-atx" ],
|
"names": [ "MD018", "no-missing-space-atx" ],
|
||||||
"description": "No space after hash on atx style heading",
|
"description": "No space after hash on atx style heading",
|
||||||
"tags": [ "headings", "headers", "atx", "spaces" ],
|
"tags": [ "headings", "headers", "atx", "spaces" ],
|
||||||
"function": function MD018(params, onError) {
|
"function": function MD018(params, onError) {
|
||||||
shared.forEachLine(function forLine(line, lineIndex, inCode) {
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
||||||
if (!inCode && /^#+[^#\s]/.test(line) && !/#$/.test(line)) {
|
if (!inCode && /^#+[^#\s]/.test(line) && !/#$/.test(line)) {
|
||||||
shared.addErrorContext(onError, lineIndex + 1, line.trim(), null,
|
addErrorContext(onError, lineIndex + 1, line.trim(), null,
|
||||||
null, shared.rangeFromRegExp(line, shared.atxHeadingSpaceRe));
|
null, rangeFromRegExp(line, atxHeadingSpaceRe));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorContext, forEachLine, rangeFromRegExp } = require("./shared");
|
||||||
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
const atxClosedHeadingNoSpaceRe = /(?:^#+[^#\s])|(?:[^#\s]#+\s*$)/;
|
const atxClosedHeadingNoSpaceRe = /(?:^#+[^#\s])|(?:[^#\s]#+\s*$)/;
|
||||||
|
|
||||||
|
|
@ -11,13 +12,13 @@ module.exports = {
|
||||||
"description": "No space inside hashes on closed atx style heading",
|
"description": "No space inside hashes on closed atx style heading",
|
||||||
"tags": [ "headings", "headers", "atx_closed", "spaces" ],
|
"tags": [ "headings", "headers", "atx_closed", "spaces" ],
|
||||||
"function": function MD020(params, onError) {
|
"function": function MD020(params, onError) {
|
||||||
shared.forEachLine(function forLine(line, lineIndex, inCode) {
|
forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
|
||||||
if (!inCode && /^#+[^#]*[^\\]#+$/.test(line)) {
|
if (!inCode && /^#+[^#]*[^\\]#+$/.test(line)) {
|
||||||
const left = /^#+[^#\s]/.test(line);
|
const left = /^#+[^#\s]/.test(line);
|
||||||
const right = /[^#\s]#+$/.test(line);
|
const right = /[^#\s]#+$/.test(line);
|
||||||
if (left || right) {
|
if (left || right) {
|
||||||
shared.addErrorContext(onError, lineIndex + 1, line.trim(), left,
|
addErrorContext(onError, lineIndex + 1, line.trim(), left,
|
||||||
right, shared.rangeFromRegExp(line, atxClosedHeadingNoSpaceRe));
|
right, rangeFromRegExp(line, atxClosedHeadingNoSpaceRe));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
16
lib/md029.js
16
lib/md029.js
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, listItemMarkerRe, orderedListItemMarkerRe,
|
||||||
|
rangeFromRegExp } = require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
const listStyleExamples = {
|
const listStyleExamples = {
|
||||||
"one": "1/1/1",
|
"one": "1/1/1",
|
||||||
|
|
@ -16,21 +18,21 @@ module.exports = {
|
||||||
"tags": [ "ol" ],
|
"tags": [ "ol" ],
|
||||||
"function": function MD029(params, onError) {
|
"function": function MD029(params, onError) {
|
||||||
const style = params.config.style || "one_or_ordered";
|
const style = params.config.style || "one_or_ordered";
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
if (!list.unordered) {
|
if (!list.unordered) {
|
||||||
let listStyle = style;
|
let listStyle = style;
|
||||||
if (listStyle === "one_or_ordered") {
|
if (listStyle === "one_or_ordered") {
|
||||||
const second = (list.items.length > 1) &&
|
const second = (list.items.length > 1) &&
|
||||||
shared.orderedListItemMarkerRe.exec(list.items[1].line);
|
orderedListItemMarkerRe.exec(list.items[1].line);
|
||||||
listStyle = (second && (second[1] !== "1")) ? "ordered" : "one";
|
listStyle = (second && (second[1] !== "1")) ? "ordered" : "one";
|
||||||
}
|
}
|
||||||
let number = (listStyle === "zero") ? 0 : 1;
|
let number = (listStyle === "zero") ? 0 : 1;
|
||||||
list.items.forEach(function forItem(item) {
|
list.items.forEach((item) => {
|
||||||
const match = shared.orderedListItemMarkerRe.exec(item.line);
|
const match = orderedListItemMarkerRe.exec(item.line);
|
||||||
shared.addErrorDetailIf(onError, item.lineNumber,
|
addErrorDetailIf(onError, item.lineNumber,
|
||||||
String(number), !match || match[1],
|
String(number), !match || match[1],
|
||||||
"Style: " + listStyleExamples[listStyle], null,
|
"Style: " + listStyleExamples[listStyle], null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
if (listStyle === "ordered") {
|
if (listStyle === "ordered") {
|
||||||
number++;
|
number++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
lib/md030.js
12
lib/md030.js
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorDetailIf, listItemMarkerRe, rangeFromRegExp } =
|
||||||
|
require("./shared");
|
||||||
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD030", "list-marker-space" ],
|
"names": [ "MD030", "list-marker-space" ],
|
||||||
|
|
@ -13,17 +15,17 @@ module.exports = {
|
||||||
const olSingle = params.config.ol_single || 1;
|
const olSingle = params.config.ol_single || 1;
|
||||||
const ulMulti = params.config.ul_multi || 1;
|
const ulMulti = params.config.ul_multi || 1;
|
||||||
const olMulti = params.config.ol_multi || 1;
|
const olMulti = params.config.ol_multi || 1;
|
||||||
shared.flattenLists().forEach(function forList(list) {
|
flattenedLists().forEach((list) => {
|
||||||
const lineCount = list.lastLineIndex - list.open.map[0];
|
const lineCount = list.lastLineIndex - list.open.map[0];
|
||||||
const allSingle = lineCount === list.items.length;
|
const allSingle = lineCount === list.items.length;
|
||||||
const expectedSpaces = list.unordered ?
|
const expectedSpaces = list.unordered ?
|
||||||
(allSingle ? ulSingle : ulMulti) :
|
(allSingle ? ulSingle : ulMulti) :
|
||||||
(allSingle ? olSingle : olMulti);
|
(allSingle ? olSingle : olMulti);
|
||||||
list.items.forEach(function forItem(item) {
|
list.items.forEach((item) => {
|
||||||
const match = /^[\s>]*\S+(\s+)/.exec(item.line);
|
const match = /^[\s>]*\S+(\s+)/.exec(item.line);
|
||||||
shared.addErrorDetailIf(onError, item.lineNumber,
|
addErrorDetailIf(onError, item.lineNumber,
|
||||||
expectedSpaces, (match ? match[1].length : 0), null, null,
|
expectedSpaces, (match ? match[1].length : 0), null, null,
|
||||||
shared.rangeFromRegExp(item.line, shared.listItemMarkerRe));
|
rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorContext, forEachLine, isBlankLine } = require("./shared");
|
||||||
const { addErrorContext, forEachLine, isBlankLine } = shared;
|
const { lineMetadata } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD031", "blanks-around-fences" ],
|
"names": [ "MD031", "blanks-around-fences" ],
|
||||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
||||||
"tags": [ "code", "blank_lines" ],
|
"tags": [ "code", "blank_lines" ],
|
||||||
"function": function MD031(params, onError) {
|
"function": function MD031(params, onError) {
|
||||||
const { lines } = params;
|
const { lines } = params;
|
||||||
forEachLine(function forLine(line, i, inCode, onFence) {
|
forEachLine(lineMetadata(), (line, i, inCode, onFence) => {
|
||||||
if (((onFence > 0) && !isBlankLine(lines[i - 1])) ||
|
if (((onFence > 0) && !isBlankLine(lines[i - 1])) ||
|
||||||
((onFence < 0) && !isBlankLine(lines[i + 1]))) {
|
((onFence < 0) && !isBlankLine(lines[i + 1]))) {
|
||||||
addErrorContext(onError, i + 1, lines[i].trim());
|
addErrorContext(onError, i + 1, lines[i].trim());
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const shared = require("./shared");
|
const { addErrorContext, isBlankLine } = require("./shared");
|
||||||
const { addErrorContext, flattenLists, isBlankLine } = shared;
|
const { flattenedLists } = require("./cache");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": [ "MD032", "blanks-around-lists" ],
|
"names": [ "MD032", "blanks-around-lists" ],
|
||||||
|
|
@ -11,7 +11,7 @@ module.exports = {
|
||||||
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
"tags": [ "bullet", "ul", "ol", "blank_lines" ],
|
||||||
"function": function MD032(params, onError) {
|
"function": function MD032(params, onError) {
|
||||||
const { lines } = params;
|
const { lines } = params;
|
||||||
flattenLists().filter((list) => !list.nesting).forEach((list) => {
|
flattenedLists().filter((list) => !list.nesting).forEach((list) => {
|
||||||
const firstIndex = list.open.map[0];
|
const firstIndex = list.open.map[0];
|
||||||
if (!isBlankLine(lines[firstIndex - 1])) {
|
if (!isBlankLine(lines[firstIndex - 1])) {
|
||||||
addErrorContext(onError, firstIndex + 1, lines[firstIndex].trim());
|
addErrorContext(onError, firstIndex + 1, lines[firstIndex].trim());
|
||||||
|
|
|
||||||
|
|
@ -154,15 +154,8 @@ function filterTokens(params, type, handler) {
|
||||||
}
|
}
|
||||||
module.exports.filterTokens = filterTokens;
|
module.exports.filterTokens = filterTokens;
|
||||||
|
|
||||||
let tokenCache = null;
|
// Get line metadata array
|
||||||
// Caches line metadata and flattened lists for reuse
|
module.exports.getLineMetadata = function getLineMetadata(params) {
|
||||||
function makeTokenCache(params) {
|
|
||||||
if (!params) {
|
|
||||||
tokenCache = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize line metadata array
|
|
||||||
const lineMetadata = params.lines.map(function mapLine(line, index) {
|
const lineMetadata = params.lines.map(function mapLine(line, index) {
|
||||||
return [ line, index, false, 0, false ];
|
return [ line, index, false, 0, false ];
|
||||||
});
|
});
|
||||||
|
|
@ -183,8 +176,19 @@ function makeTokenCache(params) {
|
||||||
lineMetadata[i][4] = true;
|
lineMetadata[i][4] = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return lineMetadata;
|
||||||
|
};
|
||||||
|
|
||||||
// Flatten lists
|
// Calls the provided function for each line (with context)
|
||||||
|
module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
|
||||||
|
lineMetadata.forEach(function forMetadata(metadata) {
|
||||||
|
// Parameters: line, lineIndex, inCode, onFence, inTable
|
||||||
|
handler(...metadata);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns (nested) lists as a flat array (in order)
|
||||||
|
module.exports.flattenLists = function flattenLists(params) {
|
||||||
const flattenedLists = [];
|
const flattenedLists = [];
|
||||||
const stack = [];
|
const stack = [];
|
||||||
let current = null;
|
let current = null;
|
||||||
|
|
@ -221,22 +225,7 @@ function makeTokenCache(params) {
|
||||||
lastWithMap = token;
|
lastWithMap = token;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return flattenedLists;
|
||||||
// Cache results
|
|
||||||
tokenCache = {
|
|
||||||
"params": params,
|
|
||||||
"lineMetadata": lineMetadata,
|
|
||||||
"flattenedLists": flattenedLists
|
|
||||||
};
|
|
||||||
}
|
|
||||||
module.exports.makeTokenCache = makeTokenCache;
|
|
||||||
|
|
||||||
// Calls the provided function for each line (with context)
|
|
||||||
module.exports.forEachLine = function forEachLine(callback) {
|
|
||||||
tokenCache.lineMetadata.forEach(function forMetadata(metadata) {
|
|
||||||
// Parameters: line, lineIndex, inCode, onFence, inTable
|
|
||||||
callback(...metadata);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calls the provided function for each specified inline child token
|
// Calls the provided function for each specified inline child token
|
||||||
|
|
@ -328,11 +317,6 @@ module.exports.forEachInlineCodeSpan =
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns (nested) lists as a flat array (in order)
|
|
||||||
module.exports.flattenLists = function flattenLists() {
|
|
||||||
return tokenCache.flattenedLists;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Adds a generic error object via the onError callback
|
// Adds a generic error object via the onError callback
|
||||||
function addError(onError, lineNumber, detail, context, range) {
|
function addError(onError, lineNumber, detail, context, range) {
|
||||||
onError({
|
onError({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue