mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2026-01-05 23:48:49 +01:00
Add support for disabling/enabling rules within Markdown content (fixes #5).
This commit is contained in:
parent
071bba88fc
commit
31141cc3ed
10 changed files with 192 additions and 42 deletions
|
|
@ -6,9 +6,11 @@ var rules = require("./rules");
|
|||
var shared = require("./shared");
|
||||
|
||||
// Mappings from rule to description and tag to rules
|
||||
var allRuleNames = [];
|
||||
var ruleToDescription = {};
|
||||
var tagUpperToRules = {};
|
||||
rules.forEach(function forRule(rule) {
|
||||
allRuleNames.push(rule.name);
|
||||
ruleToDescription[rule.name] = rule.desc;
|
||||
// The following is useful for updating README.md
|
||||
// console.log("* **" + rule.name + "** - " + rule.desc);
|
||||
|
|
@ -55,11 +57,11 @@ function uniqueFilterForSorted(value, index, array) {
|
|||
}
|
||||
|
||||
// Lints a single string
|
||||
function lintContent(content, config, frontMatter) {
|
||||
function lintContent(content, config, frontMatter) { // eslint-disable-line
|
||||
// Remove front matter (if present at beginning of content)
|
||||
var frontMatterLines = 0;
|
||||
if (frontMatter) {
|
||||
var frontMatterMatch = frontMatter.exec(content);
|
||||
var frontMatterMatch = content.match(frontMatter);
|
||||
if (frontMatterMatch && !frontMatterMatch.index) {
|
||||
var contentMatched = frontMatterMatch[0];
|
||||
content = content.slice(contentMatched.length);
|
||||
|
|
@ -93,12 +95,6 @@ function lintContent(content, config, frontMatter) {
|
|||
}
|
||||
tokenLists[token.type].push(token);
|
||||
});
|
||||
// Create parameters for rules
|
||||
var params = {
|
||||
"tokens": tokens,
|
||||
"tokenLists": tokenLists,
|
||||
"lines": lines
|
||||
};
|
||||
// Merge rules/tags and sanitize config
|
||||
var defaultKey = Object.keys(config).filter(function forKey(key) {
|
||||
return key.toUpperCase() === "DEFAULT";
|
||||
|
|
@ -126,22 +122,64 @@ function lintContent(content, config, frontMatter) {
|
|||
});
|
||||
}
|
||||
});
|
||||
// Run each enabled rule
|
||||
// Create mapping of enabled rules per line
|
||||
var enabledRules = {};
|
||||
rules.forEach(function forRule(rule) {
|
||||
enabledRules[rule.name] = !!mergedRules[rule.name];
|
||||
});
|
||||
function forMatch(match) {
|
||||
var enabled = match[1].toUpperCase() === "EN";
|
||||
var items = match[2] ?
|
||||
match[2].trim().toUpperCase().split(/\s+/) :
|
||||
allRuleNames;
|
||||
items.forEach(function forItem(nameUpper) {
|
||||
if (ruleToDescription[nameUpper]) {
|
||||
enabledRules[nameUpper] = enabled;
|
||||
} else if (tagUpperToRules[nameUpper]) {
|
||||
tagUpperToRules[nameUpper].forEach(function forRule(ruleName) {
|
||||
enabledRules[ruleName] = enabled;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
var enabledRulesPerLineNumber = [ null ];
|
||||
lines.forEach(function forLine(line) {
|
||||
var match = shared.inlineCommentRe.exec(line);
|
||||
if (match) {
|
||||
enabledRules = shared.clone(enabledRules);
|
||||
while (match) {
|
||||
forMatch(match);
|
||||
match = shared.inlineCommentRe.exec(line);
|
||||
}
|
||||
}
|
||||
enabledRulesPerLineNumber.push(enabledRules);
|
||||
});
|
||||
// Create parameters for rules
|
||||
var params = {
|
||||
"tokens": tokens,
|
||||
"tokenLists": tokenLists,
|
||||
"lines": lines
|
||||
};
|
||||
// Run each rule
|
||||
var result = {};
|
||||
rules.forEach(function forRule(rule) {
|
||||
if (mergedRules[rule.name]) {
|
||||
// Configure rule
|
||||
params.options = mergedRules[rule.name];
|
||||
var errors = [];
|
||||
rule.func(params, errors);
|
||||
// Record any errors
|
||||
if (errors.length) {
|
||||
errors.sort(numberComparison);
|
||||
result[rule.name] = errors
|
||||
.filter(uniqueFilterForSorted)
|
||||
.map(function adjustLineNumbers(error) {
|
||||
return error + frontMatterLines;
|
||||
});
|
||||
// Configure rule
|
||||
params.options = mergedRules[rule.name];
|
||||
var errors = [];
|
||||
rule.func(params, errors);
|
||||
// Record any errors (significant performance benefit from length check)
|
||||
if (errors.length) {
|
||||
errors.sort(numberComparison);
|
||||
var filteredErrors = errors
|
||||
.filter(uniqueFilterForSorted)
|
||||
.filter(function removeDisabledRules(lineNumber) {
|
||||
return enabledRulesPerLineNumber[lineNumber][rule.name];
|
||||
})
|
||||
.map(function adjustLineNumbers(error) {
|
||||
return error + frontMatterLines;
|
||||
});
|
||||
if (filteredErrors.length) {
|
||||
result[rule.name] = filteredErrors;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
13
lib/rules.js
13
lib/rules.js
|
|
@ -640,12 +640,13 @@ module.exports = [
|
|||
"desc": "Inline HTML",
|
||||
"tags": [ "html" ],
|
||||
"func": function MD033(params, errors) {
|
||||
filterTokens(params, "html_block", function forToken(token) {
|
||||
errors.push(token.lineNumber);
|
||||
});
|
||||
forEachInlineChild(params, "html_inline", function forToken(token) {
|
||||
errors.push(token.lineNumber);
|
||||
});
|
||||
function forToken(token) {
|
||||
if (token.content.search(shared.inlineCommentRe) === -1) {
|
||||
errors.push(token.lineNumber);
|
||||
}
|
||||
}
|
||||
filterTokens(params, "html_block", forToken);
|
||||
forEachInlineChild(params, "html_inline", forToken);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -6,5 +6,23 @@ module.exports.newLineRe = /\r\n|\r|\n/;
|
|||
// Regular expression for matching common front matter
|
||||
module.exports.frontMatterRe = /^---$[^]*?^---$(\r\n|\r|\n)/m;
|
||||
|
||||
// Regular expression for matching inline disable/enable comments
|
||||
module.exports.inlineCommentRe =
|
||||
/<!--\s*markdownlint-(dis|en)able((?:\s+[a-z0-9_]+)*)\s*-->/ig;
|
||||
|
||||
// readFile options for reading with the UTF-8 encoding
|
||||
module.exports.utf8Encoding = { "encoding": "utf8" };
|
||||
|
||||
// Applies key/value pairs from src to dst, returning dst
|
||||
function assign(dst, src) {
|
||||
Object.keys(src).forEach(function forKey(key) {
|
||||
dst[key] = src[key];
|
||||
});
|
||||
return dst;
|
||||
}
|
||||
module.exports.assign = assign;
|
||||
|
||||
// Clones the key/value pairs of obj, returning the clone
|
||||
module.exports.clone = function clone(obj) {
|
||||
return assign({}, obj);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue