mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 06:20:12 +01:00
Add Rule.parser property for custom rules to specify which Markdown parser output they use, honor it strictly, and add full type support.
This commit is contained in:
parent
d2acc168d2
commit
d5994ae4de
68 changed files with 635 additions and 115 deletions
|
|
@ -33,17 +33,16 @@ function validateRuleList(ruleList, synchronous) {
|
|||
for (const [ index, rule ] of ruleList.entries()) {
|
||||
const customIndex = index - rules.length;
|
||||
// eslint-disable-next-line no-inner-declarations, jsdoc/require-jsdoc
|
||||
function newError(property) {
|
||||
function newError(property, value) {
|
||||
return new Error(
|
||||
"Property '" + property + "' of custom rule at index " +
|
||||
customIndex + " is incorrect.");
|
||||
`Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`);
|
||||
}
|
||||
for (const property of [ "names", "tags" ]) {
|
||||
const value = rule[property];
|
||||
if (!result &&
|
||||
(!value || !Array.isArray(value) || (value.length === 0) ||
|
||||
!value.every(helpers.isString) || value.some(helpers.isEmptyString))) {
|
||||
result = newError(property);
|
||||
result = newError(property, value);
|
||||
}
|
||||
}
|
||||
for (const propertyInfo of [
|
||||
|
|
@ -53,22 +52,31 @@ function validateRuleList(ruleList, synchronous) {
|
|||
const property = propertyInfo[0];
|
||||
const value = rule[property];
|
||||
if (!result && (!value || (typeof value !== propertyInfo[1]))) {
|
||||
result = newError(property);
|
||||
result = newError(property, value);
|
||||
}
|
||||
}
|
||||
if (
|
||||
!result &&
|
||||
(rule.parser !== undefined) &&
|
||||
(rule.parser !== "markdownit") &&
|
||||
!((customIndex < 0) && (rule.parser === "micromark")) &&
|
||||
(rule.parser !== "none")
|
||||
) {
|
||||
result = newError("parser", rule.parser);
|
||||
}
|
||||
if (
|
||||
!result &&
|
||||
rule.information &&
|
||||
!helpers.isUrl(rule.information)
|
||||
) {
|
||||
result = newError("information");
|
||||
result = newError("information", rule.information);
|
||||
}
|
||||
if (
|
||||
!result &&
|
||||
(rule.asynchronous !== undefined) &&
|
||||
(typeof rule.asynchronous !== "boolean")
|
||||
) {
|
||||
result = newError("asynchronous");
|
||||
result = newError("asynchronous", rule.asynchronous);
|
||||
}
|
||||
if (!result && rule.asynchronous && synchronous) {
|
||||
result = new Error(
|
||||
|
|
@ -563,18 +571,26 @@ function lintContent(
|
|||
const lines = content.split(helpers.newLineRe);
|
||||
annotateAndFreezeTokens(markdownitTokens, lines);
|
||||
// Create (frozen) parameters for rules
|
||||
const parsers = Object.freeze({
|
||||
/** @type {MarkdownParsers} */
|
||||
// @ts-ignore
|
||||
const parsersMarkdownIt = Object.freeze({
|
||||
"markdownit": Object.freeze({
|
||||
"tokens": markdownitTokens
|
||||
}),
|
||||
})
|
||||
});
|
||||
/** @type {MarkdownParsers} */
|
||||
// @ts-ignore
|
||||
const parsersMicromark = Object.freeze({
|
||||
"micromark": Object.freeze({
|
||||
"tokens": micromarkTokens
|
||||
})
|
||||
});
|
||||
/** @type {MarkdownParsers} */
|
||||
// @ts-ignore
|
||||
const parsersNone = Object.freeze({});
|
||||
const paramsBase = {
|
||||
name,
|
||||
parsers,
|
||||
"tokens": markdownitTokens,
|
||||
"parsers": parsersMarkdownIt,
|
||||
"lines": Object.freeze(lines),
|
||||
"frontMatterLines": Object.freeze(frontMatterLines)
|
||||
};
|
||||
|
|
@ -583,9 +599,9 @@ function lintContent(
|
|||
const codeBlockAndSpanRanges =
|
||||
helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata);
|
||||
const flattenedLists =
|
||||
helpers.flattenLists(paramsBase.parsers.markdownit.tokens);
|
||||
helpers.flattenLists(markdownitTokens);
|
||||
const referenceLinkImageData =
|
||||
helpers.getReferenceLinkImageData(paramsBase);
|
||||
helpers.getReferenceLinkImageData(micromarkTokens);
|
||||
cache.set({
|
||||
codeBlockAndSpanRanges,
|
||||
flattenedLists,
|
||||
|
|
@ -594,12 +610,27 @@ function lintContent(
|
|||
});
|
||||
// Function to run for each rule
|
||||
let results = [];
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
function forRule(rule) {
|
||||
/**
|
||||
* @param {Rule} rule Rule.
|
||||
* @returns {Promise<void> | null} Promise.
|
||||
*/
|
||||
const forRule = (rule) => {
|
||||
// Configure rule
|
||||
const ruleName = rule.names[0].toUpperCase();
|
||||
const tokens = {};
|
||||
let parsers = parsersNone;
|
||||
if (rule.parser === undefined) {
|
||||
tokens.tokens = markdownitTokens;
|
||||
parsers = parsersMarkdownIt;
|
||||
} else if (rule.parser === "markdownit") {
|
||||
parsers = parsersMarkdownIt;
|
||||
} else if (rule.parser === "micromark") {
|
||||
parsers = parsersMicromark;
|
||||
}
|
||||
const params = {
|
||||
...paramsBase,
|
||||
...tokens,
|
||||
parsers,
|
||||
"config": effectiveConfig[ruleName]
|
||||
};
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
|
|
@ -875,6 +906,7 @@ function lintInput(options, synchronous, callback) {
|
|||
"description": rule.description,
|
||||
"information": helpers.cloneIfUrl(rule.information),
|
||||
"tags": helpers.cloneIfArray(rule.tags),
|
||||
"parser": rule.parser,
|
||||
"asynchronous": rule.asynchronous,
|
||||
"function": rule.function
|
||||
}));
|
||||
|
|
@ -1281,22 +1313,27 @@ module.exports = markdownlint;
|
|||
* @returns {void}
|
||||
*/
|
||||
|
||||
/* eslint-disable jsdoc/valid-types */
|
||||
|
||||
/**
|
||||
* Rule parameters.
|
||||
*
|
||||
* @typedef {Object} RuleParams
|
||||
* @property {string} name File/string name.
|
||||
* @property {MarkdownParsers} parsers Markdown parser data.
|
||||
* @property {string[]} lines File/string lines.
|
||||
* @property {string[]} frontMatterLines Front matter lines.
|
||||
* @property {readonly string[]} lines File/string lines.
|
||||
* @property {readonly string[]} frontMatterLines Front matter lines.
|
||||
* @property {RuleConfiguration} config Rule configuration.
|
||||
*/
|
||||
|
||||
/* eslint-enable jsdoc/valid-types */
|
||||
|
||||
/**
|
||||
* Markdown parser data.
|
||||
*
|
||||
* @typedef {Object} MarkdownParsers
|
||||
* @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it.
|
||||
* @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it (only present when Rule.parser is "markdownit").
|
||||
* @property {ParserMicromark} micromark Markdown parser data from micromark (only present when Rule.parser is "micromark").
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -1306,6 +1343,13 @@ module.exports = markdownlint;
|
|||
* @property {MarkdownItToken[]} tokens Token objects from markdown-it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Markdown parser data from micromark.
|
||||
*
|
||||
* @typedef {Object} ParserMicromark
|
||||
* @property {MicromarkToken[]} tokens Token objects from micromark.
|
||||
*/
|
||||
|
||||
/**
|
||||
* markdown-it token.
|
||||
*
|
||||
|
|
@ -1327,6 +1371,22 @@ module.exports = markdownlint;
|
|||
* @property {string} line Line content.
|
||||
*/
|
||||
|
||||
/** @typedef {import("markdownlint-micromark").TokenType} MicromarkTokenType */
|
||||
|
||||
/**
|
||||
* micromark token.
|
||||
*
|
||||
* @typedef {Object} MicromarkToken
|
||||
* @property {MicromarkTokenType} type Token type.
|
||||
* @property {number} startLine Start line (1-based).
|
||||
* @property {number} startColumn Start column (1-based).
|
||||
* @property {number} endLine End line (1-based).
|
||||
* @property {number} endColumn End column (1-based).
|
||||
* @property {string} text Token text.
|
||||
* @property {MicromarkToken[]} children Child tokens.
|
||||
* @property {MicromarkToken | null} parent Parent token.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error-reporting callback.
|
||||
*
|
||||
|
|
@ -1365,6 +1425,7 @@ module.exports = markdownlint;
|
|||
* @property {string} description Rule description.
|
||||
* @property {URL} [information] Link to more information.
|
||||
* @property {string[]} tags Rule tag(s).
|
||||
* @property {"markdownit" | "micromark" | "none"} parser Parser used.
|
||||
* @property {boolean} [asynchronous] True if asynchronous.
|
||||
* @property {RuleFunction} function Rule implementation.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue