Add parsers object to RuleParams type, annotate every rule definition with Rule type for better type validation.

This commit is contained in:
David Anson 2024-02-27 20:42:09 -08:00
parent 996d88a9b4
commit 12c4f79604
54 changed files with 363 additions and 59 deletions

View file

@ -2959,14 +2959,29 @@ module.exports = markdownlint;
* *
* @typedef {Object} RuleParams * @typedef {Object} RuleParams
* @property {string} name File/string name. * @property {string} name File/string name.
* @property {MarkdownItToken[]} tokens Token objects from markdown-it. * @property {MarkdownItToken[]} tokens Token objects from markdown-it (deprecated, use parsers.markdownit.tokens).
* @property {MarkdownParsers} parsers Markdown parser data.
* @property {string[]} lines File/string lines. * @property {string[]} lines File/string lines.
* @property {string[]} frontMatterLines Front matter lines. * @property {string[]} frontMatterLines Front matter lines.
* @property {RuleConfiguration} config Rule configuration. * @property {RuleConfiguration} config Rule configuration.
*/ */
/** /**
* Markdown-It token. * Markdown parser data.
*
* @typedef {Object} MarkdownParsers
* @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it.
*/
/**
* Markdown parser data from markdown-it.
*
* @typedef {Object} ParserMarkdownIt
* @property {MarkdownItToken[]} tokens Token objects from markdown-it.
*/
/**
* markdown-it token.
* *
* @typedef {Object} MarkdownItToken * @typedef {Object} MarkdownItToken
* @property {string[][]} attrs HTML attributes. * @property {string[][]} attrs HTML attributes.
@ -3163,6 +3178,8 @@ module.exports = markdownlint;
const { addErrorDetailIf, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorDetailIf, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD001", "heading-increment" ], "names": [ "MD001", "heading-increment" ],
"description": "Heading levels should only increment by one level at a time", "description": "Heading levels should only increment by one level at a time",
@ -3197,6 +3214,8 @@ module.exports = {
const { addErrorDetailIf, filterTokens, headingStyleFor } = const { addErrorDetailIf, filterTokens, headingStyleFor } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD003", "heading-style" ], "names": [ "MD003", "heading-style" ],
"description": "Heading style", "description": "Heading style",
@ -3263,6 +3282,8 @@ const differentItemStyle = {
}; };
const validStyles = Object.keys(expectedStyleToMarker); const validStyles = Object.keys(expectedStyleToMarker);
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD004", "ul-style" ], "names": [ "MD004", "ul-style" ],
"description": "Unordered list style", "description": "Unordered list style",
@ -3337,13 +3358,16 @@ module.exports = {
const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD005", "list-indent" ], "names": [ "MD005", "list-indent" ],
"description": "Inconsistent indentation for list items at the same level", "description": "Inconsistent indentation for list items at the same level",
"tags": [ "bullet", "ul", "indentation" ], "tags": [ "bullet", "ul", "indentation" ],
"function": function MD005(params, onError) { "function": function MD005(params, onError) {
const lists = filterByTypes( const lists = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "listOrdered", "listUnordered" ] [ "listOrdered", "listUnordered" ]
).filter((list) => !inHtmlFlow(list)); ).filter((list) => !inHtmlFlow(list));
for (const list of lists) { for (const list of lists) {
@ -3431,6 +3455,8 @@ const unorderedListTypes =
const unorderedParentTypes = const unorderedParentTypes =
[ "blockQuote", "listOrdered", "listUnordered" ]; [ "blockQuote", "listOrdered", "listUnordered" ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD007", "ul-indent" ], "names": [ "MD007", "ul-indent" ],
"description": "Unordered list indentation", "description": "Unordered list indentation",
@ -3442,7 +3468,8 @@ module.exports = {
const unorderedListNesting = new Map(); const unorderedListNesting = new Map();
let lastBlockQuotePrefix = null; let lastBlockQuotePrefix = null;
const tokens = filterByTypes( const tokens = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
unorderedListTypes unorderedListTypes
); );
for (const token of tokens) { for (const token of tokens) {
@ -3520,6 +3547,8 @@ const { addError, filterTokens, forEachLine, includesSorted,
numericSortAscending } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); numericSortAscending } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD009", "no-trailing-spaces" ], "names": [ "MD009", "no-trailing-spaces" ],
"description": "Trailing spaces", "description": "Trailing spaces",
@ -3619,6 +3648,8 @@ const { codeBlockAndSpanRanges, lineMetadata } = __webpack_require__(/*! ./cache
const tabRe = /\t+/g; const tabRe = /\t+/g;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD010", "no-hard-tabs" ], "names": [ "MD010", "no-hard-tabs" ],
"description": "Hard tabs", "description": "Hard tabs",
@ -3655,7 +3686,7 @@ module.exports = {
onError, onError,
lineIndex + 1, lineIndex + 1,
"Column: " + column, "Column: " + column,
null, undefined,
[ column, length ], [ column, length ],
{ {
"editColumn": column, "editColumn": column,
@ -3690,6 +3721,8 @@ const { codeBlockAndSpanRanges, lineMetadata } = __webpack_require__(/*! ./cache
const reversedLinkRe = const reversedLinkRe =
/(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g; /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD011", "no-reversed-links" ], "names": [ "MD011", "no-reversed-links" ],
"description": "Reversed link syntax", "description": "Reversed link syntax",
@ -3744,6 +3777,8 @@ module.exports = {
const { addErrorDetailIf, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorDetailIf, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD012", "no-multiple-blanks" ], "names": [ "MD012", "no-multiple-blanks" ],
"description": "Multiple consecutive blank lines", "description": "Multiple consecutive blank lines",
@ -3804,6 +3839,8 @@ const tokenTypeMap = {
"text": "T" "text": "T"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD013", "line-length" ], "names": [ "MD013", "line-length" ],
"description": "Line length", "description": "Line length",
@ -3895,6 +3932,8 @@ const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */
const dollarCommandRe = /^(\s*)(\$\s+)/; const dollarCommandRe = /^(\s*)(\$\s+)/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD014", "commands-show-output" ], "names": [ "MD014", "commands-show-output" ],
"description": "Dollar signs used before commands without showing output", "description": "Dollar signs used before commands without showing output",
@ -3924,6 +3963,7 @@ module.exports = {
const [ i, lineTrim, column, length ] = instance; const [ i, lineTrim, column, length ] = instance;
addErrorContext( addErrorContext(
onError, onError,
// @ts-ignore
i + 1, i + 1,
lineTrim, lineTrim,
null, null,
@ -3958,6 +3998,8 @@ module.exports = {
const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD018", "no-missing-space-atx" ], "names": [ "MD018", "no-missing-space-atx" ],
"description": "No space after hash on atx style heading", "description": "No space after hash on atx style heading",
@ -3968,6 +4010,7 @@ module.exports = {
/^#+[^# \t]/.test(line) && /^#+[^# \t]/.test(line) &&
!/#\s*$/.test(line) && !/#\s*$/.test(line) &&
!line.startsWith("#️⃣")) { !line.startsWith("#️⃣")) {
// @ts-ignore
const hashCount = /^#+/.exec(line)[0].length; const hashCount = /^#+/.exec(line)[0].length;
addErrorContext( addErrorContext(
onError, onError,
@ -4003,6 +4046,8 @@ module.exports = {
const { addErrorContext, filterTokens, headingStyleFor } = const { addErrorContext, filterTokens, headingStyleFor } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD019", "no-multiple-space-atx" ], "names": [ "MD019", "no-multiple-space-atx" ],
"description": "Multiple spaces after hash on atx style heading", "description": "Multiple spaces after hash on atx style heading",
@ -4053,6 +4098,8 @@ module.exports = {
const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext, forEachLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD020", "no-missing-space-closed-atx" ], "names": [ "MD020", "no-missing-space-closed-atx" ],
"description": "No space inside hashes on closed atx style heading", "description": "No space inside hashes on closed atx style heading",
@ -4128,6 +4175,8 @@ const { addErrorContext, filterTokens, headingStyleFor } =
const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/; const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD021", "no-multiple-space-closed-atx" ], "names": [ "MD021", "no-multiple-space-closed-atx" ],
"description": "Multiple spaces inside hashes on closed atx style heading", "description": "Multiple spaces inside hashes on closed atx style heading",
@ -4225,6 +4274,8 @@ const getBlockQuote = (str, count) => (
.repeat(count) .repeat(count)
); );
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD022", "blanks-around-headings" ], "names": [ "MD022", "blanks-around-headings" ],
"description": "Headings should be surrounded by blank lines", "description": "Headings should be surrounded by blank lines",
@ -4234,7 +4285,8 @@ module.exports = {
const getLinesBelow = getLinesFunction(params.config.lines_below); const getLinesBelow = getLinesFunction(params.config.lines_below);
const { lines, parsers } = params; const { lines, parsers } = params;
const headings = filterByTypes( const headings = filterByTypes(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
[ "atxHeading", "setextHeading" ] [ "atxHeading", "setextHeading" ]
).filter((heading) => !inHtmlFlow(heading)); ).filter((heading) => !inHtmlFlow(heading));
for (const heading of headings) { for (const heading of headings) {
@ -4319,6 +4371,8 @@ const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */
const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/; const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD023", "heading-start-left" ], "names": [ "MD023", "heading-start-left" ],
"description": "Headings must start at the beginning of the line", "description": "Headings must start at the beginning of the line",
@ -4366,6 +4420,8 @@ module.exports = {
const { addErrorContext, forEachHeading } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext, forEachHeading } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD024", "no-duplicate-heading" ], "names": [ "MD024", "no-duplicate-heading" ],
"description": "Multiple headings with the same content", "description": "Multiple headings with the same content",
@ -4420,6 +4476,8 @@ module.exports = {
const { addErrorContext, filterTokens, frontMatterHasTitle } = const { addErrorContext, filterTokens, frontMatterHasTitle } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD025", "single-title", "single-h1" ], "names": [ "MD025", "single-title", "single-h1" ],
"description": "Multiple top-level headings in the same document", "description": "Multiple top-level headings in the same document",
@ -4464,6 +4522,8 @@ const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe,
endOfLineHtmlEntityRe, escapeForRegExp } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); endOfLineHtmlEntityRe, escapeForRegExp } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD026", "no-trailing-punctuation" ], "names": [ "MD026", "no-trailing-punctuation" ],
"description": "Trailing punctuation in heading", "description": "Trailing punctuation in heading",
@ -4476,7 +4536,8 @@ module.exports = {
const trailingPunctuationRe = const trailingPunctuationRe =
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$"); new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
const headings = filterByTypes( const headings = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "atxHeadingText", "setextHeadingText" ] [ "atxHeadingText", "setextHeadingText" ]
); );
for (const heading of headings) { for (const heading of headings) {
@ -4523,12 +4584,15 @@ module.exports = {
const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": ["MD027", "no-multiple-space-blockquote"], "names": ["MD027", "no-multiple-space-blockquote"],
"description": "Multiple spaces after blockquote symbol", "description": "Multiple spaces after blockquote symbol",
"tags": ["blockquote", "whitespace", "indentation"], "tags": ["blockquote", "whitespace", "indentation"],
"function": function MD027(params, onError) { "function": function MD027(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "linePrefix" ])) { for (const token of filterByTypes(tokens, [ "linePrefix" ])) {
const siblings = token.parent?.children || tokens; const siblings = token.parent?.children || tokens;
if (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") { if (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") {
@ -4571,12 +4635,15 @@ const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ ".
const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]); const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]);
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD028", "no-blanks-blockquote" ], "names": [ "MD028", "no-blanks-blockquote" ],
"description": "Blank line inside blockquote", "description": "Blank line inside blockquote",
"tags": [ "blockquote", "whitespace" ], "tags": [ "blockquote", "whitespace" ],
"function": function MD028(params, onError) { "function": function MD028(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "blockQuote" ])) { for (const token of filterByTypes(tokens, [ "blockQuote" ])) {
const errorLineNumbers = []; const errorLineNumbers = [];
const siblings = token.parent?.children || tokens; const siblings = token.parent?.children || tokens;
@ -4627,6 +4694,8 @@ const listStyleExamples = {
"zero": "0/0/0" "zero": "0/0/0"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD029", "ol-prefix" ], "names": [ "MD029", "ol-prefix" ],
"description": "Ordered list item prefix", "description": "Ordered list item prefix",
@ -4698,6 +4767,8 @@ module.exports = {
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD030", "list-marker-space" ], "names": [ "MD030", "list-marker-space" ],
"description": "Spaces after list markers", "description": "Spaces after list markers",
@ -4708,7 +4779,8 @@ module.exports = {
const ulMulti = Number(params.config.ul_multi || 1); const ulMulti = Number(params.config.ul_multi || 1);
const olMulti = Number(params.config.ol_multi || 1); const olMulti = Number(params.config.ol_multi || 1);
const lists = filterByTypes( const lists = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "listOrdered", "listUnordered" ] [ "listOrdered", "listUnordered" ]
); );
for (const list of lists) { for (const list of lists) {
@ -4772,6 +4844,8 @@ const { lineMetadata } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
const codeFencePrefixRe = /^(.*?)[`~]/; const codeFencePrefixRe = /^(.*?)[`~]/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD031", "blanks-around-fences" ], "names": [ "MD031", "blanks-around-fences" ],
"description": "Fenced code blocks should be surrounded by blank lines", "description": "Fenced code blocks should be surrounded by blank lines",
@ -4851,6 +4925,8 @@ const addBlankLineError = (onError, lines, lineIndex, lineNumber) => {
); );
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD032", "blanks-around-lists" ], "names": [ "MD032", "blanks-around-lists" ],
"description": "Lists should be surrounded by blank lines", "description": "Lists should be surrounded by blank lines",
@ -4860,7 +4936,8 @@ module.exports = {
// For every top-level list... // For every top-level list...
const topLevelLists = filterByPredicate( const topLevelLists = filterByPredicate(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
isList, isList,
(token) => ( (token) => (
(isList(token) || (token.type === "htmlFlow")) ? [] : token.children (isList(token) || (token.type === "htmlFlow")) ? [] : token.children
@ -4911,6 +4988,8 @@ const { addError, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../help
const { filterByTypes, getHtmlTagInfo } = const { filterByTypes, getHtmlTagInfo } =
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD033", "no-inline-html" ], "names": [ "MD033", "no-inline-html" ],
"description": "Inline HTML", "description": "Inline HTML",
@ -4919,7 +4998,8 @@ module.exports = {
let allowedElements = params.config.allowed_elements; let allowedElements = params.config.allowed_elements;
allowedElements = Array.isArray(allowedElements) ? allowedElements : []; allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
allowedElements = allowedElements.map((element) => element.toLowerCase()); allowedElements = allowedElements.map((element) => element.toLowerCase());
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "htmlText" ])) { for (const token of filterByTypes(tokens, [ "htmlText" ])) {
const htmlTagInfo = getHtmlTagInfo(token); const htmlTagInfo = getHtmlTagInfo(token);
if ( if (
@ -4961,6 +5041,8 @@ const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/he
const { filterByPredicate, filterByTypes, getHtmlTagInfo, inHtmlFlow, parse } = const { filterByPredicate, filterByTypes, getHtmlTagInfo, inHtmlFlow, parse } =
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD034", "no-bare-urls" ], "names": [ "MD034", "no-bare-urls" ],
"description": "Bare URL used", "description": "Bare URL used",
@ -5002,7 +5084,8 @@ module.exports = {
) )
); );
const autoLinks = filterByTypes( const autoLinks = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "literalAutolink" ] [ "literalAutolink" ]
); );
if (autoLinks.length > 0) { if (autoLinks.length > 0) {
@ -5050,6 +5133,8 @@ module.exports = {
const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD035", "hr-style" ], "names": [ "MD035", "hr-style" ],
"description": "Horizontal rule style", "description": "Horizontal rule style",
@ -5057,7 +5142,8 @@ module.exports = {
"function": function MD035(params, onError) { "function": function MD035(params, onError) {
let style = String(params.config.style || "consistent").trim(); let style = String(params.config.style || "consistent").trim();
const thematicBreaks = const thematicBreaks =
filterByTypes(params.parsers.micromark.tokens, [ "thematicBreak" ]); // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "thematicBreak" ]);
for (const token of thematicBreaks) { for (const token of thematicBreaks) {
const { startLine, text } = token; const { startLine, text } = token;
if (style === "consistent") { if (style === "consistent") {
@ -5084,6 +5170,8 @@ module.exports = {
const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD036", "no-emphasis-as-heading" ], "names": [ "MD036", "no-emphasis-as-heading" ],
"description": "Emphasis used instead of a heading", "description": "Emphasis used instead of a heading",
@ -5152,6 +5240,8 @@ module.exports = {
const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD037", "no-space-in-emphasis" ], "names": [ "MD037", "no-space-in-emphasis" ],
"description": "Spaces inside emphasis markers", "description": "Spaces inside emphasis markers",
@ -5165,7 +5255,8 @@ module.exports = {
emphasisTokensByMarker.set(marker, []); emphasisTokensByMarker.set(marker, []);
} }
const tokens = filterByPredicate( const tokens = filterByPredicate(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
(token) => token.children.some((child) => child.type === "data") (token) => token.children.some((child) => child.type === "data")
); );
for (const token of tokens) { for (const token of tokens) {
@ -5268,13 +5359,16 @@ const trimCodeText = (text, start, end) => {
return text; return text;
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD038", "no-space-in-code" ], "names": [ "MD038", "no-space-in-code" ],
"description": "Spaces inside code span elements", "description": "Spaces inside code span elements",
"tags": [ "whitespace", "code" ], "tags": [ "whitespace", "code" ],
"function": function MD038(params, onError) { "function": function MD038(params, onError) {
const codeTexts = const codeTexts =
filterByTypes(params.parsers.micromark.tokens, [ "codeText" ]) // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "codeText" ])
.filter((codeText) => !inHtmlFlow(codeText)); .filter((codeText) => !inHtmlFlow(codeText));
for (const codeText of codeTexts) { for (const codeText of codeTexts) {
const { children } = codeText; const { children } = codeText;
@ -5366,6 +5460,8 @@ const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */
const spaceInLinkRe = const spaceInLinkRe =
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/; /\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD039", "no-space-in-links" ], "names": [ "MD039", "no-space-in-links" ],
"description": "Spaces inside link text", "description": "Spaces inside link text",
@ -5392,6 +5488,7 @@ module.exports = {
let fixInfo = null; let fixInfo = null;
const match = line.slice(lineIndex).match(spaceInLinkRe); const match = line.slice(lineIndex).match(spaceInLinkRe);
if (match) { if (match) {
// @ts-ignore
const column = match.index + lineIndex + 1; const column = match.index + lineIndex + 1;
const length = match[0].length; const length = match[0].length;
range = [ column, length ]; range = [ column, length ];
@ -5443,6 +5540,8 @@ const { addError, addErrorContext } = __webpack_require__(/*! ../helpers */ "../
const { filterByTypes, getTokenTextByType, tokenIfType } = const { filterByTypes, getTokenTextByType, tokenIfType } =
__webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD040", "fenced-code-language" ], "names": [ "MD040", "fenced-code-language" ],
"description": "Fenced code blocks should have a language specified", "description": "Fenced code blocks should have a language specified",
@ -5451,7 +5550,8 @@ module.exports = {
let allowed = params.config.allowed_languages; let allowed = params.config.allowed_languages;
allowed = Array.isArray(allowed) ? allowed : []; allowed = Array.isArray(allowed) ? allowed : [];
const languageOnly = !!params.config.language_only; const languageOnly = !!params.config.language_only;
const fencedCodes = filterByTypes(params.parsers.micromark.tokens, [ "codeFenced" ]); // eslint-disable-next-line dot-notation
const fencedCodes = filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced" ]);
for (const fencedCode of fencedCodes) { for (const fencedCode of fencedCodes) {
const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence"); const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
if (openingFence) { if (openingFence) {
@ -5486,6 +5586,8 @@ module.exports = {
const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD041", "first-line-heading", "first-line-h1" ], "names": [ "MD041", "first-line-heading", "first-line-h1" ],
"description": "First line in a file should be a top-level heading", "description": "First line in a file should be a top-level heading",
@ -5540,6 +5642,8 @@ module.exports = {
const { addErrorContext, escapeForRegExp, filterTokens } = const { addErrorContext, escapeForRegExp, filterTokens } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD042", "no-empty-links" ], "names": [ "MD042", "no-empty-links" ],
"description": "No empty links", "description": "No empty links",
@ -5568,6 +5672,7 @@ module.exports = {
); );
if (match) { if (match) {
context = match[0]; context = match[0];
// @ts-ignore
range = [ match.index + 1, match[0].length ]; range = [ match.index + 1, match[0].length ];
} }
addErrorContext( addErrorContext(
@ -5600,6 +5705,8 @@ module.exports = {
const { addErrorContext, addErrorDetailIf, forEachHeading } = const { addErrorContext, addErrorDetailIf, forEachHeading } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD043", "required-headings" ], "names": [ "MD043", "required-headings" ],
"description": "Required heading structure", "description": "Required heading structure",
@ -5681,6 +5788,8 @@ const ignoredChildTypes = new Set(
[ "codeFencedFence", "definition", "reference", "resource" ] [ "codeFencedFence", "definition", "reference", "resource" ]
); );
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD044", "proper-names" ], "names": [ "MD044", "proper-names" ],
"description": "Proper names should have the correct capitalization", "description": "Proper names should have the correct capitalization",
@ -5710,7 +5819,8 @@ module.exports = {
} }
const contentTokens = const contentTokens =
filterByPredicate( filterByPredicate(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
(token) => scannedTypes.has(token.type), (token) => scannedTypes.has(token.type),
(token) => ( (token) => (
token.children.filter((t) => !ignoredChildTypes.has(t.type)) token.children.filter((t) => !ignoredChildTypes.has(t.type))
@ -5795,12 +5905,15 @@ const { filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/mic
const altRe = getHtmlAttributeRe("alt"); const altRe = getHtmlAttributeRe("alt");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD045", "no-alt-text" ], "names": [ "MD045", "no-alt-text" ],
"description": "Images should have alternate text (alt text)", "description": "Images should have alternate text (alt text)",
"tags": [ "accessibility", "images" ], "tags": [ "accessibility", "images" ],
"function": function MD045(params, onError) { "function": function MD045(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
// Process Markdown images // Process Markdown images
const images = filterByTypes(tokens, [ "image" ]); const images = filterByTypes(tokens, [ "image" ]);
@ -5869,6 +5982,8 @@ const tokenTypeToStyle = {
"codeIndented": "indented" "codeIndented": "indented"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD046", "code-block-style" ], "names": [ "MD046", "code-block-style" ],
"description": "Code block style", "description": "Code block style",
@ -5876,7 +5991,8 @@ module.exports = {
"function": function MD046(params, onError) { "function": function MD046(params, onError) {
let expectedStyle = String(params.config.style || "consistent"); let expectedStyle = String(params.config.style || "consistent");
const codeBlocksAndFences = const codeBlocksAndFences =
filterByTypes(params.parsers.micromark.tokens, [ "codeFenced", "codeIndented" ]); // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced", "codeIndented" ]);
for (const token of codeBlocksAndFences) { for (const token of codeBlocksAndFences) {
const { startLine, type } = token; const { startLine, type } = token;
if (expectedStyle === "consistent") { if (expectedStyle === "consistent") {
@ -5907,6 +6023,8 @@ module.exports = {
const { addError, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addError, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD047", "single-trailing-newline" ], "names": [ "MD047", "single-trailing-newline" ],
"description": "Files should end with a single newline character", "description": "Files should end with a single newline character",
@ -5918,8 +6036,8 @@ module.exports = {
addError( addError(
onError, onError,
lastLineNumber, lastLineNumber,
null, undefined,
null, undefined,
[ lastLine.length, 1 ], [ lastLine.length, 1 ],
{ {
"insertText": "\n", "insertText": "\n",
@ -5947,6 +6065,8 @@ module.exports = {
const { addErrorDetailIf, fencedCodeBlockStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addErrorDetailIf, fencedCodeBlockStyleFor } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { filterByTypes, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const { filterByTypes, tokenIfType } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD048", "code-fence-style" ], "names": [ "MD048", "code-fence-style" ],
"description": "Code fence style", "description": "Code fence style",
@ -5954,7 +6074,8 @@ module.exports = {
"function": function MD048(params, onError) { "function": function MD048(params, onError) {
const style = String(params.config.style || "consistent"); const style = String(params.config.style || "consistent");
let expectedStyle = style; let expectedStyle = style;
const codeFenceds = filterByTypes(params.parsers.micromark.tokens, [ "codeFenced" ]); // eslint-disable-next-line dot-notation
const codeFenceds = filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced" ]);
for (const codeFenced of codeFenceds) { for (const codeFenced of codeFenceds) {
const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence"); const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
if (codeFencedFence) { if (codeFencedFence) {
@ -6153,12 +6274,15 @@ function unescapeStringTokenText(token) {
.join(""); .join("");
} }
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD051", "link-fragments" ], "names": [ "MD051", "link-fragments" ],
"description": "Link fragments should be valid", "description": "Link fragments should be valid",
"tags": [ "links" ], "tags": [ "links" ],
"function": function MD051(params, onError) { "function": function MD051(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
const fragments = new Map(); const fragments = new Map();
// Process headings // Process headings
@ -6278,6 +6402,8 @@ module.exports = {
const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD052", "reference-links-images" ], "names": [ "MD052", "reference-links-images" ],
"description": "description":
@ -6329,6 +6455,8 @@ const { addError, ellipsify, linkReferenceDefinitionRe } =
__webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); const { referenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD053", "link-image-reference-definitions" ], "names": [ "MD053", "link-image-reference-definitions" ],
"description": "Link and image reference definitions should be needed", "description": "Link and image reference definitions should be needed",
@ -6414,6 +6542,8 @@ const autolinkAble = (destination) => {
return !autolinkDisallowedRe.test(destination); return !autolinkDisallowedRe.test(destination);
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD054", "link-image-style" ], "names": [ "MD054", "link-image-style" ],
"description": "Link and image style", "description": "Link and image style",
@ -6432,7 +6562,8 @@ module.exports = {
} }
const { definitions } = referenceLinkImageData(); const { definitions } = referenceLinkImageData();
const links = filterByTypes( const links = filterByTypes(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
[ "autolink", "image", "link" ] [ "autolink", "image", "link" ]
); );
for (const link of links) { for (const link of links) {
@ -6542,6 +6673,8 @@ const firstOrNothing = (items) => items[0];
const lastOrNothing = (items) => items[items.length - 1]; const lastOrNothing = (items) => items[items.length - 1];
const makeRange = (start, end) => [ start, end - start + 1 ]; const makeRange = (start, end) => [ start, end - start + 1 ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD055", "table-pipe-style" ], "names": [ "MD055", "table-pipe-style" ],
"description": "Table pipe style", "description": "Table pipe style",
@ -6553,7 +6686,8 @@ module.exports = {
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only")); ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
let expectedTrailingPipe = let expectedTrailingPipe =
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only")); ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
const tables = filterByTypes(params.parsers.micromark.tokens, [ "table" ]); // eslint-disable-next-line dot-notation
const tables = filterByTypes(params.parsers["micromark"].tokens, [ "table" ]);
for (const table of tables) { for (const table of tables) {
const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]); const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]);
for (const row of rows) { for (const row of rows) {
@ -6619,12 +6753,15 @@ const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ ".
const makeRange = (start, end) => [ start, end - start + 1 ]; const makeRange = (start, end) => [ start, end - start + 1 ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD056", "table-column-count" ], "names": [ "MD056", "table-column-count" ],
"description": "Table column count", "description": "Table column count",
"tags": [ "table" ], "tags": [ "table" ],
"function": function MD056(params, onError) { "function": function MD056(params, onError) {
const tables = filterByTypes(params.parsers.micromark.tokens, [ "table" ]); // eslint-disable-next-line dot-notation
const tables = filterByTypes(params.parsers["micromark"].tokens, [ "table" ]);
for (const table of tables) { for (const table of tables) {
const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]); const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]);
let expectedCount = 0; let expectedCount = 0;

View file

@ -117,10 +117,16 @@ const testRule = {
"function": function rule(params: markdownlint.RuleParams, onError: markdownlint.RuleOnError) { "function": function rule(params: markdownlint.RuleParams, onError: markdownlint.RuleOnError) {
assert(!!params); assert(!!params);
assert(!!onError); assert(!!onError);
let tokens: markdownlint.MarkdownItToken[] = [];
let ruleParams: markdownlint.RuleParams; let ruleParams: markdownlint.RuleParams;
ruleParams = { ruleParams = {
"name": "name", "name": "name",
"tokens": <markdownlint.MarkdownItToken[]>[], "tokens": tokens,
"parsers": {
"markdownit": {
"tokens": tokens
}
},
"lines": [ "lines": [
"one", "one",
"two" "two"

28
lib/markdownlint.d.ts vendored
View file

@ -8,7 +8,7 @@ export = markdownlint;
*/ */
declare function markdownlint(options: Options | null, callback: LintCallback): void; declare function markdownlint(options: Options | null, callback: LintCallback): void;
declare namespace markdownlint { declare namespace markdownlint {
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintContentCallback, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback }; export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownParsers, ParserMarkdownIt, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintContentCallback, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
} }
/** /**
* Configuration options. * Configuration options.
@ -117,9 +117,13 @@ type RuleParams = {
*/ */
name: string; name: string;
/** /**
* Token objects from markdown-it. * Token objects from markdown-it (deprecated, use parsers.markdownit.tokens).
*/ */
tokens: MarkdownItToken[]; tokens: MarkdownItToken[];
/**
* Markdown parser data.
*/
parsers: MarkdownParsers;
/** /**
* File/string lines. * File/string lines.
*/ */
@ -134,7 +138,25 @@ type RuleParams = {
config: RuleConfiguration; config: RuleConfiguration;
}; };
/** /**
* Markdown-It token. * Markdown parser data.
*/
type MarkdownParsers = {
/**
* Markdown parser data from markdown-it.
*/
markdownit: ParserMarkdownIt;
};
/**
* Markdown parser data from markdown-it.
*/
type ParserMarkdownIt = {
/**
* Token objects from markdown-it.
*/
tokens: MarkdownItToken[];
};
/**
* markdown-it token.
*/ */
type MarkdownItToken = { type MarkdownItToken = {
/** /**

View file

@ -1286,14 +1286,29 @@ module.exports = markdownlint;
* *
* @typedef {Object} RuleParams * @typedef {Object} RuleParams
* @property {string} name File/string name. * @property {string} name File/string name.
* @property {MarkdownItToken[]} tokens Token objects from markdown-it. * @property {MarkdownItToken[]} tokens Token objects from markdown-it (deprecated, use parsers.markdownit.tokens).
* @property {MarkdownParsers} parsers Markdown parser data.
* @property {string[]} lines File/string lines. * @property {string[]} lines File/string lines.
* @property {string[]} frontMatterLines Front matter lines. * @property {string[]} frontMatterLines Front matter lines.
* @property {RuleConfiguration} config Rule configuration. * @property {RuleConfiguration} config Rule configuration.
*/ */
/** /**
* Markdown-It token. * Markdown parser data.
*
* @typedef {Object} MarkdownParsers
* @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it.
*/
/**
* Markdown parser data from markdown-it.
*
* @typedef {Object} ParserMarkdownIt
* @property {MarkdownItToken[]} tokens Token objects from markdown-it.
*/
/**
* markdown-it token.
* *
* @typedef {Object} MarkdownItToken * @typedef {Object} MarkdownItToken
* @property {string[][]} attrs HTML attributes. * @property {string[][]} attrs HTML attributes.

View file

@ -4,6 +4,8 @@
const { addErrorDetailIf, filterTokens } = require("../helpers"); const { addErrorDetailIf, filterTokens } = require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD001", "heading-increment" ], "names": [ "MD001", "heading-increment" ],
"description": "Heading levels should only increment by one level at a time", "description": "Heading levels should only increment by one level at a time",

View file

@ -5,6 +5,8 @@
const { addErrorDetailIf, filterTokens, headingStyleFor } = const { addErrorDetailIf, filterTokens, headingStyleFor } =
require("../helpers"); require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD003", "heading-style" ], "names": [ "MD003", "heading-style" ],
"description": "Heading style", "description": "Heading style",

View file

@ -18,6 +18,8 @@ const differentItemStyle = {
}; };
const validStyles = Object.keys(expectedStyleToMarker); const validStyles = Object.keys(expectedStyleToMarker);
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD004", "ul-style" ], "names": [ "MD004", "ul-style" ],
"description": "Unordered list style", "description": "Unordered list style",

View file

@ -5,13 +5,16 @@
const { addError, addErrorDetailIf } = require("../helpers"); const { addError, addErrorDetailIf } = require("../helpers");
const { filterByTypes, inHtmlFlow } = require("../helpers/micromark.cjs"); const { filterByTypes, inHtmlFlow } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD005", "list-indent" ], "names": [ "MD005", "list-indent" ],
"description": "Inconsistent indentation for list items at the same level", "description": "Inconsistent indentation for list items at the same level",
"tags": [ "bullet", "ul", "indentation" ], "tags": [ "bullet", "ul", "indentation" ],
"function": function MD005(params, onError) { "function": function MD005(params, onError) {
const lists = filterByTypes( const lists = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "listOrdered", "listUnordered" ] [ "listOrdered", "listUnordered" ]
).filter((list) => !inHtmlFlow(list)); ).filter((list) => !inHtmlFlow(list));
for (const list of lists) { for (const list of lists) {

View file

@ -15,6 +15,8 @@ const unorderedListTypes =
const unorderedParentTypes = const unorderedParentTypes =
[ "blockQuote", "listOrdered", "listUnordered" ]; [ "blockQuote", "listOrdered", "listUnordered" ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD007", "ul-indent" ], "names": [ "MD007", "ul-indent" ],
"description": "Unordered list indentation", "description": "Unordered list indentation",
@ -26,7 +28,8 @@ module.exports = {
const unorderedListNesting = new Map(); const unorderedListNesting = new Map();
let lastBlockQuotePrefix = null; let lastBlockQuotePrefix = null;
const tokens = filterByTypes( const tokens = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
unorderedListTypes unorderedListTypes
); );
for (const token of tokens) { for (const token of tokens) {

View file

@ -6,6 +6,8 @@ const { addError, filterTokens, forEachLine, includesSorted,
numericSortAscending } = require("../helpers"); numericSortAscending } = require("../helpers");
const { lineMetadata } = require("./cache"); const { lineMetadata } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD009", "no-trailing-spaces" ], "names": [ "MD009", "no-trailing-spaces" ],
"description": "Trailing spaces", "description": "Trailing spaces",

View file

@ -8,6 +8,8 @@ const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
const tabRe = /\t+/g; const tabRe = /\t+/g;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD010", "no-hard-tabs" ], "names": [ "MD010", "no-hard-tabs" ],
"description": "Hard tabs", "description": "Hard tabs",
@ -44,7 +46,7 @@ module.exports = {
onError, onError,
lineIndex + 1, lineIndex + 1,
"Column: " + column, "Column: " + column,
null, undefined,
[ column, length ], [ column, length ],
{ {
"editColumn": column, "editColumn": column,

View file

@ -8,6 +8,8 @@ const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
const reversedLinkRe = const reversedLinkRe =
/(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g; /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD011", "no-reversed-links" ], "names": [ "MD011", "no-reversed-links" ],
"description": "Reversed link syntax", "description": "Reversed link syntax",

View file

@ -5,6 +5,8 @@
const { addErrorDetailIf, forEachLine } = require("../helpers"); const { addErrorDetailIf, forEachLine } = require("../helpers");
const { lineMetadata } = require("./cache"); const { lineMetadata } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD012", "no-multiple-blanks" ], "names": [ "MD012", "no-multiple-blanks" ],
"description": "Multiple consecutive blank lines", "description": "Multiple consecutive blank lines",

View file

@ -22,6 +22,8 @@ const tokenTypeMap = {
"text": "T" "text": "T"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD013", "line-length" ], "names": [ "MD013", "line-length" ],
"description": "Line length", "description": "Line length",

View file

@ -6,6 +6,8 @@ const { addErrorContext, filterTokens } = require("../helpers");
const dollarCommandRe = /^(\s*)(\$\s+)/; const dollarCommandRe = /^(\s*)(\$\s+)/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD014", "commands-show-output" ], "names": [ "MD014", "commands-show-output" ],
"description": "Dollar signs used before commands without showing output", "description": "Dollar signs used before commands without showing output",
@ -35,6 +37,7 @@ module.exports = {
const [ i, lineTrim, column, length ] = instance; const [ i, lineTrim, column, length ] = instance;
addErrorContext( addErrorContext(
onError, onError,
// @ts-ignore
i + 1, i + 1,
lineTrim, lineTrim,
null, null,

View file

@ -5,6 +5,8 @@
const { addErrorContext, forEachLine } = require("../helpers"); const { addErrorContext, forEachLine } = require("../helpers");
const { lineMetadata } = require("./cache"); const { lineMetadata } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD018", "no-missing-space-atx" ], "names": [ "MD018", "no-missing-space-atx" ],
"description": "No space after hash on atx style heading", "description": "No space after hash on atx style heading",
@ -15,6 +17,7 @@ module.exports = {
/^#+[^# \t]/.test(line) && /^#+[^# \t]/.test(line) &&
!/#\s*$/.test(line) && !/#\s*$/.test(line) &&
!line.startsWith("#️⃣")) { !line.startsWith("#️⃣")) {
// @ts-ignore
const hashCount = /^#+/.exec(line)[0].length; const hashCount = /^#+/.exec(line)[0].length;
addErrorContext( addErrorContext(
onError, onError,

View file

@ -5,6 +5,8 @@
const { addErrorContext, filterTokens, headingStyleFor } = const { addErrorContext, filterTokens, headingStyleFor } =
require("../helpers"); require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD019", "no-multiple-space-atx" ], "names": [ "MD019", "no-multiple-space-atx" ],
"description": "Multiple spaces after hash on atx style heading", "description": "Multiple spaces after hash on atx style heading",

View file

@ -5,6 +5,8 @@
const { addErrorContext, forEachLine } = require("../helpers"); const { addErrorContext, forEachLine } = require("../helpers");
const { lineMetadata } = require("./cache"); const { lineMetadata } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD020", "no-missing-space-closed-atx" ], "names": [ "MD020", "no-missing-space-closed-atx" ],
"description": "No space inside hashes on closed atx style heading", "description": "No space inside hashes on closed atx style heading",

View file

@ -7,6 +7,8 @@ const { addErrorContext, filterTokens, headingStyleFor } =
const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/; const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD021", "no-multiple-space-closed-atx" ], "names": [ "MD021", "no-multiple-space-closed-atx" ],
"description": "Multiple spaces inside hashes on closed atx style heading", "description": "Multiple spaces inside hashes on closed atx style heading",

View file

@ -31,6 +31,8 @@ const getBlockQuote = (str, count) => (
.repeat(count) .repeat(count)
); );
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD022", "blanks-around-headings" ], "names": [ "MD022", "blanks-around-headings" ],
"description": "Headings should be surrounded by blank lines", "description": "Headings should be surrounded by blank lines",
@ -40,7 +42,8 @@ module.exports = {
const getLinesBelow = getLinesFunction(params.config.lines_below); const getLinesBelow = getLinesFunction(params.config.lines_below);
const { lines, parsers } = params; const { lines, parsers } = params;
const headings = filterByTypes( const headings = filterByTypes(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
[ "atxHeading", "setextHeading" ] [ "atxHeading", "setextHeading" ]
).filter((heading) => !inHtmlFlow(heading)); ).filter((heading) => !inHtmlFlow(heading));
for (const heading of headings) { for (const heading of headings) {

View file

@ -6,6 +6,8 @@ const { addErrorContext, filterTokens } = require("../helpers");
const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/; const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD023", "heading-start-left" ], "names": [ "MD023", "heading-start-left" ],
"description": "Headings must start at the beginning of the line", "description": "Headings must start at the beginning of the line",

View file

@ -4,6 +4,8 @@
const { addErrorContext, forEachHeading } = require("../helpers"); const { addErrorContext, forEachHeading } = require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD024", "no-duplicate-heading" ], "names": [ "MD024", "no-duplicate-heading" ],
"description": "Multiple headings with the same content", "description": "Multiple headings with the same content",

View file

@ -5,6 +5,8 @@
const { addErrorContext, filterTokens, frontMatterHasTitle } = const { addErrorContext, filterTokens, frontMatterHasTitle } =
require("../helpers"); require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD025", "single-title", "single-h1" ], "names": [ "MD025", "single-title", "single-h1" ],
"description": "Multiple top-level headings in the same document", "description": "Multiple top-level headings in the same document",

View file

@ -6,6 +6,8 @@ const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe,
endOfLineHtmlEntityRe, escapeForRegExp } = require("../helpers"); endOfLineHtmlEntityRe, escapeForRegExp } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs"); const { filterByTypes } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD026", "no-trailing-punctuation" ], "names": [ "MD026", "no-trailing-punctuation" ],
"description": "Trailing punctuation in heading", "description": "Trailing punctuation in heading",
@ -18,7 +20,8 @@ module.exports = {
const trailingPunctuationRe = const trailingPunctuationRe =
new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$"); new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$");
const headings = filterByTypes( const headings = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "atxHeadingText", "setextHeadingText" ] [ "atxHeadingText", "setextHeadingText" ]
); );
for (const heading of headings) { for (const heading of headings) {

View file

@ -5,12 +5,15 @@
const { addErrorContext } = require("../helpers"); const { addErrorContext } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs"); const { filterByTypes } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": ["MD027", "no-multiple-space-blockquote"], "names": ["MD027", "no-multiple-space-blockquote"],
"description": "Multiple spaces after blockquote symbol", "description": "Multiple spaces after blockquote symbol",
"tags": ["blockquote", "whitespace", "indentation"], "tags": ["blockquote", "whitespace", "indentation"],
"function": function MD027(params, onError) { "function": function MD027(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "linePrefix" ])) { for (const token of filterByTypes(tokens, [ "linePrefix" ])) {
const siblings = token.parent?.children || tokens; const siblings = token.parent?.children || tokens;
if (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") { if (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") {

View file

@ -7,12 +7,15 @@ const { filterByTypes } = require("../helpers/micromark.cjs");
const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]); const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]);
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD028", "no-blanks-blockquote" ], "names": [ "MD028", "no-blanks-blockquote" ],
"description": "Blank line inside blockquote", "description": "Blank line inside blockquote",
"tags": [ "blockquote", "whitespace" ], "tags": [ "blockquote", "whitespace" ],
"function": function MD028(params, onError) { "function": function MD028(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "blockQuote" ])) { for (const token of filterByTypes(tokens, [ "blockQuote" ])) {
const errorLineNumbers = []; const errorLineNumbers = [];
const siblings = token.parent?.children || tokens; const siblings = token.parent?.children || tokens;

View file

@ -12,6 +12,8 @@ const listStyleExamples = {
"zero": "0/0/0" "zero": "0/0/0"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD029", "ol-prefix" ], "names": [ "MD029", "ol-prefix" ],
"description": "Ordered list item prefix", "description": "Ordered list item prefix",

View file

@ -5,6 +5,8 @@
const { addErrorDetailIf } = require("../helpers"); const { addErrorDetailIf } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs"); const { filterByTypes } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD030", "list-marker-space" ], "names": [ "MD030", "list-marker-space" ],
"description": "Spaces after list markers", "description": "Spaces after list markers",
@ -15,7 +17,8 @@ module.exports = {
const ulMulti = Number(params.config.ul_multi || 1); const ulMulti = Number(params.config.ul_multi || 1);
const olMulti = Number(params.config.ol_multi || 1); const olMulti = Number(params.config.ol_multi || 1);
const lists = filterByTypes( const lists = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "listOrdered", "listUnordered" ] [ "listOrdered", "listUnordered" ]
); );
for (const list of lists) { for (const list of lists) {

View file

@ -7,6 +7,8 @@ const { lineMetadata } = require("./cache");
const codeFencePrefixRe = /^(.*?)[`~]/; const codeFencePrefixRe = /^(.*?)[`~]/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD031", "blanks-around-fences" ], "names": [ "MD031", "blanks-around-fences" ],
"description": "Fenced code blocks should be surrounded by blank lines", "description": "Fenced code blocks should be surrounded by blank lines",

View file

@ -35,6 +35,8 @@ const addBlankLineError = (onError, lines, lineIndex, lineNumber) => {
); );
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD032", "blanks-around-lists" ], "names": [ "MD032", "blanks-around-lists" ],
"description": "Lists should be surrounded by blank lines", "description": "Lists should be surrounded by blank lines",
@ -44,7 +46,8 @@ module.exports = {
// For every top-level list... // For every top-level list...
const topLevelLists = filterByPredicate( const topLevelLists = filterByPredicate(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
isList, isList,
(token) => ( (token) => (
(isList(token) || (token.type === "htmlFlow")) ? [] : token.children (isList(token) || (token.type === "htmlFlow")) ? [] : token.children

View file

@ -6,6 +6,8 @@ const { addError, nextLinesRe } = require("../helpers");
const { filterByTypes, getHtmlTagInfo } = const { filterByTypes, getHtmlTagInfo } =
require("../helpers/micromark.cjs"); require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD033", "no-inline-html" ], "names": [ "MD033", "no-inline-html" ],
"description": "Inline HTML", "description": "Inline HTML",
@ -14,7 +16,8 @@ module.exports = {
let allowedElements = params.config.allowed_elements; let allowedElements = params.config.allowed_elements;
allowedElements = Array.isArray(allowedElements) ? allowedElements : []; allowedElements = Array.isArray(allowedElements) ? allowedElements : [];
allowedElements = allowedElements.map((element) => element.toLowerCase()); allowedElements = allowedElements.map((element) => element.toLowerCase());
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
for (const token of filterByTypes(tokens, [ "htmlText" ])) { for (const token of filterByTypes(tokens, [ "htmlText" ])) {
const htmlTagInfo = getHtmlTagInfo(token); const htmlTagInfo = getHtmlTagInfo(token);
if ( if (

View file

@ -6,6 +6,8 @@ const { addErrorContext } = require("../helpers");
const { filterByPredicate, filterByTypes, getHtmlTagInfo, inHtmlFlow, parse } = const { filterByPredicate, filterByTypes, getHtmlTagInfo, inHtmlFlow, parse } =
require("../helpers/micromark.cjs"); require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD034", "no-bare-urls" ], "names": [ "MD034", "no-bare-urls" ],
"description": "Bare URL used", "description": "Bare URL used",
@ -47,7 +49,8 @@ module.exports = {
) )
); );
const autoLinks = filterByTypes( const autoLinks = filterByTypes(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
[ "literalAutolink" ] [ "literalAutolink" ]
); );
if (autoLinks.length > 0) { if (autoLinks.length > 0) {

View file

@ -5,6 +5,8 @@
const { addErrorDetailIf } = require("../helpers"); const { addErrorDetailIf } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs"); const { filterByTypes } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD035", "hr-style" ], "names": [ "MD035", "hr-style" ],
"description": "Horizontal rule style", "description": "Horizontal rule style",
@ -12,7 +14,8 @@ module.exports = {
"function": function MD035(params, onError) { "function": function MD035(params, onError) {
let style = String(params.config.style || "consistent").trim(); let style = String(params.config.style || "consistent").trim();
const thematicBreaks = const thematicBreaks =
filterByTypes(params.parsers.micromark.tokens, [ "thematicBreak" ]); // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "thematicBreak" ]);
for (const token of thematicBreaks) { for (const token of thematicBreaks) {
const { startLine, text } = token; const { startLine, text } = token;
if (style === "consistent") { if (style === "consistent") {

View file

@ -4,6 +4,8 @@
const { addErrorContext, allPunctuation } = require("../helpers"); const { addErrorContext, allPunctuation } = require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD036", "no-emphasis-as-heading" ], "names": [ "MD036", "no-emphasis-as-heading" ],
"description": "Emphasis used instead of a heading", "description": "Emphasis used instead of a heading",

View file

@ -5,6 +5,8 @@
const { addError } = require("../helpers"); const { addError } = require("../helpers");
const { filterByPredicate, inHtmlFlow } = require("../helpers/micromark.cjs"); const { filterByPredicate, inHtmlFlow } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD037", "no-space-in-emphasis" ], "names": [ "MD037", "no-space-in-emphasis" ],
"description": "Spaces inside emphasis markers", "description": "Spaces inside emphasis markers",
@ -18,7 +20,8 @@ module.exports = {
emphasisTokensByMarker.set(marker, []); emphasisTokensByMarker.set(marker, []);
} }
const tokens = filterByPredicate( const tokens = filterByPredicate(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
(token) => token.children.some((child) => child.type === "data") (token) => token.children.some((child) => child.type === "data")
); );
for (const token of tokens) { for (const token of tokens) {

View file

@ -19,13 +19,16 @@ const trimCodeText = (text, start, end) => {
return text; return text;
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD038", "no-space-in-code" ], "names": [ "MD038", "no-space-in-code" ],
"description": "Spaces inside code span elements", "description": "Spaces inside code span elements",
"tags": [ "whitespace", "code" ], "tags": [ "whitespace", "code" ],
"function": function MD038(params, onError) { "function": function MD038(params, onError) {
const codeTexts = const codeTexts =
filterByTypes(params.parsers.micromark.tokens, [ "codeText" ]) // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "codeText" ])
.filter((codeText) => !inHtmlFlow(codeText)); .filter((codeText) => !inHtmlFlow(codeText));
for (const codeText of codeTexts) { for (const codeText of codeTexts) {
const { children } = codeText; const { children } = codeText;

View file

@ -7,6 +7,8 @@ const { addErrorContext, filterTokens } = require("../helpers");
const spaceInLinkRe = const spaceInLinkRe =
/\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/; /\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/;
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD039", "no-space-in-links" ], "names": [ "MD039", "no-space-in-links" ],
"description": "Spaces inside link text", "description": "Spaces inside link text",
@ -33,6 +35,7 @@ module.exports = {
let fixInfo = null; let fixInfo = null;
const match = line.slice(lineIndex).match(spaceInLinkRe); const match = line.slice(lineIndex).match(spaceInLinkRe);
if (match) { if (match) {
// @ts-ignore
const column = match.index + lineIndex + 1; const column = match.index + lineIndex + 1;
const length = match[0].length; const length = match[0].length;
range = [ column, length ]; range = [ column, length ];

View file

@ -6,6 +6,8 @@ const { addError, addErrorContext } = require("../helpers");
const { filterByTypes, getTokenTextByType, tokenIfType } = const { filterByTypes, getTokenTextByType, tokenIfType } =
require("../helpers/micromark.cjs"); require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD040", "fenced-code-language" ], "names": [ "MD040", "fenced-code-language" ],
"description": "Fenced code blocks should have a language specified", "description": "Fenced code blocks should have a language specified",
@ -14,7 +16,8 @@ module.exports = {
let allowed = params.config.allowed_languages; let allowed = params.config.allowed_languages;
allowed = Array.isArray(allowed) ? allowed : []; allowed = Array.isArray(allowed) ? allowed : [];
const languageOnly = !!params.config.language_only; const languageOnly = !!params.config.language_only;
const fencedCodes = filterByTypes(params.parsers.micromark.tokens, [ "codeFenced" ]); // eslint-disable-next-line dot-notation
const fencedCodes = filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced" ]);
for (const fencedCode of fencedCodes) { for (const fencedCode of fencedCodes) {
const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence"); const openingFence = tokenIfType(fencedCode.children[0], "codeFencedFence");
if (openingFence) { if (openingFence) {

View file

@ -4,6 +4,8 @@
const { addErrorContext, frontMatterHasTitle } = require("../helpers"); const { addErrorContext, frontMatterHasTitle } = require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD041", "first-line-heading", "first-line-h1" ], "names": [ "MD041", "first-line-heading", "first-line-h1" ],
"description": "First line in a file should be a top-level heading", "description": "First line in a file should be a top-level heading",

View file

@ -5,6 +5,8 @@
const { addErrorContext, escapeForRegExp, filterTokens } = const { addErrorContext, escapeForRegExp, filterTokens } =
require("../helpers"); require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD042", "no-empty-links" ], "names": [ "MD042", "no-empty-links" ],
"description": "No empty links", "description": "No empty links",
@ -33,6 +35,7 @@ module.exports = {
); );
if (match) { if (match) {
context = match[0]; context = match[0];
// @ts-ignore
range = [ match.index + 1, match[0].length ]; range = [ match.index + 1, match[0].length ];
} }
addErrorContext( addErrorContext(

View file

@ -5,6 +5,8 @@
const { addErrorContext, addErrorDetailIf, forEachHeading } = const { addErrorContext, addErrorDetailIf, forEachHeading } =
require("../helpers"); require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD043", "required-headings" ], "names": [ "MD043", "required-headings" ],
"description": "Required heading structure", "description": "Required heading structure",

View file

@ -11,6 +11,8 @@ const ignoredChildTypes = new Set(
[ "codeFencedFence", "definition", "reference", "resource" ] [ "codeFencedFence", "definition", "reference", "resource" ]
); );
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD044", "proper-names" ], "names": [ "MD044", "proper-names" ],
"description": "Proper names should have the correct capitalization", "description": "Proper names should have the correct capitalization",
@ -40,7 +42,8 @@ module.exports = {
} }
const contentTokens = const contentTokens =
filterByPredicate( filterByPredicate(
params.parsers.micromark.tokens, // eslint-disable-next-line dot-notation
params.parsers["micromark"].tokens,
(token) => scannedTypes.has(token.type), (token) => scannedTypes.has(token.type),
(token) => ( (token) => (
token.children.filter((t) => !ignoredChildTypes.has(t.type)) token.children.filter((t) => !ignoredChildTypes.has(t.type))

View file

@ -7,12 +7,15 @@ const { filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs");
const altRe = getHtmlAttributeRe("alt"); const altRe = getHtmlAttributeRe("alt");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD045", "no-alt-text" ], "names": [ "MD045", "no-alt-text" ],
"description": "Images should have alternate text (alt text)", "description": "Images should have alternate text (alt text)",
"tags": [ "accessibility", "images" ], "tags": [ "accessibility", "images" ],
"function": function MD045(params, onError) { "function": function MD045(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
// Process Markdown images // Process Markdown images
const images = filterByTypes(tokens, [ "image" ]); const images = filterByTypes(tokens, [ "image" ]);

View file

@ -10,6 +10,8 @@ const tokenTypeToStyle = {
"codeIndented": "indented" "codeIndented": "indented"
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD046", "code-block-style" ], "names": [ "MD046", "code-block-style" ],
"description": "Code block style", "description": "Code block style",
@ -17,7 +19,8 @@ module.exports = {
"function": function MD046(params, onError) { "function": function MD046(params, onError) {
let expectedStyle = String(params.config.style || "consistent"); let expectedStyle = String(params.config.style || "consistent");
const codeBlocksAndFences = const codeBlocksAndFences =
filterByTypes(params.parsers.micromark.tokens, [ "codeFenced", "codeIndented" ]); // eslint-disable-next-line dot-notation
filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced", "codeIndented" ]);
for (const token of codeBlocksAndFences) { for (const token of codeBlocksAndFences) {
const { startLine, type } = token; const { startLine, type } = token;
if (expectedStyle === "consistent") { if (expectedStyle === "consistent") {

View file

@ -4,6 +4,8 @@
const { addError, isBlankLine } = require("../helpers"); const { addError, isBlankLine } = require("../helpers");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD047", "single-trailing-newline" ], "names": [ "MD047", "single-trailing-newline" ],
"description": "Files should end with a single newline character", "description": "Files should end with a single newline character",
@ -15,8 +17,8 @@ module.exports = {
addError( addError(
onError, onError,
lastLineNumber, lastLineNumber,
null, undefined,
null, undefined,
[ lastLine.length, 1 ], [ lastLine.length, 1 ],
{ {
"insertText": "\n", "insertText": "\n",

View file

@ -5,6 +5,8 @@
const { addErrorDetailIf, fencedCodeBlockStyleFor } = require("../helpers"); const { addErrorDetailIf, fencedCodeBlockStyleFor } = require("../helpers");
const { filterByTypes, tokenIfType } = require("../helpers/micromark.cjs"); const { filterByTypes, tokenIfType } = require("../helpers/micromark.cjs");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD048", "code-fence-style" ], "names": [ "MD048", "code-fence-style" ],
"description": "Code fence style", "description": "Code fence style",
@ -12,7 +14,8 @@ module.exports = {
"function": function MD048(params, onError) { "function": function MD048(params, onError) {
const style = String(params.config.style || "consistent"); const style = String(params.config.style || "consistent");
let expectedStyle = style; let expectedStyle = style;
const codeFenceds = filterByTypes(params.parsers.micromark.tokens, [ "codeFenced" ]); // eslint-disable-next-line dot-notation
const codeFenceds = filterByTypes(params.parsers["micromark"].tokens, [ "codeFenced" ]);
for (const codeFenced of codeFenceds) { for (const codeFenced of codeFenceds) {
const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence"); const codeFencedFence = tokenIfType(codeFenced.children[0], "codeFencedFence");
if (codeFencedFence) { if (codeFencedFence) {

View file

@ -65,12 +65,15 @@ function unescapeStringTokenText(token) {
.join(""); .join("");
} }
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD051", "link-fragments" ], "names": [ "MD051", "link-fragments" ],
"description": "Link fragments should be valid", "description": "Link fragments should be valid",
"tags": [ "links" ], "tags": [ "links" ],
"function": function MD051(params, onError) { "function": function MD051(params, onError) {
const { tokens } = params.parsers.micromark; // eslint-disable-next-line dot-notation
const { tokens } = params.parsers["micromark"];
const fragments = new Map(); const fragments = new Map();
// Process headings // Process headings

View file

@ -5,6 +5,8 @@
const { addError } = require("../helpers"); const { addError } = require("../helpers");
const { referenceLinkImageData } = require("./cache"); const { referenceLinkImageData } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD052", "reference-links-images" ], "names": [ "MD052", "reference-links-images" ],
"description": "description":

View file

@ -6,6 +6,8 @@ const { addError, ellipsify, linkReferenceDefinitionRe } =
require("../helpers"); require("../helpers");
const { referenceLinkImageData } = require("./cache"); const { referenceLinkImageData } = require("./cache");
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD053", "link-image-reference-definitions" ], "names": [ "MD053", "link-image-reference-definitions" ],
"description": "Link and image reference definitions should be needed", "description": "Link and image reference definitions should be needed",

View file

@ -21,6 +21,8 @@ const autolinkAble = (destination) => {
return !autolinkDisallowedRe.test(destination); return !autolinkDisallowedRe.test(destination);
}; };
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD054", "link-image-style" ], "names": [ "MD054", "link-image-style" ],
"description": "Link and image style", "description": "Link and image style",
@ -39,7 +41,8 @@ module.exports = {
} }
const { definitions } = referenceLinkImageData(); const { definitions } = referenceLinkImageData();
const links = filterByTypes( const links = filterByTypes(
parsers.micromark.tokens, // eslint-disable-next-line dot-notation
parsers["micromark"].tokens,
[ "autolink", "image", "link" ] [ "autolink", "image", "link" ]
); );
for (const link of links) { for (const link of links) {

View file

@ -13,6 +13,8 @@ const firstOrNothing = (items) => items[0];
const lastOrNothing = (items) => items[items.length - 1]; const lastOrNothing = (items) => items[items.length - 1];
const makeRange = (start, end) => [ start, end - start + 1 ]; const makeRange = (start, end) => [ start, end - start + 1 ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD055", "table-pipe-style" ], "names": [ "MD055", "table-pipe-style" ],
"description": "Table pipe style", "description": "Table pipe style",
@ -24,7 +26,8 @@ module.exports = {
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only")); ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
let expectedTrailingPipe = let expectedTrailingPipe =
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only")); ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
const tables = filterByTypes(params.parsers.micromark.tokens, [ "table" ]); // eslint-disable-next-line dot-notation
const tables = filterByTypes(params.parsers["micromark"].tokens, [ "table" ]);
for (const table of tables) { for (const table of tables) {
const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]); const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]);
for (const row of rows) { for (const row of rows) {

View file

@ -7,12 +7,15 @@ const { filterByTypes } = require("../helpers/micromark.cjs");
const makeRange = (start, end) => [ start, end - start + 1 ]; const makeRange = (start, end) => [ start, end - start + 1 ];
// eslint-disable-next-line jsdoc/valid-types
/** @type import("./markdownlint").Rule */
module.exports = { module.exports = {
"names": [ "MD056", "table-column-count" ], "names": [ "MD056", "table-column-count" ],
"description": "Table column count", "description": "Table column count",
"tags": [ "table" ], "tags": [ "table" ],
"function": function MD056(params, onError) { "function": function MD056(params, onError) {
const tables = filterByTypes(params.parsers.micromark.tokens, [ "table" ]); // eslint-disable-next-line dot-notation
const tables = filterByTypes(params.parsers["micromark"].tokens, [ "table" ]);
for (const table of tables) { for (const table of tables) {
const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]); const rows = filterByTypes(table.children, [ "tableDelimiterRow", "tableRow" ]);
let expectedCount = 0; let expectedCount = 0;

View file

@ -26,7 +26,7 @@
"build-config": "npm run build-config-schema && npm run build-config-example", "build-config": "npm run build-config-schema && npm run build-config-example",
"build-config-example": "node schema/build-config-example.js", "build-config-example": "node schema/build-config-example.js",
"build-config-schema": "node schema/build-config-schema.js", "build-config-schema": "node schema/build-config-schema.js",
"build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --module commonjs --resolveJsonModule --target es2015 lib/markdownlint.js && node scripts delete 'lib/{cache,constants,md,r}*.d.ts' 'micromark/*.d.cts' 'helpers/*.d.{cts,ts}'", "build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --module commonjs --outDir dts --resolveJsonModule --target es2015 lib/markdownlint.js && node scripts copy dts/lib/markdownlint.d.ts lib/markdownlint.d.ts && node scripts remove dts",
"build-demo": "node scripts copy node_modules/markdown-it/dist/markdown-it.min.js demo/markdown-it.min.js && node scripts copy node_modules/markdownlint-micromark/micromark-browser.js demo/micromark-browser.js && node scripts copy node_modules/markdownlint-micromark/micromark-html-browser.js demo/micromark-html-browser.js && cd demo && webpack --no-stats", "build-demo": "node scripts copy node_modules/markdown-it/dist/markdown-it.min.js demo/markdown-it.min.js && node scripts copy node_modules/markdownlint-micromark/micromark-browser.js demo/micromark-browser.js && node scripts copy node_modules/markdownlint-micromark/micromark-html-browser.js demo/micromark-html-browser.js && cd demo && webpack --no-stats",
"build-docs": "node doc-build/build-rules.mjs", "build-docs": "node doc-build/build-rules.mjs",
"build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2", "build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2",

View file

@ -21,6 +21,8 @@ const [ command, ...args ] = process.argv.slice(2);
) )
) )
); );
} else if (command === "remove") {
await Promise.all(args.map((dir) => fs.rm(dir, { "recursive": true })));
} else { } else {
throw new Error(`Unsupported command: ${command}`); throw new Error(`Unsupported command: ${command}`);
} }