From f70c06957279a5279708964c9ee33470b03e7bbf Mon Sep 17 00:00:00 2001 From: David Anson Date: Sat, 10 Jun 2023 20:35:20 -0700 Subject: [PATCH] Add "config" and "fix" inputs, deprecate "command" input. --- .github/dictionary.txt | 2 + .github/workflows/test.yml | 40 +- README.md | 37 +- action.yml | 9 + config/.markdownlint.jsonc | 18 - dist/index.js | 1140 ++++++++++++++++++++--------------- markdownlint-cli2-action.js | 28 +- package.json | 2 +- 8 files changed, 734 insertions(+), 542 deletions(-) delete mode 100644 config/.markdownlint.jsonc diff --git a/.github/dictionary.txt b/.github/dictionary.txt index ca0ad8a..2645e8c 100644 --- a/.github/dictionary.txt +++ b/.github/dictionary.txt @@ -1,3 +1,5 @@ CommonMark +config markdownlint-cli2-action README +truthy diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c90d7fe..d7401ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,7 @@ jobs: - run: exit 1 if: steps.test.outcome != 'failure' one-glob-pattern: - name: One glob (*.md, 0 errors) + name: One glob (README.md, 0 errors) runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -72,6 +72,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - run: rm .markdownlint.json - uses: ./ with: command: config @@ -117,6 +118,7 @@ jobs: - uses: ./ with: command: fix + globs: 'test/*' command-unsupported: name: Command = unsupported (fails) runs-on: ubuntu-latest @@ -129,3 +131,39 @@ jobs: id: test - run: exit 1 if: steps.test.outcome != 'failure' + config: + name: config (test/errors.md, 2 errors) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rm .markdownlint.json + - uses: ./ + with: + config: 'config/test.markdownlint.jsonc' + globs: 'test/*' + continue-on-error: true + id: test + - run: exit 1 + if: steps.test.outcome != 'failure' + config-invalid: + name: config (invalid configuration file, fails) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ./ + with: + config: 'invalid.markdownlint.jsonc' + globs: 'test/*' + continue-on-error: true + id: test + - run: exit 1 + if: steps.test.outcome != 'failure' + fix: + name: fix (test/errors.md, 0 errors) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ./ + with: + fix: true + globs: 'test/*' diff --git a/README.md b/README.md index f583932..5701b26 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,32 @@ information. ### command (optional) -Command to run (unset, `fix`, or `config`) +> **Deprecated in favor of the "fix" and "config" inputs** +> +> Command to run (unset, `fix`, or `config`) +> +> If unspecified or `""`, the `markdownlint-cli2` command is run. +> +> If set to `fix`, the `markdownlint-cli2-fix` command is run and supported +> issues will be fixed automatically. +> +> If set to `config`, the `markdownlint-cli2-config` command is run and the +> first element of `globs` should specify a supported configuration file. +> +> For more detail: [documentation for `markdownlint-cli2`][command-line]. -If unspecified or `""`, the `markdownlint-cli2` command is run. +### config (optional) -If set to `fix`, the `markdownlint-cli2-fix` command is run and supported issues -will be fixed automatically. +Path of a file to use for the base configuration object (defaults to none) -If set to `config`, the `markdownlint-cli2-config` command is run and the first -element of `globs` should specify a supported configuration file. +Equivalent to using the `--config` [command-line option][command-line] and +passing the specified configuration file. -For more detail: [documentation for `markdownlint-cli2`][command-line]. +### fix (optional) + +Whether to fix supported issues automatically (any truthy value enables) + +Equivalent to specifying the `--fix` [command-line option][command-line]. ### globs (optional) @@ -88,7 +103,7 @@ To fix supported issues when linting: ```yaml - uses: DavidAnson/markdownlint-cli2-action@v10 with: - command: fix + fix: true globs: '**/*.md' ``` @@ -97,10 +112,8 @@ To specify a custom configuration file: ```yaml - uses: DavidAnson/markdownlint-cli2-action@v10 with: - command: config - globs: | - config/custom.markdownlint.jsonc - **/*.md + config: 'config/custom.markdownlint.jsonc' + globs: '**/*.md' ``` To prevent linting issues from failing the workflow run: diff --git a/action.yml b/action.yml index 760349f..d67ed68 100644 --- a/action.yml +++ b/action.yml @@ -7,6 +7,15 @@ branding: inputs: command: description: Command to run (unset, "fix", or "config") + deprecationMessage: This input is deprecated in favor of the "fix" and "config" inputs + default: '' + required: false + config: + description: Path of a file to use for the base configuration object (defaults to none) + default: '' + required: false + fix: + description: Whether to fix supported issues automatically (any truthy value enables) default: '' required: false globs: diff --git a/config/.markdownlint.jsonc b/config/.markdownlint.jsonc deleted file mode 100644 index 9ed85d8..0000000 --- a/config/.markdownlint.jsonc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "line-length": { - "strict": true, - "code_blocks": false - }, - "proper-names": { - "code_blocks": false, - "names": [ - "CommonMark", - "JavaScript", - "Markdown", - "markdown-it", - "markdownlint", - "markdownlint-cli2", - "Node.js" - ] - } -} diff --git a/dist/index.js b/dist/index.js index 4a265d0..7638b7b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -15192,66 +15192,6 @@ function applyFixes(input, errors) { } module.exports.applyFixes = applyFixes; -/** - * Gets the range and fixInfo values for reporting an error if the expected - * text is found on the specified line. - * - * @param {string[]} lines Lines of Markdown content. - * @param {number} lineIndex Line index to check. - * @param {string} search Text to search for. - * @param {string} replace Text to replace with. - * @param {number} [instance] Instance on the line (1-based). - * @returns {Object} Range and fixInfo wrapper. - */ -module.exports.getRangeAndFixInfoIfFound = - (lines, lineIndex, search, replace, instance = 1) => { - let range = null; - let fixInfo = null; - let searchIndex = -1; - while (instance > 0) { - searchIndex = lines[lineIndex].indexOf(search, searchIndex + 1); - instance--; - } - if (searchIndex !== -1) { - const column = searchIndex + 1; - const length = search.length; - range = [ column, length ]; - fixInfo = { - "editColumn": column, - "deleteCount": length, - "insertText": replace - }; - } - return { - range, - fixInfo - }; - }; - -/** - * Gets the next (subsequent) child token if it is of the expected type. - * - * @param {Object} parentToken Parent token. - * @param {Object} childToken Child token basis. - * @param {string} nextType Token type of next token. - * @param {string} nextNextType Token type of next-next token. - * @returns {Object} Next token. - */ -function getNextChildToken(parentToken, childToken, nextType, nextNextType) { - const { children } = parentToken; - const index = children.indexOf(childToken); - if ( - (index !== -1) && - (children.length > index + 2) && - (children[index + 1].type === nextType) && - (children[index + 2].type === nextNextType) - ) { - return children[index + 1]; - } - return null; -} -module.exports.getNextChildToken = getNextChildToken; - /** * Expands a path with a tilde to an absolute path. * @@ -20262,7 +20202,7 @@ const resolveAndRequire = __nccwpck_require__(5317); // Variables const packageName = "markdownlint-cli2"; -const packageVersion = "0.7.1"; +const packageVersion = "0.8.1"; const libraryName = "markdownlint"; const libraryVersion = markdownlintLibrary.getVersion(); const dotOnlySubstitute = "*.{md,markdown}"; @@ -20324,8 +20264,11 @@ const importOrRequireResolve = async (dir, id) => { } catch (error) { errors.push(error); } - // Use AggregateError once available in Node 15+ - throw new Error(errors.map((error) => error.message).join(" / ")); + // @ts-ignore + throw new AggregateError( + errors, + `Unable to require or import module '${id}'.` + ); } return id; }; @@ -20415,7 +20358,7 @@ const removeIgnoredFiles = (dir, files, ignores) => { // Process/normalize command-line arguments and return glob patterns const processArgv = (argv) => { - const globPatterns = (argv || []).map( + const globPatterns = argv.map( (glob) => { if (glob.startsWith(":")) { return glob; @@ -20442,9 +20385,7 @@ const showHelp = (logMessage) => { /* eslint-disable max-len */ logMessage(`https://github.com/DavidAnson/markdownlint-cli2 -Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN] - markdownlint-cli2-fix glob0 [glob1] [...] [globN] - markdownlint-cli2-config config-file glob0 [glob1] [...] [globN] +Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN] [--config file] [--fix] Glob expressions (from the globby library): - * matches any number of characters, but not / @@ -20459,6 +20400,10 @@ Dot-only glob: - Instead, it is mapped to "markdownlint-cli2 ${dotOnlySubstitute}" which lints all Markdown files in the current directory - To lint every file in the current directory tree, the command "markdownlint-cli2 **" can be used instead +Optional parameters: +- --config specifies the path to a configuration file to define the base configuration +- --fix updates files to resolve fixable issues (can be overridden in configuration) + Configuration via: - .markdownlint-cli2.jsonc - .markdownlint-cli2.yaml @@ -21052,7 +20997,6 @@ const main = async (params) => { argv, optionsDefault, optionsOverride, - fixDefault, fileContents, nonFileContents, noErrors, @@ -21072,17 +21016,33 @@ const main = async (params) => { // eslint-disable-next-line max-len `${name || packageName} v${packageVersion} (${libraryName} v${libraryVersion})` ); + // Merge and process args/argv + let fixDefault = false; + // eslint-disable-next-line unicorn/no-useless-undefined + let configPath = undefined; + const argvFiltered = (argv || []).filter((arg) => { + if (configPath === null) { + configPath = arg; + return false; + } else if (arg === "--config") { + configPath = null; + return false; + } else if (arg === "--fix") { + fixDefault = true; + return false; + } + return true; + }); // Read argv configuration file (if relevant and present) let optionsArgv = null; let relativeDir = null; - const [ configPath ] = (argv || []); - if ((name === "markdownlint-cli2-config") && configPath) { + if (configPath) { optionsArgv = await readOptionsOrConfig(configPath, fs, noRequire); relativeDir = path.dirname(configPath); } // Process arguments and get base options - const globPatterns = processArgv(optionsArgv ? argv.slice(1) : argv); + const globPatterns = processArgv(argvFiltered); const { baseMarkdownlintOptions, dirToDirInfo } = await getBaseOptions( fs, @@ -21094,9 +21054,12 @@ const main = async (params) => { noGlobs, noRequire ); - if ((globPatterns.length === 0) && !nonFileContents) { + if ( + ((globPatterns.length === 0) && !nonFileContents) || + (configPath === null) + ) { showHelp(logMessage); - return 1; + return 2; } // Include any file overrides or non-file content const resolvedFileContents = {}; @@ -21155,11 +21118,13 @@ const main = async (params) => { }; // Run function -const run = (overrides) => { +const run = (overrides, args) => { (async () => { + const argsAndArgv = args || []; + appendToArray(argsAndArgv, process.argv.slice(2)); try { const defaultParams = { - "argv": process.argv.slice(2), + "argv": argsAndArgv, "logMessage": console.log, "logError": console.error }; @@ -21298,7 +21263,7 @@ module.exports.fixableRuleNames = [ "MD044", "MD047", "MD049", "MD050", "MD051", "MD053" ]; module.exports.homepage = "https://github.com/DavidAnson/markdownlint"; -module.exports.version = "0.28.2"; +module.exports.version = "0.29.0"; /***/ }), @@ -24468,7 +24433,7 @@ module.exports = { const { addErrorContext } = __nccwpck_require__(2935); -const { filterByPredicate, getHtmlTagInfo } = +const { filterByPredicate, getHtmlTagInfo, parse } = __nccwpck_require__(5673); module.exports = { @@ -24476,9 +24441,9 @@ module.exports = { "description": "Bare URL used", "tags": [ "links", "url" ], "function": function MD034(params, onError) { - const literalAutolinks = + const literalAutolinks = (tokens) => ( filterByPredicate( - params.parsers.micromark.tokens, + tokens, (token) => token.type === "literalAutolink", (token) => { const { children } = token; @@ -24508,26 +24473,33 @@ module.exports = { } } 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 - ); + } + ) + ); + if (literalAutolinks(params.parsers.micromark.tokens).length > 0) { + // Re-parse with correct link/image reference definition handling + const document = params.lines.join("\n"); + const tokens = parse(document, undefined, false); + for (const token of literalAutolinks(tokens)) { + 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 + ); + } } } }; @@ -24644,11 +24616,12 @@ const { addErrorContext, emphasisMarkersInContent, forEachLine, isBlankLine, const { htmlElementRanges, lineMetadata } = __nccwpck_require__(2260); const emphasisRe = /(^|[^\\]|\\\\)(?:(\*{1,3})|(_{1,3}))/g; -const embeddedUnderscoreRe = /([A-Za-z\d])_([A-Za-z\d])/g; +const embeddedUnderscoreRe = /([A-Za-z\d])(_([A-Za-z\d]))+/g; const asteriskListItemMarkerRe = /^([\s>]*)\*(\s+)/; const leftSpaceRe = /^\s+/; const rightSpaceRe = /\s+$/; const tablePipeRe = /\|/; +const allUnderscoresRe = /_/g; module.exports = { "names": [ "MD037", "no-space-in-emphasis" ], @@ -24739,7 +24712,10 @@ module.exports = { // Emphasis has no meaning here return; } - let patchedLine = line.replace(embeddedUnderscoreRe, "$1 $2"); + let patchedLine = line.replace( + embeddedUnderscoreRe, + (match) => match.replace(allUnderscoresRe, " ") + ); if (onItemStart) { // Trim overlapping '*' list item marker patchedLine = patchedLine.replace(asteriskListItemMarkerRe, "$1 $2"); @@ -24829,7 +24805,7 @@ module.exports = { const { addErrorContext } = __nccwpck_require__(2935); -const { filterByTypes } = __nccwpck_require__(5673); +const { filterByTypes, tokenIfType } = __nccwpck_require__(5673); const leftSpaceRe = /^\s(?:[^`]|$)/; const rightSpaceRe = /[^`]\s$/; @@ -24843,7 +24819,6 @@ const trimCodeText = (text, start, end) => { } return text; }; -const tokenIfType = (token, type) => token && (token.type === type) && token; module.exports = { "names": [ "MD038", "no-space-in-code" ], @@ -25229,7 +25204,7 @@ module.exports = { -const { addErrorDetailIf, escapeForRegExp, withinAnyRange } = +const { addErrorDetailIf, escapeForRegExp, newLineRe, withinAnyRange } = __nccwpck_require__(2935); const { filterByPredicate, filterByTypes, parse } = __nccwpck_require__(5673); @@ -25257,14 +25232,32 @@ module.exports = { scannedTypes.add("codeFlowValue"); scannedTypes.add("codeTextData"); } + const tokenAdjustments = new Map(); const contentTokens = filterByPredicate( params.parsers.micromark.tokens, (token) => scannedTypes.has(token.type), (token) => { let { children } = token; + const { startLine, text } = token; if (!includeHtmlElements && (token.type === "htmlFlow")) { - children = children.slice(1, -1); + if (text.startsWith("