diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index a6ed88ea..9158ffd8 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -4115,7 +4115,8 @@ module.exports = { -const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); +const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); +const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"); const dollarCommandRe = /^(\s*)(\$\s+)/; @@ -4125,47 +4126,45 @@ module.exports = { "names": [ "MD014", "commands-show-output" ], "description": "Dollar signs used before commands without showing output", "tags": [ "code" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD014(params, onError) { - for (const type of [ "code_block", "fence" ]) { - filterTokens(params, type, (token) => { - const margin = (token.type === "fence") ? 1 : 0; - const dollarInstances = []; - let allDollars = true; - for (let i = token.map[0] + margin; i < token.map[1] - margin; i++) { - const line = params.lines[i]; - const lineTrim = line.trim(); - if (lineTrim) { - const match = dollarCommandRe.exec(line); - if (match) { - const column = match[1].length + 1; - const length = match[2].length; - dollarInstances.push([ i, lineTrim, column, length ]); - } else { - allDollars = false; + const codeBlocks = filterByTypes( + params.parsers.micromark.tokens, + [ "codeFenced", "codeIndented" ] + ); + for (const codeBlock of codeBlocks) { + const codeFlowValues = filterByTypes( + codeBlock.children, + [ "codeFlowValue" ] + ); + const dollarMatches = codeFlowValues. + map((codeFlowValue) => ({ + "result": codeFlowValue.text.match(dollarCommandRe), + "startColumn": codeFlowValue.startColumn, + "startLine": codeFlowValue.startLine, + "text": codeFlowValue.text + })). + filter((dollarMatch) => dollarMatch.result); + if (dollarMatches.length === codeFlowValues.length) { + for (const dollarMatch of dollarMatches) { + // @ts-ignore + const column = dollarMatch.startColumn + dollarMatch.result[1].length; + // @ts-ignore + const length = dollarMatch.result[2].length; + addErrorContext( + onError, + dollarMatch.startLine, + dollarMatch.text, + undefined, + undefined, + [ column, length ], + { + "editColumn": column, + "deleteCount": length } - } + ); } - if (allDollars) { - for (const instance of dollarInstances) { - const [ i, lineTrim, column, length ] = instance; - addErrorContext( - onError, - // @ts-ignore - i + 1, - // @ts-ignore - lineTrim, - null, - null, - [ column, length ], - { - "editColumn": column, - "deleteCount": length - } - ); - } - } - }); + } } } }; diff --git a/lib/md014.js b/lib/md014.js index b78a4077..73af1556 100644 --- a/lib/md014.js +++ b/lib/md014.js @@ -2,7 +2,8 @@ "use strict"; -const { addErrorContext, filterTokens } = require("../helpers"); +const { addErrorContext } = require("../helpers"); +const { filterByTypes } = require("../helpers/micromark.cjs"); const dollarCommandRe = /^(\s*)(\$\s+)/; @@ -12,47 +13,45 @@ module.exports = { "names": [ "MD014", "commands-show-output" ], "description": "Dollar signs used before commands without showing output", "tags": [ "code" ], - "parser": "markdownit", + "parser": "micromark", "function": function MD014(params, onError) { - for (const type of [ "code_block", "fence" ]) { - filterTokens(params, type, (token) => { - const margin = (token.type === "fence") ? 1 : 0; - const dollarInstances = []; - let allDollars = true; - for (let i = token.map[0] + margin; i < token.map[1] - margin; i++) { - const line = params.lines[i]; - const lineTrim = line.trim(); - if (lineTrim) { - const match = dollarCommandRe.exec(line); - if (match) { - const column = match[1].length + 1; - const length = match[2].length; - dollarInstances.push([ i, lineTrim, column, length ]); - } else { - allDollars = false; + const codeBlocks = filterByTypes( + params.parsers.micromark.tokens, + [ "codeFenced", "codeIndented" ] + ); + for (const codeBlock of codeBlocks) { + const codeFlowValues = filterByTypes( + codeBlock.children, + [ "codeFlowValue" ] + ); + const dollarMatches = codeFlowValues. + map((codeFlowValue) => ({ + "result": codeFlowValue.text.match(dollarCommandRe), + "startColumn": codeFlowValue.startColumn, + "startLine": codeFlowValue.startLine, + "text": codeFlowValue.text + })). + filter((dollarMatch) => dollarMatch.result); + if (dollarMatches.length === codeFlowValues.length) { + for (const dollarMatch of dollarMatches) { + // @ts-ignore + const column = dollarMatch.startColumn + dollarMatch.result[1].length; + // @ts-ignore + const length = dollarMatch.result[2].length; + addErrorContext( + onError, + dollarMatch.startLine, + dollarMatch.text, + undefined, + undefined, + [ column, length ], + { + "editColumn": column, + "deleteCount": length } - } + ); } - if (allDollars) { - for (const instance of dollarInstances) { - const [ i, lineTrim, column, length ] = instance; - addErrorContext( - onError, - // @ts-ignore - i + 1, - // @ts-ignore - lineTrim, - null, - null, - [ column, length ], - { - "editColumn": column, - "deleteCount": length - } - ); - } - } - }); + } } } }; diff --git a/test/code_block_dollar.md b/test/code_block_dollar.md index 0d2fa40a..019d0c20 100644 --- a/test/code_block_dollar.md +++ b/test/code_block_dollar.md @@ -74,3 +74,7 @@ All commands with no output: $ mkdir test {MD014} $ cd test {MD014} $ ls test {MD014} + +Space-prefixed command with no output: + + $ ls example {MD014} diff --git a/test/code_block_dollar_fence.md b/test/code_block_dollar_fence.md index 1608075d..6f844b3e 100644 --- a/test/code_block_dollar_fence.md +++ b/test/code_block_dollar_fence.md @@ -40,4 +40,8 @@ text $ npm install --save multimatch {MD014} ``` -text +Space-prefixed command with no output: + +```sh + $ ls example {MD014} +``` diff --git a/test/snapshots/markdownlint-test-scenarios.js.md b/test/snapshots/markdownlint-test-scenarios.js.md index f86e4af9..80f04f82 100644 --- a/test/snapshots/markdownlint-test-scenarios.js.md +++ b/test/snapshots/markdownlint-test-scenarios.js.md @@ -10083,6 +10083,25 @@ Generated by [AVA](https://avajs.dev). 'commands-show-output', ], }, + { + errorContext: ' $ ls example {MD014}', + errorDetail: null, + errorRange: [ + 6, + 2, + ], + fixInfo: { + deleteCount: 2, + editColumn: 6, + }, + lineNumber: 80, + ruleDescription: 'Dollar signs used before commands without showing output', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md014.md', + ruleNames: [ + 'MD014', + 'commands-show-output', + ], + }, { errorContext: null, errorDetail: 'Expected: indented; Actual: fenced', @@ -10173,6 +10192,10 @@ Generated by [AVA](https://avajs.dev). mkdir test {MD014}␊ cd test {MD014}␊ ls test {MD014}␊ + ␊ + Space-prefixed command with no output:␊ + ␊ + ls example {MD014}␊ `, } @@ -10344,6 +10367,25 @@ Generated by [AVA](https://avajs.dev). 'commands-show-output', ], }, + { + errorContext: ' $ ls example {MD014}', + errorDetail: null, + errorRange: [ + 2, + 2, + ], + fixInfo: { + deleteCount: 2, + editColumn: 2, + }, + lineNumber: 46, + ruleDescription: 'Dollar signs used before commands without showing output', + ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md014.md', + ruleNames: [ + 'MD014', + 'commands-show-output', + ], + }, ], fixed: `# Code Block Dollar Fence␊ ␊ @@ -10387,7 +10429,11 @@ Generated by [AVA](https://avajs.dev). npm install --save multimatch {MD014}␊ \`\`\`␊ ␊ - text␊ + Space-prefixed command with no output:␊ + ␊ + \`\`\`sh␊ + ls example {MD014}␊ + \`\`\`␊ `, } diff --git a/test/snapshots/markdownlint-test-scenarios.js.snap b/test/snapshots/markdownlint-test-scenarios.js.snap index 6cb3f95f..ab01dc30 100644 Binary files a/test/snapshots/markdownlint-test-scenarios.js.snap and b/test/snapshots/markdownlint-test-scenarios.js.snap differ