mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-22 05:40:48 +02:00
Update MD013/line-length with heading_line_length parameter (fixes #170).
This commit is contained in:
parent
fa04d29485
commit
d7c0d195d7
9 changed files with 110 additions and 40 deletions
|
@ -443,13 +443,14 @@ Tags: line_length
|
|||
|
||||
Aliases: line-length
|
||||
|
||||
Parameters: line_length, code_blocks, tables, headings, headers (number; default 80, boolean; default true)
|
||||
Parameters: line_length, heading_line_length, code_blocks, tables, headings, headers (number; default 80, boolean; default true)
|
||||
|
||||
> If `headings` is not provided, `headers` (deprecated) will be used.
|
||||
|
||||
This rule is triggered when there are lines that are longer than the
|
||||
configured line length (default: 80 characters). To fix this, split the line
|
||||
up into multiple lines.
|
||||
configured `line_length` (default: 80 characters). To fix this, split the line
|
||||
up into multiple lines. To set a different maximum length for headings, use
|
||||
`heading_line_length`.
|
||||
|
||||
This rule has an exception where there is no whitespace beyond the configured
|
||||
line length. This allows you to still include items such as long URLs without
|
||||
|
|
72
lib/md013.js
72
lib/md013.js
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -129,6 +129,11 @@ rules.forEach(function forRule(rule) {
|
|||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"heading_line_length": {
|
||||
"description": "Number of characters for headings",
|
||||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"code_blocks": {
|
||||
"description": "Include code blocks",
|
||||
"type": "boolean",
|
||||
|
|
|
@ -374,6 +374,11 @@
|
|||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"heading_line_length": {
|
||||
"description": "Number of characters for headings",
|
||||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"code_blocks": {
|
||||
"description": "Include code blocks",
|
||||
"type": "boolean",
|
||||
|
@ -410,6 +415,11 @@
|
|||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"heading_line_length": {
|
||||
"description": "Number of characters for headings",
|
||||
"type": "integer",
|
||||
"default": 80
|
||||
},
|
||||
"code_blocks": {
|
||||
"description": "Include code blocks",
|
||||
"type": "boolean",
|
||||
|
|
6
test/detailed-results-MD011-MD021.json
Normal file
6
test/detailed-results-MD011-MD021.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"default": true,
|
||||
"MD013": {
|
||||
"heading_line_length": 40
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ A (reversed)[link] example.
|
|||
|
||||
123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
|
||||
## 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
|
||||
$ command with no output
|
||||
|
||||
##No space A
|
||||
|
|
|
@ -28,6 +28,15 @@
|
|||
},
|
||||
{
|
||||
"lineNumber": 10,
|
||||
"ruleNames": [ "MD013", "line-length" ],
|
||||
"ruleDescription": "Line length",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md013",
|
||||
"errorDetail": "Expected: 40; Actual: 62",
|
||||
"errorContext": null,
|
||||
"errorRange": [41, 22]
|
||||
},
|
||||
{
|
||||
"lineNumber": 12,
|
||||
"ruleNames": [ "MD014", "commands-show-output" ],
|
||||
"ruleDescription": "Dollar signs used before commands without showing output",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md014",
|
||||
|
@ -36,7 +45,7 @@
|
|||
"errorRange": [5, 2]
|
||||
},
|
||||
{
|
||||
"lineNumber": 12,
|
||||
"lineNumber": 14,
|
||||
"ruleNames": [ "MD018", "no-missing-space-atx" ],
|
||||
"ruleDescription": "No space after hash on atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md018",
|
||||
|
@ -45,7 +54,7 @@
|
|||
"errorRange": [1, 3]
|
||||
},
|
||||
{
|
||||
"lineNumber": 14,
|
||||
"lineNumber": 16,
|
||||
"ruleNames": [ "MD019", "no-multiple-space-atx" ],
|
||||
"ruleDescription": "Multiple spaces after hash on atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md019",
|
||||
|
@ -54,7 +63,7 @@
|
|||
"errorRange": [1, 5]
|
||||
},
|
||||
{
|
||||
"lineNumber": 16,
|
||||
"lineNumber": 18,
|
||||
"ruleNames": [ "MD020", "no-missing-space-closed-atx" ],
|
||||
"ruleDescription": "No space inside hashes on closed atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md020",
|
||||
|
@ -63,7 +72,7 @@
|
|||
"errorRange": [1, 3]
|
||||
},
|
||||
{
|
||||
"lineNumber": 18,
|
||||
"lineNumber": 20,
|
||||
"ruleNames": [ "MD020", "no-missing-space-closed-atx" ],
|
||||
"ruleDescription": "No space inside hashes on closed atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md020",
|
||||
|
@ -72,7 +81,7 @@
|
|||
"errorRange": [13, 3]
|
||||
},
|
||||
{
|
||||
"lineNumber": 20,
|
||||
"lineNumber": 22,
|
||||
"ruleNames": [ "MD021", "no-multiple-space-closed-atx" ],
|
||||
"ruleDescription": "Multiple spaces inside hashes on closed atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md021",
|
||||
|
@ -81,7 +90,7 @@
|
|||
"errorRange": [1, 5]
|
||||
},
|
||||
{
|
||||
"lineNumber": 22,
|
||||
"lineNumber": 24,
|
||||
"ruleNames": [ "MD021", "no-multiple-space-closed-atx" ],
|
||||
"ruleDescription": "Multiple spaces inside hashes on closed atx style heading",
|
||||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md021",
|
||||
|
|
7
test/long-lines-short-headings.json
Normal file
7
test/long-lines-short-headings.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"default": true,
|
||||
"MD003": false,
|
||||
"MD013": {
|
||||
"heading_line_length": 30
|
||||
}
|
||||
}
|
20
test/long-lines-short-headings.md
Normal file
20
test/long-lines-short-headings.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Long Lines, Short Headings
|
||||
|
||||
Text text text text text text text text text text text text text text text text text {MD013}
|
||||
|
||||
## Short heading text text text
|
||||
|
||||
Text
|
||||
|
||||
## Long heading text text text {MD013}
|
||||
|
||||
Text
|
||||
|
||||
## Long heading text text {MD013} ##
|
||||
|
||||
Text
|
||||
|
||||
Long heading of text text text text text text {MD013}
|
||||
-----------------------------------------------------
|
||||
|
||||
Text
|
Loading…
Add table
Add a link
Reference in a new issue