mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 14:30:12 +01:00
Validate errorInfo.fixInfo object/properties in extension calls to onError.
This commit is contained in:
parent
5895ea62cb
commit
65f6d38978
3 changed files with 95 additions and 22 deletions
|
|
@ -44,6 +44,11 @@ module.exports.isEmptyString = function isEmptyString(str) {
|
||||||
return str.length === 0;
|
return str.length === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns true iff the input is an object
|
||||||
|
module.exports.isObject = function isObject(obj) {
|
||||||
|
return (obj !== null) && (typeof obj === "object") && !Array.isArray(obj);
|
||||||
|
};
|
||||||
|
|
||||||
// Returns true iff the input line is blank (no content)
|
// Returns true iff the input line is blank (no content)
|
||||||
// Example: Contains nothing, whitespace, or comments
|
// Example: Contains nothing, whitespace, or comments
|
||||||
const blankLineRe = />|(?:<!--.*?-->)/g;
|
const blankLineRe = />|(?:<!--.*?-->)/g;
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,37 @@ function lintContent(
|
||||||
lines[errorInfo.lineNumber - 1].length))) {
|
lines[errorInfo.lineNumber - 1].length))) {
|
||||||
throwError("range");
|
throwError("range");
|
||||||
}
|
}
|
||||||
|
const fixInfo = errorInfo.fixInfo;
|
||||||
|
if (fixInfo) {
|
||||||
|
if (!helpers.isObject(fixInfo)) {
|
||||||
|
throwError("fixInfo");
|
||||||
|
}
|
||||||
|
if ((fixInfo.lineNumber !== undefined) &&
|
||||||
|
(!helpers.isNumber(fixInfo.lineNumber) ||
|
||||||
|
(fixInfo.lineNumber < 1) ||
|
||||||
|
(fixInfo.lineNumber > lines.length))) {
|
||||||
|
throwError("fixInfo.lineNumber");
|
||||||
|
}
|
||||||
|
const effectiveLineNumber = fixInfo.lineNumber || errorInfo.lineNumber;
|
||||||
|
if ((fixInfo.editColumn !== undefined) &&
|
||||||
|
(!helpers.isNumber(fixInfo.editColumn) ||
|
||||||
|
(fixInfo.editColumn < 1) ||
|
||||||
|
(fixInfo.editColumn >
|
||||||
|
lines[effectiveLineNumber - 1].length + 1))) {
|
||||||
|
throwError("fixInfo.editColumn");
|
||||||
|
}
|
||||||
|
if ((fixInfo.deleteCount !== undefined) &&
|
||||||
|
(!helpers.isNumber(fixInfo.deleteCount) ||
|
||||||
|
(fixInfo.deleteCount < -1) ||
|
||||||
|
(fixInfo.deleteCount >
|
||||||
|
lines[effectiveLineNumber - 1].length))) {
|
||||||
|
throwError("fixInfo.deleteCount");
|
||||||
|
}
|
||||||
|
if ((fixInfo.insertText !== undefined) &&
|
||||||
|
!helpers.isString(fixInfo.insertText)) {
|
||||||
|
throwError("fixInfo.insertText");
|
||||||
|
}
|
||||||
|
}
|
||||||
errors.push({
|
errors.push({
|
||||||
"lineNumber": errorInfo.lineNumber + frontMatterLines.length,
|
"lineNumber": errorInfo.lineNumber + frontMatterLines.length,
|
||||||
"detail": errorInfo.detail || null,
|
"detail": errorInfo.detail || null,
|
||||||
|
|
|
||||||
|
|
@ -3177,19 +3177,32 @@ module.exports.customRulesOnErrorNull = function customRulesOnErrorNull(test) {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.customRulesOnErrorBad = function customRulesOnErrorBad(test) {
|
module.exports.customRulesOnErrorBad = function customRulesOnErrorBad(test) {
|
||||||
test.expect(44);
|
test.expect(84);
|
||||||
[
|
[
|
||||||
[ "lineNumber", [ null, "string" ] ],
|
[ "lineNumber", null, [ null, "string" ] ],
|
||||||
[ "detail", [ 10, [] ] ],
|
[ "detail", null, [ 10, [] ] ],
|
||||||
[ "context", [ 10, [] ] ],
|
[ "context", null, [ 10, [] ] ],
|
||||||
[ "range", [ 10, [], [ 10 ], [ 10, null ], [ 10, 11, 12 ] ] ]
|
[ "range", null, [ 10, [], [ 10 ], [ 10, null ], [ 10, 11, 12 ] ] ],
|
||||||
|
[ "fixInfo", null, [ 10, "string" ] ],
|
||||||
|
[ "fixInfo", "lineNumber", [ null, "string" ] ],
|
||||||
|
[ "fixInfo", "editColumn", [ null, "string" ] ],
|
||||||
|
[ "fixInfo", "deleteCount", [ null, "string" ] ],
|
||||||
|
[ "fixInfo", "insertText", [ 10, [] ] ]
|
||||||
].forEach(function forProperty(property) {
|
].forEach(function forProperty(property) {
|
||||||
const propertyName = property[0];
|
const [ propertyName, subPropertyName, propertyValues ] = property;
|
||||||
property[1].forEach(function forPropertyValue(propertyValue) {
|
propertyValues.forEach(function forPropertyValue(propertyValue) {
|
||||||
const badObject = {
|
const badObject = {
|
||||||
"lineNumber": 1
|
"lineNumber": 1
|
||||||
};
|
};
|
||||||
|
let propertyNames = null;
|
||||||
|
if (subPropertyName) {
|
||||||
|
badObject[propertyName] = {};
|
||||||
|
badObject[propertyName][subPropertyName] = propertyValue;
|
||||||
|
propertyNames = `${propertyName}.${subPropertyName}`;
|
||||||
|
} else {
|
||||||
badObject[propertyName] = propertyValue;
|
badObject[propertyName] = propertyValue;
|
||||||
|
propertyNames = propertyName;
|
||||||
|
}
|
||||||
const options = {
|
const options = {
|
||||||
"customRules": [
|
"customRules": [
|
||||||
{
|
{
|
||||||
|
|
@ -3211,7 +3224,7 @@ module.exports.customRulesOnErrorBad = function customRulesOnErrorBad(test) {
|
||||||
test.ok(err, "Did not get an error for bad object.");
|
test.ok(err, "Did not get an error for bad object.");
|
||||||
test.ok(err instanceof Error, "Error not instance of Error.");
|
test.ok(err instanceof Error, "Error not instance of Error.");
|
||||||
test.equal(err.message,
|
test.equal(err.message,
|
||||||
"Property '" + propertyName + "' of onError parameter is incorrect.",
|
"Property '" + propertyNames + "' of onError parameter is incorrect.",
|
||||||
"Incorrect message for bad object.");
|
"Incorrect message for bad object.");
|
||||||
return true;
|
return true;
|
||||||
}, "Did not get exception for bad object.");
|
}, "Did not get exception for bad object.");
|
||||||
|
|
@ -3222,17 +3235,28 @@ module.exports.customRulesOnErrorBad = function customRulesOnErrorBad(test) {
|
||||||
|
|
||||||
module.exports.customRulesOnErrorInvalid =
|
module.exports.customRulesOnErrorInvalid =
|
||||||
function customRulesOnErrorInvalid(test) {
|
function customRulesOnErrorInvalid(test) {
|
||||||
test.expect(36);
|
test.expect(68);
|
||||||
[
|
[
|
||||||
[ "lineNumber", [ -1, 0, 3, 4 ] ],
|
[ "lineNumber", null, [ -1, 0, 3, 4 ] ],
|
||||||
[ "range", [ [ 0, 1 ], [ 1, 0 ], [ 5, 1 ], [ 1, 5 ], [ 4, 2 ] ] ]
|
[ "range", null, [ [ 0, 1 ], [ 1, 0 ], [ 5, 1 ], [ 1, 5 ], [ 4, 2 ] ] ],
|
||||||
|
[ "fixInfo", "lineNumber", [ -1, 0, 3, 4 ] ],
|
||||||
|
[ "fixInfo", "editColumn", [ 0, 6 ] ],
|
||||||
|
[ "fixInfo", "deleteCount", [ -2, 5 ] ]
|
||||||
].forEach(function forProperty(property) {
|
].forEach(function forProperty(property) {
|
||||||
const propertyName = property[0];
|
const [ propertyName, subPropertyName, propertyValues ] = property;
|
||||||
property[1].forEach(function forPropertyValue(propertyValue) {
|
propertyValues.forEach(function forPropertyValue(propertyValue) {
|
||||||
const badObject = {
|
const badObject = {
|
||||||
"lineNumber": 1
|
"lineNumber": 1
|
||||||
};
|
};
|
||||||
|
let propertyNames = null;
|
||||||
|
if (subPropertyName) {
|
||||||
|
badObject[propertyName] = {};
|
||||||
|
badObject[propertyName][subPropertyName] = propertyValue;
|
||||||
|
propertyNames = `${propertyName}.${subPropertyName}`;
|
||||||
|
} else {
|
||||||
badObject[propertyName] = propertyValue;
|
badObject[propertyName] = propertyValue;
|
||||||
|
propertyNames = propertyName;
|
||||||
|
}
|
||||||
const options = {
|
const options = {
|
||||||
"customRules": [
|
"customRules": [
|
||||||
{
|
{
|
||||||
|
|
@ -3254,7 +3278,7 @@ module.exports.customRulesOnErrorInvalid =
|
||||||
test.ok(err, "Did not get an error for invalid object.");
|
test.ok(err, "Did not get an error for invalid object.");
|
||||||
test.ok(err instanceof Error, "Error not instance of Error.");
|
test.ok(err instanceof Error, "Error not instance of Error.");
|
||||||
test.equal(err.message,
|
test.equal(err.message,
|
||||||
`Property '${propertyName}' of onError parameter is incorrect.`,
|
`Property '${propertyNames}' of onError parameter is incorrect.`,
|
||||||
"Incorrect message for invalid object.");
|
"Incorrect message for invalid object.");
|
||||||
return true;
|
return true;
|
||||||
}, "Did not get exception for invalid object.");
|
}, "Did not get exception for invalid object.");
|
||||||
|
|
@ -3265,17 +3289,30 @@ module.exports.customRulesOnErrorInvalid =
|
||||||
|
|
||||||
module.exports.customRulesOnErrorValid =
|
module.exports.customRulesOnErrorValid =
|
||||||
function customRulesOnErrorValid(test) {
|
function customRulesOnErrorValid(test) {
|
||||||
test.expect(7);
|
test.expect(24);
|
||||||
[
|
[
|
||||||
[ "lineNumber", [ 1, 2 ] ],
|
[ "lineNumber", null, [ 1, 2 ] ],
|
||||||
[ "range", [ [ 1, 1 ], [ 1, 4 ], [ 2, 2 ], [ 3, 2 ], [ 4, 1 ] ] ]
|
[ "range", null, [ [ 1, 1 ], [ 1, 4 ], [ 2, 2 ], [ 3, 2 ], [ 4, 1 ] ] ],
|
||||||
|
[ "fixInfo", "lineNumber", [ 1, 2 ] ],
|
||||||
|
[ "fixInfo", "editColumn", [ 1, 2, 4, 5 ] ],
|
||||||
|
[ "fixInfo", "deleteCount", [ -1, 0, 1, 4 ] ],
|
||||||
|
[
|
||||||
|
"fixInfo",
|
||||||
|
"insertText",
|
||||||
|
[ "", "1", "123456", "\n", "\nText", "Text\n", "\nText\n" ]
|
||||||
|
]
|
||||||
].forEach(function forProperty(property) {
|
].forEach(function forProperty(property) {
|
||||||
const propertyName = property[0];
|
const [ propertyName, subPropertyName, propertyValues ] = property;
|
||||||
property[1].forEach(function forPropertyValue(propertyValue) {
|
propertyValues.forEach(function forPropertyValue(propertyValue) {
|
||||||
const goodObject = {
|
const goodObject = {
|
||||||
"lineNumber": 1
|
"lineNumber": 1
|
||||||
};
|
};
|
||||||
|
if (subPropertyName) {
|
||||||
|
goodObject[propertyName] = {};
|
||||||
|
goodObject[propertyName][subPropertyName] = propertyValue;
|
||||||
|
} else {
|
||||||
goodObject[propertyName] = propertyValue;
|
goodObject[propertyName] = propertyValue;
|
||||||
|
}
|
||||||
const options = {
|
const options = {
|
||||||
"customRules": [
|
"customRules": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue