mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-16 14:00:13 +01:00
Address new TypeScript warnings in core files, improve type definitions.
Some checks are pending
Checkers / linkcheck (push) Waiting to run
Checkers / spellcheck (push) Waiting to run
CI / build (20, macos-latest) (push) Waiting to run
CI / build (20, ubuntu-latest) (push) Waiting to run
CI / build (20, windows-latest) (push) Waiting to run
CI / build (22, macos-latest) (push) Waiting to run
CI / build (22, ubuntu-latest) (push) Waiting to run
CI / build (22, windows-latest) (push) Waiting to run
CI / build (24, macos-latest) (push) Waiting to run
CI / build (24, ubuntu-latest) (push) Waiting to run
CI / build (24, windows-latest) (push) Waiting to run
CI / pnpm (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
TestRepos / build (latest, ubuntu-latest) (push) Waiting to run
UpdateTestRepos / update (push) Waiting to run
Some checks are pending
Checkers / linkcheck (push) Waiting to run
Checkers / spellcheck (push) Waiting to run
CI / build (20, macos-latest) (push) Waiting to run
CI / build (20, ubuntu-latest) (push) Waiting to run
CI / build (20, windows-latest) (push) Waiting to run
CI / build (22, macos-latest) (push) Waiting to run
CI / build (22, ubuntu-latest) (push) Waiting to run
CI / build (22, windows-latest) (push) Waiting to run
CI / build (24, macos-latest) (push) Waiting to run
CI / build (24, ubuntu-latest) (push) Waiting to run
CI / build (24, windows-latest) (push) Waiting to run
CI / pnpm (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
TestRepos / build (latest, ubuntu-latest) (push) Waiting to run
UpdateTestRepos / update (push) Waiting to run
This commit is contained in:
parent
bd02390014
commit
7beb9fc9d0
32 changed files with 354 additions and 170 deletions
|
|
@ -54,6 +54,7 @@ export default [
|
||||||
"multiline-comment-style": [ "error", "separate-lines" ],
|
"multiline-comment-style": [ "error", "separate-lines" ],
|
||||||
"no-empty-function": "off",
|
"no-empty-function": "off",
|
||||||
"no-implicit-coercion": "off",
|
"no-implicit-coercion": "off",
|
||||||
|
"no-inline-comments": [ "error", { "ignorePattern": " @type \\{.+\\} " } ],
|
||||||
"no-magic-numbers": "off",
|
"no-magic-numbers": "off",
|
||||||
"no-param-reassign": "off",
|
"no-param-reassign": "off",
|
||||||
"no-plusplus": "off",
|
"no-plusplus": "off",
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ function assertLintResults(results: LintResults) {
|
||||||
assert.equal(results["string"][0].lineNumber, 1);
|
assert.equal(results["string"][0].lineNumber, 1);
|
||||||
assert.deepEqual(results["string"][0].ruleNames, [ "MD047", "single-trailing-newline" ]);
|
assert.deepEqual(results["string"][0].ruleNames, [ "MD047", "single-trailing-newline" ]);
|
||||||
assert.equal(results["string"][0].ruleDescription, "Files should end with a single newline character");
|
assert.equal(results["string"][0].ruleDescription, "Files should end with a single newline character");
|
||||||
assert.equal(results["string"][0].ruleInformation.replace(/v\d+\.\d+\.\d+/, "v0.0.0"), "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md047.md");
|
assert.equal(results["string"][0].ruleInformation?.replace(/v\d+\.\d+\.\d+/, "v0.0.0"), "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md047.md");
|
||||||
assert.equal(results["string"][0].errorDetail, null);
|
assert.equal(results["string"][0].errorDetail, null);
|
||||||
assert.equal(results["string"][0].errorContext, null);
|
assert.equal(results["string"][0].errorContext, null);
|
||||||
assert.deepEqual(results["string"][0].errorRange, [ 9, 1 ]);
|
assert.deepEqual(results["string"][0].errorRange, [ 9, 1 ]);
|
||||||
|
|
|
||||||
|
|
@ -111,10 +111,11 @@ module.exports.cloneIfArray = cloneIfArray;
|
||||||
/**
|
/**
|
||||||
* Clones the input if it is a URL.
|
* Clones the input if it is a URL.
|
||||||
*
|
*
|
||||||
* @param {Object} url Object of unknown type.
|
* @param {Object | undefined} url Object of unknown type.
|
||||||
* @returns {Object} Clone of obj iff obj is a URL.
|
* @returns {Object} Clone of obj iff obj is a URL.
|
||||||
*/
|
*/
|
||||||
function cloneIfUrl(url) {
|
function cloneIfUrl(url) {
|
||||||
|
// @ts-ignore
|
||||||
return isUrl(url) ? new URL(url) : url;
|
return isUrl(url) ? new URL(url) : url;
|
||||||
}
|
}
|
||||||
module.exports.cloneIfUrl = cloneIfUrl;
|
module.exports.cloneIfUrl = cloneIfUrl;
|
||||||
|
|
@ -139,7 +140,7 @@ module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) {
|
||||||
function isBlankLine(line) {
|
function isBlankLine(line) {
|
||||||
const startComment = "<!--";
|
const startComment = "<!--";
|
||||||
const endComment = "-->";
|
const endComment = "-->";
|
||||||
const removeComments = (s) => {
|
const removeComments = (/** @type {string} */ s) => {
|
||||||
while (true) {
|
while (true) {
|
||||||
const start = s.indexOf(startComment);
|
const start = s.indexOf(startComment);
|
||||||
const end = s.indexOf(endComment);
|
const end = s.indexOf(endComment);
|
||||||
|
|
@ -177,8 +178,8 @@ const startsWithPipeRe = /^ *\|/;
|
||||||
const notCrLfRe = /[^\r\n]/g;
|
const notCrLfRe = /[^\r\n]/g;
|
||||||
const notSpaceCrLfRe = /[^ \r\n]/g;
|
const notSpaceCrLfRe = /[^ \r\n]/g;
|
||||||
const trailingSpaceRe = / +[\r\n]/g;
|
const trailingSpaceRe = / +[\r\n]/g;
|
||||||
const replaceTrailingSpace = (s) => s.replace(notCrLfRe, safeCommentCharacter);
|
const replaceTrailingSpace = (/** @type {string} */ s) => s.replace(notCrLfRe, safeCommentCharacter);
|
||||||
module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
module.exports.clearHtmlCommentText = function clearHtmlCommentText(/** @type {string} */ text) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
||||||
const j = text.indexOf(htmlCommentEnd, i + 2);
|
const j = text.indexOf(htmlCommentEnd, i + 2);
|
||||||
|
|
@ -220,7 +221,7 @@ module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Escapes a string for use in a RegExp
|
// Escapes a string for use in a RegExp
|
||||||
module.exports.escapeForRegExp = function escapeForRegExp(str) {
|
module.exports.escapeForRegExp = function escapeForRegExp(/** @type {string} */ str) {
|
||||||
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -355,7 +356,7 @@ module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) {
|
||||||
|
|
||||||
// Determines if the front matter includes a title
|
// Determines if the front matter includes a title
|
||||||
module.exports.frontMatterHasTitle =
|
module.exports.frontMatterHasTitle =
|
||||||
function frontMatterHasTitle(frontMatterLines, frontMatterTitlePattern) {
|
function frontMatterHasTitle(/** @type {readonly string[]} */ frontMatterLines, /** @type {string} */ frontMatterTitlePattern) {
|
||||||
const ignoreFrontMatter =
|
const ignoreFrontMatter =
|
||||||
(frontMatterTitlePattern !== undefined) && !frontMatterTitlePattern;
|
(frontMatterTitlePattern !== undefined) && !frontMatterTitlePattern;
|
||||||
const frontMatterTitleRe =
|
const frontMatterTitleRe =
|
||||||
|
|
@ -367,18 +368,31 @@ module.exports.frontMatterHasTitle =
|
||||||
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result object for getReferenceLinkImageData.
|
||||||
|
*
|
||||||
|
* @typedef {Object} GetReferenceLinkImageDataResult
|
||||||
|
* @property {Map<string, number[][]>} references References.
|
||||||
|
* @property {Map<string, number[][]>} shortcuts Shortcuts.
|
||||||
|
* @property {Map<string, [number, string]>} definitions Definitions.
|
||||||
|
* @property {[string, number][]} duplicateDefinitions Duplicate definitions.
|
||||||
|
* @property {number[]} definitionLineIndices Definition line indices.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object with information about reference links and images.
|
* Returns an object with information about reference links and images.
|
||||||
*
|
*
|
||||||
* @param {MicromarkToken[]} tokens Micromark tokens.
|
* @param {MicromarkToken[]} tokens Micromark tokens.
|
||||||
* @returns {Object} Reference link/image data.
|
* @returns {GetReferenceLinkImageDataResult} Reference link/image data.
|
||||||
*/
|
*/
|
||||||
function getReferenceLinkImageData(tokens) {
|
function getReferenceLinkImageData(tokens) {
|
||||||
const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
const normalizeReference = (/** @type {string} */ s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
||||||
const getText = (t) => t?.children.filter((c) => c.type !== "blockQuotePrefix").map((c) => c.text).join("");
|
const getText = (/** @type {MicromarkToken} */ t) => t?.children.filter((c) => c.type !== "blockQuotePrefix").map((c) => c.text).join("");
|
||||||
|
/** @type {Map<string, number[][]>} */
|
||||||
const references = new Map();
|
const references = new Map();
|
||||||
|
/** @type {Map<string, number[][]>} */
|
||||||
const shortcuts = new Map();
|
const shortcuts = new Map();
|
||||||
const addReferenceToDictionary = (token, label, isShortcut) => {
|
const addReferenceToDictionary = (/** @type {MicromarkToken} */ token, /** @type {string} */ label, /** @type {boolean} */ isShortcut) => {
|
||||||
const referenceDatum = [
|
const referenceDatum = [
|
||||||
token.startLine - 1,
|
token.startLine - 1,
|
||||||
token.startColumn - 1,
|
token.startColumn - 1,
|
||||||
|
|
@ -390,8 +404,11 @@ function getReferenceLinkImageData(tokens) {
|
||||||
referenceData.push(referenceDatum);
|
referenceData.push(referenceDatum);
|
||||||
dictionary.set(reference, referenceData);
|
dictionary.set(reference, referenceData);
|
||||||
};
|
};
|
||||||
|
/** @type {Map<string, [number, string]>} */
|
||||||
const definitions = new Map();
|
const definitions = new Map();
|
||||||
|
/** @type {number[]} */
|
||||||
const definitionLineIndices = [];
|
const definitionLineIndices = [];
|
||||||
|
/** @type {[string, number][]} */
|
||||||
const duplicateDefinitions = [];
|
const duplicateDefinitions = [];
|
||||||
const filteredTokens =
|
const filteredTokens =
|
||||||
micromark.filterByTypes(
|
micromark.filterByTypes(
|
||||||
|
|
@ -433,7 +450,7 @@ function getReferenceLinkImageData(tokens) {
|
||||||
micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
|
micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
|
||||||
definitions.set(
|
definitions.set(
|
||||||
reference,
|
reference,
|
||||||
[ token.startLine - 1, destinationString ]
|
[ token.startLine - 1, destinationString || "" ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +507,7 @@ module.exports.getReferenceLinkImageData = getReferenceLinkImageData;
|
||||||
* Gets the most common line ending, falling back to the platform default.
|
* Gets the most common line ending, falling back to the platform default.
|
||||||
*
|
*
|
||||||
* @param {string} input Markdown content to analyze.
|
* @param {string} input Markdown content to analyze.
|
||||||
* @param {Object} [os] Node.js "os" module.
|
* @param {{EOL: string}} [os] Node.js "os" module.
|
||||||
* @returns {string} Preferred line ending.
|
* @returns {string} Preferred line ending.
|
||||||
*/
|
*/
|
||||||
function getPreferredLineEnding(input, os) {
|
function getPreferredLineEnding(input, os) {
|
||||||
|
|
@ -530,7 +547,7 @@ module.exports.getPreferredLineEnding = getPreferredLineEnding;
|
||||||
* Expands a path with a tilde to an absolute path.
|
* Expands a path with a tilde to an absolute path.
|
||||||
*
|
*
|
||||||
* @param {string} file Path that may begin with a tilde.
|
* @param {string} file Path that may begin with a tilde.
|
||||||
* @param {Object} os Node.js "os" module.
|
* @param {{homedir: () => string}} os Node.js "os" module.
|
||||||
* @returns {string} Absolute path (or original path).
|
* @returns {string} Absolute path (or original path).
|
||||||
*/
|
*/
|
||||||
function expandTildePath(file, os) {
|
function expandTildePath(file, os) {
|
||||||
|
|
@ -591,6 +608,7 @@ function convertLintErrorsVersion2To1(errors) {
|
||||||
* @returns {LintErrors} Lint errors (v0).
|
* @returns {LintErrors} Lint errors (v0).
|
||||||
*/
|
*/
|
||||||
function convertLintErrorsVersion2To0(errors) {
|
function convertLintErrorsVersion2To0(errors) {
|
||||||
|
/** @type {Object.<string, number[]>} */
|
||||||
const dictionary = {};
|
const dictionary = {};
|
||||||
for (const error of errors) {
|
for (const error of errors) {
|
||||||
const ruleName = error.ruleNames[0];
|
const ruleName = error.ruleNames[0];
|
||||||
|
|
@ -606,10 +624,11 @@ function convertLintErrorsVersion2To0(errors) {
|
||||||
* Copies and transforms lint results from resultVersion 3 to ?.
|
* Copies and transforms lint results from resultVersion 3 to ?.
|
||||||
*
|
*
|
||||||
* @param {LintResults} results Lint results (v3).
|
* @param {LintResults} results Lint results (v3).
|
||||||
* @param {(LintErrors) => LintErrors} transform Lint errors (v?).
|
* @param {(errors: LintErrors) => LintErrors} transform Lint errors (v?).
|
||||||
* @returns {LintResults} Lint results (v?).
|
* @returns {LintResults} Lint results (v?).
|
||||||
*/
|
*/
|
||||||
function copyAndTransformResults(results, transform) {
|
function copyAndTransformResults(results, transform) {
|
||||||
|
/** @type {Object.<string, LintErrors>} */
|
||||||
const newResults = {};
|
const newResults = {};
|
||||||
Object.defineProperty(newResults, "toString", { "value": results.toString });
|
Object.defineProperty(newResults, "toString", { "value": results.toString });
|
||||||
for (const key of Object.keys(results)) {
|
for (const key of Object.keys(results)) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = require("./shared.cjs");
|
||||||
* @returns {boolean} True iff the token is within an htmlFlow type.
|
* @returns {boolean} True iff the token is within an htmlFlow type.
|
||||||
*/
|
*/
|
||||||
function inHtmlFlow(token) {
|
function inHtmlFlow(token) {
|
||||||
|
// @ts-ignore
|
||||||
return Boolean(token[htmlFlowSymbol]);
|
return Boolean(token[htmlFlowSymbol]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,8 +127,11 @@ function filterByPredicate(tokens, allowed, transformChildren) {
|
||||||
* @returns {Token[]} Filtered tokens.
|
* @returns {Token[]} Filtered tokens.
|
||||||
*/
|
*/
|
||||||
function filterByTypes(tokens, types, htmlFlow) {
|
function filterByTypes(tokens, types, htmlFlow) {
|
||||||
const predicate = (token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token));
|
const predicate = (/** @type {Token} */ token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token));
|
||||||
const flatTokens = tokens[flatTokensSymbol];
|
/** @type {Token[]} */
|
||||||
|
const flatTokens =
|
||||||
|
// @ts-ignore
|
||||||
|
tokens[flatTokensSymbol];
|
||||||
if (flatTokens) {
|
if (flatTokens) {
|
||||||
return flatTokens.filter(predicate);
|
return flatTokens.filter(predicate);
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +167,7 @@ function getBlockQuotePrefixText(tokens, lineNumber, count = 1) {
|
||||||
function getDescendantsByType(parent, typePath) {
|
function getDescendantsByType(parent, typePath) {
|
||||||
let tokens = Array.isArray(parent) ? parent : [ parent ];
|
let tokens = Array.isArray(parent) ? parent : [ parent ];
|
||||||
for (const type of typePath) {
|
for (const type of typePath) {
|
||||||
const predicate = (token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type);
|
const predicate = (/** @type {Token} */ token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type);
|
||||||
tokens = tokens.flatMap((t) => t.children.filter(predicate));
|
tokens = tokens.flatMap((t) => t.children.filter(predicate));
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { filterByTypes } from "../helpers/micromark-helpers.cjs";
|
||||||
/** @typedef {import("markdownlint").RuleParams} RuleParams */
|
/** @typedef {import("markdownlint").RuleParams} RuleParams */
|
||||||
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
/** @typedef {import("markdownlint").MicromarkTokenType} MicromarkTokenType */
|
/** @typedef {import("markdownlint").MicromarkTokenType} MicromarkTokenType */
|
||||||
|
/** @typedef {import("../helpers/helpers.cjs").GetReferenceLinkImageDataResult} GetReferenceLinkImageDataResult */
|
||||||
|
|
||||||
/** @type {Map<string, object>} */
|
/** @type {Map<string, object>} */
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
|
|
@ -68,9 +69,10 @@ export function filterByTypesCached(types, htmlFlow) {
|
||||||
/**
|
/**
|
||||||
* Gets a reference link and image data object.
|
* Gets a reference link and image data object.
|
||||||
*
|
*
|
||||||
* @returns {Object} Reference link and image data object.
|
* @returns {GetReferenceLinkImageDataResult} Reference link and image data object.
|
||||||
*/
|
*/
|
||||||
export function getReferenceLinkImageData() {
|
export function getReferenceLinkImageData() {
|
||||||
|
// @ts-ignore
|
||||||
return getCached(
|
return getCached(
|
||||||
getReferenceLinkImageData.name,
|
getReferenceLinkImageData.name,
|
||||||
() => helpersGetReferenceLinkImageData(micromarkTokens())
|
() => helpersGetReferenceLinkImageData(micromarkTokens())
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
/** @type {string[]} */
|
||||||
export const deprecatedRuleNames = [];
|
export const deprecatedRuleNames = [];
|
||||||
export const fixableRuleNames = [
|
export const fixableRuleNames = [
|
||||||
"MD004", "MD005", "MD007", "MD009", "MD010", "MD011",
|
"MD004", "MD005", "MD007", "MD009", "MD010", "MD011",
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ function annotateAndFreezeTokens(tokens, lines) {
|
||||||
}
|
}
|
||||||
// Annotate children with lineNumber
|
// Annotate children with lineNumber
|
||||||
if (token.children) {
|
if (token.children) {
|
||||||
|
/** @type {number[]} */
|
||||||
const codeSpanExtraLines = [];
|
const codeSpanExtraLines = [];
|
||||||
if (token.children.some((child) => child.type === "code_inline")) {
|
if (token.children.some((child) => child.type === "code_inline")) {
|
||||||
forEachInlineCodeSpan(token.content, (code) => {
|
forEachInlineCodeSpan(token.content, (code) => {
|
||||||
|
|
@ -140,7 +141,7 @@ function annotateAndFreezeTokens(tokens, lines) {
|
||||||
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
|
if ((child.type === "softbreak") || (child.type === "hardbreak")) {
|
||||||
lineNumber++;
|
lineNumber++;
|
||||||
} else if (child.type === "code_inline") {
|
} else if (child.type === "code_inline") {
|
||||||
lineNumber += codeSpanExtraLines.shift();
|
lineNumber += codeSpanExtraLines.shift() || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,39 +26,38 @@ export function lintSync(options: Options | null): LintResults;
|
||||||
* @param {Configuration} config Configuration object.
|
* @param {Configuration} config Configuration object.
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
||||||
* @param {Object} fs File system implementation.
|
* @param {FsLike} fs File system implementation.
|
||||||
* @returns {Promise<Configuration>} Configuration object.
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function extendConfigPromise(config: Configuration, file: string, parsers: ConfigurationParser[] | undefined, fs: any): Promise<Configuration>;
|
export function extendConfigPromise(config: Configuration, file: string, parsers: ConfigurationParser[] | undefined, fs: FsLike): Promise<Configuration>;
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing
|
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing function(s).
|
||||||
* function(s).
|
* @param {FsLike | ReadConfigCallback} [fs] File system implementation.
|
||||||
* @param {Object} [fs] File system implementation.
|
|
||||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function readConfigAsync(file: string, parsers?: ConfigurationParser[] | ReadConfigCallback, fs?: any, callback?: ReadConfigCallback): void;
|
export function readConfigAsync(file: string, parsers?: ConfigurationParser[] | ReadConfigCallback, fs?: FsLike | ReadConfigCallback, callback?: ReadConfigCallback): void;
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
* @param {Object} [fs] File system implementation.
|
* @param {FsLike} [fs] File system implementation.
|
||||||
* @returns {Promise<Configuration>} Configuration object.
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function readConfigPromise(file: string, parsers?: ConfigurationParser[], fs?: any): Promise<Configuration>;
|
export function readConfigPromise(file: string, parsers?: ConfigurationParser[], fs?: FsLike): Promise<Configuration>;
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
* @param {Object} [fs] File system implementation.
|
* @param {FsLike} [fs] File system implementation.
|
||||||
* @returns {Configuration} Configuration object.
|
* @returns {Configuration} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: any): Configuration;
|
export function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: FsLike): Configuration;
|
||||||
/**
|
/**
|
||||||
* Applies the specified fix to a Markdown content line.
|
* Applies the specified fix to a Markdown content line.
|
||||||
*
|
*
|
||||||
|
|
@ -82,6 +81,19 @@ export function applyFixes(input: string, errors: LintError[]): string;
|
||||||
* @returns {string} SemVer string.
|
* @returns {string} SemVer string.
|
||||||
*/
|
*/
|
||||||
export function getVersion(): string;
|
export function getVersion(): string;
|
||||||
|
/**
|
||||||
|
* Result object for removeFrontMatter.
|
||||||
|
*/
|
||||||
|
export type RemoveFrontMatterResult = {
|
||||||
|
/**
|
||||||
|
* Markdown content.
|
||||||
|
*/
|
||||||
|
content: string;
|
||||||
|
/**
|
||||||
|
* Front matter lines.
|
||||||
|
*/
|
||||||
|
frontMatterLines: string[];
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Result object for getEffectiveConfig.
|
* Result object for getEffectiveConfig.
|
||||||
*/
|
*/
|
||||||
|
|
@ -120,6 +132,27 @@ export type EnabledRulesPerLineNumberResult = {
|
||||||
*/
|
*/
|
||||||
rulesSeverity: Map<string, "error" | "warning">;
|
rulesSeverity: Map<string, "error" | "warning">;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Node fs instance (or compatible object).
|
||||||
|
*/
|
||||||
|
export type FsLike = {
|
||||||
|
/**
|
||||||
|
* access method.
|
||||||
|
*/
|
||||||
|
access: (path: string, callback: (err: Error) => void) => void;
|
||||||
|
/**
|
||||||
|
* accessSync method.
|
||||||
|
*/
|
||||||
|
accessSync: (path: string) => void;
|
||||||
|
/**
|
||||||
|
* readFile method.
|
||||||
|
*/
|
||||||
|
readFile: (path: string, encoding: string, callback: (err: Error, data: string) => void) => void;
|
||||||
|
/**
|
||||||
|
* readFileSync method.
|
||||||
|
*/
|
||||||
|
readFileSync: (path: string, encoding: string) => string;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Function to implement rule logic.
|
* Function to implement rule logic.
|
||||||
*/
|
*/
|
||||||
|
|
@ -418,7 +451,7 @@ export type Options = {
|
||||||
/**
|
/**
|
||||||
* File system implementation.
|
* File system implementation.
|
||||||
*/
|
*/
|
||||||
fs?: any;
|
fs?: FsLike;
|
||||||
/**
|
/**
|
||||||
* True to catch exceptions.
|
* True to catch exceptions.
|
||||||
*/
|
*/
|
||||||
|
|
@ -467,15 +500,15 @@ export type LintError = {
|
||||||
/**
|
/**
|
||||||
* Link to more information.
|
* Link to more information.
|
||||||
*/
|
*/
|
||||||
ruleInformation: string;
|
ruleInformation: string | null;
|
||||||
/**
|
/**
|
||||||
* Detail about the error.
|
* Detail about the error.
|
||||||
*/
|
*/
|
||||||
errorDetail: string;
|
errorDetail: string | null;
|
||||||
/**
|
/**
|
||||||
* Context for the error.
|
* Context for the error.
|
||||||
*/
|
*/
|
||||||
errorContext: string;
|
errorContext: string | null;
|
||||||
/**
|
/**
|
||||||
* Column number (1-based) and length.
|
* Column number (1-based) and length.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,17 @@ function validateRuleList(ruleList, synchronous) {
|
||||||
// No need to validate if only using built-in rules
|
// No need to validate if only using built-in rules
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
/** @type {Object.<string, boolean>} */
|
||||||
const allIds = {};
|
const allIds = {};
|
||||||
for (const [ index, rule ] of ruleList.entries()) {
|
for (const [ index, rule ] of ruleList.entries()) {
|
||||||
const customIndex = index - rules.length;
|
const customIndex = index - rules.length;
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/reject-any-type, jsdoc/require-jsdoc
|
||||||
function newError(property, value) {
|
function newError(/** @type {string} */ property, /** @type {any} */ value) {
|
||||||
return new Error(
|
return new Error(
|
||||||
`Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`);
|
`Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`);
|
||||||
}
|
}
|
||||||
for (const property of [ "names", "tags" ]) {
|
for (const property of [ "names", "tags" ]) {
|
||||||
|
// @ts-ignore
|
||||||
const value = rule[property];
|
const value = rule[property];
|
||||||
if (!result &&
|
if (!result &&
|
||||||
(!value || !Array.isArray(value) || (value.length === 0) ||
|
(!value || !Array.isArray(value) || (value.length === 0) ||
|
||||||
|
|
@ -45,6 +47,7 @@ function validateRuleList(ruleList, synchronous) {
|
||||||
[ "function", "function" ]
|
[ "function", "function" ]
|
||||||
]) {
|
]) {
|
||||||
const property = propertyInfo[0];
|
const property = propertyInfo[0];
|
||||||
|
// @ts-ignore
|
||||||
const value = rule[property];
|
const value = rule[property];
|
||||||
if (!result && (!value || (typeof value !== propertyInfo[1]))) {
|
if (!result && (!value || (typeof value !== propertyInfo[1]))) {
|
||||||
result = newError(property, value);
|
result = newError(property, value);
|
||||||
|
|
@ -113,10 +116,12 @@ function newResults(ruleList) {
|
||||||
*
|
*
|
||||||
* @param {boolean} useAlias True if rule alias should be used instead of name.
|
* @param {boolean} useAlias True if rule alias should be used instead of name.
|
||||||
* @returns {string} String representation of the instance.
|
* @returns {string} String representation of the instance.
|
||||||
|
* @this {LintResults}
|
||||||
*/
|
*/
|
||||||
function toString(useAlias) {
|
function toString(useAlias) {
|
||||||
// eslint-disable-next-line consistent-this, no-invalid-this, unicorn/no-this-assignment
|
// eslint-disable-next-line consistent-this, unicorn/no-this-assignment
|
||||||
const lintResults = this;
|
const lintResults = this;
|
||||||
|
/** @type {Object.<string, Rule> | null} */
|
||||||
let ruleNameToRule = null;
|
let ruleNameToRule = null;
|
||||||
const results = [];
|
const results = [];
|
||||||
const keys = Object.keys(lintResults);
|
const keys = Object.keys(lintResults);
|
||||||
|
|
@ -127,6 +132,7 @@ function newResults(ruleList) {
|
||||||
for (const result of fileResults) {
|
for (const result of fileResults) {
|
||||||
const ruleMoniker = result.ruleNames ?
|
const ruleMoniker = result.ruleNames ?
|
||||||
result.ruleNames.join("/") :
|
result.ruleNames.join("/") :
|
||||||
|
// @ts-ignore
|
||||||
(result.ruleName + "/" + result.ruleAlias);
|
(result.ruleName + "/" + result.ruleAlias);
|
||||||
results.push(
|
results.push(
|
||||||
file + ": " +
|
file + ": " +
|
||||||
|
|
@ -173,14 +179,23 @@ function newResults(ruleList) {
|
||||||
return lintResults;
|
return lintResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result object for removeFrontMatter.
|
||||||
|
*
|
||||||
|
* @typedef {Object} RemoveFrontMatterResult
|
||||||
|
* @property {string} content Markdown content.
|
||||||
|
* @property {string[]} frontMatterLines Front matter lines.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove front matter (if present at beginning of content).
|
* Remove front matter (if present at beginning of content).
|
||||||
*
|
*
|
||||||
* @param {string} content Markdown content.
|
* @param {string} content Markdown content.
|
||||||
* @param {RegExp | null} frontMatter Regular expression to match front matter.
|
* @param {RegExp | null} frontMatter Regular expression to match front matter.
|
||||||
* @returns {Object} Trimmed content and front matter lines.
|
* @returns {RemoveFrontMatterResult} Trimmed content and front matter lines.
|
||||||
*/
|
*/
|
||||||
function removeFrontMatter(content, frontMatter) {
|
function removeFrontMatter(content, frontMatter) {
|
||||||
|
/** @type {string[]} */
|
||||||
let frontMatterLines = [];
|
let frontMatterLines = [];
|
||||||
if (frontMatter) {
|
if (frontMatter) {
|
||||||
const frontMatterMatch = content.match(frontMatter);
|
const frontMatterMatch = content.match(frontMatter);
|
||||||
|
|
@ -207,6 +222,7 @@ function removeFrontMatter(content, frontMatter) {
|
||||||
* @returns {Object.<string, string[]>} Map of alias to rule name.
|
* @returns {Object.<string, string[]>} Map of alias to rule name.
|
||||||
*/
|
*/
|
||||||
function mapAliasToRuleNames(ruleList) {
|
function mapAliasToRuleNames(ruleList) {
|
||||||
|
/** @type {Object.<string, string[]>} */
|
||||||
const aliasToRuleNames = {};
|
const aliasToRuleNames = {};
|
||||||
// const tagToRuleNames = {};
|
// const tagToRuleNames = {};
|
||||||
for (const rule of ruleList) {
|
for (const rule of ruleList) {
|
||||||
|
|
@ -357,7 +373,7 @@ function getEnabledRulesPerLineNumber(
|
||||||
const enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
const enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function handleInlineConfig(input, forEachMatch, forEachLine) {
|
function handleInlineConfig(/** @type {string[]} */ input, /** @type {(act: string, par: string, ind: number) => void} */ forEachMatch, /** @type {(() => void)|undefined} */ forEachLine = undefined) {
|
||||||
for (const [ lineIndex, line ] of input.entries()) {
|
for (const [ lineIndex, line ] of input.entries()) {
|
||||||
if (!noInlineConfig) {
|
if (!noInlineConfig) {
|
||||||
let match = null;
|
let match = null;
|
||||||
|
|
@ -378,7 +394,7 @@ function getEnabledRulesPerLineNumber(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function configureFile(action, parameter) {
|
function configureFile(/** @type {string} */ action, /** @type {string} */ parameter) {
|
||||||
if (action === "CONFIGURE-FILE") {
|
if (action === "CONFIGURE-FILE") {
|
||||||
const { "config": parsed } = parseConfiguration(
|
const { "config": parsed } = parseConfiguration(
|
||||||
"CONFIGURE-FILE", parameter, configParsers
|
"CONFIGURE-FILE", parameter, configParsers
|
||||||
|
|
@ -392,7 +408,7 @@ function getEnabledRulesPerLineNumber(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function applyEnableDisable(action, parameter, state) {
|
function applyEnableDisable(/** @type {string} */ action, /** @type {string} */ parameter, /** @type {Map<string, boolean>} */ state) {
|
||||||
state = new Map(state);
|
state = new Map(state);
|
||||||
const enabled = (action.startsWith("ENABLE"));
|
const enabled = (action.startsWith("ENABLE"));
|
||||||
const trimmed = parameter && parameter.trim();
|
const trimmed = parameter && parameter.trim();
|
||||||
|
|
@ -406,13 +422,13 @@ function getEnabledRulesPerLineNumber(
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function enableDisableFile(action, parameter) {
|
function enableDisableFile(/** @type {string} */ action, /** @type {string} */ parameter) {
|
||||||
if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) {
|
if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) {
|
||||||
enabledRules = applyEnableDisable(action, parameter, enabledRules);
|
enabledRules = applyEnableDisable(action, parameter, enabledRules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function captureRestoreEnableDisable(action, parameter) {
|
function captureRestoreEnableDisable(/** @type {string} */ action, /** @type {string} */ parameter) {
|
||||||
if (action === "CAPTURE") {
|
if (action === "CAPTURE") {
|
||||||
capturedRules = enabledRules;
|
capturedRules = enabledRules;
|
||||||
} else if (action === "RESTORE") {
|
} else if (action === "RESTORE") {
|
||||||
|
|
@ -426,7 +442,7 @@ function getEnabledRulesPerLineNumber(
|
||||||
enabledRulesPerLineNumber.push(enabledRules);
|
enabledRulesPerLineNumber.push(enabledRules);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function disableLineNextLine(action, parameter, lineNumber) {
|
function disableLineNextLine(/** @type {string} */ action, /** @type {string} */ parameter, /** @type {number} */ lineNumber) {
|
||||||
const disableLine = (action === "DISABLE-LINE");
|
const disableLine = (action === "DISABLE-LINE");
|
||||||
const disableNextLine = (action === "DISABLE-NEXT-LINE");
|
const disableNextLine = (action === "DISABLE-NEXT-LINE");
|
||||||
if (disableLine || disableNextLine) {
|
if (disableLine || disableNextLine) {
|
||||||
|
|
@ -496,7 +512,8 @@ function lintContent(
|
||||||
synchronous,
|
synchronous,
|
||||||
callback) {
|
callback) {
|
||||||
// Provide a consistent error-reporting callback
|
// Provide a consistent error-reporting callback
|
||||||
const callbackError = (error) => callback(error instanceof Error ? error : new Error(error));
|
// eslint-disable-next-line jsdoc/reject-any-type
|
||||||
|
const callbackError = (/** @type {any} */ error) => callback(error instanceof Error ? error : new Error(error));
|
||||||
// Remove UTF-8 byte order marker (if present)
|
// Remove UTF-8 byte order marker (if present)
|
||||||
content = content.replace(/^\uFEFF/, "");
|
content = content.replace(/^\uFEFF/, "");
|
||||||
// Remove front matter
|
// Remove front matter
|
||||||
|
|
@ -531,7 +548,7 @@ function lintContent(
|
||||||
// Parse content into lines and get markdown-it tokens
|
// Parse content into lines and get markdown-it tokens
|
||||||
const lines = content.split(helpers.newLineRe);
|
const lines = content.split(helpers.newLineRe);
|
||||||
// Function to run after fetching markdown-it tokens (when needed)
|
// Function to run after fetching markdown-it tokens (when needed)
|
||||||
const lintContentInternal = (markdownitTokens) => {
|
const lintContentInternal = (/** @type {MarkdownItToken[]} */ markdownitTokens) => {
|
||||||
// Create (frozen) parameters for rules
|
// Create (frozen) parameters for rules
|
||||||
/** @type {MarkdownParsers} */
|
/** @type {MarkdownParsers} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
@ -585,15 +602,17 @@ function lintContent(
|
||||||
...paramsBase,
|
...paramsBase,
|
||||||
...tokens,
|
...tokens,
|
||||||
parsers,
|
parsers,
|
||||||
|
/** @type {RuleConfiguration} */
|
||||||
|
// @ts-ignore
|
||||||
"config": effectiveConfig[ruleName]
|
"config": effectiveConfig[ruleName]
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function throwError(property) {
|
function throwError(/** @type {string} */ property) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Value of '${property}' passed to onError by '${ruleName}' is incorrect for '${name}'.`);
|
`Value of '${property}' passed to onError by '${ruleName}' is incorrect for '${name}'.`);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function onError(errorInfo) {
|
function onError(/** @type {RuleOnErrorInfo} */ errorInfo) {
|
||||||
if (!errorInfo ||
|
if (!errorInfo ||
|
||||||
!helpers.isNumber(errorInfo.lineNumber) ||
|
!helpers.isNumber(errorInfo.lineNumber) ||
|
||||||
(errorInfo.lineNumber < 1) ||
|
(errorInfo.lineNumber < 1) ||
|
||||||
|
|
@ -683,6 +702,7 @@ function lintContent(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Call (possibly external) rule function to report errors
|
// Call (possibly external) rule function to report errors
|
||||||
|
// @ts-ignore
|
||||||
const catchCallsOnError = (error) => onError({
|
const catchCallsOnError = (error) => onError({
|
||||||
"lineNumber": 1,
|
"lineNumber": 1,
|
||||||
"detail": `This rule threw an exception: ${error.message || error}`
|
"detail": `This rule threw an exception: ${error.message || error}`
|
||||||
|
|
@ -772,7 +792,7 @@ function lintContent(
|
||||||
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
||||||
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
||||||
* @param {number} resultVersion Version of the LintResults object to return.
|
* @param {number} resultVersion Version of the LintResults object to return.
|
||||||
* @param {Object} fs File system implementation.
|
* @param {FsLike} fs File system implementation.
|
||||||
* @param {boolean} synchronous Whether to execute synchronously.
|
* @param {boolean} synchronous Whether to execute synchronously.
|
||||||
* @param {LintContentCallback} callback Callback (err, result) function.
|
* @param {LintContentCallback} callback Callback (err, result) function.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
|
|
@ -792,7 +812,7 @@ function lintFile(
|
||||||
synchronous,
|
synchronous,
|
||||||
callback) {
|
callback) {
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function lintContentWrapper(err, content) {
|
function lintContentWrapper(/** @type {Error | null} */ err, /** @type {string} */ content) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
@ -832,6 +852,8 @@ function lintInput(options, synchronous, callback) {
|
||||||
// Normalize inputs
|
// Normalize inputs
|
||||||
options = options || {};
|
options = options || {};
|
||||||
callback = callback || function noop() {};
|
callback = callback || function noop() {};
|
||||||
|
/** @type {Rule[]} */
|
||||||
|
// @ts-ignore
|
||||||
const customRuleList =
|
const customRuleList =
|
||||||
[ options.customRules || [] ]
|
[ options.customRules || [] ]
|
||||||
.flat()
|
.flat()
|
||||||
|
|
@ -851,6 +873,7 @@ function lintInput(options, synchronous, callback) {
|
||||||
callback(ruleErr);
|
callback(ruleErr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/** @type {string[]} */
|
||||||
let files = [];
|
let files = [];
|
||||||
if (Array.isArray(options.files)) {
|
if (Array.isArray(options.files)) {
|
||||||
files = [ ...options.files ];
|
files = [ ...options.files ];
|
||||||
|
|
@ -866,11 +889,14 @@ function lintInput(options, synchronous, callback) {
|
||||||
options.frontMatter;
|
options.frontMatter;
|
||||||
const handleRuleFailures = !!options.handleRuleFailures;
|
const handleRuleFailures = !!options.handleRuleFailures;
|
||||||
const noInlineConfig = !!options.noInlineConfig;
|
const noInlineConfig = !!options.noInlineConfig;
|
||||||
|
// @ts-ignore
|
||||||
// eslint-disable-next-line dot-notation
|
// eslint-disable-next-line dot-notation
|
||||||
const resultVersion = (options["resultVersion"] === undefined) ? 3 : options["resultVersion"];
|
const resultVersion = (options["resultVersion"] === undefined) ? 3 : options["resultVersion"];
|
||||||
const markdownItFactory =
|
const markdownItFactory =
|
||||||
options.markdownItFactory ||
|
options.markdownItFactory ||
|
||||||
(() => { throw new Error("The option 'markdownItFactory' was required (due to the option 'customRules' including a rule requiring the 'markdown-it' parser), but 'markdownItFactory' was not set."); });
|
(() => { throw new Error("The option 'markdownItFactory' was required (due to the option 'customRules' including a rule requiring the 'markdown-it' parser), but 'markdownItFactory' was not set."); });
|
||||||
|
/** @type {FsLike} */
|
||||||
|
// @ts-ignore
|
||||||
const fs = options.fs || nodeFs;
|
const fs = options.fs || nodeFs;
|
||||||
const aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
const aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
||||||
const results = newResults(ruleList);
|
const results = newResults(ruleList);
|
||||||
|
|
@ -878,14 +904,16 @@ function lintInput(options, synchronous, callback) {
|
||||||
let concurrency = 0;
|
let concurrency = 0;
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function lintWorker() {
|
function lintWorker() {
|
||||||
let currentItem = null;
|
/** @type {string | undefined} */
|
||||||
|
let currentItem = undefined;
|
||||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||||
function lintWorkerCallback(err, result) {
|
function lintWorkerCallback(/** @type {Error | null} */ err, /** @type {LintError[] | undefined} */ result) {
|
||||||
concurrency--;
|
concurrency--;
|
||||||
if (err) {
|
if (err) {
|
||||||
done = true;
|
done = true;
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
// @ts-ignore
|
||||||
results[currentItem] = result;
|
results[currentItem] = result;
|
||||||
if (!synchronous) {
|
if (!synchronous) {
|
||||||
lintWorker();
|
lintWorker();
|
||||||
|
|
@ -894,10 +922,9 @@ function lintInput(options, synchronous, callback) {
|
||||||
}
|
}
|
||||||
if (done) {
|
if (done) {
|
||||||
// Abort for error or nothing left to do
|
// Abort for error or nothing left to do
|
||||||
} else if (files.length > 0) {
|
} else if ((currentItem = files.shift())) {
|
||||||
// Lint next file
|
// Lint next file
|
||||||
concurrency++;
|
concurrency++;
|
||||||
currentItem = files.shift();
|
|
||||||
lintFile(
|
lintFile(
|
||||||
ruleList,
|
ruleList,
|
||||||
aliasToRuleNames,
|
aliasToRuleNames,
|
||||||
|
|
@ -1013,15 +1040,24 @@ export function lintSync(options) {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node fs instance (or compatible object).
|
||||||
|
*
|
||||||
|
* @typedef FsLike
|
||||||
|
* @property {(path: string, callback: (err: Error) => void) => void} access access method.
|
||||||
|
* @property {(path: string) => void} accessSync accessSync method.
|
||||||
|
* @property {(path: string, encoding: string, callback: (err: Error, data: string) => void) => void} readFile readFile method.
|
||||||
|
* @property {(path: string, encoding: string) => string} readFileSync readFileSync method.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve referenced "extends" path in a configuration file
|
* Resolve referenced "extends" path in a configuration file
|
||||||
* using path.resolve() with require.resolve() as a fallback.
|
* using path.resolve() with require.resolve() as a fallback.
|
||||||
*
|
*
|
||||||
* @param {string} configFile Configuration file name.
|
* @param {string} configFile Configuration file name.
|
||||||
* @param {string} referenceId Referenced identifier to resolve.
|
* @param {string} referenceId Referenced identifier to resolve.
|
||||||
* @param {Object} fs File system implementation.
|
* @param {FsLike} fs File system implementation.
|
||||||
* @param {ResolveConfigExtendsCallback} callback Callback (err, result)
|
* @param {ResolveConfigExtendsCallback} callback Callback (err, result) function.
|
||||||
* function.
|
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
||||||
|
|
@ -1049,7 +1085,7 @@ function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
||||||
*
|
*
|
||||||
* @param {string} configFile Configuration file name.
|
* @param {string} configFile Configuration file name.
|
||||||
* @param {string} referenceId Referenced identifier to resolve.
|
* @param {string} referenceId Referenced identifier to resolve.
|
||||||
* @param {Object} fs File system implementation.
|
* @param {FsLike} fs File system implementation.
|
||||||
* @returns {string} Resolved path to file.
|
* @returns {string} Resolved path to file.
|
||||||
*/
|
*/
|
||||||
function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
||||||
|
|
@ -1074,9 +1110,8 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
||||||
*
|
*
|
||||||
* @param {Configuration} config Configuration object.
|
* @param {Configuration} config Configuration object.
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[] | undefined} parsers Parsing
|
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
||||||
* function(s).
|
* @param {FsLike} fs File system implementation.
|
||||||
* @param {Object} fs File system implementation.
|
|
||||||
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
@ -1116,7 +1151,7 @@ function extendConfig(config, file, parsers, fs, callback) {
|
||||||
* @param {Configuration} config Configuration object.
|
* @param {Configuration} config Configuration object.
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
||||||
* @param {Object} fs File system implementation.
|
* @param {FsLike} fs File system implementation.
|
||||||
* @returns {Promise<Configuration>} Configuration object.
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function extendConfigPromise(config, file, parsers, fs) {
|
export function extendConfigPromise(config, file, parsers, fs) {
|
||||||
|
|
@ -1135,16 +1170,17 @@ export function extendConfigPromise(config, file, parsers, fs) {
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing
|
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing function(s).
|
||||||
* function(s).
|
* @param {FsLike | ReadConfigCallback} [fs] File system implementation.
|
||||||
* @param {Object} [fs] File system implementation.
|
|
||||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function readConfigAsync(file, parsers, fs, callback) {
|
export function readConfigAsync(file, parsers, fs, callback) {
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
if (fs) {
|
if (fs) {
|
||||||
|
// @ts-ignore
|
||||||
callback = fs;
|
callback = fs;
|
||||||
|
// @ts-ignore
|
||||||
fs = null;
|
fs = null;
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
@ -1153,12 +1189,12 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
||||||
parsers = null;
|
parsers = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fs) {
|
/** @type {FsLike} */
|
||||||
fs = nodeFs;
|
// @ts-ignore
|
||||||
}
|
const fsLike = fs || nodeFs;
|
||||||
// Read file
|
// Read file
|
||||||
file = helpers.expandTildePath(file, os);
|
file = helpers.expandTildePath(file, os);
|
||||||
fs.readFile(file, "utf8", (err, content) => {
|
fsLike.readFile(file, "utf8", (err, content) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
@ -1172,7 +1208,7 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
||||||
}
|
}
|
||||||
// Extend configuration
|
// Extend configuration
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return extendConfig(config, file, parsers, fs, callback);
|
return extendConfig(config, file, parsers, fsLike, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,7 +1217,7 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
* @param {Object} [fs] File system implementation.
|
* @param {FsLike} [fs] File system implementation.
|
||||||
* @returns {Promise<Configuration>} Configuration object.
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function readConfigPromise(file, parsers, fs) {
|
export function readConfigPromise(file, parsers, fs) {
|
||||||
|
|
@ -1201,16 +1237,16 @@ export function readConfigPromise(file, parsers, fs) {
|
||||||
*
|
*
|
||||||
* @param {string} file Configuration file name.
|
* @param {string} file Configuration file name.
|
||||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
* @param {Object} [fs] File system implementation.
|
* @param {FsLike} [fs] File system implementation.
|
||||||
* @returns {Configuration} Configuration object.
|
* @returns {Configuration} Configuration object.
|
||||||
*/
|
*/
|
||||||
export function readConfigSync(file, parsers, fs) {
|
export function readConfigSync(file, parsers, fs) {
|
||||||
if (!fs) {
|
/** @type {FsLike} */
|
||||||
fs = nodeFs;
|
// @ts-ignore
|
||||||
}
|
const fsLike = fs || nodeFs;
|
||||||
// Read file
|
// Read file
|
||||||
file = helpers.expandTildePath(file, os);
|
file = helpers.expandTildePath(file, os);
|
||||||
const content = fs.readFileSync(file, "utf8");
|
const content = fsLike.readFileSync(file, "utf8");
|
||||||
// Try to parse file
|
// Try to parse file
|
||||||
const { config, message } = parseConfiguration(file, content, parsers);
|
const { config, message } = parseConfiguration(file, content, parsers);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
|
|
@ -1224,7 +1260,7 @@ export function readConfigSync(file, parsers, fs) {
|
||||||
const resolvedExtends = resolveConfigExtendsSync(
|
const resolvedExtends = resolveConfigExtendsSync(
|
||||||
file,
|
file,
|
||||||
helpers.expandTildePath(configExtends, os),
|
helpers.expandTildePath(configExtends, os),
|
||||||
fs
|
fsLike
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
...readConfigSync(resolvedExtends, parsers, fs),
|
...readConfigSync(resolvedExtends, parsers, fs),
|
||||||
|
|
@ -1512,7 +1548,7 @@ export function getVersion() {
|
||||||
* @property {Rule[] | Rule} [customRules] Custom rules.
|
* @property {Rule[] | Rule} [customRules] Custom rules.
|
||||||
* @property {string[] | string} [files] Files to lint.
|
* @property {string[] | string} [files] Files to lint.
|
||||||
* @property {RegExp | null} [frontMatter] Front matter pattern.
|
* @property {RegExp | null} [frontMatter] Front matter pattern.
|
||||||
* @property {Object} [fs] File system implementation.
|
* @property {FsLike} [fs] File system implementation.
|
||||||
* @property {boolean} [handleRuleFailures] True to catch exceptions.
|
* @property {boolean} [handleRuleFailures] True to catch exceptions.
|
||||||
* @property {MarkdownItFactory} [markdownItFactory] Function to create a markdown-it parser.
|
* @property {MarkdownItFactory} [markdownItFactory] Function to create a markdown-it parser.
|
||||||
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
||||||
|
|
@ -1522,7 +1558,7 @@ export function getVersion() {
|
||||||
/**
|
/**
|
||||||
* A markdown-it plugin.
|
* A markdown-it plugin.
|
||||||
*
|
*
|
||||||
* @typedef {Array} Plugin
|
* @typedef {Object[]} Plugin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1538,11 +1574,11 @@ export function getVersion() {
|
||||||
* @property {number} lineNumber Line number (1-based).
|
* @property {number} lineNumber Line number (1-based).
|
||||||
* @property {string[]} ruleNames Rule name(s).
|
* @property {string[]} ruleNames Rule name(s).
|
||||||
* @property {string} ruleDescription Rule description.
|
* @property {string} ruleDescription Rule description.
|
||||||
* @property {string} ruleInformation Link to more information.
|
* @property {string | null} ruleInformation Link to more information.
|
||||||
* @property {string} errorDetail Detail about the error.
|
* @property {string | null} errorDetail Detail about the error.
|
||||||
* @property {string} errorContext Context for the error.
|
* @property {string | null} errorContext Context for the error.
|
||||||
* @property {number[]|null} errorRange Column number (1-based) and length.
|
* @property {number[] | null} errorRange Column number (1-based) and length.
|
||||||
* @property {FixInfo|null} fixInfo Fix information.
|
* @property {FixInfo | null} fixInfo Fix information.
|
||||||
* @property {"error" | "warning"} severity Severity of the error.
|
* @property {"error" | "warning"} severity Severity of the error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,9 @@ import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
||||||
import { getDescendantsByType, getParentOfType } from "../helpers/micromark-helpers.cjs";
|
import { getDescendantsByType, getParentOfType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
const markerToStyle = {
|
const markerToStyle = (/** @type {string} */ marker) => (marker === "-") ? "dash" : ((marker === "+") ? "plus" : "asterisk");
|
||||||
"-": "dash",
|
const styleToMarker = (/** @type {string} */ style) => (style === "dash") ? "-" : ((style === "plus") ? "+" : "*");
|
||||||
"+": "plus",
|
const differentItemStyle = (/** @type {string} */ style) => (style === "dash") ? "plus" : ((style === "plus") ? "asterisk" : "dash");
|
||||||
"*": "asterisk"
|
|
||||||
};
|
|
||||||
const styleToMarker = {
|
|
||||||
"dash": "-",
|
|
||||||
"plus": "+",
|
|
||||||
"asterisk": "*"
|
|
||||||
};
|
|
||||||
const differentItemStyle = {
|
|
||||||
"dash": "plus",
|
|
||||||
"plus": "asterisk",
|
|
||||||
"asterisk": "dash"
|
|
||||||
};
|
|
||||||
const validStyles = new Set([
|
const validStyles = new Set([
|
||||||
"asterisk",
|
"asterisk",
|
||||||
"consistent",
|
"consistent",
|
||||||
|
|
@ -36,6 +24,7 @@ export default {
|
||||||
"function": function MD004(params, onError) {
|
"function": function MD004(params, onError) {
|
||||||
const style = String(params.config.style || "consistent");
|
const style = String(params.config.style || "consistent");
|
||||||
let expectedStyle = validStyles.has(style) ? style : "dash";
|
let expectedStyle = validStyles.has(style) ? style : "dash";
|
||||||
|
/** @type {("asterisk"|"dash"|"plus")[]} */
|
||||||
const nestingStyles = [];
|
const nestingStyles = [];
|
||||||
for (const listUnordered of filterByTypesCached([ "listUnordered" ])) {
|
for (const listUnordered of filterByTypesCached([ "listUnordered" ])) {
|
||||||
let nesting = 0;
|
let nesting = 0;
|
||||||
|
|
@ -49,12 +38,12 @@ export default {
|
||||||
}
|
}
|
||||||
const listItemMarkers = getDescendantsByType(listUnordered, [ "listItemPrefix", "listItemMarker" ]);
|
const listItemMarkers = getDescendantsByType(listUnordered, [ "listItemPrefix", "listItemMarker" ]);
|
||||||
for (const listItemMarker of listItemMarkers) {
|
for (const listItemMarker of listItemMarkers) {
|
||||||
const itemStyle = markerToStyle[listItemMarker.text];
|
const itemStyle = markerToStyle(listItemMarker.text);
|
||||||
if (style === "sublist") {
|
if (style === "sublist") {
|
||||||
if (!nestingStyles[nesting]) {
|
if (!nestingStyles[nesting]) {
|
||||||
nestingStyles[nesting] =
|
nestingStyles[nesting] =
|
||||||
(itemStyle === nestingStyles[nesting - 1]) ?
|
(itemStyle === nestingStyles[nesting - 1]) ?
|
||||||
differentItemStyle[itemStyle] :
|
differentItemStyle(itemStyle) :
|
||||||
itemStyle;
|
itemStyle;
|
||||||
}
|
}
|
||||||
expectedStyle = nestingStyles[nesting];
|
expectedStyle = nestingStyles[nesting];
|
||||||
|
|
@ -74,7 +63,7 @@ export default {
|
||||||
{
|
{
|
||||||
"editColumn": column,
|
"editColumn": column,
|
||||||
"deleteCount": length,
|
"deleteCount": length,
|
||||||
"insertText": styleToMarker[expectedStyle]
|
"insertText": styleToMarker(expectedStyle)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
|
const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
|
||||||
const ignoreCodeLanguages = new Set(
|
const ignoreCodeLanguages = new Set(
|
||||||
(params.config.ignore_code_languages || [])
|
(params.config.ignore_code_languages || [])
|
||||||
.map((language) => language.toLowerCase())
|
.map((/** @type {void} */ language) => String(language).toLowerCase())
|
||||||
);
|
);
|
||||||
const spacesPerTab = params.config.spaces_per_tab;
|
const spacesPerTab = params.config.spaces_per_tab;
|
||||||
const spaceMultiplier = (spacesPerTab === undefined) ?
|
const spaceMultiplier = (spacesPerTab === undefined) ?
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,18 @@ import { addErrorDetailIf, isBlankLine } from "../helpers/helpers.cjs";
|
||||||
import { getBlockQuotePrefixText, getHeadingLevel } from "../helpers/micromark-helpers.cjs";
|
import { getBlockQuotePrefixText, getHeadingLevel } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
|
|
||||||
const defaultLines = 1;
|
const defaultLines = 1;
|
||||||
|
|
||||||
const getLinesFunction = (linesParam) => {
|
// eslint-disable-next-line jsdoc/reject-any-type
|
||||||
|
const getLinesFunction = (/** @type {any} */ linesParam) => {
|
||||||
if (Array.isArray(linesParam)) {
|
if (Array.isArray(linesParam)) {
|
||||||
const linesArray = new Array(6).fill(defaultLines);
|
const linesArray = new Array(6).fill(defaultLines);
|
||||||
for (const [ index, value ] of [ ...linesParam.entries() ].slice(0, 6)) {
|
for (const [ index, value ] of [ ...linesParam.entries() ].slice(0, 6)) {
|
||||||
linesArray[index] = value;
|
linesArray[index] = value;
|
||||||
}
|
}
|
||||||
return (heading) => linesArray[getHeadingLevel(heading) - 1];
|
return (/** @type {MicromarkToken} */ heading) => linesArray[getHeadingLevel(heading) - 1];
|
||||||
}
|
}
|
||||||
// Coerce linesParam to a number
|
// Coerce linesParam to a number
|
||||||
const lines = (linesParam === undefined) ? defaultLines : Number(linesParam);
|
const lines = (linesParam === undefined) ? defaultLines : Number(linesParam);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default {
|
||||||
"tags": [ "ol" ],
|
"tags": [ "ol" ],
|
||||||
"parser": "micromark",
|
"parser": "micromark",
|
||||||
"function": function MD029(params, onError) {
|
"function": function MD029(params, onError) {
|
||||||
const style = String(params.config.style || "one_or_ordered");
|
const style = String(params.config.style);
|
||||||
for (const listOrdered of filterByTypesCached([ "listOrdered" ])) {
|
for (const listOrdered of filterByTypesCached([ "listOrdered" ])) {
|
||||||
const listItemPrefixes = getDescendantsByType(listOrdered, [ "listItemPrefix" ]);
|
const listItemPrefixes = getDescendantsByType(listOrdered, [ "listItemPrefix" ]);
|
||||||
let expected = 1;
|
let expected = 1;
|
||||||
|
|
@ -48,10 +48,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Determine effective style
|
// Determine effective style
|
||||||
let listStyle = style;
|
const listStyle = ((style === "one") || (style === "ordered") || (style === "zero")) ?
|
||||||
if (listStyle === "one_or_ordered") {
|
style :
|
||||||
listStyle = incrementing ? "ordered" : "one";
|
(incrementing ? "ordered" : "one");
|
||||||
} else if (listStyle === "zero") {
|
if (listStyle === "zero") {
|
||||||
expected = 0;
|
expected = 0;
|
||||||
} else if (listStyle === "one") {
|
} else if (listStyle === "one") {
|
||||||
expected = 1;
|
expected = 1;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import { addErrorContext, isBlankLine } from "../helpers/helpers.cjs";
|
||||||
import { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } from "../helpers/micromark-helpers.cjs";
|
import { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
const isList = (token) => (
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
|
|
||||||
|
const isList = (/** @type {MicromarkToken} */ token) => (
|
||||||
(token.type === "listOrdered") || (token.type === "listUnordered")
|
(token.type === "listOrdered") || (token.type === "listUnordered")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@ import { addError, nextLinesRe } from "../helpers/helpers.cjs";
|
||||||
import { getHtmlTagInfo, getParentOfType } from "../helpers/micromark-helpers.cjs";
|
import { getHtmlTagInfo, getParentOfType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
|
/** @typedef {import("micromark-extension-gfm-table")} */
|
||||||
|
|
||||||
|
// eslint-disable-next-line jsdoc/reject-any-type
|
||||||
|
const toLowerCaseStringArray = (/** @type {any} */ arr) => Array.isArray(arr) ? arr.map((elm) => String(elm).toLowerCase()) : [];
|
||||||
|
|
||||||
/** @type {import("markdownlint").Rule} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
export default {
|
export default {
|
||||||
"names": [ "MD033", "no-inline-html" ],
|
"names": [ "MD033", "no-inline-html" ],
|
||||||
|
|
@ -11,35 +16,30 @@ export default {
|
||||||
"tags": [ "html" ],
|
"tags": [ "html" ],
|
||||||
"parser": "micromark",
|
"parser": "micromark",
|
||||||
"function": function MD033(params, onError) {
|
"function": function MD033(params, onError) {
|
||||||
let allowedElements = params.config.allowed_elements;
|
const allowedElements = toLowerCaseStringArray(params.config.allowed_elements);
|
||||||
allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
|
// If not defined, use allowedElements for backward compatibility
|
||||||
allowedElements = allowedElements.map((element) => element.toLowerCase());
|
const tableAllowedElements = toLowerCaseStringArray(params.config.table_allowed_elements || params.config.allowed_elements);
|
||||||
let tableAllowedElements = params.config.table_allowed_elements;
|
|
||||||
// if not defined, use allowedElements for backward compatibility
|
|
||||||
tableAllowedElements = Array.isArray(tableAllowedElements) ? tableAllowedElements : allowedElements;
|
|
||||||
tableAllowedElements = tableAllowedElements.map((element) => element.toLowerCase());
|
|
||||||
for (const token of filterByTypesCached([ "htmlText" ], true)) {
|
for (const token of filterByTypesCached([ "htmlText" ], true)) {
|
||||||
const htmlTagInfo = getHtmlTagInfo(token);
|
const htmlTagInfo = getHtmlTagInfo(token);
|
||||||
const elementName = htmlTagInfo?.name.toLowerCase();
|
if (htmlTagInfo && !htmlTagInfo.close) {
|
||||||
const inTable = !!getParentOfType(token, [ "table" ]);
|
const elementName = htmlTagInfo?.name.toLowerCase();
|
||||||
if (
|
const inTable = !!getParentOfType(token, [ "table" ]);
|
||||||
htmlTagInfo &&
|
if (
|
||||||
!htmlTagInfo.close && !(
|
(inTable || !allowedElements.includes(elementName)) &&
|
||||||
(!inTable && allowedElements.includes(elementName)) ||
|
(!inTable || !tableAllowedElements.includes(elementName))
|
||||||
(inTable && tableAllowedElements.includes(elementName))
|
) {
|
||||||
)
|
const range = [
|
||||||
) {
|
token.startColumn,
|
||||||
const range = [
|
token.text.replace(nextLinesRe, "").length
|
||||||
token.startColumn,
|
];
|
||||||
token.text.replace(nextLinesRe, "").length
|
addError(
|
||||||
];
|
onError,
|
||||||
addError(
|
token.startLine,
|
||||||
onError,
|
"Element: " + htmlTagInfo.name,
|
||||||
token.startLine,
|
undefined,
|
||||||
"Element: " + htmlTagInfo.name,
|
range
|
||||||
undefined,
|
);
|
||||||
range
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import { addErrorContext } from "../helpers/helpers.cjs";
|
import { addErrorContext } from "../helpers/helpers.cjs";
|
||||||
import { filterByPredicate, getHtmlTagInfo, inHtmlFlow } from "../helpers/micromark-helpers.cjs";
|
import { filterByPredicate, getHtmlTagInfo, inHtmlFlow } from "../helpers/micromark-helpers.cjs";
|
||||||
|
|
||||||
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
/** @typedef {import("micromark-extension-gfm-autolink-literal")} */
|
/** @typedef {import("micromark-extension-gfm-autolink-literal")} */
|
||||||
|
|
||||||
/** @type {import("markdownlint").Rule} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
|
|
@ -12,7 +13,7 @@ export default {
|
||||||
"tags": [ "links", "url" ],
|
"tags": [ "links", "url" ],
|
||||||
"parser": "micromark",
|
"parser": "micromark",
|
||||||
"function": function MD034(params, onError) {
|
"function": function MD034(params, onError) {
|
||||||
const literalAutolinks = (tokens) => (
|
const literalAutolinks = (/** @type {MicromarkToken[]} */ tokens) => (
|
||||||
filterByPredicate(
|
filterByPredicate(
|
||||||
tokens,
|
tokens,
|
||||||
(token) => {
|
(token) => {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,16 @@ import { addErrorContext, allPunctuation } from "../helpers/helpers.cjs";
|
||||||
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
/** @typedef {import("markdownlint").MicromarkTokenType} TokenType */
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
/** @type {TokenType[][]} */
|
/** @typedef {import("markdownlint").MicromarkTokenType} MicromarkTokenType */
|
||||||
|
|
||||||
|
/** @type {MicromarkTokenType[][]} */
|
||||||
const emphasisTypes = [
|
const emphasisTypes = [
|
||||||
[ "emphasis", "emphasisText" ],
|
[ "emphasis", "emphasisText" ],
|
||||||
[ "strong", "strongText" ]
|
[ "strong", "strongText" ]
|
||||||
];
|
];
|
||||||
|
|
||||||
const isParagraphChildMeaningful = (token) => !(
|
const isParagraphChildMeaningful = (/** @type {MicromarkToken} */ token) => !(
|
||||||
(token.type === "htmlText") ||
|
(token.type === "htmlText") ||
|
||||||
((token.type === "data") && (token.text.trim().length === 0))
|
((token.type === "data") && (token.text.trim().length === 0))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { addErrorContext } from "../helpers/helpers.cjs";
|
||||||
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs";
|
import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
|
|
||||||
/** @type {import("markdownlint").Rule} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
export default {
|
export default {
|
||||||
"names": [ "MD042", "no-empty-links" ],
|
"names": [ "MD042", "no-empty-links" ],
|
||||||
|
|
@ -12,9 +14,9 @@ export default {
|
||||||
"parser": "micromark",
|
"parser": "micromark",
|
||||||
"function": function MD042(params, onError) {
|
"function": function MD042(params, onError) {
|
||||||
const { definitions } = getReferenceLinkImageData();
|
const { definitions } = getReferenceLinkImageData();
|
||||||
const isReferenceDefinitionHash = (token) => {
|
const isReferenceDefinitionHash = (/** @type {MicromarkToken} */ token) => {
|
||||||
const definition = definitions.get(token.text.trim());
|
const definition = definitions.get(token.text.trim());
|
||||||
return (definition && (definition[1] === "#"));
|
return Boolean(definition && (definition[1] === "#"));
|
||||||
};
|
};
|
||||||
const links = filterByTypesCached([ "link" ]);
|
const links = filterByTypesCached([ "link" ]);
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ export default {
|
||||||
let matchAny = false;
|
let matchAny = false;
|
||||||
let hasError = false;
|
let hasError = false;
|
||||||
let anyHeadings = false;
|
let anyHeadings = false;
|
||||||
const getExpected = () => requiredHeadings[i++] || "[None]";
|
const getExpected = () => String(requiredHeadings[i++] || "[None]");
|
||||||
const handleCase = (str) => (matchCase ? str : str.toLowerCase());
|
const handleCase = (/** @type {string} */ str) => (matchCase ? str : str.toLowerCase());
|
||||||
for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
|
for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
|
||||||
if (!hasError) {
|
if (!hasError) {
|
||||||
const headingText = getHeadingText(heading);
|
const headingText = getHeadingText(heading);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
"function": function MD044(params, onError) {
|
"function": function MD044(params, onError) {
|
||||||
let names = params.config.names;
|
let names = params.config.names;
|
||||||
names = Array.isArray(names) ? names : [];
|
names = Array.isArray(names) ? names : [];
|
||||||
names.sort((a, b) => (b.length - a.length) || a.localeCompare(b));
|
names.sort((/** @type {string} */ a, /** @type {string} */ b) => (b.length - a.length) || a.localeCompare(b));
|
||||||
if (names.length === 0) {
|
if (names.length === 0) {
|
||||||
// Nothing to check; avoid doing any work
|
// Nothing to check; avoid doing any work
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,9 @@
|
||||||
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
const tokenTypeToStyle = {
|
/** @typedef {import("markdownlint").MicromarkTokenType} MicromarkTokenType */
|
||||||
"codeFenced": "fenced",
|
|
||||||
"codeIndented": "indented"
|
const tokenTypeToStyle = (/** @type {MicromarkTokenType} */ tokenType) => (tokenType === "codeFenced") ? "fenced" : "indented";
|
||||||
};
|
|
||||||
|
|
||||||
/** @type {import("markdownlint").Rule} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -19,13 +18,14 @@ export default {
|
||||||
for (const token of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
for (const token of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
||||||
const { startLine, type } = token;
|
const { startLine, type } = token;
|
||||||
if (expectedStyle === "consistent") {
|
if (expectedStyle === "consistent") {
|
||||||
expectedStyle = tokenTypeToStyle[type];
|
expectedStyle = tokenTypeToStyle(type);
|
||||||
}
|
}
|
||||||
addErrorDetailIf(
|
addErrorDetailIf(
|
||||||
onError,
|
onError,
|
||||||
startLine,
|
startLine,
|
||||||
expectedStyle,
|
expectedStyle,
|
||||||
tokenTypeToStyle[type]);
|
tokenTypeToStyle(type)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export default {
|
||||||
const lines = params.lines;
|
const lines = params.lines;
|
||||||
const { references, shortcuts, definitions, duplicateDefinitions } =
|
const { references, shortcuts, definitions, duplicateDefinitions } =
|
||||||
getReferenceLinkImageData();
|
getReferenceLinkImageData();
|
||||||
const singleLineDefinition = (line) => (
|
const singleLineDefinition = (/** @type {string} */ line) => (
|
||||||
line.replace(linkReferenceDefinitionRe, "").trim().length > 0
|
line.replace(linkReferenceDefinitionRe, "").trim().length > 0
|
||||||
);
|
);
|
||||||
const deleteFixInfo = {
|
const deleteFixInfo = {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs";
|
import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
||||||
const removeBackslashEscapes = (text) => text.replace(backslashEscapeRe, "$1");
|
const removeBackslashEscapes = (/** @type {string} **/ text) => text.replace(backslashEscapeRe, "$1");
|
||||||
const autolinkDisallowedRe = /[ <>]/;
|
const autolinkDisallowedRe = /[ <>]/;
|
||||||
const autolinkAble = (destination) => {
|
const autolinkAble = (/** @type {string} */ destination) => {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
new URL(destination);
|
new URL(destination);
|
||||||
|
|
@ -73,9 +73,11 @@ export default {
|
||||||
const referenceString = getDescendantsByType(link, [ "reference", "referenceString" ])[0]?.text;
|
const referenceString = getDescendantsByType(link, [ "reference", "referenceString" ])[0]?.text;
|
||||||
const isCollapsed = (referenceString === undefined);
|
const isCollapsed = (referenceString === undefined);
|
||||||
const definition = definitions.get(referenceString || label);
|
const definition = definitions.get(referenceString || label);
|
||||||
destination = definition && definition[1];
|
destination = (definition && definition[1]) || "";
|
||||||
isError = destination &&
|
isError = Boolean(
|
||||||
(isShortcut ? !shortcut : (isCollapsed ? !collapsed : !full));
|
destination &&
|
||||||
|
(isShortcut ? !shortcut : (isCollapsed ? !collapsed : !full))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isError) {
|
if (isError) {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,16 @@
|
||||||
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
||||||
|
/** @typedef {import("micromark-extension-gfm-table")} */
|
||||||
|
|
||||||
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
||||||
const ignoreWhitespace = (tokens) => tokens.filter(
|
const ignoreWhitespace = (/** @type {MicromarkToken[]} */ tokens) => tokens.filter(
|
||||||
(token) => !whitespaceTypes.has(token.type)
|
(token) => !whitespaceTypes.has(token.type)
|
||||||
);
|
);
|
||||||
const firstOrNothing = (items) => items[0];
|
const firstOrNothing = (/** @type {MicromarkToken[]} */ items) => items[0];
|
||||||
const lastOrNothing = (items) => items[items.length - 1];
|
const lastOrNothing = (/** @type {MicromarkToken[]} */ items) => items[items.length - 1];
|
||||||
const makeRange = (start, end) => [ start, end - start + 1 ];
|
const makeRange = (/** @type {number} */ start, /** @type {number} */ end) => [ start, end - start + 1 ];
|
||||||
|
|
||||||
/** @typedef {import("micromark-extension-gfm-table")} */
|
|
||||||
|
|
||||||
/** @type {import("markdownlint").Rule} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
||||||
import { getParentOfType } from "../helpers/micromark-helpers.cjs";
|
import { getParentOfType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
import { filterByTypesCached } from "./cache.mjs";
|
||||||
|
|
||||||
const makeRange = (start, end) => [ start, end - start + 1 ];
|
const makeRange = (/** @type {number} */ start, /** @type {number} */ end) => [ start, end - start + 1 ];
|
||||||
|
|
||||||
/** @typedef {import("micromark-extension-gfm-table")} */
|
/** @typedef {import("micromark-extension-gfm-table")} */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ export default {
|
||||||
const headingRow = rows[0];
|
const headingRow = rows[0];
|
||||||
|
|
||||||
// Determine errors for style "aligned"
|
// Determine errors for style "aligned"
|
||||||
|
/** @type {RuleOnErrorInfo[]} */
|
||||||
const errorsIfAligned = [];
|
const errorsIfAligned = [];
|
||||||
if (styleAlignedAllowed) {
|
if (styleAlignedAllowed) {
|
||||||
const headingDividerColumns = filterByTypes(headingRow.children, [ "tableCellDivider" ]).map((divider) => divider.startColumn);
|
const headingDividerColumns = filterByTypes(headingRow.children, [ "tableCellDivider" ]).map((divider) => divider.startColumn);
|
||||||
|
|
@ -56,7 +57,9 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine errors for styles "compact" and "tight"
|
// Determine errors for styles "compact" and "tight"
|
||||||
|
/** @type {RuleOnErrorInfo[]} */
|
||||||
const errorsIfCompact = [];
|
const errorsIfCompact = [];
|
||||||
|
/** @type {RuleOnErrorInfo[]} */
|
||||||
const errorsIfTight = [];
|
const errorsIfTight = [];
|
||||||
if (
|
if (
|
||||||
(styleCompactAllowed || styleTightAllowed) &&
|
(styleCompactAllowed || styleTightAllowed) &&
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,9 @@ function parseInternal(
|
||||||
const events = getEvents(markdown, micromarkParseOptions);
|
const events = getEvents(markdown, micromarkParseOptions);
|
||||||
|
|
||||||
// Create Token objects
|
// Create Token objects
|
||||||
|
/** @type {MicromarkToken[]} */
|
||||||
const document = [];
|
const document = [];
|
||||||
|
/** @type {MicromarkToken[]} */
|
||||||
let flatTokens = [];
|
let flatTokens = [];
|
||||||
/** @type {MicromarkToken} */
|
/** @type {MicromarkToken} */
|
||||||
const root = {
|
const root = {
|
||||||
|
|
@ -282,6 +284,7 @@ function parseInternal(
|
||||||
);
|
);
|
||||||
current.children = tokens;
|
current.children = tokens;
|
||||||
// Avoid stack overflow of Array.push(...spread)
|
// Avoid stack overflow of Array.push(...spread)
|
||||||
|
// @ts-ignore
|
||||||
// eslint-disable-next-line unicorn/prefer-spread
|
// eslint-disable-next-line unicorn/prefer-spread
|
||||||
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ const throwForSync = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fs = {
|
export const fs = {
|
||||||
|
// @ts-ignore
|
||||||
"access": (path, callback) => callback(getError()),
|
"access": (path, callback) => callback(getError()),
|
||||||
"accessSync": throwForSync,
|
"accessSync": throwForSync,
|
||||||
|
// @ts-ignore
|
||||||
"readFile": (path, options, callback) => callback(getError()),
|
"readFile": (path, options, callback) => callback(getError()),
|
||||||
"readFileSync": throwForSync
|
"readFileSync": throwForSync
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
* Result of a call to parseConfiguration.
|
* Result of a call to parseConfiguration.
|
||||||
*
|
*
|
||||||
* @typedef {Object} ParseConfigurationResult
|
* @typedef {Object} ParseConfigurationResult
|
||||||
* @property {Object | null} config Configuration object if successful.
|
* @property {import("markdownlint").Configuration | null} config Configuration object if successful.
|
||||||
* @property {string | null} message Error message if an error occurred.
|
* @property {string | null} message Error message if an error occurred.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
*
|
*
|
||||||
* @param {string} name Name of the configuration file.
|
* @param {string} name Name of the configuration file.
|
||||||
* @param {string} content Configuration content.
|
* @param {string} content Configuration content.
|
||||||
* @param {import("./markdownlint.mjs").ConfigurationParser[]} [parsers] Parsing function(s).
|
* @param {import("markdownlint").ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
* @returns {ParseConfigurationResult} Parse configuration result.
|
* @returns {ParseConfigurationResult} Parse configuration result.
|
||||||
*/
|
*/
|
||||||
export default function parseConfiguration(name, content, parsers) {
|
export default function parseConfiguration(name, content, parsers) {
|
||||||
|
|
@ -28,8 +28,9 @@ export default function parseConfiguration(name, content, parsers) {
|
||||||
config = (result && (typeof result === "object") && !Array.isArray(result)) ? result : {};
|
config = (result && (typeof result === "object") && !Array.isArray(result)) ? result : {};
|
||||||
// Succeeded
|
// Succeeded
|
||||||
return false;
|
return false;
|
||||||
} catch(error) {
|
// eslint-disable-next-line jsdoc/reject-any-type
|
||||||
errors.push(`Parser ${index++}: ${error.message}`);
|
} catch(/** @type {any} */ error) {
|
||||||
|
errors.push(`Parser ${index++}: ${error?.message}`);
|
||||||
}
|
}
|
||||||
// Failed, try the next parser
|
// Failed, try the next parser
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -60691,6 +60691,48 @@ Generated by [AVA](https://avajs.dev).
|
||||||
],
|
],
|
||||||
severity: 'error',
|
severity: 'error',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
errorContext: null,
|
||||||
|
errorDetail: 'Expected: plus; Actual: dash',
|
||||||
|
errorRange: [
|
||||||
|
13,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
fixInfo: {
|
||||||
|
deleteCount: 1,
|
||||||
|
editColumn: 13,
|
||||||
|
insertText: '+',
|
||||||
|
},
|
||||||
|
lineNumber: 66,
|
||||||
|
ruleDescription: 'Unordered list style',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md004.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD004',
|
||||||
|
'ul-style',
|
||||||
|
],
|
||||||
|
severity: 'error',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
errorContext: null,
|
||||||
|
errorDetail: 'Expected: asterisk; Actual: plus',
|
||||||
|
errorRange: [
|
||||||
|
15,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
fixInfo: {
|
||||||
|
deleteCount: 1,
|
||||||
|
editColumn: 15,
|
||||||
|
insertText: '*',
|
||||||
|
},
|
||||||
|
lineNumber: 75,
|
||||||
|
ruleDescription: 'Unordered list style',
|
||||||
|
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md004.md',
|
||||||
|
ruleNames: [
|
||||||
|
'MD004',
|
||||||
|
'ul-style',
|
||||||
|
],
|
||||||
|
severity: 'error',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
fixed: `# sublist-bullet-style␊
|
fixed: `# sublist-bullet-style␊
|
||||||
␊
|
␊
|
||||||
|
|
@ -60751,6 +60793,23 @@ Generated by [AVA](https://avajs.dev).
|
||||||
- item␊
|
- item␊
|
||||||
- item {MD004}␊
|
- item {MD004}␊
|
||||||
␊
|
␊
|
||||||
|
- item␊
|
||||||
|
* item␊
|
||||||
|
+ item␊
|
||||||
|
- item␊
|
||||||
|
* item␊
|
||||||
|
- item␊
|
||||||
|
+ item {MD004}␊
|
||||||
|
␊
|
||||||
|
- item␊
|
||||||
|
* item␊
|
||||||
|
+ item␊
|
||||||
|
- item␊
|
||||||
|
* item␊
|
||||||
|
- item␊
|
||||||
|
+ item␊
|
||||||
|
* item {MD004}␊
|
||||||
|
␊
|
||||||
<!-- markdownlint-configure-file {␊
|
<!-- markdownlint-configure-file {␊
|
||||||
"ul-style": {␊
|
"ul-style": {␊
|
||||||
"style": "sublist"␊
|
"style": "sublist"␊
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -57,6 +57,23 @@
|
||||||
- item
|
- item
|
||||||
+ item {MD004}
|
+ item {MD004}
|
||||||
|
|
||||||
|
- item
|
||||||
|
* item
|
||||||
|
+ item
|
||||||
|
- item
|
||||||
|
* item
|
||||||
|
- item
|
||||||
|
- item {MD004}
|
||||||
|
|
||||||
|
- item
|
||||||
|
* item
|
||||||
|
+ item
|
||||||
|
- item
|
||||||
|
* item
|
||||||
|
- item
|
||||||
|
+ item
|
||||||
|
+ item {MD004}
|
||||||
|
|
||||||
<!-- markdownlint-configure-file {
|
<!-- markdownlint-configure-file {
|
||||||
"ul-style": {
|
"ul-style": {
|
||||||
"style": "sublist"
|
"style": "sublist"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue