mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-16 22:10:13 +01:00
Add strings option to enable file-less scenarios.
This commit is contained in:
parent
fde1947031
commit
548e3d35cb
4 changed files with 176 additions and 87 deletions
|
|
@ -53,86 +53,90 @@ function uniqueFilterForSorted(value, index, array) {
|
|||
return (index === 0) || (value > array[index - 1]);
|
||||
}
|
||||
|
||||
// Lints a single string
|
||||
function lintContent(content, config) {
|
||||
// Parse content into tokens and lines
|
||||
var tokens = md.parse(content, {});
|
||||
var lines = content.split(shared.newLineRe);
|
||||
// Annotate tokens with line/lineNumber
|
||||
tokens.forEach(function forToken(token) {
|
||||
if (token.map) {
|
||||
token.line = lines[token.map[0]];
|
||||
token.lineNumber = token.map[0] + 1;
|
||||
// Trim bottom of token to exclude whitespace lines
|
||||
while (!(lines[token.map[1] - 1].trim())) {
|
||||
token.map[1]--;
|
||||
}
|
||||
// Annotate children with lineNumber
|
||||
var lineNumber = token.lineNumber;
|
||||
(token.children || []).forEach(function forChild(child) {
|
||||
child.lineNumber = lineNumber;
|
||||
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
|
||||
lineNumber++;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// Create parameters for rules
|
||||
var params = {
|
||||
"tokens": tokens,
|
||||
"lines": lines
|
||||
};
|
||||
// Merge rules/tags and sanitize config
|
||||
var mergedRules = {};
|
||||
var ruleDefault = (config.default === undefined) || !!config.default;
|
||||
rules.forEach(function forRule(rule) {
|
||||
mergedRules[rule.name] = ruleDefault;
|
||||
});
|
||||
Object.keys(config).forEach(function forKey(key) {
|
||||
var value = config[key];
|
||||
if (value) {
|
||||
if (!(value instanceof Object)) {
|
||||
value = {};
|
||||
}
|
||||
} else {
|
||||
value = false;
|
||||
}
|
||||
if (ruleToDescription[key]) {
|
||||
mergedRules[key] = value;
|
||||
} else if (tagToRules[key]) {
|
||||
tagToRules[key].forEach(function forRule(rule) {
|
||||
mergedRules[rule] = value;
|
||||
});
|
||||
}
|
||||
});
|
||||
// Run each enabled 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Lints a single file
|
||||
function lintFile(file, config, synchronous, callback) {
|
||||
// Callback for read file API
|
||||
function readFile(err, contents) {
|
||||
function lintContentWrapper(err, content) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
// Parse file into tokens and lines
|
||||
var tokens = md.parse(contents, {});
|
||||
var lines = contents.split(shared.newLineRe);
|
||||
// Annotate tokens with line/lineNumber
|
||||
tokens.forEach(function forToken(token) {
|
||||
if (token.map) {
|
||||
token.line = lines[token.map[0]];
|
||||
token.lineNumber = token.map[0] + 1;
|
||||
// Trim bottom of token to exclude whitespace lines
|
||||
while (!(lines[token.map[1] - 1].trim())) {
|
||||
token.map[1]--;
|
||||
}
|
||||
// Annotate children with lineNumber
|
||||
var lineNumber = token.lineNumber;
|
||||
(token.children || []).forEach(function forChild(child) {
|
||||
child.lineNumber = lineNumber;
|
||||
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
|
||||
lineNumber++;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// Create parameters for rules
|
||||
var params = {
|
||||
"tokens": tokens,
|
||||
"lines": lines
|
||||
};
|
||||
// Merge rules/tags and sanitize config
|
||||
var mergedRules = {};
|
||||
var ruleDefault = (config.default === undefined) || !!config.default;
|
||||
rules.forEach(function forRule(rule) {
|
||||
mergedRules[rule.name] = ruleDefault;
|
||||
});
|
||||
Object.keys(config).forEach(function forKey(key) {
|
||||
var value = config[key];
|
||||
if (value) {
|
||||
if (!(value instanceof Object)) {
|
||||
value = {};
|
||||
}
|
||||
} else {
|
||||
value = false;
|
||||
}
|
||||
if (ruleToDescription[key]) {
|
||||
mergedRules[key] = value;
|
||||
} else if (tagToRules[key]) {
|
||||
tagToRules[key].forEach(function forRule(rule) {
|
||||
mergedRules[rule] = value;
|
||||
});
|
||||
}
|
||||
});
|
||||
// Run each enabled 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
callback(null, result);
|
||||
return callback(err);
|
||||
}
|
||||
var result = lintContent(content, config);
|
||||
callback(null, result);
|
||||
}
|
||||
// Make a/synchronous call to read file
|
||||
if (synchronous) {
|
||||
readFile(null, fs.readFileSync(file, shared.utf8Encoding));
|
||||
lintContentWrapper(null, fs.readFileSync(file, shared.utf8Encoding));
|
||||
} else {
|
||||
fs.readFile(file, shared.utf8Encoding, readFile);
|
||||
fs.readFile(file, shared.utf8Encoding, lintContentWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,27 +160,34 @@ function markdownlint(options, callback) {
|
|||
options = options || {};
|
||||
callback = callback || function noop() {};
|
||||
var files = (options.files || []).slice();
|
||||
var strings = options.strings || {};
|
||||
var config = options.config || { "default": true };
|
||||
var synchronous = (callback === markdownlintSynchronousCallback);
|
||||
var results = new Results();
|
||||
// Lint each input file
|
||||
function lintFiles() {
|
||||
// Helper to lint the next file in the array
|
||||
function lintFilesArray() {
|
||||
var file = files.shift();
|
||||
if (file) {
|
||||
lintFile(file, config, synchronous, function lintedFile(err, result) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
// Record errors and lint next file
|
||||
results[file] = result;
|
||||
lintFiles();
|
||||
return callback(err);
|
||||
}
|
||||
// Record errors and lint next file
|
||||
results[file] = result;
|
||||
lintFilesArray();
|
||||
});
|
||||
} else {
|
||||
callback(null, results);
|
||||
}
|
||||
}
|
||||
lintFiles();
|
||||
// Lint strings
|
||||
Object.keys(strings).forEach(function forKey(key) {
|
||||
var result = lintContent(strings[key] || "", config);
|
||||
results[key] = result;
|
||||
});
|
||||
// Lint files
|
||||
lintFilesArray();
|
||||
// Return results
|
||||
if (synchronous) {
|
||||
return results;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue