mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02: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
|
@ -1,38 +1,44 @@
|
||||||
This rule is triggered for code spans that have content with spaces next to the
|
This rule is triggered for code spans containing content with unnecessary space
|
||||||
beginning or ending backticks:
|
next to the beginning or ending backticks:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text `
|
`some text `
|
||||||
|
|
||||||
` some text`
|
` some text`
|
||||||
|
|
||||||
|
` some text `
|
||||||
```
|
```
|
||||||
|
|
||||||
To fix this, remove any spaces at the beginning or ending:
|
To fix this, remove the extra space characters from the beginning and ending:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text`
|
`some text`
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Code spans containing only spaces are allowed by the specification:
|
Note: A single leading *and* trailing space is allowed by the specification and
|
||||||
|
trimmed by the parser to support code spans that begin or end with a backtick:
|
||||||
```markdown
|
|
||||||
` ` or ` `
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: A single leading and trailing space is allowed by the specification and
|
|
||||||
automatically trimmed by the parser (in order to allow for code spans that embed
|
|
||||||
backticks):
|
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` `backticks` ``
|
`` `backticks` ``
|
||||||
|
|
||||||
|
`` backtick` ``
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: A single leading or trailing space is allowed if used to separate code
|
Note: When single-space padding is present in the input, it will be preserved
|
||||||
span markers from an embedded backtick (though the space is not trimmed):
|
(even if unnecessary):
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` ` embedded backtick``
|
` code `
|
||||||
```
|
```
|
||||||
|
|
||||||
Rationale: Violations of this rule are usually unintentional and may lead to
|
Note: Code spans containing only spaces are allowed by the specification and are
|
||||||
|
also preserved:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
` `
|
||||||
|
|
||||||
|
` `
|
||||||
|
```
|
||||||
|
|
||||||
|
Rationale: Violations of this rule are usually unintentional and can lead to
|
||||||
improperly-rendered content.
|
improperly-rendered content.
|
||||||
|
|
38
doc/Rules.md
38
doc/Rules.md
|
@ -1528,43 +1528,49 @@ Aliases: `no-space-in-code`
|
||||||
|
|
||||||
Fixable: Some violations can be fixed by tooling
|
Fixable: Some violations can be fixed by tooling
|
||||||
|
|
||||||
This rule is triggered for code spans that have content with spaces next to the
|
This rule is triggered for code spans containing content with unnecessary space
|
||||||
beginning or ending backticks:
|
next to the beginning or ending backticks:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text `
|
`some text `
|
||||||
|
|
||||||
` some text`
|
` some text`
|
||||||
|
|
||||||
|
` some text `
|
||||||
```
|
```
|
||||||
|
|
||||||
To fix this, remove any spaces at the beginning or ending:
|
To fix this, remove the extra space characters from the beginning and ending:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text`
|
`some text`
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Code spans containing only spaces are allowed by the specification:
|
Note: A single leading *and* trailing space is allowed by the specification and
|
||||||
|
trimmed by the parser to support code spans that begin or end with a backtick:
|
||||||
```markdown
|
|
||||||
` ` or ` `
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: A single leading and trailing space is allowed by the specification and
|
|
||||||
automatically trimmed by the parser (in order to allow for code spans that embed
|
|
||||||
backticks):
|
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` `backticks` ``
|
`` `backticks` ``
|
||||||
|
|
||||||
|
`` backtick` ``
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: A single leading or trailing space is allowed if used to separate code
|
Note: When single-space padding is present in the input, it will be preserved
|
||||||
span markers from an embedded backtick (though the space is not trimmed):
|
(even if unnecessary):
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` ` embedded backtick``
|
` code `
|
||||||
```
|
```
|
||||||
|
|
||||||
Rationale: Violations of this rule are usually unintentional and may lead to
|
Note: Code spans containing only spaces are allowed by the specification and are
|
||||||
|
also preserved:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
` `
|
||||||
|
|
||||||
|
` `
|
||||||
|
```
|
||||||
|
|
||||||
|
Rationale: Violations of this rule are usually unintentional and can lead to
|
||||||
improperly-rendered content.
|
improperly-rendered content.
|
||||||
|
|
||||||
<a name="md039"></a>
|
<a name="md039"></a>
|
||||||
|
|
38
doc/md038.md
38
doc/md038.md
|
@ -6,41 +6,47 @@ Aliases: `no-space-in-code`
|
||||||
|
|
||||||
Fixable: Some violations can be fixed by tooling
|
Fixable: Some violations can be fixed by tooling
|
||||||
|
|
||||||
This rule is triggered for code spans that have content with spaces next to the
|
This rule is triggered for code spans containing content with unnecessary space
|
||||||
beginning or ending backticks:
|
next to the beginning or ending backticks:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text `
|
`some text `
|
||||||
|
|
||||||
` some text`
|
` some text`
|
||||||
|
|
||||||
|
` some text `
|
||||||
```
|
```
|
||||||
|
|
||||||
To fix this, remove any spaces at the beginning or ending:
|
To fix this, remove the extra space characters from the beginning and ending:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`some text`
|
`some text`
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Code spans containing only spaces are allowed by the specification:
|
Note: A single leading *and* trailing space is allowed by the specification and
|
||||||
|
trimmed by the parser to support code spans that begin or end with a backtick:
|
||||||
```markdown
|
|
||||||
` ` or ` `
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: A single leading and trailing space is allowed by the specification and
|
|
||||||
automatically trimmed by the parser (in order to allow for code spans that embed
|
|
||||||
backticks):
|
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` `backticks` ``
|
`` `backticks` ``
|
||||||
|
|
||||||
|
`` backtick` ``
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: A single leading or trailing space is allowed if used to separate code
|
Note: When single-space padding is present in the input, it will be preserved
|
||||||
span markers from an embedded backtick (though the space is not trimmed):
|
(even if unnecessary):
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`` ` embedded backtick``
|
` code `
|
||||||
```
|
```
|
||||||
|
|
||||||
Rationale: Violations of this rule are usually unintentional and may lead to
|
Note: Code spans containing only spaces are allowed by the specification and are
|
||||||
|
also preserved:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
` `
|
||||||
|
|
||||||
|
` `
|
||||||
|
```
|
||||||
|
|
||||||
|
Rationale: Violations of this rule are usually unintentional and can lead to
|
||||||
improperly-rendered content.
|
improperly-rendered content.
|
||||||
|
|
129
lib/md038.mjs
129
lib/md038.mjs
|
@ -1,23 +1,9 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
import { addErrorContext } from "../helpers/helpers.cjs";
|
import { addErrorContext, newLineRe } from "../helpers/helpers.cjs";
|
||||||
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
import { getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
||||||
import { filterByTypesCached } from "./cache.mjs";
|
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} */
|
/** @type {import("markdownlint").Rule} */
|
||||||
export default {
|
export default {
|
||||||
"names": [ "MD038", "no-space-in-code" ],
|
"names": [ "MD038", "no-space-in-code" ],
|
||||||
|
@ -27,68 +13,59 @@ export default {
|
||||||
"function": function MD038(params, onError) {
|
"function": function MD038(params, onError) {
|
||||||
const codeTexts = filterByTypesCached([ "codeText" ]);
|
const codeTexts = filterByTypesCached([ "codeText" ]);
|
||||||
for (const codeText of codeTexts) {
|
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 datas = getDescendantsByType(codeText, [ "codeTextData" ]);
|
||||||
const startData = datas[0];
|
if (datas.length > 0) {
|
||||||
const endData = datas[datas.length - 1];
|
const paddings = getDescendantsByType(codeText, [ "codeTextPadding" ]);
|
||||||
if (startSequence && endSequence && startData && endData) {
|
// Check for extra space at start of code
|
||||||
const spaceLeft = leftSpaceRe.test(startData.text);
|
const startPadding = paddings[0];
|
||||||
const spaceRight = rightSpaceRe.test(endData.text);
|
const startData = datas[0];
|
||||||
if (
|
const startMatch = /^(\s+)(\S)/.exec(startData.text) || [ null, "", "" ];
|
||||||
(spaceLeft || spaceRight) &&
|
const startBacktick = (startMatch[2] === "`");
|
||||||
!datas.every((data) => allSpaceRe.test(data.text))
|
const startCount = startMatch[1].length - ((startBacktick && !startPadding) ? 1 : 0);
|
||||||
) {
|
const startSpaces = startCount > 0;
|
||||||
let lineNumber = startSequence.startLine;
|
// Check for extra space at end of code
|
||||||
let range = undefined;
|
const endPadding = paddings[paddings.length - 1];
|
||||||
let fixInfo = undefined;
|
const endData = datas[datas.length - 1];
|
||||||
if (startSequence.startLine === endSequence.endLine) {
|
const endMatch = /(\S)(\s+)$/.exec(endData.text) || [ null, "", "" ];
|
||||||
range = [
|
const endBacktick = (endMatch[1] === "`");
|
||||||
startSequence.startColumn,
|
const endCount = endMatch[2].length - ((endBacktick && !endPadding) ? 1 : 0);
|
||||||
endSequence.endColumn - startSequence.startColumn
|
const endSpaces = endCount > 0;
|
||||||
];
|
// Check if safe to remove 1-space padding
|
||||||
fixInfo = {
|
const removePadding = startSpaces && endSpaces && startPadding && endPadding && !startBacktick && !endBacktick;
|
||||||
"editColumn": startSequence.endColumn,
|
const context = codeText.text.replace(newLineRe, "\n");
|
||||||
"deleteCount": endSequence.startColumn - startSequence.endColumn,
|
// If extra space at start, report violation
|
||||||
"insertText": trimCodeText(startData.text, true, true)
|
if (startSpaces) {
|
||||||
};
|
const startColumn = (removePadding ? startPadding : startData).startColumn;
|
||||||
} else if (spaceLeft && (startSequence.endLine === startData.startLine)) {
|
const length = startCount + (removePadding ? startPadding.text.length : 0);
|
||||||
range = [
|
addErrorContext(
|
||||||
startSequence.startColumn,
|
onError,
|
||||||
startData.endColumn - startSequence.startColumn
|
startData.startLine,
|
||||||
];
|
context,
|
||||||
fixInfo = {
|
true,
|
||||||
"editColumn": startSequence.endColumn,
|
false,
|
||||||
"deleteCount": startData.endColumn - startData.startColumn,
|
[ startColumn, length ],
|
||||||
"insertText": trimCodeText(startData.text, true, false)
|
{
|
||||||
};
|
"editColumn": startColumn,
|
||||||
} else if (spaceRight && (endData.text.trim().length > 0)) {
|
"deleteCount": length
|
||||||
lineNumber = endSequence.endLine;
|
}
|
||||||
range = [
|
);
|
||||||
endData.startColumn,
|
}
|
||||||
endSequence.endColumn - endData.startColumn
|
// If extra space at end, report violation
|
||||||
];
|
if (endSpaces) {
|
||||||
fixInfo = {
|
const endColumn = (removePadding ? endPadding : endData).endColumn;
|
||||||
"editColumn": endData.startColumn,
|
const length = endCount + (removePadding ? endPadding.text.length : 0);
|
||||||
"deleteCount": endData.endColumn - endData.startColumn,
|
addErrorContext(
|
||||||
"insertText": trimCodeText(endData.text, false, true)
|
onError,
|
||||||
};
|
endData.endLine,
|
||||||
}
|
context,
|
||||||
if (range) {
|
false,
|
||||||
const context = params
|
true,
|
||||||
.lines[lineNumber - 1]
|
[ endColumn - length, length ],
|
||||||
.substring(range[0] - 1, range[0] - 1 + range[1]);
|
{
|
||||||
addErrorContext(
|
"editColumn": endColumn - length,
|
||||||
onError,
|
"deleteCount": length
|
||||||
lineNumber,
|
}
|
||||||
context,
|
);
|
||||||
spaceLeft,
|
|
||||||
spaceRight,
|
|
||||||
range,
|
|
||||||
fixInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,6 @@
|
||||||
|
|
||||||
`` `code `` (fixed)
|
`` `code `` (fixed)
|
||||||
|
|
||||||
`` `code` `` {Could be MD038}
|
`` `code` `` {MD038}
|
||||||
|
|
||||||
`` `code` `` (fixed)
|
`` `code` `` (fixed)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -60,11 +60,11 @@ text and ``\`code with ignored escaped \` backticks``
|
||||||
|
|
||||||
` `` ` text `code`
|
` `` ` text `code`
|
||||||
|
|
||||||
``` ` leading space allowed for backtick``` text `code`
|
``` ` surrounding space allowed for backtick ``` text `code`
|
||||||
|
|
||||||
``` ` multiple leading spaces not allowed``` text `code` {MD038}
|
``` ` multiple leading spaces not allowed``` text `code` {MD038}
|
||||||
|
|
||||||
``trailing space allowed for backtick ` `` text `code`
|
`` surrounding space allowed for backtick ` `` text `code`
|
||||||
|
|
||||||
``multiple trailing spaces not allowed ` `` text `code` {MD038}
|
``multiple trailing spaces not allowed ` `` text `code` {MD038}
|
||||||
|
|
||||||
|
@ -126,13 +126,13 @@ Again, 2 characters: ` ab `
|
||||||
Again, 1 character: ` a `
|
Again, 1 character: ` a `
|
||||||
Many internal spaces: ` code code code code code code `
|
Many internal spaces: ` code code code code code code `
|
||||||
|
|
||||||
text ``` ` leading space
|
text ``` ` surrounding space
|
||||||
allowed for backtick``` text
|
allowed for backtick ``` text
|
||||||
|
|
||||||
text ``` ` multiple leading {MD038}
|
text ``` ` multiple leading {MD038}
|
||||||
spaces not allowed``` text
|
spaces not allowed``` text
|
||||||
|
|
||||||
text ``trailing space
|
text `` surrounding space
|
||||||
allowed for backtick ` `` text
|
allowed for backtick ` `` text
|
||||||
|
|
||||||
text ``multiple trailing spaces
|
text ``multiple trailing spaces
|
||||||
|
@ -150,7 +150,7 @@ Code
|
||||||
|
|
||||||
Text
|
Text
|
||||||
```
|
```
|
||||||
Code
|
Code {MD038}
|
||||||
```
|
```
|
||||||
|
|
||||||
Text
|
Text
|
||||||
|
@ -160,7 +160,7 @@ Code
|
||||||
|
|
||||||
Text
|
Text
|
||||||
```
|
```
|
||||||
Code
|
Code {MD038}
|
||||||
```
|
```
|
||||||
Text
|
Text
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue