mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-24 01:40:13 +01:00
Reimplement MD013/line-length using micromark tokens.
This commit is contained in:
parent
4072cf7417
commit
3b581a7f6d
10 changed files with 173 additions and 185 deletions
78
lib/md013.js
78
lib/md013.js
|
|
@ -2,25 +2,14 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
||||
includesSorted } = require("../helpers");
|
||||
const { lineMetadata, referenceLinkImageData } = require("./cache");
|
||||
const { addErrorDetailIf } = require("../helpers");
|
||||
const { referenceLinkImageData } = require("./cache");
|
||||
const { addRangeToSet, filterByTypes, getDescendantsByType } = require("../helpers/micromark.cjs");
|
||||
|
||||
const longLineRePrefix = "^.{";
|
||||
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
||||
const longLineRePostfixStrict = "}.+$";
|
||||
const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/;
|
||||
const sternModeRe = /^(?:[#>\s]*\s)?\S*$/;
|
||||
const tokenTypeMap = {
|
||||
"em_open": "e",
|
||||
"em_close": "E",
|
||||
"image": "I",
|
||||
"link_open": "l",
|
||||
"link_close": "L",
|
||||
"strong_open": "s",
|
||||
"strong_close": "S",
|
||||
"text": "T"
|
||||
};
|
||||
|
||||
// eslint-disable-next-line jsdoc/valid-types
|
||||
/** @type import("./markdownlint").Rule */
|
||||
|
|
@ -28,7 +17,7 @@ module.exports = {
|
|||
"names": [ "MD013", "line-length" ],
|
||||
"description": "Line length",
|
||||
"tags": [ "line_length" ],
|
||||
"parser": "markdownit",
|
||||
"parser": "micromark",
|
||||
"function": function MD013(params, onError) {
|
||||
const lineLength = Number(params.config.line_length || 80);
|
||||
const headingLineLength =
|
||||
|
|
@ -51,26 +40,42 @@ module.exports = {
|
|||
const includeTables = (tables === undefined) ? true : !!tables;
|
||||
const headings = params.config.headings;
|
||||
const includeHeadings = (headings === undefined) ? true : !!headings;
|
||||
const headingLineNumbers = [];
|
||||
forEachHeading(params, (heading) => {
|
||||
headingLineNumbers.push(heading.lineNumber);
|
||||
});
|
||||
const linkOnlyLineNumbers = [];
|
||||
filterTokens(params, "inline", (token) => {
|
||||
let childTokenTypes = "";
|
||||
for (const child of token.children) {
|
||||
if (child.type !== "text" || child.content !== "") {
|
||||
childTokenTypes += tokenTypeMap[child.type] || "x";
|
||||
}
|
||||
const { tokens } = params.parsers.micromark;
|
||||
const headingLineNumbers = new Set();
|
||||
for (const heading of filterByTypes(tokens, [ "atxHeading", "setextHeading" ])) {
|
||||
addRangeToSet(headingLineNumbers, heading.startLine, heading.endLine);
|
||||
}
|
||||
const codeBlockLineNumbers = new Set();
|
||||
for (const codeBlock of filterByTypes(tokens, [ "codeFenced", "codeIndented" ])) {
|
||||
addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine);
|
||||
}
|
||||
const tableLineNumbers = new Set();
|
||||
for (const table of filterByTypes(tokens, [ "table" ])) {
|
||||
addRangeToSet(tableLineNumbers, table.startLine, table.endLine);
|
||||
}
|
||||
const linkLineNumbers = new Set();
|
||||
for (const link of filterByTypes(tokens, [ "autolink", "image", "link", "literalAutolink" ])) {
|
||||
addRangeToSet(linkLineNumbers, link.startLine, link.endLine);
|
||||
}
|
||||
const paragraphDataLineNumbers = new Set();
|
||||
for (const paragraph of filterByTypes(tokens, [ "paragraph" ])) {
|
||||
for (const data of getDescendantsByType(paragraph, [ "data" ])) {
|
||||
addRangeToSet(paragraphDataLineNumbers, data.startLine, data.endLine);
|
||||
}
|
||||
if (linkOrImageOnlyLineRe.test(childTokenTypes)) {
|
||||
linkOnlyLineNumbers.push(token.lineNumber);
|
||||
}
|
||||
const linkOnlyLineNumbers = new Set();
|
||||
for (const lineNumber of linkLineNumbers) {
|
||||
if (!paragraphDataLineNumbers.has(lineNumber)) {
|
||||
linkOnlyLineNumbers.add(lineNumber);
|
||||
}
|
||||
});
|
||||
const { definitionLineIndices } = referenceLinkImageData();
|
||||
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
|
||||
}
|
||||
const definitionLineIndices = new Set(referenceLinkImageData().definitionLineIndices);
|
||||
for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) {
|
||||
const line = params.lines[lineIndex];
|
||||
const lineNumber = lineIndex + 1;
|
||||
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
||||
const isHeading = headingLineNumbers.has(lineNumber);
|
||||
const inCode = codeBlockLineNumbers.has(lineNumber);
|
||||
const inTable = tableLineNumbers.has(lineNumber);
|
||||
const length = inCode ?
|
||||
codeLineLength :
|
||||
(isHeading ? headingLineLength : lineLength);
|
||||
|
|
@ -80,10 +85,10 @@ module.exports = {
|
|||
if ((includeCodeBlocks || !inCode) &&
|
||||
(includeTables || !inTable) &&
|
||||
(includeHeadings || !isHeading) &&
|
||||
!includesSorted(definitionLineIndices, lineIndex) &&
|
||||
!definitionLineIndices.has(lineIndex) &&
|
||||
(strict ||
|
||||
(!(stern && sternModeRe.test(line)) &&
|
||||
!includesSorted(linkOnlyLineNumbers, lineNumber))) &&
|
||||
!linkOnlyLineNumbers.has(lineNumber))) &&
|
||||
lengthRe.test(line)) {
|
||||
addErrorDetailIf(
|
||||
onError,
|
||||
|
|
@ -92,8 +97,9 @@ module.exports = {
|
|||
line.length,
|
||||
undefined,
|
||||
undefined,
|
||||
[ length + 1, line.length - length ]);
|
||||
[ length + 1, line.length - length ]
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue