Update MD013/line-length with heading_line_length parameter (fixes #170).

This commit is contained in:
David Anson 2019-03-26 22:34:19 -07:00
parent fa04d29485
commit d7c0d195d7
9 changed files with 110 additions and 40 deletions

View file

@ -3,8 +3,23 @@
"use strict";
const shared = require("./shared");
const {
addErrorDetailIf, filterTokens, forEachHeading, forEachLine, rangeFromRegExp
} = shared;
const longLineRePrefix = "^(.{";
const longLineRePostfix = "})(.*\\s.*)$";
const labelRe = /^\s*\[.*[^\\]]:/;
const linkOnlyLineRe = /^[es]*lT?L[ES]*$/;
const tokenTypeMap = {
"em_open": "e",
"em_close": "E",
"link_open": "l",
"link_close": "L",
"strong_open": "s",
"strong_close": "S",
"text": "T"
};
module.exports = {
"names": [ "MD013", "line-length" ],
@ -12,6 +27,11 @@ module.exports = {
"tags": [ "line_length" ],
"function": function MD013(params, onError) {
const lineLength = params.config.line_length || 80;
const headingLineLength = params.config.heading_line_length || lineLength;
const longLineRe =
new RegExp(longLineRePrefix + lineLength + longLineRePostfix);
const longHeadingLineRe =
new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix);
const codeBlocks = params.config.code_blocks;
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
const tables = params.config.tables;
@ -22,45 +42,35 @@ module.exports = {
}
const includeHeadings = (headings === undefined) ? true : !!headings;
const headingLineNumbers = [];
if (!includeHeadings) {
shared.forEachHeading(params, function forHeading(heading) {
headingLineNumbers.push(heading.lineNumber);
});
}
const tokenTypeMap = {
"em_open": "e",
"em_close": "E",
"link_open": "l",
"link_close": "L",
"strong_open": "s",
"strong_close": "S",
"text": "T"
};
forEachHeading(params, (heading) => {
headingLineNumbers.push(heading.lineNumber);
});
const linkOnlyLineNumbers = [];
shared.filterTokens(params, "inline", function forToken(token) {
filterTokens(params, "inline", (token) => {
let childTokenTypes = "";
token.children.forEach(function forChild(child) {
token.children.forEach((child) => {
if (child.type !== "text" || child.content !== "") {
childTokenTypes += tokenTypeMap[child.type] || "x";
}
});
if (/^[es]*lT?L[ES]*$/.test(childTokenTypes)) {
if (linkOnlyLineRe.test(childTokenTypes)) {
linkOnlyLineNumbers.push(token.lineNumber);
}
});
const longLineRe = new RegExp("^(.{" + lineLength + "})(.*\\s.*)$");
shared.forEachLine(
function forLine(line, lineIndex, inCode, onFence, inTable) {
const lineNumber = lineIndex + 1;
if ((includeCodeBlocks || !inCode) &&
(includeTables || !inTable) &&
(includeHeadings || (headingLineNumbers.indexOf(lineNumber)) < 0) &&
(linkOnlyLineNumbers.indexOf(lineNumber) < 0) &&
longLineRe.test(line) &&
!labelRe.test(line)) {
shared.addErrorDetailIf(onError, lineNumber, lineLength,
line.length, null, null, shared.rangeFromRegExp(line, longLineRe));
}
});
forEachLine((line, lineIndex, inCode, onFence, inTable) => {
const lineNumber = lineIndex + 1;
const isHeading = headingLineNumbers.indexOf(lineNumber) >= 0;
const length = isHeading ? headingLineLength : lineLength;
const lengthRe = isHeading ? longHeadingLineRe : longLineRe;
if ((includeCodeBlocks || !inCode) &&
(includeTables || !inTable) &&
(includeHeadings || !isHeading) &&
(linkOnlyLineNumbers.indexOf(lineNumber) < 0) &&
lengthRe.test(line) &&
!labelRe.test(line)) {
addErrorDetailIf(onError, lineNumber, length, line.length,
null, null, rangeFromRegExp(line, lengthRe));
}
});
}
};