2018-01-21 21:44:25 -08:00
|
|
|
// @ts-check
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
2019-03-28 22:06:42 -07:00
|
|
|
const { addErrorDetailIf, filterTokens, forEachHeading, forEachLine,
|
2019-12-12 21:22:45 -08:00
|
|
|
includesSorted } = require("../helpers");
|
2019-04-10 21:26:59 -07:00
|
|
|
const { lineMetadata } = require("./cache");
|
2018-01-21 21:44:25 -08:00
|
|
|
|
2019-12-12 21:22:45 -08:00
|
|
|
const longLineRePrefix = "^.{";
|
|
|
|
const longLineRePostfixRelaxed = "}.*\\s.*$";
|
|
|
|
const longLineRePostfixStrict = "}.+$";
|
2018-04-27 22:05:34 -07:00
|
|
|
const labelRe = /^\s*\[.*[^\\]]:/;
|
2020-01-24 21:50:50 -08:00
|
|
|
const linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/;
|
2019-03-26 22:34:19 -07:00
|
|
|
const tokenTypeMap = {
|
|
|
|
"em_open": "e",
|
|
|
|
"em_close": "E",
|
2020-01-24 21:50:50 -08:00
|
|
|
"image": "I",
|
2019-03-26 22:34:19 -07:00
|
|
|
"link_open": "l",
|
|
|
|
"link_close": "L",
|
|
|
|
"strong_open": "s",
|
|
|
|
"strong_close": "S",
|
|
|
|
"text": "T"
|
|
|
|
};
|
2018-01-21 21:44:25 -08:00
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
"names": [ "MD013", "line-length" ],
|
|
|
|
"description": "Line length",
|
|
|
|
"tags": [ "line_length" ],
|
|
|
|
"function": function MD013(params, onError) {
|
2018-04-27 22:05:34 -07:00
|
|
|
const lineLength = params.config.line_length || 80;
|
2019-03-26 22:34:19 -07:00
|
|
|
const headingLineLength = params.config.heading_line_length || lineLength;
|
2019-06-07 19:57:15 -07:00
|
|
|
const codeLineLength = params.config.code_block_line_length || lineLength;
|
2019-12-12 21:22:45 -08:00
|
|
|
const strict = !!params.config.strict;
|
|
|
|
const longLineRePostfix =
|
|
|
|
strict ? longLineRePostfixStrict : longLineRePostfixRelaxed;
|
2019-03-26 22:34:19 -07:00
|
|
|
const longLineRe =
|
|
|
|
new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
|
|
|
|
const longHeadingLineRe =
|
|
|
|
new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
|
2019-06-07 19:57:15 -07:00
|
|
|
const longCodeLineRe =
|
|
|
|
new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix);
|
2018-04-27 22:05:34 -07:00
|
|
|
const codeBlocks = params.config.code_blocks;
|
|
|
|
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
|
|
|
|
const tables = params.config.tables;
|
|
|
|
const includeTables = (tables === undefined) ? true : !!tables;
|
|
|
|
let headings = params.config.headings;
|
2018-03-19 23:39:42 +01:00
|
|
|
if (headings === undefined) {
|
|
|
|
headings = params.config.headers;
|
|
|
|
}
|
2018-04-27 22:05:34 -07:00
|
|
|
const includeHeadings = (headings === undefined) ? true : !!headings;
|
|
|
|
const headingLineNumbers = [];
|
2019-03-26 22:34:19 -07:00
|
|
|
forEachHeading(params, (heading) => {
|
|
|
|
headingLineNumbers.push(heading.lineNumber);
|
|
|
|
});
|
2018-04-27 22:05:34 -07:00
|
|
|
const linkOnlyLineNumbers = [];
|
2019-03-26 22:34:19 -07:00
|
|
|
filterTokens(params, "inline", (token) => {
|
2018-04-27 22:05:34 -07:00
|
|
|
let childTokenTypes = "";
|
2019-03-26 22:34:19 -07:00
|
|
|
token.children.forEach((child) => {
|
2018-01-21 21:44:25 -08:00
|
|
|
if (child.type !== "text" || child.content !== "") {
|
|
|
|
childTokenTypes += tokenTypeMap[child.type] || "x";
|
|
|
|
}
|
|
|
|
});
|
2020-01-24 21:50:50 -08:00
|
|
|
if (linkOrImageOnlyLineRe.test(childTokenTypes)) {
|
2018-01-21 21:44:25 -08:00
|
|
|
linkOnlyLineNumbers.push(token.lineNumber);
|
|
|
|
}
|
|
|
|
});
|
2019-04-10 21:26:59 -07:00
|
|
|
forEachLine(lineMetadata(), (line, lineIndex, inCode, onFence, inTable) => {
|
2019-03-26 22:34:19 -07:00
|
|
|
const lineNumber = lineIndex + 1;
|
2019-03-28 22:06:42 -07:00
|
|
|
const isHeading = includesSorted(headingLineNumbers, lineNumber);
|
2019-06-07 19:57:15 -07:00
|
|
|
const length = inCode ?
|
|
|
|
codeLineLength :
|
|
|
|
(isHeading ? headingLineLength : lineLength);
|
|
|
|
const lengthRe = inCode ?
|
|
|
|
longCodeLineRe :
|
|
|
|
(isHeading ? longHeadingLineRe : longLineRe);
|
2019-03-26 22:34:19 -07:00
|
|
|
if ((includeCodeBlocks || !inCode) &&
|
|
|
|
(includeTables || !inTable) &&
|
|
|
|
(includeHeadings || !isHeading) &&
|
2019-12-12 21:22:45 -08:00
|
|
|
(strict ||
|
|
|
|
(!includesSorted(linkOnlyLineNumbers, lineNumber) &&
|
|
|
|
!labelRe.test(line))) &&
|
|
|
|
lengthRe.test(line)) {
|
|
|
|
addErrorDetailIf(
|
|
|
|
onError,
|
|
|
|
lineNumber,
|
|
|
|
length,
|
|
|
|
line.length,
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
[ length + 1, line.length - length ]);
|
2019-03-26 22:34:19 -07:00
|
|
|
}
|
|
|
|
});
|
2018-01-21 21:44:25 -08:00
|
|
|
}
|
|
|
|
};
|