diff --git a/dist/index.js b/dist/index.js index 1b15307..a023ef0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -134,7 +134,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; const command_1 = __nccwpck_require__(7351); const file_command_1 = __nccwpck_require__(717); const utils_1 = __nccwpck_require__(5278); @@ -312,19 +312,30 @@ exports.debug = debug; /** * Adds an error issue * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. */ -function error(message) { - command_1.issue('error', message instanceof Error ? message.toString() : message); +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); } exports.error = error; /** - * Adds an warning issue + * Adds a warning issue * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. */ -function warning(message) { - command_1.issue('warning', message instanceof Error ? message.toString() : message); +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); } exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; /** * Writes info to log with console.log. * @param message info message @@ -458,7 +469,7 @@ exports.issueCommand = issueCommand; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toCommandValue = void 0; +exports.toCommandProperties = exports.toCommandValue = void 0; /** * Sanitizes an input into a string so it can be passed into issueCommand safely * @param input input to sanitize into a string @@ -473,6 +484,25 @@ function toCommandValue(input) { return JSON.stringify(input); } exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; //# sourceMappingURL=utils.js.map /***/ }), @@ -7005,7 +7035,7 @@ function normalizeLinkText(url) { * highlight: function (str, lang) { * if (lang && hljs.getLanguage(lang)) { * try { - * return hljs.highlight(lang, str, true).value; + * return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value; * } catch (__) {} * } * @@ -7025,7 +7055,7 @@ function normalizeLinkText(url) { * if (lang && hljs.getLanguage(lang)) { * try { * return '
' +
- * hljs.highlight(lang, str, true).value +
+ * hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
* '';
* } catch (__) {}
* }
@@ -7426,9 +7456,9 @@ var _rules = [
[ 'hr', __nccwpck_require__(3514), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'list', __nccwpck_require__(2050), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'reference', __nccwpck_require__(2235) ],
+ [ 'html_block', __nccwpck_require__(725), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'heading', __nccwpck_require__(2702), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'lheading', __nccwpck_require__(3551) ],
- [ 'html_block', __nccwpck_require__(725), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'paragraph', __nccwpck_require__(9450) ]
];
@@ -8295,6 +8325,8 @@ Renderer.prototype.renderInlineAsText = function (tokens, options, env) {
result += tokens[i].content;
} else if (tokens[i].type === 'image') {
result += this.renderInlineAsText(tokens[i].children, options, env);
+ } else if (tokens[i].type === 'softbreak') {
+ result += '\n';
}
}
@@ -9021,7 +9053,7 @@ module.exports = function code(state, startLine, endLine/*, silent*/) {
state.line = last;
token = state.push('code_block', 'code', 0);
- token.content = state.getLines(startLine, last, 4 + state.blkIndent, true);
+ token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n';
token.map = [ startLine, state.line ];
return true;
@@ -9268,7 +9300,7 @@ var HTML_OPEN_CLOSE_TAG_RE = __nccwpck_require__(6537)/* .HTML_OPEN_CLOSE_TAG_RE
// last argument defines whether it can terminate a paragraph or not
//
var HTML_SEQUENCES = [
- [ /^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true ],
+ [ /^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true ],
[ /^/, true ],
[ /^<\?/, /\?>/, true ],
[ /^/, true ],
@@ -9592,7 +9624,7 @@ module.exports = function list(state, startLine, endLine, silent) {
if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
isOrdered = true;
start = state.bMarks[startLine] + state.tShift[startLine];
- markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));
+ markerValue = Number(state.src.slice(start, posAfterMarker - 1));
// If we're starting a new ordered list right after
// a paragraph, it should start with 1.
@@ -9685,6 +9717,9 @@ module.exports = function list(state, startLine, endLine, silent) {
token = state.push('list_item_open', 'li', 1);
token.markup = String.fromCharCode(markerCharCode);
token.map = itemLines = [ startLine, 0 ];
+ if (isOrdered) {
+ token.info = state.src.slice(start, posAfterMarker - 1);
+ }
// change current state, then restore it after parser subcall
oldTight = state.tight;
@@ -9761,6 +9796,7 @@ module.exports = function list(state, startLine, endLine, silent) {
if (isOrdered) {
posAfterMarker = skipOrderedListMarker(state, nextLine);
if (posAfterMarker < 0) { break; }
+ start = state.bMarks[nextLine] + state.tShift[nextLine];
} else {
posAfterMarker = skipBulletListMarker(state, nextLine);
if (posAfterMarker < 0) { break; }
@@ -10356,7 +10392,7 @@ function escapedSplit(str) {
module.exports = function table(state, startLine, endLine, silent) {
var ch, lineText, pos, i, l, nextLine, columns, columnCount, token,
aligns, t, tableLines, tbodyLines, oldParentType, terminate,
- terminatorRules;
+ terminatorRules, firstCh, secondCh;
// should have at least two lines
if (startLine + 2 > endLine) { return false; }
@@ -10375,8 +10411,19 @@ module.exports = function table(state, startLine, endLine, silent) {
pos = state.bMarks[nextLine] + state.tShift[nextLine];
if (pos >= state.eMarks[nextLine]) { return false; }
- ch = state.src.charCodeAt(pos++);
- if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */) { return false; }
+ firstCh = state.src.charCodeAt(pos++);
+ if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false; }
+
+ if (pos >= state.eMarks[nextLine]) { return false; }
+
+ secondCh = state.src.charCodeAt(pos++);
+ if (secondCh !== 0x7C/* | */ && secondCh !== 0x2D/* - */ && secondCh !== 0x3A/* : */ && !isSpace(secondCh)) {
+ return false;
+ }
+
+ // if first character is '-', then second character must not be a space
+ // (due to parsing ambiguity with list)
+ if (firstCh === 0x2D/* - */ && isSpace(secondCh)) { return false; }
while (pos < state.eMarks[nextLine]) {
ch = state.src.charCodeAt(pos);
@@ -11265,12 +11312,14 @@ function processDelimiters(state, delimiters) {
if (!closer.close) continue;
// Previously calculated lower bounds (previous fails)
- // for each marker and each delimiter length modulo 3.
+ // for each marker, each delimiter length modulo 3,
+ // and for whether this closer can be an opener;
+ // https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460
if (!openersBottom.hasOwnProperty(closer.marker)) {
- openersBottom[closer.marker] = [ -1, -1, -1 ];
+ openersBottom[closer.marker] = [ -1, -1, -1, -1, -1, -1 ];
}
- minOpenerIdx = openersBottom[closer.marker][closer.length % 3];
+ minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)];
openerIdx = closerIdx - closer.jump - 1;
@@ -11331,7 +11380,7 @@ function processDelimiters(state, delimiters) {
// See details here:
// https://github.com/commonmark/cmark/issues/178#issuecomment-270417442
//
- openersBottom[closer.marker][(closer.length || 0) % 3] = newMinOpenerIdx;
+ openersBottom[closer.marker][(closer.open ? 3 : 0) + ((closer.length || 0) % 3)] = newMinOpenerIdx;
}
}
}
@@ -12573,7 +12622,11 @@ function Token(type, tag, nesting) {
/**
* Token#info -> String
*
- * fence infostring
+ * Additional information:
+ *
+ * - Info string for "fence" tokens
+ * - The value "auto" for autolink "link_open" and "link_close" tokens
+ * - The string value of the item marker for ordered-list "list_item_open" tokens
**/
this.info = '';
@@ -12768,7 +12821,6 @@ const dynamicRequire = (typeof require === "undefined") ? require : /* c8 ignore
// Capture native require implementation for dynamic loading of modules
// Requires
-const fs = __nccwpck_require__(5747).promises;
const path = __nccwpck_require__(5622);
const globby = __nccwpck_require__(3398);
const markdownlintLibrary = __nccwpck_require__(3611);
@@ -12781,7 +12833,7 @@ const resolveAndRequire = __nccwpck_require__(3924);
// Variables
const packageName = "markdownlint-cli2";
-const packageVersion = "0.1.3";
+const packageVersion = "0.3.1";
const libraryName = "markdownlint";
const libraryVersion = markdownlintLibrary.getVersion();
const dotOnlySubstitute = "*.{md,markdown}";
@@ -12803,12 +12855,12 @@ const negateGlob = (glob) => `!${glob}`;
const posixPath = (p) => p.split(path.sep).join(path.posix.sep);
// Read a JSON(C) or YAML file and return the object
-const readConfig = (dir, name, otherwise) => {
+const readConfig = (fs, dir, name, otherwise) => {
const file = path.posix.join(dir, name);
- return () => fs.access(file).
+ return () => fs.promises.access(file).
then(
// @ts-ignore
- () => markdownlintReadConfig(file, [ jsoncParse, yamlParse ]),
+ () => markdownlintReadConfig(file, [ jsoncParse, yamlParse ], fs),
otherwise
);
};
@@ -12839,19 +12891,23 @@ const requireIdsAndParams = (dir, idsAndParams, noRequire) => {
};
// Require a JS file and return the exported object
-const requireConfig = (dir, name, noRequire) => {
- const file = path.posix.join(dir, name);
- // eslint-disable-next-line prefer-promise-reject-errors
- return () => (noRequire ? Promise.reject() : fs.access(file)).
+const requireConfig = (fs, dir, name, noRequire) => (
+ () => (noRequire
+ // eslint-disable-next-line prefer-promise-reject-errors
+ ? Promise.reject()
+ : fs.promises.access(path.posix.join(dir, name))
+ ).
then(
() => requireResolve(dir, `./${name}`),
noop
- );
-};
+ )
+);
// Process command-line arguments and return glob patterns
const processArgv = (argv) => {
- const globPatterns = argv.map((glob) => glob.replace(/^#/u, "!"));
+ const globPatterns = (argv || []).map(
+ (glob) => glob.replace(/^#/u, "!").replace(/\\(?![$()*+?[\]^])/gu, "/")
+ );
if ((globPatterns.length === 1) && (globPatterns[0] === ".")) {
// Substitute a more reasonable pattern
globPatterns[0] = dotOnlySubstitute;
@@ -12888,11 +12944,11 @@ Configuration via:
- .markdownlint.js
Cross-platform compatibility:
-- UNIX and Windows shells expand globs according to different rules, so quoting glob arguments is recommended
-- Shells that expand globs do not support negated patterns (!node_modules), so quoting negated globs is required
-- Some Windows shells do not handle single-quoted (') arguments correctly, so double-quotes (") are recommended
-- Some UNIX shells handle exclamation (!) in double-quotes specially, so hashtag (#) is recommended for negated globs
-- Some shells use backslash (\\) to escape special characters, so forward slash (/) is the recommended path separator
+- UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
+- Some Windows shells don't handle single-quoted (') arguments well; double-quote (") is recommended
+- Shells that expand globs do not support negated patterns (!node_modules); quoting is required here
+- Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
+- The path separator is forward slash (/) on all platforms; backslash (\\) is automatically converted
Therefore, the most compatible glob syntax for cross-platform support:
$ ${name} "**/*.md" "#node_modules"`
@@ -12901,7 +12957,8 @@ $ ${name} "**/*.md" "#node_modules"`
};
// Get (creating if necessary) and process a directory's info object
-const getAndProcessDirInfo = (tasks, dirToDirInfo, dir, noRequire, func) => {
+const getAndProcessDirInfo =
+(fs, tasks, dirToDirInfo, dir, noRequire, func) => {
let dirInfo = dirToDirInfo[dir];
if (!dirInfo) {
dirInfo = {
@@ -12919,13 +12976,18 @@ const getAndProcessDirInfo = (tasks, dirToDirInfo, dir, noRequire, func) => {
const markdownlintCli2Yaml =
path.posix.join(dir, ".markdownlint-cli2.yaml");
tasks.push(
- fs.access(markdownlintCli2Jsonc).
+ fs.promises.access(markdownlintCli2Jsonc).
then(
- () => fs.readFile(markdownlintCli2Jsonc, utf8).then(jsoncParse),
- () => fs.access(markdownlintCli2Yaml).
+ () => fs.promises.
+ readFile(markdownlintCli2Jsonc, utf8).
+ then(jsoncParse),
+ () => fs.promises.access(markdownlintCli2Yaml).
then(
- () => fs.readFile(markdownlintCli2Yaml, utf8).then(yamlParse),
+ () => fs.promises.
+ readFile(markdownlintCli2Yaml, utf8).
+ then(yamlParse),
requireConfig(
+ fs,
dir,
".markdownlint-cli2.js",
noRequire
@@ -12940,18 +13002,23 @@ const getAndProcessDirInfo = (tasks, dirToDirInfo, dir, noRequire, func) => {
// Load markdownlint object(s)
const readConfigs =
readConfig(
+ fs,
dir,
".markdownlint.jsonc",
readConfig(
+ fs,
dir,
".markdownlint.json",
readConfig(
+ fs,
dir,
".markdownlint.yaml",
readConfig(
+ fs,
dir,
".markdownlint.yml",
requireConfig(
+ fs,
dir,
".markdownlint.js",
noRequire
@@ -12974,11 +13041,18 @@ const getAndProcessDirInfo = (tasks, dirToDirInfo, dir, noRequire, func) => {
};
// Get base markdownlint-cli2 options object
-const getBaseOptions =
-async (baseDir, globPatterns, optionsDefault, fixDefault, noRequire) => {
+const getBaseOptions = async (
+ fs,
+ baseDir,
+ globPatterns,
+ optionsDefault,
+ fixDefault,
+ noGlobs,
+ noRequire
+) => {
const tasks = [];
const dirToDirInfo = {};
- getAndProcessDirInfo(tasks, dirToDirInfo, baseDir, noRequire);
+ getAndProcessDirInfo(fs, tasks, dirToDirInfo, baseDir, noRequire);
await Promise.all(tasks);
// eslint-disable-next-line no-multi-assign
const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions =
@@ -12987,12 +13061,15 @@ async (baseDir, globPatterns, optionsDefault, fixDefault, noRequire) => {
dirToDirInfo[baseDir].markdownlintOptions
);
- // Append any globs specified in markdownlint-cli2 configuration
- const globs = baseMarkdownlintOptions.globs || [];
- appendToArray(globPatterns, globs);
+ if (!noGlobs) {
+ // Append any globs specified in markdownlint-cli2 configuration
+ const globs = baseMarkdownlintOptions.globs || [];
+ appendToArray(globPatterns, globs);
+ }
// Pass base ignore globs as globby patterns (best performance)
const ignorePatterns =
+ // eslint-disable-next-line unicorn/no-array-callback-reference
(baseMarkdownlintOptions.ignores || []).map(negateGlob);
appendToArray(globPatterns, ignorePatterns);
delete baseMarkdownlintOptions.ignores;
@@ -13005,24 +13082,48 @@ async (baseDir, globPatterns, optionsDefault, fixDefault, noRequire) => {
// Enumerate files from globs and build directory infos
const enumerateFiles =
-async (baseDir, globPatterns, dirToDirInfo, noRequire) => {
+async (fs, baseDir, globPatterns, dirToDirInfo, noRequire) => {
const tasks = [];
const globbyOptions = {
"absolute": true,
- "cwd": baseDir
+ "cwd": baseDir,
+ "expandDirectories": false,
+ fs
};
- for await (const file of globby.stream(globPatterns, globbyOptions)) {
- // @ts-ignore
+ // Manually expand directories to avoid globby call to dir-glob.sync
+ const expandedDirectories = await Promise.all(
+ globPatterns.map((globPattern) => {
+ const globPath = path.resolve(
+ baseDir,
+ globPattern[0] === "!" ? globPattern.slice(1) : globPattern
+ );
+ return fs.promises.stat(globPath).
+ then((stats) => (stats.isDirectory()
+ ? path.posix.join(globPattern, "**")
+ : globPattern)).
+ catch(() => globPattern);
+ })
+ );
+ // Process glob patterns
+ const files = await globby(expandedDirectories, globbyOptions);
+ for (const file of files) {
const dir = path.posix.dirname(file);
- getAndProcessDirInfo(tasks, dirToDirInfo, dir, noRequire, (dirInfo) => {
- dirInfo.files.push(file);
- });
+ getAndProcessDirInfo(
+ fs,
+ tasks,
+ dirToDirInfo,
+ dir,
+ noRequire,
+ (dirInfo) => {
+ dirInfo.files.push(file);
+ }
+ );
}
await Promise.all(tasks);
};
// Enumerate (possibly missing) parent directories and update directory infos
-const enumerateParents = async (baseDir, dirToDirInfo, noRequire) => {
+const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
const tasks = [];
// Create a lookup of baseDir and parents
@@ -13044,10 +13145,17 @@ const enumerateParents = async (baseDir, dirToDirInfo, noRequire) => {
) {
lastDir = dir;
lastDirInfo =
- // eslint-disable-next-line no-loop-func
- getAndProcessDirInfo(tasks, dirToDirInfo, dir, noRequire, (dirInfo) => {
- lastDirInfo.parent = dirInfo;
- });
+ getAndProcessDirInfo(
+ fs,
+ tasks,
+ dirToDirInfo,
+ dir,
+ noRequire,
+ // eslint-disable-next-line no-loop-func
+ (dirInfo) => {
+ lastDirInfo.parent = dirInfo;
+ }
+ );
}
// If dir not under baseDir, inject it as parent for configuration
@@ -13060,9 +13168,9 @@ const enumerateParents = async (baseDir, dirToDirInfo, noRequire) => {
// Create directory info objects by enumerating file globs
const createDirInfos =
-async (baseDir, globPatterns, dirToDirInfo, optionsOverride, noRequire) => {
- await enumerateFiles(baseDir, globPatterns, dirToDirInfo, noRequire);
- await enumerateParents(baseDir, dirToDirInfo, noRequire);
+async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noRequire) => {
+ await enumerateFiles(fs, baseDir, globPatterns, dirToDirInfo, noRequire);
+ await enumerateParents(fs, baseDir, dirToDirInfo, noRequire);
// Merge file lists with identical configuration
const dirs = Object.keys(dirToDirInfo);
@@ -13091,7 +13199,7 @@ async (baseDir, globPatterns, dirToDirInfo, optionsOverride, noRequire) => {
noRequire
);
// Expand nested arrays (for packages that export multiple rules)
- markdownlintOptions.customRules = [].concat(...customRules);
+ markdownlintOptions.customRules = customRules.flat();
}
if (markdownlintOptions && markdownlintOptions.markdownItPlugins) {
markdownlintOptions.markdownItPlugins =
@@ -13169,33 +13277,35 @@ async (baseDir, globPatterns, dirToDirInfo, optionsOverride, noRequire) => {
};
// Lint files in groups by shared configuration
-const lintFiles = (dirInfos, fileContents) => {
+const lintFiles = (fs, dirInfos, fileContents) => {
const tasks = [];
// For each dirInfo
for (const dirInfo of dirInfos) {
const { dir, files, markdownlintConfig, markdownlintOptions } = dirInfo;
// Filter file/string inputs to only those in the dirInfo
- const filteredFileContents = {};
- for (const file in fileContents) {
- if (files.includes(file)) {
- filteredFileContents[file] = fileContents[file];
- }
- }
- let filteredFiles = files.filter(
- (file) => fileContents[file] === undefined
- );
+ let filesAfterIgnores = files;
if (markdownlintOptions.ignores) {
+ // eslint-disable-next-line unicorn/no-array-callback-reference
const ignores = markdownlintOptions.ignores.map(negateGlob);
const micromatch = __nccwpck_require__(6228);
- filteredFiles = micromatch(
+ filesAfterIgnores = micromatch(
files.map((file) => path.posix.relative(dir, file)),
ignores
).map((file) => path.posix.join(dir, file));
}
+ const filteredFiles = filesAfterIgnores.filter(
+ (file) => fileContents[file] === undefined
+ );
+ const filteredStrings = {};
+ for (const file of filesAfterIgnores) {
+ if (fileContents[file] !== undefined) {
+ filteredStrings[file] = fileContents[file];
+ }
+ }
// Create markdownlint options object
const options = {
"files": filteredFiles,
- "strings": filteredFileContents,
+ "strings": filteredStrings,
"config": markdownlintConfig || markdownlintOptions.config,
"customRules": markdownlintOptions.customRules,
"frontMatter": markdownlintOptions.frontMatter
@@ -13204,7 +13314,8 @@ const lintFiles = (dirInfos, fileContents) => {
"handleRuleFailures": true,
"markdownItPlugins": markdownlintOptions.markdownItPlugins,
"noInlineConfig": Boolean(markdownlintOptions.noInlineConfig),
- "resultVersion": 3
+ "resultVersion": 3,
+ fs
};
// Invoke markdownlint
// @ts-ignore
@@ -13221,11 +13332,11 @@ const lintFiles = (dirInfos, fileContents) => {
if (errorInfos.length > 0) {
delete results[fileName];
options.files.push(fileName);
- subTasks.push(fs.readFile(fileName, utf8).
+ subTasks.push(fs.promises.readFile(fileName, utf8).
then((original) => {
const fixed = markdownlintRuleHelpers.
applyFixes(original, errorInfos);
- return fs.writeFile(fileName, fixed, utf8);
+ return fs.promises.writeFile(fileName, fixed, utf8);
})
);
}
@@ -13309,10 +13420,12 @@ const main = async (params) => {
fixDefault,
fileContents,
nonFileContents,
+ noGlobs,
noRequire
} = params;
const logMessage = params.logMessage || noop;
const logError = params.logError || noop;
+ const fs = params.fs || __nccwpck_require__(5747);
const baseDirSystem =
(directory && path.resolve(directory)) ||
process.cwd();
@@ -13325,10 +13438,12 @@ const main = async (params) => {
const globPatterns = processArgv(argv);
const { baseMarkdownlintOptions, dirToDirInfo } =
await getBaseOptions(
+ fs,
baseDir,
globPatterns,
optionsDefault,
fixDefault,
+ noGlobs,
noRequire
);
if ((globPatterns.length === 0) && !nonFileContents) {
@@ -13357,6 +13472,7 @@ const main = async (params) => {
// Create linting tasks
const dirInfos =
await createDirInfos(
+ fs,
baseDir,
globPatterns,
dirToDirInfo,
@@ -13372,7 +13488,7 @@ const main = async (params) => {
logMessage(`Linting: ${fileCount} file(s)`);
}
// Lint files
- const lintResults = await lintFiles(dirInfos, resolvedFileContents);
+ const lintResults = await lintFiles(fs, dirInfos, resolvedFileContents);
// Output summary
const summary = createSummary(baseDir, lintResults);
if (showProgress) {
@@ -13520,10 +13636,11 @@ module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
const emphasisMarkersRe = /[_*]/g;
// Regular expression for inline links and shortcut reference links
-const linkRe = /\[(?:[^[\]]|\[[^\]]*\])*\](?:\(\S*\))?/g;
+const linkRe = /(\[(?:[^[\]]|\[[^\]]*\])*\])(\(\S*\)|\[\S*\])?/g;
+module.exports.linkRe = linkRe;
-// readFile options for reading with the UTF-8 encoding
-module.exports.utf8Encoding = "utf8";
+// Regular expression for link reference definition lines
+module.exports.linkReferenceRe = /^ {0,3}\[[^\]]+]:\s.*$/;
// All punctuation characters (normal and full-width)
const allPunctuation = ".,;:!?。,;:!?";
@@ -13793,14 +13910,14 @@ module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
};
// Returns (nested) lists as a flat array (in order)
-module.exports.flattenLists = function flattenLists(params) {
+module.exports.flattenLists = function flattenLists(tokens) {
const flattenedLists = [];
const stack = [];
let current = null;
let nesting = 0;
const nestingStack = [];
let lastWithMap = { "map": [ 0, 1 ] };
- params.tokens.forEach((token) => {
+ tokens.forEach((token) => {
if (isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
@@ -14010,6 +14127,47 @@ module.exports.addErrorContext = function addErrorContext(
addError(onError, lineNumber, null, context, range, fixInfo);
};
+/**
+ * Returns an array of code span ranges.
+ *
+ * @param {string[]} lines Lines to scan for code span ranges.
+ * @returns {number[][]} Array of ranges (line, index, length).
+ */
+module.exports.inlineCodeSpanRanges = (lines) => {
+ const exclusions = [];
+ forEachInlineCodeSpan(
+ lines.join("\n"),
+ (code, lineIndex, columnIndex) => {
+ const codeLines = code.split(newLineRe);
+ // eslint-disable-next-line unicorn/no-for-loop
+ for (let i = 0; i < codeLines.length; i++) {
+ exclusions.push(
+ [ lineIndex + i, columnIndex, codeLines[i].length ]
+ );
+ columnIndex = 0;
+ }
+ }
+ );
+ return exclusions;
+};
+
+/**
+ * Determines whether the specified range overlaps another range.
+ *
+ * @param {number[][]} ranges Array of ranges (line, index, length).
+ * @param {number} lineIndex Line index to check.
+ * @param {number} index Index to check.
+ * @param {number} length Length to check.
+ * @returns {boolean} True iff the specified range overlaps.
+ */
+module.exports.overlapsAnyRange = (ranges, lineIndex, index, length) => (
+ !ranges.every((span) => (
+ (lineIndex !== span[0]) ||
+ (index + length < span[1]) ||
+ (index > span[1] + span[2])
+ ))
+);
+
// Returns a range object for a line by applying a RegExp
module.exports.rangeFromRegExp = function rangeFromRegExp(line, regexp) {
let range = null;
@@ -14265,10 +14423,11 @@ module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
const emphasisMarkersRe = /[_*]/g;
// Regular expression for inline links and shortcut reference links
-const linkRe = /\[(?:[^[\]]|\[[^\]]*\])*\](?:\(\S*\))?/g;
+const linkRe = /(\[(?:[^[\]]|\[[^\]]*\])*\])(\(\S*\)|\[\S*\])?/g;
+module.exports.linkRe = linkRe;
-// readFile options for reading with the UTF-8 encoding
-module.exports.utf8Encoding = "utf8";
+// Regular expression for link reference definition lines
+module.exports.linkReferenceRe = /^ {0,3}\[[^\]]+]:\s.*$/;
// All punctuation characters (normal and full-width)
const allPunctuation = ".,;:!?。,;:!?";
@@ -14538,14 +14697,14 @@ module.exports.forEachLine = function forEachLine(lineMetadata, handler) {
};
// Returns (nested) lists as a flat array (in order)
-module.exports.flattenLists = function flattenLists(params) {
+module.exports.flattenLists = function flattenLists(tokens) {
const flattenedLists = [];
const stack = [];
let current = null;
let nesting = 0;
const nestingStack = [];
let lastWithMap = { "map": [ 0, 1 ] };
- params.tokens.forEach((token) => {
+ tokens.forEach((token) => {
if (isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
@@ -14755,6 +14914,47 @@ module.exports.addErrorContext = function addErrorContext(
addError(onError, lineNumber, null, context, range, fixInfo);
};
+/**
+ * Returns an array of code span ranges.
+ *
+ * @param {string[]} lines Lines to scan for code span ranges.
+ * @returns {number[][]} Array of ranges (line, index, length).
+ */
+module.exports.inlineCodeSpanRanges = (lines) => {
+ const exclusions = [];
+ forEachInlineCodeSpan(
+ lines.join("\n"),
+ (code, lineIndex, columnIndex) => {
+ const codeLines = code.split(newLineRe);
+ // eslint-disable-next-line unicorn/no-for-loop
+ for (let i = 0; i < codeLines.length; i++) {
+ exclusions.push(
+ [ lineIndex + i, columnIndex, codeLines[i].length ]
+ );
+ columnIndex = 0;
+ }
+ }
+ );
+ return exclusions;
+};
+
+/**
+ * Determines whether the specified range overlaps another range.
+ *
+ * @param {number[][]} ranges Array of ranges (line, index, length).
+ * @param {number} lineIndex Line index to check.
+ * @param {number} index Index to check.
+ * @param {number} length Length to check.
+ * @returns {boolean} True iff the specified range overlaps.
+ */
+module.exports.overlapsAnyRange = (ranges, lineIndex, index, length) => (
+ !ranges.every((span) => (
+ (lineIndex !== span[0]) ||
+ (index + length < span[1]) ||
+ (index > span[1] + span[2])
+ ))
+);
+
// Returns a range object for a line by applying a RegExp
module.exports.rangeFromRegExp = function rangeFromRegExp(line, regexp) {
let range = null;
@@ -14983,14 +15183,6 @@ module.exports.applyFixes = function applyFixes(input, errors) {
-let lineMetadata = null;
-module.exports.lineMetadata = (value) => {
- if (value) {
- lineMetadata = value;
- }
- return lineMetadata;
-};
-
let flattenedLists = null;
module.exports.flattenedLists = (value) => {
if (value) {
@@ -14999,9 +15191,26 @@ module.exports.flattenedLists = (value) => {
return flattenedLists;
};
+let inlineCodeSpanRanges = null;
+module.exports.inlineCodeSpanRanges = (value) => {
+ if (value) {
+ inlineCodeSpanRanges = value;
+ }
+ return inlineCodeSpanRanges;
+};
+
+let lineMetadata = null;
+module.exports.lineMetadata = (value) => {
+ if (value) {
+ lineMetadata = value;
+ }
+ return lineMetadata;
+};
+
module.exports.clear = () => {
- lineMetadata = null;
flattenedLists = null;
+ inlineCodeSpanRanges = null;
+ lineMetadata = null;
};
@@ -15015,7 +15224,6 @@ module.exports.clear = () => {
-const fs = __nccwpck_require__(5747);
const path = __nccwpck_require__(5622);
const { promisify } = __nccwpck_require__(1669);
const markdownIt = __nccwpck_require__(8561);
@@ -15203,7 +15411,7 @@ function annotateTokens(tokens, lines) {
(token.type === "thead_open") ||
(token.type === "tbody_open")
) {
- tableMap = token.map.slice();
+ tableMap = [ ...token.map ];
} else if (
(token.type === "tr_close") &&
tableMap
@@ -15216,7 +15424,7 @@ function annotateTokens(tokens, lines) {
tableMap = null;
}
if (tableMap && !token.map) {
- token.map = tableMap.slice();
+ token.map = [ ...tableMap ];
}
// Update token metadata
if (token.map) {
@@ -15529,7 +15737,8 @@ function lintContent(
frontMatterLines
};
cache.lineMetadata(helpers.getLineMetadata(params));
- cache.flattenedLists(helpers.flattenLists(params));
+ cache.flattenedLists(helpers.flattenLists(params.tokens));
+ cache.inlineCodeSpanRanges(helpers.inlineCodeSpanRanges(params.lines));
// Function to run for each rule
const result = (resultVersion === 0) ? {} : [];
// eslint-disable-next-line jsdoc/require-jsdoc
@@ -15697,6 +15906,7 @@ function lintContent(
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
* @param {boolean} noInlineConfig Whether to allow inline configuration.
* @param {number} resultVersion Version of the LintResults object to return.
+ * @param {Object} fs File system implementation.
* @param {boolean} synchronous Whether to execute synchronously.
* @param {Function} callback Callback (err, result) function.
* @returns {void}
@@ -15710,6 +15920,7 @@ function lintFile(
handleRuleFailures,
noInlineConfig,
resultVersion,
+ fs,
synchronous,
callback) {
// eslint-disable-next-line jsdoc/require-jsdoc
@@ -15722,10 +15933,9 @@ function lintFile(
}
// Make a/synchronous call to read file
if (synchronous) {
- // @ts-ignore
- lintContentWrapper(null, fs.readFileSync(file, helpers.utf8Encoding));
+ lintContentWrapper(null, fs.readFileSync(file, "utf8"));
} else {
- fs.readFile(file, helpers.utf8Encoding, lintContentWrapper);
+ fs.readFile(file, "utf8", lintContentWrapper);
}
}
@@ -15749,7 +15959,7 @@ function lintInput(options, synchronous, callback) {
}
let files = [];
if (Array.isArray(options.files)) {
- files = options.files.slice();
+ files = [ ...options.files ];
} else if (options.files) {
files = [ String(options.files) ];
}
@@ -15768,6 +15978,7 @@ function lintInput(options, synchronous, callback) {
// @ts-ignore
md.use(...plugin);
});
+ const fs = options.fs || __nccwpck_require__(5747);
const results = newResults(ruleList);
let done = false;
// Linting of strings is always synchronous
@@ -15807,6 +16018,7 @@ function lintInput(options, synchronous, callback) {
handleRuleFailures,
noInlineConfig,
resultVersion,
+ fs,
synchronous,
syncCallback
);
@@ -15831,6 +16043,7 @@ function lintInput(options, synchronous, callback) {
handleRuleFailures,
noInlineConfig,
resultVersion,
+ fs,
synchronous,
(err, result) => {
concurrency--;
@@ -15941,17 +16154,47 @@ function parseConfiguration(name, content, parsers) {
*
* @param {string} configFile Configuration file name.
* @param {string} referenceId Referenced identifier to resolve.
+ * @param {Object} fs File system implementation.
+ * @param {ResolveConfigExtendsCallback} [callback] Callback (err, result)
+ * function.
+ * @returns {void}
+ */
+function resolveConfigExtends(configFile, referenceId, fs, callback) {
+ const configFileDirname = path.dirname(configFile);
+ const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
+ fs.access(resolvedExtendsFile, (err) => {
+ if (err) {
+ // Not a file, try require.resolve
+ try {
+ return callback(null, dynamicRequire.resolve(
+ referenceId,
+ { "paths": [ configFileDirname ] }
+ ));
+ } catch {
+ // Unable to resolve, use resolvedExtendsFile
+ }
+ }
+ return callback(null, resolvedExtendsFile);
+ });
+}
+
+/**
+ * Resolve referenced "extends" path in a configuration file
+ * using path.resolve() with require.resolve() as a fallback.
+ *
+ * @param {string} configFile Configuration file name.
+ * @param {string} referenceId Referenced identifier to resolve.
+ * @param {Object} fs File system implementation.
* @returns {string} Resolved path to file.
*/
-function resolveConfigExtends(configFile, referenceId) {
+function resolveConfigExtendsSync(configFile, referenceId, fs) {
const configFileDirname = path.dirname(configFile);
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
try {
- if (fs.statSync(resolvedExtendsFile).isFile()) {
- return resolvedExtendsFile;
- }
+ fs.accessSync(resolvedExtendsFile);
+ return resolvedExtendsFile;
} catch {
- // If not a file or fs.statSync throws, try require.resolve
+ // Not a file, try require.resolve
}
try {
return dynamicRequire.resolve(
@@ -15959,7 +16202,7 @@ function resolveConfigExtends(configFile, referenceId) {
{ "paths": [ configFileDirname ] }
);
} catch {
- // If require.resolve throws, return resolvedExtendsFile
+ // Unable to resolve, return resolvedExtendsFile
}
return resolvedExtendsFile;
}
@@ -15970,17 +16213,26 @@ function resolveConfigExtends(configFile, referenceId) {
* @param {string} file Configuration file name.
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
* function(s).
+ * @param {Object} [fs] File system implementation.
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
* @returns {void}
*/
-function readConfig(file, parsers, callback) {
+function readConfig(file, parsers, fs, callback) {
if (!callback) {
- // @ts-ignore
- callback = parsers;
- parsers = null;
+ if (fs) {
+ callback = fs;
+ fs = null;
+ } else {
+ // @ts-ignore
+ callback = parsers;
+ parsers = null;
+ }
+ }
+ if (!fs) {
+ fs = __nccwpck_require__(5747);
}
// Read file
- fs.readFile(file, helpers.utf8Encoding, (err, content) => {
+ fs.readFile(file, "utf8", (err, content) => {
if (err) {
return callback(err);
}
@@ -15994,16 +16246,25 @@ function readConfig(file, parsers, callback) {
const configExtends = config.extends;
if (configExtends) {
delete config.extends;
- const resolvedExtends = resolveConfigExtends(file, configExtends);
- return readConfig(resolvedExtends, parsers, (errr, extendsConfig) => {
- if (errr) {
- return callback(errr);
- }
- return callback(null, {
- ...extendsConfig,
- ...config
- });
- });
+ return resolveConfigExtends(
+ file,
+ configExtends,
+ fs,
+ (_, resolvedExtends) => readConfig(
+ resolvedExtends,
+ parsers,
+ fs,
+ (errr, extendsConfig) => {
+ if (errr) {
+ return callback(errr);
+ }
+ return callback(null, {
+ ...extendsConfig,
+ ...config
+ });
+ }
+ )
+ );
}
return callback(null, config);
});
@@ -16016,11 +16277,12 @@ const readConfigPromisify = promisify && promisify(readConfig);
*
* @param {string} file Configuration file name.
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
+ * @param {Object} [fs] File system implementation.
* @returns {Promise