Reimplement MD030/list-marker-space using micromark tokens, improve range accuracy.

This commit is contained in:
David Anson 2023-10-10 22:03:18 -07:00
parent 0c4b89c4af
commit e89ff6ea98
4 changed files with 79 additions and 60 deletions

View file

@ -3,7 +3,7 @@
"use strict";
const { addErrorDetailIf } = require("../helpers");
const { flattenedLists } = require("./cache");
const { filterByTypes } = require("../helpers/micromark.cjs");
module.exports = {
"names": [ "MD030", "list-marker-space" ],
@ -14,33 +14,44 @@ module.exports = {
const olSingle = Number(params.config.ol_single || 1);
const ulMulti = Number(params.config.ul_multi || 1);
const olMulti = Number(params.config.ol_multi || 1);
for (const list of flattenedLists()) {
const lineCount = list.lastLineIndex - list.open.map[0];
const allSingle = lineCount === list.items.length;
const expectedSpaces = list.unordered ?
(allSingle ? ulSingle : ulMulti) :
(allSingle ? olSingle : olMulti);
for (const item of list.items) {
const { line, lineNumber } = item;
const match = /^[\s>]*\S+(\s*)/.exec(line);
const [ { "length": matchLength }, { "length": actualSpaces } ] = match;
if (matchLength < line.length) {
let fixInfo = null;
if (expectedSpaces !== actualSpaces) {
fixInfo = {
"editColumn": matchLength - actualSpaces + 1,
"deleteCount": actualSpaces,
"insertText": "".padEnd(expectedSpaces)
};
}
const lists = filterByTypes(
params.parsers.micromark.tokens,
[ "listOrdered", "listUnordered" ]
);
for (const list of lists) {
const ordered = (list.type === "listOrdered");
const listItemPrefixes =
list.children.filter((token) => (token.type === "listItemPrefix"));
const allSingleLine =
(list.endLine - list.startLine + 1) === listItemPrefixes.length;
const expectedSpaces = ordered ?
(allSingleLine ? olSingle : olMulti) :
(allSingleLine ? ulSingle : ulMulti);
for (const listItemPrefix of listItemPrefixes) {
const range = [
listItemPrefix.startColumn,
listItemPrefix.endColumn - listItemPrefix.startColumn
];
const listItemPrefixWhitespaces = listItemPrefix.children.filter(
(token) => (token.type === "listItemPrefixWhitespace")
);
for (const listItemPrefixWhitespace of listItemPrefixWhitespaces) {
const { endColumn, startColumn, startLine } =
listItemPrefixWhitespace;
const actualSpaces = endColumn - startColumn;
const fixInfo = {
"editColumn": startColumn,
"deleteCount": actualSpaces,
"insertText": "".padEnd(expectedSpaces)
};
addErrorDetailIf(
onError,
lineNumber,
startLine,
expectedSpaces,
actualSpaces,
null,
null,
[ 1, matchLength ],
range,
fixInfo
);
}