Stop running the markdown-it parser unless a custom rule that requires it is present (~7% runtime reduction).

This commit is contained in:
David Anson 2024-08-21 21:19:40 -07:00
parent 697780b3b6
commit ea8d596a9b
5 changed files with 102 additions and 36 deletions

View file

@ -8,7 +8,7 @@ export = markdownlint;
*/
declare function markdownlint(options: Options | null, callback: LintCallback): void;
declare namespace markdownlint {
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownParsers, ParserMarkdownIt, ParserMicromark, MarkdownItToken, MicromarkTokenType, MicromarkToken, 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, GetMarkdownIt, RuleFunction, RuleParams, MarkdownParsers, ParserMarkdownIt, ParserMicromark, MarkdownItToken, MicromarkTokenType, MicromarkToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintContentCallback, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
}
/**
* Lint specified Markdown files synchronously.
@ -49,6 +49,10 @@ declare namespace promises {
export { extendConfigPromise as extendConfig };
export { readConfigPromise as readConfig };
}
/**
* Function to get an instance of the markdown-it parser.
*/
type GetMarkdownIt = () => any;
/**
* Function to implement rule logic.
*/

View file

@ -4,7 +4,6 @@
const path = require("node:path");
const { promisify } = require("node:util");
const markdownit = require("markdown-it");
const micromark = require("../helpers/micromark.cjs");
// const { deprecatedRuleNames } = require("./constants");
const rules = require("./rules");
@ -226,13 +225,17 @@ function freezeToken(token) {
/**
* Annotate tokens with line/lineNumber and freeze them.
*
* @param {MarkdownItToken[]} tokens Array of markdown-it tokens.
* @param {import("markdown-it").Token[]} tokens Array of markdown-it tokens.
* @param {string[]} lines Lines of Markdown content.
* @returns {void}
*/
function annotateAndFreezeTokens(tokens, lines) {
let trMap = null;
for (const token of tokens) {
// eslint-disable-next-line jsdoc/valid-types
/** @type MarkdownItToken[] */
// @ts-ignore
const markdownItTokens = tokens;
for (const token of markdownItTokens) {
// Provide missing maps for table content
if (token.type === "tr_open") {
trMap = token.map;
@ -522,7 +525,7 @@ function getEnabledRulesPerLineNumber(
* names.
* @param {string} name Identifier for the content.
* @param {string} content Markdown content.
* @param {Object} md Instance of markdown-it.
* @param {GetMarkdownIt} getMarkdownIt Getter for instance of markdown-it.
* @param {Configuration} config Configuration object.
* @param {ConfigurationParser[] | null} configParsers Configuration parsers.
* @param {RegExp | null} frontMatter Regular expression for front matter.
@ -537,7 +540,7 @@ function lintContent(
aliasToRuleNames,
name,
content,
md,
getMarkdownIt,
config,
configParsers,
frontMatter,
@ -562,8 +565,11 @@ function lintContent(
configParsers,
aliasToRuleNames
);
const needMarkdownItTokens = ruleList.some(
(rule) => (rule.parser === "markdownit") || (rule.parser === undefined)
);
// Parse content into parser tokens
const markdownitTokens = md.parse(content, {});
const markdownitTokens = needMarkdownItTokens ? getMarkdownIt().parse(content, {}) : [];
const micromarkTokens = micromark.parse(content);
// Hide the content of HTML comments from rules
content = helpers.clearHtmlCommentText(content);
@ -823,7 +829,7 @@ function lintContent(
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
* names.
* @param {string} file Path of file to lint.
* @param {Object} md Instance of markdown-it.
* @param {GetMarkdownIt} getMarkdownIt Getter for instance of markdown-it.
* @param {Configuration} config Configuration object.
* @param {ConfigurationParser[] | null} configParsers Configuration parsers.
* @param {RegExp | null} frontMatter Regular expression for front matter.
@ -839,7 +845,7 @@ function lintFile(
ruleList,
aliasToRuleNames,
file,
md,
getMarkdownIt,
config,
configParsers,
frontMatter,
@ -859,7 +865,7 @@ function lintFile(
aliasToRuleNames,
file,
content,
md,
getMarkdownIt,
config,
configParsers,
frontMatter,
@ -924,12 +930,16 @@ function lintInput(options, synchronous, callback) {
const noInlineConfig = !!options.noInlineConfig;
const resultVersion = (options.resultVersion === undefined) ?
3 : options.resultVersion;
const md = markdownit({ "html": true });
const markdownItPlugins = options.markdownItPlugins || [];
for (const plugin of markdownItPlugins) {
// @ts-ignore
md.use(...plugin);
}
const getMarkdownIt = () => {
const markdownit = require("markdown-it");
const md = markdownit({ "html": true });
const markdownItPlugins = options.markdownItPlugins || [];
for (const plugin of markdownItPlugins) {
// @ts-ignore
md.use(...plugin);
}
return md;
};
const fs = options.fs || require("node:fs");
const aliasToRuleNames = mapAliasToRuleNames(ruleList);
const results = newResults(ruleList);
@ -961,7 +971,7 @@ function lintInput(options, synchronous, callback) {
ruleList,
aliasToRuleNames,
currentItem,
md,
getMarkdownIt,
config,
configParsers,
frontMatter,
@ -980,7 +990,7 @@ function lintInput(options, synchronous, callback) {
aliasToRuleNames,
currentItem,
strings[currentItem] || "",
md,
getMarkdownIt,
config,
configParsers,
frontMatter,
@ -1295,6 +1305,13 @@ module.exports = markdownlint;
// Type declarations
/**
* Function to get an instance of the markdown-it parser.
*
* @callback GetMarkdownIt
* @returns {import("markdown-it")}
*/
/**
* Function to implement rule logic.
*