Update MD010/no-hard-tabs to allow tabs in code spans when the code_blocks parameter is set to false (for consistency) (fixes #454).

This commit is contained in:
David Anson 2021-12-17 17:24:00 -08:00
parent 0d9dfe7120
commit d57b4770ed
6 changed files with 110 additions and 33 deletions

View file

@ -551,7 +551,7 @@ module.exports.codeBlockAndSpanRanges = function (params, lineMetadata) {
// Add code block ranges (excludes fences) // Add code block ranges (excludes fences)
forEachLine(lineMetadata, function (line, lineIndex, inCode, onFence) { forEachLine(lineMetadata, function (line, lineIndex, inCode, onFence) {
if (inCode && !onFence) { if (inCode && !onFence) {
exclusions.push(lineIndex, 0, line.length); exclusions.push([lineIndex, 0, line.length]);
} }
}); });
// Add code span ranges (excludes ticks) // Add code span ranges (excludes ticks)
@ -2326,8 +2326,8 @@ module.exports = {
"use strict"; "use strict";
// @ts-check // @ts-check
var _a = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addError = _a.addError, forEachLine = _a.forEachLine; var _a = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addError = _a.addError, forEachLine = _a.forEachLine, overlapsAnyRange = _a.overlapsAnyRange;
var lineMetadata = __webpack_require__(/*! ./cache */ "../lib/cache.js").lineMetadata; var _b = __webpack_require__(/*! ./cache */ "../lib/cache.js"), codeBlockAndSpanRanges = _b.codeBlockAndSpanRanges, lineMetadata = _b.lineMetadata;
var tabRe = /\t+/g; var tabRe = /\t+/g;
module.exports = { module.exports = {
"names": ["MD010", "no-hard-tabs"], "names": ["MD010", "no-hard-tabs"],
@ -2335,22 +2335,26 @@ module.exports = {
"tags": ["whitespace", "hard_tab"], "tags": ["whitespace", "hard_tab"],
"function": function MD010(params, onError) { "function": function MD010(params, onError) {
var codeBlocks = params.config.code_blocks; var codeBlocks = params.config.code_blocks;
var includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks; var includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
var spacesPerTab = params.config.spaces_per_tab; var spacesPerTab = params.config.spaces_per_tab;
var spaceMultiplier = (spacesPerTab === undefined) ? var spaceMultiplier = (spacesPerTab === undefined) ?
1 : 1 :
Math.max(0, Number(spacesPerTab)); Math.max(0, Number(spacesPerTab));
var exclusions = includeCode ? [] : codeBlockAndSpanRanges();
forEachLine(lineMetadata(), function (line, lineIndex, inCode) { forEachLine(lineMetadata(), function (line, lineIndex, inCode) {
if (!inCode || includeCodeBlocks) { if (includeCode || !inCode) {
var match = null; var match = null;
while ((match = tabRe.exec(line)) !== null) { while ((match = tabRe.exec(line)) !== null) {
var column = match.index + 1; var index = match.index;
var column = index + 1;
var length = match[0].length; var length = match[0].length;
addError(onError, lineIndex + 1, "Column: " + column, null, [column, length], { if (!overlapsAnyRange(exclusions, lineIndex, index, length)) {
"editColumn": column, addError(onError, lineIndex + 1, "Column: " + column, null, [column, length], {
"deleteCount": length, "editColumn": column,
"insertText": "".padEnd(length * spaceMultiplier) "deleteCount": length,
}); "insertText": "".padEnd(length * spaceMultiplier)
});
}
} }
} }
}); });

View file

@ -424,12 +424,14 @@ Some text
* Spaces used to indent the list item instead * Spaces used to indent the list item instead
``` ```
You have the option to exclude this rule for code blocks. To do so, set the You have the option to exclude this rule for code blocks and spans. To do so,
`code_blocks` parameter to `false`. Code blocks are included by default since set the `code_blocks` parameter to `false`. Code blocks and spans are included
handling of tabs by tools is often inconsistent (ex: using 4 vs. 8 spaces). by default since handling of tabs by Markdown tools can be inconsistent (e.g.,
using 4 vs. 8 spaces).
If you would like the fixer to change tabs to x spaces, then configure the `spaces_per_tab` By default, violations of this rule are fixed by replacing the tab with 1 space
parameter to the number x. The default value would be 1. character. To use a different number of spaces, set the `spaces_per_tab`
parameter to the desired value.
Rationale: Hard tabs are often rendered inconsistently by different editors and Rationale: Hard tabs are often rendered inconsistently by different editors and
can be harder to work with than spaces. can be harder to work with than spaces.

View file

@ -555,7 +555,7 @@ module.exports.codeBlockAndSpanRanges = (params, lineMetadata) => {
// Add code block ranges (excludes fences) // Add code block ranges (excludes fences)
forEachLine(lineMetadata, (line, lineIndex, inCode, onFence) => { forEachLine(lineMetadata, (line, lineIndex, inCode, onFence) => {
if (inCode && !onFence) { if (inCode && !onFence) {
exclusions.push(lineIndex, 0, line.length); exclusions.push([ lineIndex, 0, line.length ]);
} }
}); });
// Add code span ranges (excludes ticks) // Add code span ranges (excludes ticks)

View file

@ -2,8 +2,8 @@
"use strict"; "use strict";
const { addError, forEachLine } = require("../helpers"); const { addError, forEachLine, overlapsAnyRange } = require("../helpers");
const { lineMetadata } = require("./cache"); const { codeBlockAndSpanRanges, lineMetadata } = require("./cache");
const tabRe = /\t+/g; const tabRe = /\t+/g;
@ -13,28 +13,33 @@ module.exports = {
"tags": [ "whitespace", "hard_tab" ], "tags": [ "whitespace", "hard_tab" ],
"function": function MD010(params, onError) { "function": function MD010(params, onError) {
const codeBlocks = params.config.code_blocks; const codeBlocks = params.config.code_blocks;
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks; const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks;
const spacesPerTab = params.config.spaces_per_tab; const spacesPerTab = params.config.spaces_per_tab;
const spaceMultiplier = (spacesPerTab === undefined) ? const spaceMultiplier = (spacesPerTab === undefined) ?
1 : 1 :
Math.max(0, Number(spacesPerTab)); Math.max(0, Number(spacesPerTab));
const exclusions = includeCode ? [] : codeBlockAndSpanRanges();
forEachLine(lineMetadata(), (line, lineIndex, inCode) => { forEachLine(lineMetadata(), (line, lineIndex, inCode) => {
if (!inCode || includeCodeBlocks) { if (includeCode || !inCode) {
let match = null; let match = null;
while ((match = tabRe.exec(line)) !== null) { while ((match = tabRe.exec(line)) !== null) {
const column = match.index + 1; const { index } = match;
const column = index + 1;
const length = match[0].length; const length = match[0].length;
addError( if (!overlapsAnyRange(exclusions, lineIndex, index, length)) {
onError, addError(
lineIndex + 1, onError,
"Column: " + column, lineIndex + 1,
null, "Column: " + column,
[ column, length ], null,
{ [ column, length ],
"editColumn": column, {
"deleteCount": length, "editColumn": column,
"insertText": "".padEnd(length * spaceMultiplier) "deleteCount": length,
}); "insertText": "".padEnd(length * spaceMultiplier)
}
);
}
} }
} }
}); });

View file

@ -0,0 +1,33 @@
# Code With Tabs Allowed
Text text {MD010}
Text `code code` text
Text ` code` text
Text `code ` text
Text `code code
code code
code code` text
console.log(" ");
```js
console.log(" ");
```
```j s {MD010}
console.log(" ");
```
console.log("");
<!-- markdownlint-configure-file {
"code-block-style": false,
"no-space-in-code": false,
"no-hard-tabs": {
"code_blocks": false
}
} -->

View file

@ -0,0 +1,33 @@
# Code With Tabs Blocked
Text text {MD010}
Text `code code` text {MD010}
Text ` code` text {MD010}
Text `code ` text {MD010}
Text `code code
code code {MD010}
code code` text
console.log(" "); // {MD010}
```js
console.log(" "); // {MD010}
```
```j s {MD010}
console.log(" "); // {MD010}
```
console.log(""); // {MD010}
<!-- markdownlint-configure-file {
"code-block-style": false,
"no-space-in-code": false,
"no-hard-tabs": {
"code_blocks": true
}
} -->