mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 06:20:12 +01:00
Update to version 0.20.0.
This commit is contained in:
parent
5c60e00a90
commit
190716da39
4 changed files with 283 additions and 144 deletions
|
|
@ -856,6 +856,9 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||||
MD005/list-indent, improve MD007/MD013/MD014, deprecate MD006/ul-start-left, add
|
MD005/list-indent, improve MD007/MD013/MD014, deprecate MD006/ul-start-left, add
|
||||||
rationale for every rule, update test runner and code coverage, add more JSDoc
|
rationale for every rule, update test runner and code coverage, add more JSDoc
|
||||||
comments, update dependencies.
|
comments, update dependencies.
|
||||||
|
* 0.20.0 - Add `markdownlint-configure-file` inline comment,
|
||||||
|
improve MD005/MD007/MD013/MD018/MD029/MD031/MD034/MD037/MD038/MD039, improve HTML
|
||||||
|
comment handling, update dependencies.
|
||||||
|
|
||||||
[npm-image]: https://img.shields.io/npm/v/markdownlint.svg
|
[npm-image]: https://img.shields.io/npm/v/markdownlint.svg
|
||||||
[npm-url]: https://www.npmjs.com/package/markdownlint
|
[npm-url]: https://www.npmjs.com/package/markdownlint
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ module.exports.frontMatterRe =
|
||||||
// Regular expression for matching inline disable/enable comments
|
// Regular expression for matching inline disable/enable comments
|
||||||
var inlineCommentRe =
|
var inlineCommentRe =
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file)((?:\s+[a-z0-9_-]+)*)\s*-->/ig;
|
/<!--\s*markdownlint-(?:(?:(disable|enable|capture|restore|disable-file|enable-file)((?:\s+[a-z0-9_-]+)*))|(?:(configure-file)\s+([\s\S]*?)))\s*-->/ig;
|
||||||
module.exports.inlineCommentRe = inlineCommentRe;
|
module.exports.inlineCommentRe = inlineCommentRe;
|
||||||
// Regular expressions for range matching
|
// Regular expressions for range matching
|
||||||
module.exports.bareUrlRe = /(?:http|ftp)s?:\/\/[^\s]*/ig;
|
module.exports.bareUrlRe = /(?:http|ftp)s?:\/\/[^\s\]"']*/ig;
|
||||||
module.exports.listItemMarkerRe = /^([\s>]*)(?:[*+-]|\d+[.)])\s+/;
|
module.exports.listItemMarkerRe = /^([\s>]*)(?:[*+-]|\d+[.)])\s+/;
|
||||||
module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
|
module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
|
||||||
// readFile options for reading with the UTF-8 encoding
|
// readFile options for reading with the UTF-8 encoding
|
||||||
|
|
@ -102,8 +102,8 @@ module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
||||||
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
||||||
var j = text.indexOf(htmlCommentEnd, i);
|
var j = text.indexOf(htmlCommentEnd, i);
|
||||||
if (j === -1) {
|
if (j === -1) {
|
||||||
j = text.length;
|
// Un-terminated comments are treated as text
|
||||||
text += "\\\n";
|
break;
|
||||||
}
|
}
|
||||||
var comment = text.slice(i + htmlCommentBegin.length, j);
|
var comment = text.slice(i + htmlCommentBegin.length, j);
|
||||||
if ((comment.length > 0) &&
|
if ((comment.length > 0) &&
|
||||||
|
|
@ -230,16 +230,21 @@ module.exports.getLineMetadata = function getLineMetadata(params) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
filterTokens(params, "list_item_open", function forToken(token) {
|
filterTokens(params, "list_item_open", function forToken(token) {
|
||||||
|
var count = 1;
|
||||||
for (var i = token.map[0]; i < token.map[1]; i++) {
|
for (var i = token.map[0]; i < token.map[1]; i++) {
|
||||||
lineMetadata[i][5] = true;
|
lineMetadata[i][5] = count;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
filterTokens(params, "hr", function forToken(token) {
|
||||||
|
lineMetadata[token.map[0]][6] = true;
|
||||||
|
});
|
||||||
return lineMetadata;
|
return lineMetadata;
|
||||||
};
|
};
|
||||||
// Calls the provided function for each line (with context)
|
// Calls the provided function for each line (with context)
|
||||||
module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
|
module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
|
||||||
lineMetadata.forEach(function forMetadata(metadata) {
|
lineMetadata.forEach(function forMetadata(metadata) {
|
||||||
// Parameters: line, lineIndex, inCode, onFence, inTable
|
// Parameters: line, lineIndex, inCode, onFence, inTable, inBreak
|
||||||
handler.apply(void 0, metadata);
|
handler.apply(void 0, metadata);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -248,6 +253,8 @@ module.exports.flattenLists = function flattenLists(params) {
|
||||||
var flattenedLists = [];
|
var flattenedLists = [];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
var current = null;
|
var current = null;
|
||||||
|
var nesting = 0;
|
||||||
|
var nestingStack = [];
|
||||||
var lastWithMap = { "map": [0, 1] };
|
var lastWithMap = { "map": [0, 1] };
|
||||||
params.tokens.forEach(function forToken(token) {
|
params.tokens.forEach(function forToken(token) {
|
||||||
if ((token.type === "bullet_list_open") ||
|
if ((token.type === "bullet_list_open") ||
|
||||||
|
|
@ -262,10 +269,11 @@ module.exports.flattenLists = function flattenLists(params) {
|
||||||
"indent": indentFor(token),
|
"indent": indentFor(token),
|
||||||
"parentIndent": (current && current.indent) || 0,
|
"parentIndent": (current && current.indent) || 0,
|
||||||
"items": [],
|
"items": [],
|
||||||
"nesting": stack.length - 1,
|
"nesting": nesting,
|
||||||
"lastLineIndex": -1,
|
"lastLineIndex": -1,
|
||||||
"insert": flattenedLists.length
|
"insert": flattenedLists.length
|
||||||
};
|
};
|
||||||
|
nesting++;
|
||||||
}
|
}
|
||||||
else if ((token.type === "bullet_list_close") ||
|
else if ((token.type === "bullet_list_close") ||
|
||||||
(token.type === "ordered_list_close")) {
|
(token.type === "ordered_list_close")) {
|
||||||
|
|
@ -274,11 +282,19 @@ module.exports.flattenLists = function flattenLists(params) {
|
||||||
flattenedLists.splice(current.insert, 0, current);
|
flattenedLists.splice(current.insert, 0, current);
|
||||||
delete current.insert;
|
delete current.insert;
|
||||||
current = stack.pop();
|
current = stack.pop();
|
||||||
|
nesting--;
|
||||||
}
|
}
|
||||||
else if (token.type === "list_item_open") {
|
else if (token.type === "list_item_open") {
|
||||||
// Add list item
|
// Add list item
|
||||||
current.items.push(token);
|
current.items.push(token);
|
||||||
}
|
}
|
||||||
|
else if (token.type === "blockquote_open") {
|
||||||
|
nestingStack.push(nesting);
|
||||||
|
nesting = 0;
|
||||||
|
}
|
||||||
|
else if (token.type === "blockquote_close") {
|
||||||
|
nesting = nestingStack.pop();
|
||||||
|
}
|
||||||
else if (token.map) {
|
else if (token.map) {
|
||||||
// Track last token with map
|
// Track last token with map
|
||||||
lastWithMap = token;
|
lastWithMap = token;
|
||||||
|
|
@ -921,68 +937,98 @@ function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
||||||
* @param {string[]} lines List of content lines.
|
* @param {string[]} lines List of content lines.
|
||||||
* @param {string[]} frontMatterLines List of front matter lines.
|
* @param {string[]} frontMatterLines List of front matter lines.
|
||||||
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
||||||
* @param {Configuration} effectiveConfig Effective configuration.
|
* @param {Configuration} config Configuration object.
|
||||||
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
||||||
* names.
|
* names.
|
||||||
* @returns {Object.<string, RuleConfiguration>[]} Enabled rules for each line.
|
* @returns {Object} Effective configuration and enabled rules per line number.
|
||||||
*/
|
*/
|
||||||
function getEnabledRulesPerLineNumber(ruleList, lines, frontMatterLines, noInlineConfig, effectiveConfig, aliasToRuleNames) {
|
function getEnabledRulesPerLineNumber(ruleList, lines, frontMatterLines, noInlineConfig, config, aliasToRuleNames) {
|
||||||
|
// Shared variables
|
||||||
var enabledRules = {};
|
var enabledRules = {};
|
||||||
|
var capturedRules = {};
|
||||||
var allRuleNames = [];
|
var allRuleNames = [];
|
||||||
|
var enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
||||||
|
// Helper functions
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function handleInlineConfig(perLine, forEachMatch, forEachLine) {
|
||||||
|
var input = perLine ? lines : [lines.join("\n")];
|
||||||
|
input.forEach(function (line) {
|
||||||
|
if (!noInlineConfig) {
|
||||||
|
var match = null;
|
||||||
|
while ((match = helpers.inlineCommentRe.exec(line))) {
|
||||||
|
var action = (match[1] || match[3]).toUpperCase();
|
||||||
|
var parameter = match[2] || match[4];
|
||||||
|
forEachMatch(action, parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (forEachLine) {
|
||||||
|
forEachLine();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function configureFile(action, parameter) {
|
||||||
|
if (action === "CONFIGURE-FILE") {
|
||||||
|
try {
|
||||||
|
var json = JSON.parse(parameter);
|
||||||
|
config = __assign(__assign({}, config), json);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
// Ignore parse errors for inline configuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function applyEnableDisable(action, parameter) {
|
||||||
|
var enabled = (action.startsWith("ENABLE"));
|
||||||
|
var items = parameter ?
|
||||||
|
parameter.trim().toUpperCase().split(/\s+/) :
|
||||||
|
allRuleNames;
|
||||||
|
items.forEach(function (nameUpper) {
|
||||||
|
(aliasToRuleNames[nameUpper] || []).forEach(function (ruleName) {
|
||||||
|
enabledRules[ruleName] = enabled;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function enableDisableFile(action, parameter) {
|
||||||
|
if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) {
|
||||||
|
applyEnableDisable(action, parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function captureRestoreEnableDisable(action, parameter) {
|
||||||
|
if (action === "CAPTURE") {
|
||||||
|
capturedRules = __assign({}, enabledRules);
|
||||||
|
}
|
||||||
|
else if (action === "RESTORE") {
|
||||||
|
enabledRules = __assign({}, capturedRules);
|
||||||
|
}
|
||||||
|
else if ((action === "ENABLE") || (action === "DISABLE")) {
|
||||||
|
enabledRules = __assign({}, enabledRules);
|
||||||
|
applyEnableDisable(action, parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
|
function updateLineState() {
|
||||||
|
enabledRulesPerLineNumber.push(enabledRules);
|
||||||
|
}
|
||||||
|
// Handle inline comments
|
||||||
|
handleInlineConfig(false, configureFile);
|
||||||
|
var effectiveConfig = getEffectiveConfig(ruleList, config, aliasToRuleNames);
|
||||||
ruleList.forEach(function (rule) {
|
ruleList.forEach(function (rule) {
|
||||||
var ruleName = rule.names[0].toUpperCase();
|
var ruleName = rule.names[0].toUpperCase();
|
||||||
allRuleNames.push(ruleName);
|
allRuleNames.push(ruleName);
|
||||||
enabledRules[ruleName] = !!effectiveConfig[ruleName];
|
enabledRules[ruleName] = !!effectiveConfig[ruleName];
|
||||||
});
|
});
|
||||||
var capturedRules = enabledRules;
|
capturedRules = enabledRules;
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
handleInlineConfig(true, enableDisableFile);
|
||||||
function forMatch(match, byLine) {
|
handleInlineConfig(true, captureRestoreEnableDisable, updateLineState);
|
||||||
var action = match[1].toUpperCase();
|
// Return results
|
||||||
if (action === "CAPTURE") {
|
return {
|
||||||
if (byLine) {
|
effectiveConfig: effectiveConfig,
|
||||||
capturedRules = __assign({}, enabledRules);
|
enabledRulesPerLineNumber: enabledRulesPerLineNumber
|
||||||
}
|
};
|
||||||
}
|
|
||||||
else if (action === "RESTORE") {
|
|
||||||
if (byLine) {
|
|
||||||
enabledRules = __assign({}, capturedRules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// action in [ENABLE, DISABLE, ENABLE-FILE, DISABLE-FILE]
|
|
||||||
var isfile = action.endsWith("-FILE");
|
|
||||||
if ((byLine && !isfile) || (!byLine && isfile)) {
|
|
||||||
var enabled_1 = (action.startsWith("ENABLE"));
|
|
||||||
var items = match[2] ?
|
|
||||||
match[2].trim().toUpperCase().split(/\s+/) :
|
|
||||||
allRuleNames;
|
|
||||||
items.forEach(function (nameUpper) {
|
|
||||||
(aliasToRuleNames[nameUpper] || []).forEach(function (ruleName) {
|
|
||||||
enabledRules[ruleName] = enabled_1;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
|
||||||
[false, true].forEach(function (byLine) {
|
|
||||||
lines.forEach(function (line) {
|
|
||||||
if (!noInlineConfig) {
|
|
||||||
var match = helpers.inlineCommentRe.exec(line);
|
|
||||||
if (match) {
|
|
||||||
enabledRules = __assign({}, enabledRules);
|
|
||||||
while (match) {
|
|
||||||
forMatch(match, byLine);
|
|
||||||
match = helpers.inlineCommentRe.exec(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (byLine) {
|
|
||||||
enabledRulesPerLineNumber.push(enabledRules);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return enabledRulesPerLineNumber;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Compare function for Array.prototype.sort for ascending order of errors.
|
* Compare function for Array.prototype.sort for ascending order of errors.
|
||||||
|
|
@ -1041,8 +1087,7 @@ function lintContent(ruleList, name, content, md, config, frontMatter, handleRul
|
||||||
var lines = content.split(helpers.newLineRe);
|
var lines = content.split(helpers.newLineRe);
|
||||||
annotateTokens(tokens, lines);
|
annotateTokens(tokens, lines);
|
||||||
var aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
var aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
||||||
var effectiveConfig = getEffectiveConfig(ruleList, config, aliasToRuleNames);
|
var _a = getEnabledRulesPerLineNumber(ruleList, lines, frontMatterLines, noInlineConfig, config, aliasToRuleNames), effectiveConfig = _a.effectiveConfig, enabledRulesPerLineNumber = _a.enabledRulesPerLineNumber;
|
||||||
var enabledRulesPerLineNumber = getEnabledRulesPerLineNumber(ruleList, lines, frontMatterLines, noInlineConfig, effectiveConfig, aliasToRuleNames);
|
|
||||||
// Create parameters for rules
|
// Create parameters for rules
|
||||||
var params = {
|
var params = {
|
||||||
name: name,
|
name: name,
|
||||||
|
|
@ -1576,13 +1621,13 @@ module.exports = {
|
||||||
list.items.forEach(function (item) {
|
list.items.forEach(function (item) {
|
||||||
var line = item.line, lineNumber = item.lineNumber;
|
var line = item.line, lineNumber = item.lineNumber;
|
||||||
var actualIndent = indentFor(item);
|
var actualIndent = indentFor(item);
|
||||||
|
var match = null;
|
||||||
if (list.unordered) {
|
if (list.unordered) {
|
||||||
addErrorDetailIf(onError, lineNumber, expectedIndent, actualIndent, null, null, rangeFromRegExp(line, listItemMarkerRe)
|
addErrorDetailIf(onError, lineNumber, expectedIndent, actualIndent, null, null, rangeFromRegExp(line, listItemMarkerRe)
|
||||||
// No fixInfo; MD007 handles this scenario better
|
// No fixInfo; MD007 handles this scenario better
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else if ((match = orderedListItemMarkerRe.exec(line))) {
|
||||||
var match = orderedListItemMarkerRe.exec(line);
|
|
||||||
actualEnd = match[0].length;
|
actualEnd = match[0].length;
|
||||||
expectedEnd = expectedEnd || actualEnd;
|
expectedEnd = expectedEnd || actualEnd;
|
||||||
var markerLength = match[1].length + 1;
|
var markerLength = match[1].length + 1;
|
||||||
|
|
@ -1833,6 +1878,7 @@ var longLineRePostfixRelaxed = "}.*\\s.*$";
|
||||||
var longLineRePostfixStrict = "}.+$";
|
var longLineRePostfixStrict = "}.+$";
|
||||||
var labelRe = /^\s*\[.*[^\\]]:/;
|
var labelRe = /^\s*\[.*[^\\]]:/;
|
||||||
var linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
var linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
||||||
|
var sternModeRe = /^([#>\s]*\s)?\S*$/;
|
||||||
var tokenTypeMap = {
|
var tokenTypeMap = {
|
||||||
"em_open": "e",
|
"em_open": "e",
|
||||||
"em_close": "E",
|
"em_close": "E",
|
||||||
|
|
@ -1852,7 +1898,8 @@ module.exports = {
|
||||||
var headingLineLength = Number(params.config.heading_line_length || lineLength);
|
var headingLineLength = Number(params.config.heading_line_length || lineLength);
|
||||||
var codeLineLength = Number(params.config.code_block_line_length || lineLength);
|
var codeLineLength = Number(params.config.code_block_line_length || lineLength);
|
||||||
var strict = !!params.config.strict;
|
var strict = !!params.config.strict;
|
||||||
var longLineRePostfix = strict ? longLineRePostfixStrict : longLineRePostfixRelaxed;
|
var stern = !!params.config.stern;
|
||||||
|
var longLineRePostfix = (strict || stern) ? longLineRePostfixStrict : longLineRePostfixRelaxed;
|
||||||
var longLineRe = new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
|
var longLineRe = new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
|
||||||
var longHeadingLineRe = new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
|
var longHeadingLineRe = new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
|
||||||
var longCodeLineRe = new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix);
|
var longCodeLineRe = new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix);
|
||||||
|
|
@ -1894,7 +1941,8 @@ module.exports = {
|
||||||
(includeTables || !inTable) &&
|
(includeTables || !inTable) &&
|
||||||
(includeHeadings || !isHeading) &&
|
(includeHeadings || !isHeading) &&
|
||||||
(strict ||
|
(strict ||
|
||||||
(!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
(!(stern && sternModeRe.test(line)) &&
|
||||||
|
!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
||||||
!labelRe.test(line))) &&
|
!labelRe.test(line))) &&
|
||||||
lengthRe.test(line)) {
|
lengthRe.test(line)) {
|
||||||
addErrorDetailIf(onError, lineNumber, length, line.length, null, null, [length + 1, line.length - length]);
|
addErrorDetailIf(onError, lineNumber, length, line.length, null, null, [length + 1, line.length - length]);
|
||||||
|
|
@ -1958,7 +2006,10 @@ module.exports = {
|
||||||
"tags": ["headings", "headers", "atx", "spaces"],
|
"tags": ["headings", "headers", "atx", "spaces"],
|
||||||
"function": function MD018(params, onError) {
|
"function": function MD018(params, onError) {
|
||||||
forEachLine(lineMetadata(), function (line, lineIndex, inCode) {
|
forEachLine(lineMetadata(), function (line, lineIndex, inCode) {
|
||||||
if (!inCode && /^#+[^#\s]/.test(line) && !/#\s*$/.test(line)) {
|
if (!inCode &&
|
||||||
|
/^#+[^#\s]/.test(line) &&
|
||||||
|
!/#\s*$/.test(line) &&
|
||||||
|
!line.startsWith("#️⃣")) {
|
||||||
var hashCount = /^#+/.exec(line)[0].length;
|
var hashCount = /^#+/.exec(line)[0].length;
|
||||||
addErrorContext(onError, lineIndex + 1, line.trim(), null, null, [1, hashCount + 1], {
|
addErrorContext(onError, lineIndex + 1, line.trim(), null, null, [1, hashCount + 1], {
|
||||||
"editColumn": hashCount + 1,
|
"editColumn": hashCount + 1,
|
||||||
|
|
@ -2329,23 +2380,47 @@ module.exports = {
|
||||||
"tags": ["ol"],
|
"tags": ["ol"],
|
||||||
"function": function MD029(params, onError) {
|
"function": function MD029(params, onError) {
|
||||||
var style = String(params.config.style || "one_or_ordered");
|
var style = String(params.config.style || "one_or_ordered");
|
||||||
flattenedLists().forEach(function (list) {
|
flattenedLists().filter(function (list) { return !list.unordered; }).forEach(function (list) {
|
||||||
if (!list.unordered) {
|
var items = list.items;
|
||||||
var listStyle_1 = style;
|
var current = 1;
|
||||||
if (listStyle_1 === "one_or_ordered") {
|
var incrementing = false;
|
||||||
var second = (list.items.length > 1) &&
|
// Check for incrementing number pattern 1/2/3 or 0/1/2
|
||||||
orderedListItemMarkerRe.exec(list.items[1].line);
|
if (items.length >= 2) {
|
||||||
listStyle_1 = (second && (second[1] !== "1")) ? "ordered" : "one";
|
var first = orderedListItemMarkerRe.exec(items[0].line);
|
||||||
}
|
var second = orderedListItemMarkerRe.exec(items[1].line);
|
||||||
var number_1 = (listStyle_1 === "zero") ? 0 : 1;
|
if (first && second) {
|
||||||
list.items.forEach(function (item) {
|
var firstNumber = first[1];
|
||||||
var match = orderedListItemMarkerRe.exec(item.line);
|
var secondNumber = second[1];
|
||||||
addErrorDetailIf(onError, item.lineNumber, String(number_1), !match || match[1], "Style: " + listStyleExamples[listStyle_1], null, rangeFromRegExp(item.line, listItemMarkerRe));
|
if ((secondNumber !== "1") || (firstNumber === "0")) {
|
||||||
if (listStyle_1 === "ordered") {
|
incrementing = true;
|
||||||
number_1++;
|
if (firstNumber === "0") {
|
||||||
|
current = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
// Determine effective style
|
||||||
|
var listStyle = style;
|
||||||
|
if (listStyle === "one_or_ordered") {
|
||||||
|
listStyle = incrementing ? "ordered" : "one";
|
||||||
|
}
|
||||||
|
// Force expected value for 0/0/0 and 1/1/1 patterns
|
||||||
|
if (listStyle === "zero") {
|
||||||
|
current = 0;
|
||||||
|
}
|
||||||
|
else if (listStyle === "one") {
|
||||||
|
current = 1;
|
||||||
|
}
|
||||||
|
// Validate each list item marker
|
||||||
|
items.forEach(function (item) {
|
||||||
|
var match = orderedListItemMarkerRe.exec(item.line);
|
||||||
|
if (match) {
|
||||||
|
addErrorDetailIf(onError, item.lineNumber, String(current), match[1], "Style: " + listStyleExamples[listStyle], null, rangeFromRegExp(item.line, listItemMarkerRe));
|
||||||
|
if (listStyle === "ordered") {
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -2395,6 +2470,7 @@ module.exports = {
|
||||||
"use strict";
|
"use strict";
|
||||||
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, forEachLine = _a.forEachLine, isBlankLine = _a.isBlankLine;
|
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, forEachLine = _a.forEachLine, isBlankLine = _a.isBlankLine;
|
||||||
var lineMetadata = require("./cache").lineMetadata;
|
var lineMetadata = require("./cache").lineMetadata;
|
||||||
|
var codeFencePrefixRe = /^(.*?)\s*[`~]/;
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": ["MD031", "blanks-around-fences"],
|
"names": ["MD031", "blanks-around-fences"],
|
||||||
"description": "Fenced code blocks should be surrounded by blank lines",
|
"description": "Fenced code blocks should be surrounded by blank lines",
|
||||||
|
|
@ -2409,9 +2485,10 @@ module.exports = {
|
||||||
if ((includeListItems || !inItem) &&
|
if ((includeListItems || !inItem) &&
|
||||||
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
((onTopFence && !isBlankLine(lines[i - 1])) ||
|
||||||
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
(onBottomFence && !isBlankLine(lines[i + 1])))) {
|
||||||
|
var _a = line.match(codeFencePrefixRe), prefix = _a[1];
|
||||||
addErrorContext(onError, i + 1, lines[i].trim(), null, null, null, {
|
addErrorContext(onError, i + 1, lines[i].trim(), null, null, null, {
|
||||||
"lineNumber": i + (onTopFence ? 1 : 2),
|
"lineNumber": i + (onTopFence ? 1 : 2),
|
||||||
"insertText": "\n"
|
"insertText": prefix + "\n"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -2517,17 +2594,28 @@ module.exports = {
|
||||||
else if ((type === "text") && !inLink) {
|
else if ((type === "text") && !inLink) {
|
||||||
while ((match = bareUrlRe.exec(content)) !== null) {
|
while ((match = bareUrlRe.exec(content)) !== null) {
|
||||||
var bareUrl = match[0];
|
var bareUrl = match[0];
|
||||||
var index = line.indexOf(content);
|
var matchIndex = match.index;
|
||||||
var range = (index === -1) ? null : [
|
var bareUrlLength = bareUrl.length;
|
||||||
line.indexOf(content) + match.index + 1,
|
// Allow "[https://example.com]" to avoid conflicts with
|
||||||
bareUrl.length
|
// MD011/no-reversed-links; allow quoting as another way
|
||||||
];
|
// of deliberately including a bare URL
|
||||||
var fixInfo = range ? {
|
var leftChar = content[matchIndex - 1];
|
||||||
"editColumn": range[0],
|
var rightChar = content[matchIndex + bareUrlLength];
|
||||||
"deleteCount": range[1],
|
if (!((leftChar === "[") && (rightChar === "]")) &&
|
||||||
"insertText": "<" + bareUrl + ">"
|
!((leftChar === "\"") && (rightChar === "\"")) &&
|
||||||
} : null;
|
!((leftChar === "'") && (rightChar === "'"))) {
|
||||||
addErrorContext(onError, lineNumber, bareUrl, null, null, range, fixInfo);
|
var index = line.indexOf(content);
|
||||||
|
var range = (index === -1) ? null : [
|
||||||
|
index + matchIndex + 1,
|
||||||
|
bareUrlLength
|
||||||
|
];
|
||||||
|
var fixInfo = range ? {
|
||||||
|
"editColumn": range[0],
|
||||||
|
"deleteCount": range[1],
|
||||||
|
"insertText": "<" + bareUrl + ">"
|
||||||
|
} : null;
|
||||||
|
addErrorContext(onError, lineNumber, bareUrl, null, null, range, fixInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -2614,50 +2702,90 @@ module.exports = {
|
||||||
},{"../helpers":2}],37:[function(require,module,exports){
|
},{"../helpers":2}],37:[function(require,module,exports){
|
||||||
// @ts-check
|
// @ts-check
|
||||||
"use strict";
|
"use strict";
|
||||||
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, forEachInlineChild = _a.forEachInlineChild;
|
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, forEachLine = _a.forEachLine;
|
||||||
var leftSpaceRe = /(?:^|\s)(\*\*?\*?|__?_?)\s.*[^\\]\1/g;
|
var lineMetadata = require("./cache").lineMetadata;
|
||||||
var rightSpaceRe = /(?:^|[^\\])(\*\*?\*?|__?_?).+\s\1(?:\s|$)/g;
|
var emphasisRe = /(^|[^\\])(?:(\*\*?\*?)|(__?_?))/g;
|
||||||
|
var asteriskListItemMarkerRe = /^(\s*)\*(\s+)/;
|
||||||
|
var leftSpaceRe = /^\s+/;
|
||||||
|
var rightSpaceRe = /\s+$/;
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": ["MD037", "no-space-in-emphasis"],
|
"names": ["MD037", "no-space-in-emphasis"],
|
||||||
"description": "Spaces inside emphasis markers",
|
"description": "Spaces inside emphasis markers",
|
||||||
"tags": ["whitespace", "emphasis"],
|
"tags": ["whitespace", "emphasis"],
|
||||||
"function": function MD037(params, onError) {
|
"function": function MD037(params, onError) {
|
||||||
forEachInlineChild(params, "text", function (token) {
|
forEachLine(lineMetadata(), function (line, lineIndex, inCode, onFence, inTable, inItem, inBreak) {
|
||||||
var content = token.content, lineNumber = token.lineNumber;
|
if (inCode || inBreak) {
|
||||||
var columnsReported = [];
|
// Emphasis has no meaning here
|
||||||
[leftSpaceRe, rightSpaceRe].forEach(function (spaceRe, index) {
|
return;
|
||||||
var match = null;
|
}
|
||||||
while ((match = spaceRe.exec(content)) !== null) {
|
if (inItem === 1) {
|
||||||
var fullText = match[0], marker = match[1];
|
// Trim overlapping '*' list item marker
|
||||||
var line = params.lines[lineNumber - 1];
|
line = line.replace(asteriskListItemMarkerRe, "$1 $2");
|
||||||
if (line.includes(fullText)) {
|
}
|
||||||
var text = fullText.trim();
|
var match = null;
|
||||||
var column = line.indexOf(text) + 1;
|
var emphasisIndex = -1;
|
||||||
if (!columnsReported.includes(column)) {
|
var emphasisLength = 0;
|
||||||
var length_1 = text.length;
|
var effectiveEmphasisLength = 0;
|
||||||
var markerLength = marker.length;
|
// Match all emphasis-looking runs in the line...
|
||||||
var emphasized = text.slice(markerLength, length_1 - markerLength);
|
while ((match = emphasisRe.exec(line))) {
|
||||||
var fixedText = "" + marker + emphasized.trim() + marker;
|
var matchIndex = match.index + match[1].length;
|
||||||
addErrorContext(onError, lineNumber, text, index === 0, index !== 0, [column, length_1], {
|
var matchLength = match[0].length - match[1].length;
|
||||||
"editColumn": column,
|
if (emphasisIndex === -1) {
|
||||||
"deleteCount": length_1,
|
// New run
|
||||||
"insertText": fixedText
|
emphasisIndex = matchIndex + matchLength;
|
||||||
});
|
emphasisLength = matchLength;
|
||||||
columnsReported.push(column);
|
effectiveEmphasisLength = matchLength;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
else if (matchLength === effectiveEmphasisLength) {
|
||||||
|
// Close current run
|
||||||
|
var content = line.substring(emphasisIndex, matchIndex);
|
||||||
|
var leftSpace = leftSpaceRe.test(content);
|
||||||
|
var rightSpace = rightSpaceRe.test(content);
|
||||||
|
if (leftSpace || rightSpace) {
|
||||||
|
// Report the violation
|
||||||
|
var contextStart = emphasisIndex - emphasisLength;
|
||||||
|
var contextEnd = matchIndex + effectiveEmphasisLength;
|
||||||
|
var context = line.substring(contextStart, contextEnd);
|
||||||
|
var column = contextStart + 1;
|
||||||
|
var length_1 = contextEnd - contextStart;
|
||||||
|
var leftMarker = line.substring(contextStart, emphasisIndex);
|
||||||
|
var rightMarker = match[2] || match[3];
|
||||||
|
var fixedText = "" + leftMarker + content.trim() + rightMarker;
|
||||||
|
addErrorContext(onError, lineIndex + 1, context, leftSpace, rightSpace, [column, length_1], {
|
||||||
|
"editColumn": column,
|
||||||
|
"deleteCount": length_1,
|
||||||
|
"insertText": fixedText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Reset
|
||||||
|
emphasisIndex = -1;
|
||||||
|
emphasisLength = 0;
|
||||||
|
effectiveEmphasisLength = 0;
|
||||||
|
}
|
||||||
|
else if (matchLength === 3) {
|
||||||
|
// Swap internal run length (1->2 or 2->1)
|
||||||
|
effectiveEmphasisLength = matchLength - effectiveEmphasisLength;
|
||||||
|
}
|
||||||
|
else if (effectiveEmphasisLength === 3) {
|
||||||
|
// Downgrade internal run (3->1 or 3->2)
|
||||||
|
effectiveEmphasisLength -= matchLength;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Upgrade to internal run (1->3 or 2->3)
|
||||||
|
effectiveEmphasisLength += matchLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
},{"../helpers":2}],38:[function(require,module,exports){
|
},{"../helpers":2,"./cache":3}],38:[function(require,module,exports){
|
||||||
// @ts-check
|
// @ts-check
|
||||||
"use strict";
|
"use strict";
|
||||||
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, filterTokens = _a.filterTokens, forEachInlineCodeSpan = _a.forEachInlineCodeSpan, newLineRe = _a.newLineRe;
|
var _a = require("../helpers"), addErrorContext = _a.addErrorContext, filterTokens = _a.filterTokens, forEachInlineCodeSpan = _a.forEachInlineCodeSpan, newLineRe = _a.newLineRe;
|
||||||
var leftSpaceRe = /^\s([^`]|$)/;
|
var leftSpaceRe = /^\s([^`]|$)/;
|
||||||
var rightSpaceRe = /[^`]\s$/;
|
var rightSpaceRe = /[^`]\s$/;
|
||||||
|
var singleLeftRightSpaceRe = /^\s\S+\s$/;
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"names": ["MD038", "no-space-in-code"],
|
"names": ["MD038", "no-space-in-code"],
|
||||||
"description": "Spaces inside code span elements",
|
"description": "Spaces inside code span elements",
|
||||||
|
|
@ -2680,7 +2808,8 @@ module.exports = {
|
||||||
rangeLineOffset = codeLines.length - 1;
|
rangeLineOffset = codeLines.length - 1;
|
||||||
fixIndex = 0;
|
fixIndex = 0;
|
||||||
}
|
}
|
||||||
if (left || right) {
|
var allowed = singleLeftRightSpaceRe.test(code);
|
||||||
|
if ((left || right) && !allowed) {
|
||||||
var codeLinesRange = codeLines[rangeLineOffset];
|
var codeLinesRange = codeLines[rangeLineOffset];
|
||||||
if (codeLines.length > 1) {
|
if (codeLines.length > 1) {
|
||||||
rangeLength = codeLinesRange.length + tickCount;
|
rangeLength = codeLinesRange.length + tickCount;
|
||||||
|
|
@ -2732,15 +2861,21 @@ module.exports = {
|
||||||
var right = linkText.trimRight().length !== linkText.length;
|
var right = linkText.trimRight().length !== linkText.length;
|
||||||
if (left || right) {
|
if (left || right) {
|
||||||
var line = params.lines[lineNumber - 1];
|
var line = params.lines[lineNumber - 1];
|
||||||
|
var range = null;
|
||||||
|
var fixInfo = null;
|
||||||
var match = line.slice(lineIndex).match(spaceInLinkRe);
|
var match = line.slice(lineIndex).match(spaceInLinkRe);
|
||||||
var column = match.index + lineIndex + 1;
|
if (match) {
|
||||||
var length_1 = match[0].length;
|
var column = match.index + lineIndex + 1;
|
||||||
lineIndex = column + length_1 - 1;
|
var length_1 = match[0].length;
|
||||||
addErrorContext(onError, lineNumber, "[" + linkText + "]", left, right, [column, length_1], {
|
range = [column, length_1];
|
||||||
"editColumn": column + 1,
|
fixInfo = {
|
||||||
"deleteCount": length_1 - 2,
|
"editColumn": column + 1,
|
||||||
"insertText": linkText.trim()
|
"deleteCount": length_1 - 2,
|
||||||
});
|
"insertText": linkText.trim()
|
||||||
|
};
|
||||||
|
lineIndex = column + length_1 - 1;
|
||||||
|
}
|
||||||
|
addErrorContext(onError, lineNumber, "[" + linkText + "]", left, right, range, fixInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((type === "softbreak") || (type === "hardbreak")) {
|
else if ((type === "softbreak") || (type === "hardbreak")) {
|
||||||
|
|
@ -3088,7 +3223,7 @@ module.exports = rules;
|
||||||
},{"../package.json":50,"./md001":5,"./md002":6,"./md003":7,"./md004":8,"./md005":9,"./md006":10,"./md007":11,"./md009":12,"./md010":13,"./md011":14,"./md012":15,"./md013":16,"./md014":17,"./md018":18,"./md019":19,"./md020":20,"./md021":21,"./md022":22,"./md023":23,"./md024":24,"./md025":25,"./md026":26,"./md027":27,"./md028":28,"./md029":29,"./md030":30,"./md031":31,"./md032":32,"./md033":33,"./md034":34,"./md035":35,"./md036":36,"./md037":37,"./md038":38,"./md039":39,"./md040":40,"./md041":41,"./md042":42,"./md043":43,"./md044":44,"./md045":45,"./md046":46,"./md047":47,"./md048":48,"url":59}],50:[function(require,module,exports){
|
},{"../package.json":50,"./md001":5,"./md002":6,"./md003":7,"./md004":8,"./md005":9,"./md006":10,"./md007":11,"./md009":12,"./md010":13,"./md011":14,"./md012":15,"./md013":16,"./md014":17,"./md018":18,"./md019":19,"./md020":20,"./md021":21,"./md022":22,"./md023":23,"./md024":24,"./md025":25,"./md026":26,"./md027":27,"./md028":28,"./md029":29,"./md030":30,"./md031":31,"./md032":32,"./md033":33,"./md034":34,"./md035":35,"./md036":36,"./md037":37,"./md038":38,"./md039":39,"./md040":40,"./md041":41,"./md042":42,"./md043":43,"./md044":44,"./md045":45,"./md046":46,"./md047":47,"./md048":48,"url":59}],50:[function(require,module,exports){
|
||||||
module.exports={
|
module.exports={
|
||||||
"name": "markdownlint",
|
"name": "markdownlint",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
|
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
|
||||||
"main": "lib/markdownlint.js",
|
"main": "lib/markdownlint.js",
|
||||||
"types": "lib/markdownlint.d.ts",
|
"types": "lib/markdownlint.d.ts",
|
||||||
|
|
@ -3121,25 +3256,26 @@ module.exports={
|
||||||
"markdown-it": "10.0.0"
|
"markdown-it": "10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "~13.5.0",
|
"@types/node": "~13.11.1",
|
||||||
"browserify": "~16.5.0",
|
"browserify": "~16.5.1",
|
||||||
"c8": "~7.0.1",
|
"c8": "~7.1.0",
|
||||||
"cpy-cli": "~3.0.0",
|
"cpy-cli": "~3.1.0",
|
||||||
"eslint": "~6.8.0",
|
"eslint": "~6.8.0",
|
||||||
"eslint-plugin-jsdoc": "~21.0.0",
|
"eslint-plugin-jsdoc": "~22.1.0",
|
||||||
"glob": "~7.1.6",
|
"glob": "~7.1.6",
|
||||||
"js-yaml": "~3.13.1",
|
"js-yaml": "~3.13.1",
|
||||||
"markdown-it-for-inline": "~0.1.1",
|
"markdown-it-for-inline": "~0.1.1",
|
||||||
"markdown-it-katex": "~2.0.3",
|
"markdown-it-katex": "~2.0.3",
|
||||||
"markdown-it-sub": "~1.0.0",
|
"markdown-it-sub": "~1.0.0",
|
||||||
"markdown-it-sup": "~1.0.0",
|
"markdown-it-sup": "~1.0.0",
|
||||||
"markdownlint-rule-helpers": "~0.6.0",
|
"markdownlint-rule-helpers": "~0.7.0",
|
||||||
"rimraf": "~3.0.0",
|
"rimraf": "~3.0.2",
|
||||||
"tape": "~4.13.0",
|
"tape": "~4.13.2",
|
||||||
|
"tape-player": "~0.1.0",
|
||||||
"toml": "~3.0.0",
|
"toml": "~3.0.0",
|
||||||
"tv4": "~1.3.0",
|
"tv4": "~1.3.0",
|
||||||
"typescript": "~3.7.5",
|
"typescript": "~3.8.3",
|
||||||
"uglify-js": "~3.7.6"
|
"uglify-js": "~3.8.1"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"markdown",
|
"markdown",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "markdownlint-rule-helpers",
|
"name": "markdownlint-rule-helpers",
|
||||||
"version": "0.7.0",
|
"version": "0.8.0",
|
||||||
"description": "A collection of markdownlint helper functions for custom rules",
|
"description": "A collection of markdownlint helper functions for custom rules",
|
||||||
"main": "helpers.js",
|
"main": "helpers.js",
|
||||||
"author": "David Anson (https://dlaa.me/)",
|
"author": "David Anson (https://dlaa.me/)",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "markdownlint",
|
"name": "markdownlint",
|
||||||
"version": "0.19.0",
|
"version": "0.20.0",
|
||||||
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
|
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.",
|
||||||
"main": "lib/markdownlint.js",
|
"main": "lib/markdownlint.js",
|
||||||
"types": "lib/markdownlint.d.ts",
|
"types": "lib/markdownlint.d.ts",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue