mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-16 14:00:13 +01:00
Refactor MD038/no-space-in-code to produce smaller/simpler edits and address an additional scenario.
This commit is contained in:
parent
656254e64f
commit
b23fc96ab2
8 changed files with 699 additions and 610 deletions
129
lib/md038.mjs
129
lib/md038.mjs
|
|
@ -1,23 +1,9 @@
|
|||
// @ts-check
|
||||
|
||||
import { addErrorContext } from "../helpers/helpers.cjs";
|
||||
import { addErrorContext, newLineRe } from "../helpers/helpers.cjs";
|
||||
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
||||
import { filterByTypesCached } from "./cache.mjs";
|
||||
|
||||
const leftSpaceRe = /^\s(?:[^`]|$)/;
|
||||
const rightSpaceRe = /[^`]\s$/;
|
||||
const allSpaceRe = /^\s*$/;
|
||||
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;
|
||||
};
|
||||
|
||||
/** @type {import("markdownlint").Rule} */
|
||||
export default {
|
||||
"names": [ "MD038", "no-space-in-code" ],
|
||||
|
|
@ -27,68 +13,59 @@ export default {
|
|||
"function": function MD038(params, onError) {
|
||||
const codeTexts = filterByTypesCached([ "codeText" ]);
|
||||
for (const codeText of codeTexts) {
|
||||
const sequences = getDescendantsByType(codeText, [ "codeTextSequence" ]);
|
||||
const startSequence = sequences[0];
|
||||
const endSequence = sequences[sequences.length - 1];
|
||||
const datas = getDescendantsByType(codeText, [ "codeTextData" ]);
|
||||
const startData = datas[0];
|
||||
const endData = datas[datas.length - 1];
|
||||
if (startSequence && endSequence && startData && endData) {
|
||||
const spaceLeft = leftSpaceRe.test(startData.text);
|
||||
const spaceRight = rightSpaceRe.test(endData.text);
|
||||
if (
|
||||
(spaceLeft || spaceRight) &&
|
||||
!datas.every((data) => allSpaceRe.test(data.text))
|
||||
) {
|
||||
let lineNumber = startSequence.startLine;
|
||||
let range = undefined;
|
||||
let fixInfo = undefined;
|
||||
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 && (startSequence.endLine === startData.startLine)) {
|
||||
range = [
|
||||
startSequence.startColumn,
|
||||
startData.endColumn - startSequence.startColumn
|
||||
];
|
||||
fixInfo = {
|
||||
"editColumn": startSequence.endColumn,
|
||||
"deleteCount": startData.endColumn - startData.startColumn,
|
||||
"insertText": trimCodeText(startData.text, true, false)
|
||||
};
|
||||
} else if (spaceRight && (endData.text.trim().length > 0)) {
|
||||
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)
|
||||
};
|
||||
}
|
||||
if (range) {
|
||||
const context = params
|
||||
.lines[lineNumber - 1]
|
||||
.substring(range[0] - 1, range[0] - 1 + range[1]);
|
||||
addErrorContext(
|
||||
onError,
|
||||
lineNumber,
|
||||
context,
|
||||
spaceLeft,
|
||||
spaceRight,
|
||||
range,
|
||||
fixInfo
|
||||
);
|
||||
}
|
||||
if (datas.length > 0) {
|
||||
const paddings = getDescendantsByType(codeText, [ "codeTextPadding" ]);
|
||||
// Check for extra space at start of code
|
||||
const startPadding = paddings[0];
|
||||
const startData = datas[0];
|
||||
const startMatch = /^(\s+)(\S)/.exec(startData.text) || [ null, "", "" ];
|
||||
const startBacktick = (startMatch[2] === "`");
|
||||
const startCount = startMatch[1].length - ((startBacktick && !startPadding) ? 1 : 0);
|
||||
const startSpaces = startCount > 0;
|
||||
// Check for extra space at end of code
|
||||
const endPadding = paddings[paddings.length - 1];
|
||||
const endData = datas[datas.length - 1];
|
||||
const endMatch = /(\S)(\s+)$/.exec(endData.text) || [ null, "", "" ];
|
||||
const endBacktick = (endMatch[1] === "`");
|
||||
const endCount = endMatch[2].length - ((endBacktick && !endPadding) ? 1 : 0);
|
||||
const endSpaces = endCount > 0;
|
||||
// Check if safe to remove 1-space padding
|
||||
const removePadding = startSpaces && endSpaces && startPadding && endPadding && !startBacktick && !endBacktick;
|
||||
const context = codeText.text.replace(newLineRe, "\n");
|
||||
// If extra space at start, report violation
|
||||
if (startSpaces) {
|
||||
const startColumn = (removePadding ? startPadding : startData).startColumn;
|
||||
const length = startCount + (removePadding ? startPadding.text.length : 0);
|
||||
addErrorContext(
|
||||
onError,
|
||||
startData.startLine,
|
||||
context,
|
||||
true,
|
||||
false,
|
||||
[ startColumn, length ],
|
||||
{
|
||||
"editColumn": startColumn,
|
||||
"deleteCount": length
|
||||
}
|
||||
);
|
||||
}
|
||||
// If extra space at end, report violation
|
||||
if (endSpaces) {
|
||||
const endColumn = (removePadding ? endPadding : endData).endColumn;
|
||||
const length = endCount + (removePadding ? endPadding.text.length : 0);
|
||||
addErrorContext(
|
||||
onError,
|
||||
endData.endLine,
|
||||
context,
|
||||
false,
|
||||
true,
|
||||
[ endColumn - length, length ],
|
||||
{
|
||||
"editColumn": endColumn - length,
|
||||
"deleteCount": length
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue