Reimplement MD007/ul-indent using micromark tokens, reduce the length of fix edits (fixes #969).

This commit is contained in:
David Anson 2023-10-15 21:24:59 -07:00
parent cdf0818752
commit da17cec722
11 changed files with 1138 additions and 238 deletions

View file

@ -2,9 +2,8 @@
"use strict";
const { addErrorDetailIf, indentFor, listItemMarkerRe } =
require("../helpers");
const { flattenedLists } = require("./cache");
const { addErrorDetailIf } = require("../helpers");
const { filterByTypes } = require("../helpers/micromark.cjs");
module.exports = {
"names": [ "MD007", "ul-indent" ],
@ -14,34 +13,60 @@ module.exports = {
const indent = Number(params.config.indent || 2);
const startIndented = !!params.config.start_indented;
const startIndent = Number(params.config.start_indent || indent);
for (const list of flattenedLists()) {
if (list.unordered && list.parentsUnordered) {
for (const item of list.items) {
const { lineNumber, line } = item;
const expectedIndent =
(startIndented ? startIndent : 0) +
(list.nesting * indent);
const actualIndent = indentFor(item);
let range = null;
let editColumn = 1;
const match = line.match(listItemMarkerRe);
if (match) {
range = [ 1, match[0].length ];
editColumn += match[1].length - actualIndent;
const unorderedListNesting = new Map();
let lastBlockQuotePrefix = null;
const tokens = filterByTypes(
params.parsers.micromark.tokens,
[ "blockQuotePrefix", "listItemPrefix", "listUnordered" ]
);
for (const token of tokens) {
const { startColumn, startLine, type } = token;
if (type === "blockQuotePrefix") {
lastBlockQuotePrefix = token;
} else if (type === "listUnordered") {
let nesting = 0;
let current = token;
while ((current = current.parent())) {
if (current.type === "listUnordered") {
nesting++;
} else if (current.type === "listOrdered") {
nesting = -1;
break;
} else if (current.type === "blockQuote") {
break;
}
}
if (nesting >= 0) {
unorderedListNesting.set(token, nesting);
}
} else {
// listItemPrefix
const nesting = unorderedListNesting.get(token.parent());
if (nesting !== undefined) {
// listItemPrefix for listUnordered
const expectedIndent =
(startIndented ? startIndent : 0) + (nesting * indent);
const blockQuoteAdjustment =
(lastBlockQuotePrefix?.endLine === startLine) ?
(lastBlockQuotePrefix.endColumn - 1) :
0;
const actualIndent = startColumn - 1 - blockQuoteAdjustment;
const range = [ 1, startColumn + 1 ];
const fixInfo = {
"editColumn": startColumn - actualIndent,
"deleteCount": Math.max(actualIndent - expectedIndent, 0),
"insertText": "".padEnd(Math.max(expectedIndent - actualIndent, 0))
};
addErrorDetailIf(
onError,
lineNumber,
startLine,
expectedIndent,
actualIndent,
null,
null,
undefined,
undefined,
range,
{
editColumn,
"deleteCount": actualIndent,
"insertText": "".padEnd(expectedIndent)
});
fixInfo
);
}
}
}