diff --git a/dist/index.js b/dist/index.js index 71e1c04..31be306 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1726,6 +1726,10 @@ function checkBypass(reqUrl) { if (!reqUrl.hostname) { return false; } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; if (!noProxy) { return false; @@ -1751,13 +1755,24 @@ function checkBypass(reqUrl) { .split(',') .map(x => x.trim().toUpperCase()) .filter(x => x)) { - if (upperReqHosts.some(x => x === upperNoProxyItem)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { return true; } } return false; } exports.checkBypass = checkBypass; +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} //# sourceMappingURL=proxy.js.map /***/ }), @@ -14099,6 +14114,8 @@ module.exports = outputFormatter; +const micromark = __nccwpck_require__(5673); + // Regular expression for matching common newline characters // See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js const newLineRe = /\r\n?|\n/g; @@ -14130,10 +14147,6 @@ const emphasisMarkersRe = /[_*]/g; const blockquotePrefixRe = /^[>\s]*/; module.exports.blockquotePrefixRe = blockquotePrefixRe; -// Regular expression for reference links (full, collapsed, and shortcut) -const referenceLinkRe = - /!?\\?\[((?:\[[^\]\0]*\]|[^[\]\0])*)\](?:\[([^\]\0]*)\]|([^(])|$)/g; - // Regular expression for link reference definitions const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/; module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe; @@ -14290,19 +14303,6 @@ module.exports.escapeForRegExp = function escapeForRegExp(str) { return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); }; -// Un-escapes Markdown content (simple algorithm; not a parser) -const escapedMarkdownRe = /\\./g; -module.exports.unescapeMarkdown = - function unescapeMarkdown(markdown, replacement) { - return markdown.replace(escapedMarkdownRe, (match) => { - const char = match[1]; - if ("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".includes(char)) { - return replacement || char; - } - return match; - }); - }; - /** * Return the string representation of a fence markup character. * @@ -14385,7 +14385,7 @@ module.exports.unorderedListStyleFor = function unorderedListStyleFor(token) { * @returns {void} */ function filterTokens(params, type, handler) { - for (const token of params.tokens) { + for (const token of params.parsers.markdownit.tokens) { if (token.type === type) { handler(token); } @@ -14440,7 +14440,7 @@ module.exports.getLineMetadata = function getLineMetadata(params) { filterTokens(params, "hr", (token) => { lineMetadata[token.map[0]][6] = true; }); - for (const token of params.tokens.filter(isMathBlock)) { + for (const token of params.parsers.markdownit.tokens.filter(isMathBlock)) { for (let i = token.map[0]; i < token.map[1]; i++) { lineMetadata[i][7] = true; } @@ -14534,7 +14534,7 @@ module.exports.forEachInlineChild = forEachInlineChild; // Calls the provided function for each heading's content module.exports.forEachHeading = function forEachHeading(params, handler) { let heading = null; - for (const token of params.tokens) { + for (const token of params.parsers.markdownit.tokens) { if (token.type === "heading_open") { heading = token; } else if (token.type === "heading_close") { @@ -14915,137 +14915,117 @@ module.exports.emphasisMarkersInContent = emphasisMarkersInContent; /** * Returns an object with information about reference links and images. * - * @param {Object} lineMetadata Line metadata object. + * @param {Object} params RuleParams instance. * @returns {Object} Reference link/image data. */ -function getReferenceLinkImageData(lineMetadata) { - // Initialize return values +function getReferenceLinkImageData(params) { + const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " "); + const definitions = new Map(); + const definitionLineIndices = []; + const duplicateDefinitions = []; const references = new Map(); const shortcuts = new Map(); - const definitions = new Map(); - const duplicateDefinitions = []; - const definitionLineIndices = []; - // Define helper functions - const normalizeLabel = (s) => s.toLowerCase().trim().replace(/\s+/g, " "); - const exclusions = []; - const excluded = (match) => withinAnyRange( - exclusions, 0, match.index, match[0].length - (match[3] || "").length - ); - // Convert input to single-line so multi-line links/images are easier - const lineOffsets = []; - let currentOffset = 0; - const contentLines = []; - forEachLine(lineMetadata, (line, lineIndex, inCode) => { - lineOffsets[lineIndex] = currentOffset; - if (!inCode) { - line = line.replace(blockquotePrefixRe, ""); - if (line.trim().length === 0) { - // Allow RegExp to detect the end of a block - line = "\0"; - } - contentLines.push(line); - currentOffset += line.length + 1; - } - }); - lineOffsets.push(currentOffset); - const contentLine = contentLines.join(" "); - // Determine single-line exclusions for inline code spans - forEachInlineCodeSpan(contentLine, (code, lineIndex, columnIndex) => { - exclusions.push([ 0, columnIndex, code.length ]); - }); - // Identify all link/image reference definitions - forEachLine(lineMetadata, (line, lineIndex, inCode) => { - if (!inCode) { - const linkReferenceDefinitionMatch = linkReferenceDefinitionRe.exec(line); - if (linkReferenceDefinitionMatch) { - const label = normalizeLabel(linkReferenceDefinitionMatch[1]); - if (definitions.has(label)) { - duplicateDefinitions.push([ label, lineIndex ]); - } else { - definitions.set(label, lineIndex); + const filteredTokens = + micromark.filterByTypes( + params.parsers.micromark.tokens, + [ + // definitionLineIndices + "definition", "gfmFootnoteDefinition", + // definitions and definitionLineIndices + "definitionLabelString", "gfmFootnoteDefinitionLabelString", + // references and shortcuts + "gfmFootnoteCall", "image", "link" + ] + ); + for (const token of filteredTokens) { + let labelPrefix = ""; + // eslint-disable-next-line default-case + switch (token.type) { + case "definition": + case "gfmFootnoteDefinition": + // definitionLineIndices + for (let i = token.startLine; i <= token.endLine; i++) { + definitionLineIndices.push(i - 1); } - const labelLength = linkReferenceDefinitionMatch[0].length; - exclusions.push([ 0, lineOffsets[lineIndex], labelLength ]); - const hasDefinition = line.slice(labelLength).trim().length > 0; - definitionLineIndices.push(lineIndex); - if (!hasDefinition) { - definitionLineIndices.push(lineIndex + 1); - } - } - } - }); - // Identify all link and image references - let lineIndex = 0; - const pendingContents = [ - { - "content": contentLine, - "contentLineIndex": 0, - "contentIndex": 0, - "topLevel": true - } - ]; - let pendingContent = null; - while ((pendingContent = pendingContents.shift())) { - const { content, contentLineIndex, contentIndex, topLevel } = - pendingContent; - let referenceLinkMatch = null; - while ((referenceLinkMatch = referenceLinkRe.exec(content)) !== null) { - const [ matchString, matchText, matchLabel ] = referenceLinkMatch; - if ( - !matchString.startsWith("\\") && - !matchString.startsWith("!\\") && - !matchText.endsWith("\\") && - !(matchLabel || "").endsWith("\\") && - !(topLevel && excluded(referenceLinkMatch)) - ) { - const shortcutLink = (matchLabel === undefined); - const collapsedLink = - (!shortcutLink && (matchLabel.length === 0)); - const label = normalizeLabel( - (shortcutLink || collapsedLink) ? matchText : matchLabel - ); - if (label.length > 0) { - const referenceindex = referenceLinkMatch.index; - if (topLevel) { - // Calculate line index - while (lineOffsets[lineIndex + 1] <= referenceindex) { - lineIndex++; - } + break; + case "gfmFootnoteDefinitionLabelString": + labelPrefix = "^"; + case "definitionLabelString": // eslint-disable-line no-fallthrough + { + // definitions and definitionLineIndices + const reference = normalizeReference(`${labelPrefix}${token.text}`); + if (definitions.has(reference)) { + duplicateDefinitions.push([ reference, token.startLine - 1 ]); } else { - // Use provided line index - lineIndex = contentLineIndex; + definitions.set(reference, token.startLine - 1); } - const referenceIndex = referenceindex + - (topLevel ? -lineOffsets[lineIndex] : contentIndex); - const referenceDatum = [ - lineIndex, - referenceIndex, - matchString.length, - matchText.length, - (matchLabel || "").length - ]; - if (shortcutLink) { - // Track separately due to ambiguity in "text [text] text" - const shortcutData = shortcuts.get(label) || []; - shortcutData.push(referenceDatum); - shortcuts.set(label, shortcutData); - } else { - // Track reference and location - const referenceData = references.get(label) || []; + } + break; + case "gfmFootnoteCall": + case "image": + case "link": + { + let isShortcut = false; + let isFullOrCollapsed = false; + let labelText = null; + let referenceStringText = null; + const shortcutCandidate = + micromark.matchAndGetTokensByType(token.children, [ "label" ]); + if (shortcutCandidate) { + labelText = + micromark.getTokenTextByType( + shortcutCandidate[0].children, "labelText" + ); + isShortcut = (labelText !== null); + } + const fullAndCollapsedCandidate = + micromark.matchAndGetTokensByType( + token.children, [ "label", "reference" ] + ); + if (fullAndCollapsedCandidate) { + labelText = + micromark.getTokenTextByType( + fullAndCollapsedCandidate[0].children, "labelText" + ); + referenceStringText = + micromark.getTokenTextByType( + fullAndCollapsedCandidate[1].children, "referenceString" + ); + isFullOrCollapsed = (labelText !== null); + } + const footnote = micromark.matchAndGetTokensByType( + token.children, + [ + "gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker", + "gfmFootnoteCallString", "gfmFootnoteCallLabelMarker" + ], + [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ] + ); + if (footnote) { + const callMarkerText = footnote[0].text; + const callString = footnote[1].text; + labelText = `${callMarkerText}${callString}`; + isShortcut = true; + } + // Track shortcuts separately due to ambiguity in "text [text] text" + if (isShortcut || isFullOrCollapsed) { + const referenceDatum = [ + token.startLine - 1, + token.startColumn - 1, + token.text.length, + // @ts-ignore + labelText.length, + (referenceStringText || "").length + ]; + const reference = + normalizeReference(referenceStringText || labelText); + const dictionary = isShortcut ? shortcuts : references; + const referenceData = dictionary.get(reference) || []; referenceData.push(referenceDatum); - references.set(label, referenceData); - } - // Check for links embedded in brackets - if (!matchString.startsWith("!")) { - pendingContents.push({ - "content": matchText, - "contentLineIndex": lineIndex, - "contentIndex": referenceIndex + 1, - "topLevel": false - }); + dictionary.set(reference, referenceData); } } - } + break; } } return { @@ -15285,113 +15265,6 @@ function expandTildePath(file, os) { } module.exports.expandTildePath = expandTildePath; -/** - * RegExp.exec-style implementation of function expressions. - * - * @param {Function} funcExp Function that takes string and returns - * [index, length] or null. - * @param {string} input String to search. - * @returns {string[] | null} RegExp.exec-style [match] with an index property. - */ -function funcExpExec(funcExp, input) { - // Start or resume match - // @ts-ignore - const lastIndex = funcExp.lastIndex || 0; - const result = funcExp(input.slice(lastIndex)); - if (result) { - // Update lastIndex and return match - const [ subIndex, length ] = result; - const index = lastIndex + subIndex; - // @ts-ignore - funcExp.lastIndex = index + length; - const match = [ input.slice(index, index + length) ]; - // @ts-ignore - match.index = index; - return match; - } - // Reset lastIndex and return no match - // @ts-ignore - funcExp.lastIndex = 0; - return null; -} -module.exports.funcExpExec = funcExpExec; - -const urlFeProtocolRe = /(?:http|ftp)s?:\/\//i; -const urlFeAutolinkTerminalsRe = / |$/; -const urlFeBareTerminalsRe = /[ ,!`'"\]]|$/; -const urlFeNonTerminalsRe = "-#/"; -const urlFePunctuationRe = /\p{Punctuation}/u; -const urlFePrefixToPostfix = new Map([ - [ " ", " " ], - [ "`", "`" ], - [ "'", "'" ], - [ "\"", "\"" ], - [ "‘", "’" ], - [ "“", "”" ], - [ "«", "»" ], - [ "*", "*" ], - [ "_", "_" ], - [ "(", ")" ], - [ "[", "]" ], - [ "{", "}" ], - [ "<", ">" ], - [ ">", "<" ] -]); - -/** - * Function expression that matches URLs. - * - * @param {string} input Substring to search for a URL. - * @returns {Array | null} [index, length] of URL or null. - */ -function urlFe(input) { - // Find start of URL by searching for protocol - const match = input.match(urlFeProtocolRe); - if (match) { - // Look for matching pre/postfix characters (ex: <...>) - const start = match.index || 0; - const length = match[0].length; - const prefix = input[start - 1] || " "; - const postfix = urlFePrefixToPostfix.get(prefix); - // @ts-ignore - let endPostfix = input.indexOf(postfix, start + length); - if (endPostfix === -1) { - endPostfix = input.length; - } - // Look for characters that terminate a URL - const terminalsRe = - (prefix === "<") ? urlFeAutolinkTerminalsRe : urlFeBareTerminalsRe; - const endTerminal = start + input.slice(start).search(terminalsRe); - // Determine tentative end of URL - let end = Math.min(endPostfix, endTerminal); - if (prefix === " ") { - // If the URL used " " as pre/postfix characters, trim the end - if (input[end - 1] === ")") { - // Trim any ")" beyond the last "(...)" pair - const lastOpenParen = input.lastIndexOf("(", end - 2); - if (lastOpenParen <= start) { - end--; - } else { - const nextCloseParen = input.indexOf(")", lastOpenParen + 1); - end = nextCloseParen + 1; - } - } else { - // Trim unwanted punctuation - while ( - !urlFeNonTerminalsRe.includes(input[end - 1]) && - urlFePunctuationRe.test(input[end - 1]) - ) { - end--; - } - } - } - return [ start, end - start ]; - } - // No match - return null; -} -module.exports.urlFe = urlFe; - /***/ }), @@ -20377,8 +20250,11 @@ const dynamicRequire = (typeof require === "undefined") ? require : /* c8 ignore const path = __nccwpck_require__(9411); const { pathToFileURL } = __nccwpck_require__(1041); const markdownlintLibrary = __nccwpck_require__(8397); -const { markdownlint, "readConfig": markdownlintReadConfig } = - markdownlintLibrary.promises; +const { + markdownlint, + "extendConfig": markdownlintExtendConfig, + "readConfig": markdownlintReadConfig +} = markdownlintLibrary.promises; const markdownlintRuleHelpers = __nccwpck_require__(2935); const appendToArray = __nccwpck_require__(7314); const mergeOptions = __nccwpck_require__(8446); @@ -20386,7 +20262,7 @@ const resolveAndRequire = __nccwpck_require__(5317); // Variables const packageName = "markdownlint-cli2"; -const packageVersion = "0.6.0"; +const packageVersion = "0.7.0"; const libraryName = "markdownlint"; const libraryVersion = markdownlintLibrary.getVersion(); const dotOnlySubstitute = "*.{md,markdown}"; @@ -20606,105 +20482,121 @@ $ markdownlint-cli2 "**/*.md" "#node_modules"` // Get (creating if necessary) and process a directory's info object const getAndProcessDirInfo = -(fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => { - let dirInfo = dirToDirInfo[dir]; - if (!dirInfo) { - dirInfo = { - dir, - relativeDir, - "parent": null, - "files": [], - "markdownlintConfig": null, - "markdownlintOptions": null - }; - dirToDirInfo[dir] = dirInfo; + (fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => { + let dirInfo = dirToDirInfo[dir]; + if (!dirInfo) { + dirInfo = { + dir, + relativeDir, + "parent": null, + "files": [], + "markdownlintConfig": null, + "markdownlintOptions": null + }; + dirToDirInfo[dir] = dirInfo; - // Load markdownlint-cli2 object(s) - const markdownlintCli2Jsonc = - path.posix.join(dir, ".markdownlint-cli2.jsonc"); - const markdownlintCli2Yaml = - path.posix.join(dir, ".markdownlint-cli2.yaml"); - tasks.push( - fs.promises.access(markdownlintCli2Jsonc). - then( - () => fs.promises. - readFile(markdownlintCli2Jsonc, utf8). - then( - (content) => getJsoncParse(). - then((jsoncParse) => jsoncParse(content)) - ), - () => fs.promises.access(markdownlintCli2Yaml). - then( - () => fs.promises. - readFile(markdownlintCli2Yaml, utf8). - then(yamlParse), - importOrRequireConfig( - fs, - dir, - ".markdownlint-cli2.cjs", - noRequire, + // Load markdownlint-cli2 object(s) + const markdownlintCli2Jsonc = + path.posix.join(dir, ".markdownlint-cli2.jsonc"); + const markdownlintCli2Yaml = + path.posix.join(dir, ".markdownlint-cli2.yaml"); + tasks.push( + fs.promises.access(markdownlintCli2Jsonc). + then( + () => fs.promises. + readFile(markdownlintCli2Jsonc, utf8). + then( + (content) => getJsoncParse(). + then((jsoncParse) => jsoncParse(content)) + ), + () => fs.promises.access(markdownlintCli2Yaml). + then( + () => fs.promises. + readFile(markdownlintCli2Yaml, utf8). + then(yamlParse), importOrRequireConfig( fs, dir, - ".markdownlint-cli2.mjs", + ".markdownlint-cli2.cjs", noRequire, - noop + importOrRequireConfig( + fs, + dir, + ".markdownlint-cli2.mjs", + noRequire, + noop + ) ) ) - ) - ). - then((options) => { - dirInfo.markdownlintOptions = options; - }) - ); + ). + then((options) => { + dirInfo.markdownlintOptions = options; + return options && + options.config && + options.config.extends && + getJsoncParse(). + then( + (jsoncParse) => markdownlintExtendConfig( + options.config, + // Just needs to identify a file in the right directory + markdownlintCli2Jsonc, + [ jsoncParse, yamlParse ], + fs + ) + ). + then((config) => { + options.config = config; + }); + }) + ); - // Load markdownlint object(s) - const readConfigs = - readConfig( - fs, - dir, - ".markdownlint.jsonc", + // Load markdownlint object(s) + const readConfigs = readConfig( fs, dir, - ".markdownlint.json", + ".markdownlint.jsonc", readConfig( fs, dir, - ".markdownlint.yaml", + ".markdownlint.json", readConfig( fs, dir, - ".markdownlint.yml", - importOrRequireConfig( + ".markdownlint.yaml", + readConfig( fs, dir, - ".markdownlint.cjs", - noRequire, + ".markdownlint.yml", importOrRequireConfig( fs, dir, - ".markdownlint.mjs", + ".markdownlint.cjs", noRequire, - noop + importOrRequireConfig( + fs, + dir, + ".markdownlint.mjs", + noRequire, + noop + ) ) ) ) ) - ) + ); + tasks.push( + readConfigs(). + then((config) => { + dirInfo.markdownlintConfig = config; + }) ); - tasks.push( - readConfigs(). - then((config) => { - dirInfo.markdownlintConfig = config; - }) - ); - } - if (func) { - func(dirInfo); - } - return dirInfo; -}; + } + if (func) { + func(dirInfo); + } + return dirInfo; + }; // Get base markdownlint-cli2 options object const getBaseOptions = async ( @@ -20731,7 +20623,10 @@ const getBaseOptions = async ( // eslint-disable-next-line no-multi-assign const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions = mergeOptions( - mergeOptions(options, { "fix": fixDefault }), + mergeOptions( + { "fix": fixDefault }, + options + ), dirToDirInfo[baseDir].markdownlintOptions ); @@ -20755,81 +20650,81 @@ const getBaseOptions = async ( // Enumerate files from globs and build directory infos const enumerateFiles = -// eslint-disable-next-line max-len -async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => { - const tasks = []; - const globbyOptions = { - "absolute": true, - "cwd": baseDir, - "dot": true, - "expandDirectories": false, - fs - }; - if (noErrors) { - globbyOptions.suppressErrors = true; - } - // Special-case literal files - const literalFiles = []; - const filteredGlobPatterns = globPatterns.filter( - (globPattern) => { - if (globPattern.startsWith(":")) { - literalFiles.push( - posixPath(path.resolve(baseDirSystem, globPattern.slice(1))) - ); - return false; - } - return true; + // eslint-disable-next-line max-len + async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => { + const tasks = []; + const globbyOptions = { + "absolute": true, + "cwd": baseDir, + "dot": true, + "expandDirectories": false, + fs + }; + if (noErrors) { + globbyOptions.suppressErrors = true; } - ).map((globPattern) => globPattern.replace(/^\\:/u, ":")); - const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions; - const globsForIgnore = - (baseMarkdownlintOptions.globs || []). - filter((glob) => glob.startsWith("!")); - const filteredLiteralFiles = - ((literalFiles.length > 0) && (globsForIgnore.length > 0)) - ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore) - : literalFiles; - // Manually expand directories to avoid globby call to dir-glob.sync - const expandedDirectories = await Promise.all( - filteredGlobPatterns.map((globPattern) => { - const barePattern = - globPattern.startsWith("!") - ? globPattern.slice(1) - : globPattern; - const globPath = - (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern)) - ? barePattern - : path.posix.join(baseDir, barePattern); - return fs.promises.stat(globPath). - then((stats) => (stats.isDirectory() - ? path.posix.join(globPattern, "**") - : globPattern)). - catch(() => globPattern); - }) - ); - // Process glob patterns - // eslint-disable-next-line no-inline-comments - const { globby } = await Promise.resolve(/* import() eager */).then(__nccwpck_require__.bind(__nccwpck_require__, 277)); - const files = [ - ...await globby(expandedDirectories, globbyOptions), - ...filteredLiteralFiles - ]; - for (const file of files) { - const dir = path.posix.dirname(file); - getAndProcessDirInfo( - fs, - tasks, - dirToDirInfo, - dir, - null, - noRequire, - (dirInfo) => { - dirInfo.files.push(file); + // Special-case literal files + const literalFiles = []; + const filteredGlobPatterns = globPatterns.filter( + (globPattern) => { + if (globPattern.startsWith(":")) { + literalFiles.push( + posixPath(path.resolve(baseDirSystem, globPattern.slice(1))) + ); + return false; + } + return true; } + ).map((globPattern) => globPattern.replace(/^\\:/u, ":")); + const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions; + const globsForIgnore = + (baseMarkdownlintOptions.globs || []). + filter((glob) => glob.startsWith("!")); + const filteredLiteralFiles = + ((literalFiles.length > 0) && (globsForIgnore.length > 0)) + ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore) + : literalFiles; + // Manually expand directories to avoid globby call to dir-glob.sync + const expandedDirectories = await Promise.all( + filteredGlobPatterns.map((globPattern) => { + const barePattern = + globPattern.startsWith("!") + ? globPattern.slice(1) + : globPattern; + const globPath = + (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern)) + ? barePattern + : path.posix.join(baseDir, barePattern); + return fs.promises.stat(globPath). + then((stats) => (stats.isDirectory() + ? path.posix.join(globPattern, "**") + : globPattern)). + catch(() => globPattern); + }) ); - } - await Promise.all(tasks); -}; + // Process glob patterns + // eslint-disable-next-line no-inline-comments + const { globby } = await Promise.resolve(/* import() eager */).then(__nccwpck_require__.bind(__nccwpck_require__, 277)); + const files = [ + ...await globby(expandedDirectories, globbyOptions), + ...filteredLiteralFiles + ]; + for (const file of files) { + const dir = path.posix.dirname(file); + getAndProcessDirInfo( + fs, + tasks, + dirToDirInfo, + dir, + null, + noRequire, + (dirInfo) => { + dirInfo.files.push(file); + } + ); + } + await Promise.all(tasks); + }; // Enumerate (possibly missing) parent directories and update directory infos const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => { @@ -20878,135 +20773,135 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => { // Create directory info objects by enumerating file globs const createDirInfos = -// eslint-disable-next-line max-len -async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => { - await enumerateFiles( - fs, - baseDirSystem, - baseDir, - globPatterns, - dirToDirInfo, - noErrors, - noRequire - ); - await enumerateParents( - fs, - baseDir, - dirToDirInfo, - noRequire - ); - - // Merge file lists with identical configuration - const dirs = Object.keys(dirToDirInfo); - dirs.sort((a, b) => b.length - a.length); - const dirInfos = []; - const noConfigDirInfo = - // eslint-disable-next-line unicorn/consistent-function-scoping - (dirInfo) => ( - dirInfo.parent && - !dirInfo.markdownlintConfig && - !dirInfo.markdownlintOptions + // eslint-disable-next-line max-len + async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => { + await enumerateFiles( + fs, + baseDirSystem, + baseDir, + globPatterns, + dirToDirInfo, + noErrors, + noRequire ); - const tasks = []; - for (const dir of dirs) { - const dirInfo = dirToDirInfo[dir]; - if (noConfigDirInfo(dirInfo)) { - if (dirInfo.parent) { - appendToArray(dirInfo.parent.files, dirInfo.files); - } - dirToDirInfo[dir] = null; - } else { - const { markdownlintOptions, relativeDir } = dirInfo; - if (markdownlintOptions && markdownlintOptions.customRules) { - tasks.push( - importOrRequireIds( - relativeDir || dir, - markdownlintOptions.customRules, - noRequire - ).then((customRules) => { - // Expand nested arrays (for packages that export multiple rules) - markdownlintOptions.customRules = customRules.flat(); - }) - ); - } - if (markdownlintOptions && markdownlintOptions.markdownItPlugins) { - tasks.push( - importOrRequireIdsAndParams( - relativeDir || dir, - markdownlintOptions.markdownItPlugins, - noRequire - ).then((markdownItPlugins) => { - markdownlintOptions.markdownItPlugins = markdownItPlugins; - }) - ); - } - dirInfos.push(dirInfo); - } - } - await Promise.all(tasks); - for (const dirInfo of dirInfos) { - while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) { - dirInfo.parent = dirInfo.parent.parent; - } - } - - // Verify dirInfos is simplified - // if ( - // dirInfos.filter( - // (di) => di.parent && !dirInfos.includes(di.parent) - // ).length > 0 - // ) { - // throw new Error("Extra parent"); - // } - // if ( - // dirInfos.filter( - // (di) => !di.parent && (di.dir !== baseDir) - // ).length > 0 - // ) { - // throw new Error("Missing parent"); - // } - // if ( - // dirInfos.filter( - // (di) => di.parent && - // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0)) - // ).length > 0 - // ) { - // throw new Error("Missing object"); - // } - // if (dirInfos.filter((di) => di.dir === "/").length > 0) { - // throw new Error("Includes root"); - // } - - // Merge configuration by inheritance - for (const dirInfo of dirInfos) { - let markdownlintOptions = dirInfo.markdownlintOptions || {}; - let { markdownlintConfig } = dirInfo; - let parent = dirInfo; - // eslint-disable-next-line prefer-destructuring - while ((parent = parent.parent)) { - if (parent.markdownlintOptions) { - markdownlintOptions = mergeOptions( - parent.markdownlintOptions, - markdownlintOptions - ); - } - if ( - !markdownlintConfig && - parent.markdownlintConfig && - !markdownlintOptions.config - ) { - // eslint-disable-next-line prefer-destructuring - markdownlintConfig = parent.markdownlintConfig; - } - } - dirInfo.markdownlintOptions = mergeOptions( - markdownlintOptions, - optionsOverride + await enumerateParents( + fs, + baseDir, + dirToDirInfo, + noRequire ); - dirInfo.markdownlintConfig = markdownlintConfig; - } - return dirInfos; -}; + + // Merge file lists with identical configuration + const dirs = Object.keys(dirToDirInfo); + dirs.sort((a, b) => b.length - a.length); + const dirInfos = []; + const noConfigDirInfo = + // eslint-disable-next-line unicorn/consistent-function-scoping + (dirInfo) => ( + dirInfo.parent && + !dirInfo.markdownlintConfig && + !dirInfo.markdownlintOptions + ); + const tasks = []; + for (const dir of dirs) { + const dirInfo = dirToDirInfo[dir]; + if (noConfigDirInfo(dirInfo)) { + if (dirInfo.parent) { + appendToArray(dirInfo.parent.files, dirInfo.files); + } + dirToDirInfo[dir] = null; + } else { + const { markdownlintOptions, relativeDir } = dirInfo; + if (markdownlintOptions && markdownlintOptions.customRules) { + tasks.push( + importOrRequireIds( + relativeDir || dir, + markdownlintOptions.customRules, + noRequire + ).then((customRules) => { + // Expand nested arrays (for packages that export multiple rules) + markdownlintOptions.customRules = customRules.flat(); + }) + ); + } + if (markdownlintOptions && markdownlintOptions.markdownItPlugins) { + tasks.push( + importOrRequireIdsAndParams( + relativeDir || dir, + markdownlintOptions.markdownItPlugins, + noRequire + ).then((markdownItPlugins) => { + markdownlintOptions.markdownItPlugins = markdownItPlugins; + }) + ); + } + dirInfos.push(dirInfo); + } + } + await Promise.all(tasks); + for (const dirInfo of dirInfos) { + while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) { + dirInfo.parent = dirInfo.parent.parent; + } + } + + // Verify dirInfos is simplified + // if ( + // dirInfos.filter( + // (di) => di.parent && !dirInfos.includes(di.parent) + // ).length > 0 + // ) { + // throw new Error("Extra parent"); + // } + // if ( + // dirInfos.filter( + // (di) => !di.parent && (di.dir !== baseDir) + // ).length > 0 + // ) { + // throw new Error("Missing parent"); + // } + // if ( + // dirInfos.filter( + // (di) => di.parent && + // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0)) + // ).length > 0 + // ) { + // throw new Error("Missing object"); + // } + // if (dirInfos.filter((di) => di.dir === "/").length > 0) { + // throw new Error("Includes root"); + // } + + // Merge configuration by inheritance + for (const dirInfo of dirInfos) { + let markdownlintOptions = dirInfo.markdownlintOptions || {}; + let { markdownlintConfig } = dirInfo; + let parent = dirInfo; + // eslint-disable-next-line prefer-destructuring + while ((parent = parent.parent)) { + if (parent.markdownlintOptions) { + markdownlintOptions = mergeOptions( + parent.markdownlintOptions, + markdownlintOptions + ); + } + if ( + !markdownlintConfig && + parent.markdownlintConfig && + !markdownlintOptions.config + ) { + // eslint-disable-next-line prefer-destructuring + markdownlintConfig = parent.markdownlintConfig; + } + } + dirInfo.markdownlintOptions = mergeOptions( + markdownlintOptions, + optionsOverride + ); + dirInfo.markdownlintConfig = markdownlintConfig; + } + return dirInfos; + }; // Lint files in groups by shared configuration const lintFiles = async (fs, dirInfos, fileContents) => { @@ -21403,7 +21298,7 @@ module.exports.fixableRuleNames = [ "MD044", "MD047", "MD049", "MD050", "MD051", "MD053" ]; module.exports.homepage = "https://github.com/DavidAnson/markdownlint"; -module.exports.version = "0.27.0"; +module.exports.version = "0.28.1"; /***/ }), @@ -21418,7 +21313,8 @@ module.exports.version = "0.27.0"; const path = __nccwpck_require__(9411); const { promisify } = __nccwpck_require__(7261); -const markdownIt = __nccwpck_require__(8561); +const markdownit = __nccwpck_require__(8561); +const micromark = __nccwpck_require__(5673); const { deprecatedRuleNames } = __nccwpck_require__(983); const rules = __nccwpck_require__(1796); const helpers = __nccwpck_require__(2935); @@ -21580,7 +21476,7 @@ function newResults(ruleList) { * Remove front matter (if present at beginning of content). * * @param {string} content Markdown content. - * @param {RegExp} frontMatter Regular expression to match front matter. + * @param {RegExp | null} frontMatter Regular expression to match front matter. * @returns {Object} Trimmed content and front matter lines. */ function removeFrontMatter(content, frontMatter) { @@ -21922,12 +21818,14 @@ function getEnabledRulesPerLineNumber( * Lints a string containing Markdown content. * * @param {Rule[]} ruleList List of rules. + * @param {Object.} aliasToRuleNames Map of alias to rule + * names. * @param {string} name Identifier for the content. * @param {string} content Markdown content. * @param {Object} md Instance of markdown-it. * @param {Configuration} config Configuration object. * @param {ConfigurationParser[] | null} configParsers Configuration parsers. - * @param {RegExp} frontMatter Regular expression for front matter. + * @param {RegExp | null} frontMatter Regular expression for front matter. * @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. @@ -21936,6 +21834,7 @@ function getEnabledRulesPerLineNumber( */ function lintContent( ruleList, + aliasToRuleNames, name, content, md, @@ -21961,18 +21860,29 @@ function lintContent( noInlineConfig, config, configParsers, - mapAliasToRuleNames(ruleList) + aliasToRuleNames ); - // Hide the content of HTML comments from rules, etc. + // Parse content into parser tokens + const markdownitTokens = md.parse(content, {}); + const micromarkTokens = micromark.parse(content); + // Hide the content of HTML comments from rules content = helpers.clearHtmlCommentText(content); - // Parse content into tokens and lines - const tokens = md.parse(content, {}); + // Parse content into lines and update markdown-it tokens const lines = content.split(helpers.newLineRe); - annotateAndFreezeTokens(tokens, lines); + annotateAndFreezeTokens(markdownitTokens, lines); // Create (frozen) parameters for rules + const parsers = Object.freeze({ + "markdownit": Object.freeze({ + "tokens": markdownitTokens + }), + "micromark": Object.freeze({ + "tokens": micromarkTokens + }) + }); const paramsBase = { name, - tokens, + parsers, + "tokens": markdownitTokens, "lines": Object.freeze(lines), "frontMatterLines": Object.freeze(frontMatterLines) }; @@ -21981,11 +21891,11 @@ function lintContent( const codeBlockAndSpanRanges = helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata); const flattenedLists = - helpers.flattenLists(paramsBase.tokens); + helpers.flattenLists(paramsBase.parsers.markdownit.tokens); const htmlElementRanges = helpers.htmlElementRanges(paramsBase, lineMetadata); const referenceLinkImageData = - helpers.getReferenceLinkImageData(lineMetadata); + helpers.getReferenceLinkImageData(paramsBase); cache.set({ codeBlockAndSpanRanges, flattenedLists, @@ -22194,11 +22104,13 @@ function lintContent( * Lints a file containing Markdown content. * * @param {Rule[]} ruleList List of rules. + * @param {Object.} aliasToRuleNames Map of alias to rule + * names. * @param {string} file Path of file to lint. * @param {Object} md Instance of markdown-it. * @param {Configuration} config Configuration object. * @param {ConfigurationParser[] | null} configParsers Configuration parsers. - * @param {RegExp} frontMatter Regular expression for front matter. + * @param {RegExp | null} frontMatter Regular expression for front matter. * @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. @@ -22209,6 +22121,7 @@ function lintContent( */ function lintFile( ruleList, + aliasToRuleNames, file, md, config, @@ -22227,6 +22140,7 @@ function lintFile( } return lintContent( ruleList, + aliasToRuleNames, file, content, md, @@ -22250,7 +22164,7 @@ function lintFile( /** * Lint files and strings specified in the Options object. * - * @param {Options} options Options object. + * @param {Options | null} options Options object. * @param {boolean} synchronous Whether to execute synchronously. * @param {Function} callback Callback (err, result) function. * @returns {void} @@ -22282,13 +22196,14 @@ function lintInput(options, synchronous, callback) { const noInlineConfig = !!options.noInlineConfig; const resultVersion = (options.resultVersion === undefined) ? 3 : options.resultVersion; - const md = markdownIt({ "html": true }); + const md = markdownit({ "html": true }); const markdownItPlugins = options.markdownItPlugins || []; for (const plugin of markdownItPlugins) { // @ts-ignore md.use(...plugin); } const fs = options.fs || __nccwpck_require__(7561); + const aliasToRuleNames = mapAliasToRuleNames(ruleList); const results = newResults(ruleList); let done = false; let concurrency = 0; @@ -22316,6 +22231,7 @@ function lintInput(options, synchronous, callback) { currentItem = files.shift(); lintFile( ruleList, + aliasToRuleNames, currentItem, md, config, @@ -22333,6 +22249,7 @@ function lintInput(options, synchronous, callback) { concurrency++; lintContent( ruleList, + aliasToRuleNames, currentItem, strings[currentItem] || "", md, @@ -22373,7 +22290,7 @@ function lintInput(options, synchronous, callback) { /** * Lint specified Markdown files. * - * @param {Options} options Configuration options. + * @param {Options | null} options Configuration options. * @param {LintCallback} callback Callback (err, result) function. * @returns {void} */ @@ -22397,7 +22314,7 @@ function markdownlintPromise(options) { /** * Lint specified Markdown files synchronously. * - * @param {Options} options Configuration options. + * @param {Options | null} options Configuration options. * @returns {LintResults} Results object. */ function markdownlintSync(options) { @@ -22471,6 +22388,63 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) { return resolvedExtendsFile; } +/** + * Extend specified configuration object. + * + * @param {Configuration} config Configuration object. + * @param {string} file Configuration file name. + * @param {ConfigurationParser[]} parsers Parsing + * function(s). + * @param {Object} fs File system implementation. + * @param {ReadConfigCallback} callback Callback (err, result) function. + * @returns {void} + */ +function extendConfig(config, file, parsers, fs, callback) { + const configExtends = config.extends; + if (configExtends) { + return resolveConfigExtends( + file, + helpers.expandTildePath(configExtends, __nccwpck_require__(612)), + fs, + // eslint-disable-next-line no-use-before-define + (_, resolvedExtends) => readConfig( + // @ts-ignore + resolvedExtends, + parsers, + fs, + (err, extendsConfig) => { + if (err) { + return callback(err); + } + const result = { + ...extendsConfig, + ...config + }; + delete result.extends; + return callback(null, result); + } + ) + ); + } + return callback(null, config); +} + +const extendConfigPromisify = promisify && promisify(extendConfig); + +/** + * Extend specified configuration object. + * + * @param {Configuration} config Configuration object. + * @param {string} file Configuration file name. + * @param {ConfigurationParser[]} [parsers] Parsing function(s). + * @param {Object} [fs] File system implementation. + * @returns {Promise} Configuration object. + */ +function extendConfigPromise(config, file, parsers, fs) { + // @ts-ignore + return extendConfigPromisify(config, file, parsers, fs); +} + /** * Read specified configuration file. * @@ -22497,8 +22471,7 @@ function readConfig(file, parsers, fs, callback) { fs = __nccwpck_require__(7561); } // Read file - const os = __nccwpck_require__(612); - file = helpers.expandTildePath(file, os); + file = helpers.expandTildePath(file, __nccwpck_require__(612)); fs.readFile(file, "utf8", (err, content) => { if (err) { // @ts-ignore @@ -22512,34 +22485,8 @@ function readConfig(file, parsers, fs, callback) { return callback(new Error(message)); } // Extend configuration - const configExtends = config.extends; - if (configExtends) { - delete config.extends; - return resolveConfigExtends( - file, - helpers.expandTildePath(configExtends, os), - fs, - (_, resolvedExtends) => readConfig( - // @ts-ignore - resolvedExtends, - parsers, - fs, - (errr, extendsConfig) => { - if (errr) { - // @ts-ignore - return callback(errr); - } - // @ts-ignore - return callback(null, { - ...extendsConfig, - ...config - }); - } - ) - ); - } // @ts-ignore - return callback(null, config); + return extendConfig(config, file, parsers, fs, callback); }); } @@ -22613,6 +22560,7 @@ markdownlint.readConfigSync = readConfigSync; markdownlint.getVersion = getVersion; markdownlint.promises = { "markdownlint": markdownlintPromise, + "extendConfig": extendConfigPromise, "readConfig": readConfigPromise }; module.exports = markdownlint; @@ -22709,7 +22657,7 @@ module.exports = markdownlint; * @property {ConfigurationParser[]} [configParsers] Configuration parsers. * @property {Rule[] | Rule} [customRules] Custom rules. * @property {string[] | string} [files] Files to lint. - * @property {RegExp} [frontMatter] Front matter pattern. + * @property {RegExp | null} [frontMatter] Front matter pattern. * @property {Object} [fs] File system implementation. * @property {boolean} [handleRuleFailures] True to catch exceptions. * @property {Plugin[]} [markdownItPlugins] Additional plugins. @@ -22861,7 +22809,7 @@ module.exports = { "function": function MD002(params, onError) { const level = Number(params.config.level || 1); const tag = "h" + level; - params.tokens.every(function forToken(token) { + params.parsers.markdownit.tokens.every(function forToken(token) { if (token.type === "heading_open") { addErrorDetailIf(onError, token.lineNumber, tag, token.tag); return false; @@ -24115,7 +24063,7 @@ module.exports = { "function": function MD027(params, onError) { let blockquoteNesting = 0; let listItemNesting = 0; - for (const token of params.tokens) { + for (const token of params.parsers.markdownit.tokens) { const { content, lineNumber, type } = token; if (type === "blockquote_open") { blockquoteNesting++; @@ -24177,7 +24125,7 @@ module.exports = { "function": function MD028(params, onError) { let prevToken = {}; let prevLineNumber = null; - for (const token of params.tokens) { + for (const token of params.parsers.markdownit.tokens) { if ((token.type === "blockquote_open") && (prevToken.type === "blockquote_close")) { for ( @@ -24445,17 +24393,11 @@ module.exports = { -const { - addError, forEachLine, htmlElementRe, withinAnyRange, unescapeMarkdown -} = __nccwpck_require__(2935); -const { codeBlockAndSpanRanges, lineMetadata, referenceLinkImageData } = - __nccwpck_require__(2260); +const { addError } = __nccwpck_require__(2935); +const { filterByTypes, getHtmlTagInfo, parse } = + __nccwpck_require__(5673); -const linkDestinationRe = /\]\(\s*$/; -// See https://spec.commonmark.org/0.29/#autolinks -const emailAddressRe = - // eslint-disable-next-line max-len - /^[\w.!#$%&'*+/=?^`{|}~-]+@[a-zA-Z\d](?:[a-zA-Z\d-]{0,61}[a-zA-Z\d])?(?:\.[a-zA-Z\d](?:[a-zA-Z\d-]{0,61}[a-zA-Z\d])?)*$/; +const nextLinesRe = /[\r\n][\s\S]*$/; module.exports = { "names": [ "MD033", "no-inline-html" ], @@ -24465,39 +24407,52 @@ module.exports = { let allowedElements = params.config.allowed_elements; allowedElements = Array.isArray(allowedElements) ? allowedElements : []; allowedElements = allowedElements.map((element) => element.toLowerCase()); - const exclusions = codeBlockAndSpanRanges(); - const { references, definitionLineIndices } = referenceLinkImageData(); - for (const datas of references.values()) { - for (const data of datas) { - const [ lineIndex, index, , textLength, labelLength ] = data; - if (labelLength > 0) { - exclusions.push([ lineIndex, index + 3 + textLength, labelLength ]); + const pending = [ [ 0, params.parsers.micromark.tokens ] ]; + let current = null; + while ((current = pending.shift())) { + const [ offset, tokens ] = current; + for (const token of filterByTypes(tokens, [ "htmlFlow", "htmlText" ])) { + if (token.type === "htmlText") { + const htmlTagInfo = getHtmlTagInfo(token); + if ( + htmlTagInfo && + !htmlTagInfo.close && + !allowedElements.includes(htmlTagInfo.name.toLowerCase()) + ) { + const range = [ + token.startColumn, + token.text.replace(nextLinesRe, "").length + ]; + addError( + onError, + token.startLine + offset, + "Element: " + htmlTagInfo.name, + undefined, + range + ); + } + } else { + // token.type === "htmlFlow" + // Re-parse without "htmlFlow" to get only "htmlText" tokens + const options = { + "extensions": [ + { + "disable": { + "null": [ "codeIndented", "htmlFlow" ] + } + } + ] + }; + // Use lines instead of token.text for accurate columns + const lines = + params.lines.slice(token.startLine - 1, token.endLine).join("\n"); + const flowTokens = parse(lines, options); + pending.push( + [ token.startLine - 1, flowTokens ] + ); } } } - forEachLine(lineMetadata(), (line, lineIndex, inCode) => { - let match = null; - // eslint-disable-next-line no-unmodified-loop-condition - while (!inCode && ((match = htmlElementRe.exec(line)) !== null)) { - const [ tag, content, element ] = match; - if ( - !allowedElements.includes(element.toLowerCase()) && - !tag.endsWith("\\>") && - !emailAddressRe.test(content) && - !withinAnyRange(exclusions, lineIndex, match.index, tag.length) && - !definitionLineIndices.includes(lineIndex) - ) { - const prefix = line.substring(0, match.index); - if (!linkDestinationRe.test(prefix)) { - const unescaped = unescapeMarkdown(prefix + "<", "_"); - if (!unescaped.endsWith("_")) { - addError(onError, lineIndex + 1, "Element: " + element, - undefined, [ match.index + 1, tag.length ]); - } - } - } - } - }); } }; @@ -24512,85 +24467,67 @@ module.exports = { -const { addErrorContext, filterTokens, funcExpExec, urlFe, withinAnyRange } = - __nccwpck_require__(2935); -const { codeBlockAndSpanRanges, htmlElementRanges, referenceLinkImageData } = - __nccwpck_require__(2260); - -const htmlLinkRe = /]*)?>[^<>]*<\/a\s*>/gi; +const { addErrorContext } = __nccwpck_require__(2935); +const { filterByPredicate, getHtmlTagInfo } = + __nccwpck_require__(5673); module.exports = { "names": [ "MD034", "no-bare-urls" ], "description": "Bare URL used", "tags": [ "links", "url" ], "function": function MD034(params, onError) { - const { lines } = params; - const codeExclusions = [ - ...codeBlockAndSpanRanges(), - ...htmlElementRanges() - ]; - filterTokens(params, "html_block", (token) => { - for (let i = token.map[0]; i < token.map[1]; i++) { - codeExclusions.push([ i, 0, lines[i].length ]); - } - }); - const { definitionLineIndices } = referenceLinkImageData(); - for (const [ lineIndex, line ] of lines.entries()) { - if (definitionLineIndices[0] === lineIndex) { - definitionLineIndices.shift(); - } else { - let match = null; - const lineExclusions = []; - while ((match = htmlLinkRe.exec(line)) !== null) { - lineExclusions.push([ lineIndex, match.index, match[0].length ]); - } - while ((match = funcExpExec(urlFe, line)) !== null) { - const [ bareUrl ] = match; - // @ts-ignore - const matchIndex = match.index; - const bareUrlLength = bareUrl.length; - const prefix = line.slice(0, matchIndex); - const postfix = line.slice(matchIndex + bareUrlLength); - if ( - // Allow <...> to avoid reporting non-bare links - !(prefix.endsWith("<") && postfix.startsWith(">")) && - // Allow >...... - !(prefix.endsWith(">") && postfix.startsWith("` - }; - addErrorContext( - onError, - lineIndex + 1, - bareUrl, - null, - null, - range, - fixInfo - ); + const literalAutolinks = + filterByPredicate( + params.parsers.micromark.tokens, + (token) => token.type === "literalAutolink", + (token) => { + const { children } = token; + const result = []; + for (let i = 0; i < children.length; i++) { + const openToken = children[i]; + const openTagInfo = getHtmlTagInfo(openToken); + if (openTagInfo && !openTagInfo.close) { + let count = 1; + for (let j = i + 1; j < children.length; j++) { + const closeToken = children[j]; + const closeTagInfo = getHtmlTagInfo(closeToken); + if (closeTagInfo && (openTagInfo.name === closeTagInfo.name)) { + if (closeTagInfo.close) { + count--; + if (count === 0) { + i = j; + break; + } + } else { + count++; + } + } + } + } else { + result.push(openToken); + } } - } - } + return result; + }); + for (const token of literalAutolinks) { + const range = [ + token.startColumn, + token.endColumn - token.startColumn + ]; + const fixInfo = { + "editColumn": range[0], + "deleteCount": range[1], + "insertText": `<${token.text}>` + }; + addErrorContext( + onError, + token.startLine, + token.text, + null, + null, + range, + fixInfo + ); } } }; @@ -24606,7 +24543,8 @@ module.exports = { -const { addErrorDetailIf, filterTokens } = __nccwpck_require__(2935); +const { addErrorDetailIf } = __nccwpck_require__(2935); +const { filterByTypes } = __nccwpck_require__(5673); module.exports = { "names": [ "MD035", "hr-style" ], @@ -24614,18 +24552,15 @@ module.exports = { "tags": [ "hr" ], "function": function MD035(params, onError) { let style = String(params.config.style || "consistent").trim(); - filterTokens(params, "hr", (token) => { - const { line, lineNumber } = token; - let { markup } = token; - const match = line.match(/[_*\-\s]+$/); - if (match) { - markup = match[0].trim(); - } + const thematicBreaks = + filterByTypes(params.parsers.micromark.tokens, [ "thematicBreak" ]); + for (const token of thematicBreaks) { + const { startLine, text } = token; if (style === "consistent") { - style = markup; + style = text; } - addErrorDetailIf(onError, lineNumber, style, markup); - }); + addErrorDetailIf(onError, startLine, style, text); + } } }; @@ -24687,7 +24622,7 @@ module.exports = { return base; } let state = base; - for (const token of params.tokens) { + for (const token of params.parsers.markdownit.tokens) { state = state(token); } } @@ -24893,71 +24828,96 @@ module.exports = { -const { addErrorContext, filterTokens, forEachInlineCodeSpan, newLineRe } = - __nccwpck_require__(2935); +const { addErrorContext } = __nccwpck_require__(2935); +const { filterByTypes } = __nccwpck_require__(5673); const leftSpaceRe = /^\s(?:[^`]|$)/; const rightSpaceRe = /[^`]\s$/; - -const spaceInsideCodeInline = (token) => ( - (token.type === "code_inline") && - (leftSpaceRe.test(token.content) || rightSpaceRe.test(token.content)) -); +const trimCodeText = (text, start, end) => { + text = text.replace(/^\s+$/, ""); + if (start) { + text = text.replace(/^\s+?(\s`|\S)/, "$1"); + } + if (end) { + text = text.replace(/(`\s|\S)\s+$/, "$1"); + } + return text; +}; +const tokenIfType = (token, type) => token && (token.type === type) && token; module.exports = { "names": [ "MD038", "no-space-in-code" ], "description": "Spaces inside code span elements", "tags": [ "whitespace", "code" ], "function": function MD038(params, onError) { - filterTokens(params, "inline", (token) => { - if (token.children.some(spaceInsideCodeInline)) { - const tokenLines = params.lines.slice(token.map[0], token.map[1]); - forEachInlineCodeSpan( - tokenLines.join("\n"), - (code, lineIndex, columnIndex, tickCount) => { - let rangeIndex = columnIndex - tickCount; - let rangeLength = code.length + (2 * tickCount); - let rangeLineOffset = 0; - let fixIndex = columnIndex; - let fixLength = code.length; - const codeLines = code.split(newLineRe); - const left = leftSpaceRe.test(code); - const right = !left && rightSpaceRe.test(code); - if (right && (codeLines.length > 1)) { - rangeIndex = 0; - rangeLineOffset = codeLines.length - 1; - fixIndex = 0; - } - if (left || right) { - const codeLinesRange = codeLines[rangeLineOffset]; - if (codeLines.length > 1) { - rangeLength = codeLinesRange.length + tickCount; - fixLength = codeLinesRange.length; - } - const context = tokenLines[lineIndex + rangeLineOffset] - .substring(rangeIndex, rangeIndex + rangeLength); - const codeLinesRangeTrim = codeLinesRange.trim(); - const fixText = - (codeLinesRangeTrim.startsWith("`") ? " " : "") + - codeLinesRangeTrim + - (codeLinesRangeTrim.endsWith("`") ? " " : ""); - addErrorContext( - onError, - token.lineNumber + lineIndex + rangeLineOffset, - context, - left, - right, - [ rangeIndex + 1, rangeLength ], - { - "editColumn": fixIndex + 1, - "deleteCount": fixLength, - "insertText": fixText - } - ); - } - }); + const codeTextTokens = + filterByTypes(params.parsers.micromark.tokens, [ "codeText" ]); + for (const token of codeTextTokens) { + const { children } = token; + const first = 0; + const last = children.length - 1; + const startSequence = tokenIfType(children[first], "codeTextSequence"); + const endSequence = tokenIfType(children[last], "codeTextSequence"); + const startData = + tokenIfType(children[first + 1], "codeTextData") || + tokenIfType(children[first + 2], "codeTextData"); + const endData = + tokenIfType(children[last - 1], "codeTextData") || + tokenIfType(children[last - 2], "codeTextData"); + if (startSequence && endSequence && startData && endData) { + const spaceLeft = leftSpaceRe.test(startData.text); + const spaceRight = !spaceLeft && rightSpaceRe.test(endData.text); + if (spaceLeft || spaceRight) { + let lineNumber = startSequence.startLine; + let range = null; + let fixInfo = null; + if (startSequence.startLine === endSequence.endLine) { + range = [ + startSequence.startColumn, + endSequence.endColumn - startSequence.startColumn + ]; + fixInfo = { + "editColumn": startSequence.endColumn, + "deleteCount": endSequence.startColumn - startSequence.endColumn, + "insertText": trimCodeText(startData.text, true, true) + }; + } else if (spaceLeft) { + range = [ + startSequence.startColumn, + startData.endColumn - startSequence.startColumn + ]; + fixInfo = { + "editColumn": startSequence.endColumn, + "deleteCount": startData.endColumn - startData.startColumn, + "insertText": trimCodeText(startData.text, true, false) + }; + } else { + lineNumber = endSequence.endLine; + range = [ + endData.startColumn, + endSequence.endColumn - endData.startColumn + ]; + fixInfo = { + "editColumn": endData.startColumn, + "deleteCount": endData.endColumn - endData.startColumn, + "insertText": trimCodeText(endData.text, false, true) + }; + } + const context = params + .lines[lineNumber - 1] + .substring(range[0] - 1, range[0] - 1 + range[1]); + addErrorContext( + onError, + lineNumber, + context, + spaceLeft, + spaceRight, + range, + fixInfo + ); + } } - }); + } } }; @@ -25108,7 +25068,7 @@ module.exports = { ); if (!foundFrontMatterTitle) { const htmlHeadingRe = new RegExp(`^]`, "i"); - params.tokens.every((token) => { + params.parsers.markdownit.tokens.every((token) => { let isError = false; if (token.type === "html_block") { if (token.content.startsWith("