Support front matter title property override for MD041/first-line-h1 (fixes #53).

This commit is contained in:
David Anson 2017-05-06 15:25:14 -07:00
parent 4ae649c462
commit 942f0600d2
18 changed files with 131 additions and 12 deletions

View file

@ -57,7 +57,7 @@
"max-lines": "off", "max-lines": "off",
"max-nested-callbacks": "error", "max-nested-callbacks": "error",
"max-params": ["error", 6], "max-params": ["error", 6],
"max-statements": ["error", 28], "max-statements": ["error", 30],
"max-statements-per-line": "error", "max-statements-per-line": "error",
"multiline-ternary": "off", "multiline-ternary": "off",
"new-cap": "error", "new-cap": "error",

View file

@ -1032,7 +1032,7 @@ Tags: headers
Aliases: first-line-h1 Aliases: first-line-h1
Parameters: level (number; default 1) Parameters: level, front_matter_title (number; default 1, string; default "^\s*title:")
This rule is triggered when the first line in the file isn't a top level (h1) This rule is triggered when the first line in the file isn't a top level (h1)
header: header:
@ -1045,8 +1045,14 @@ To fix this, add a header to the top of your file:
This is a file with a top level header This is a file with a top level header
Note: The `level` parameter can be used to change the top level (ex: to h2) in The `level` parameter can be used to change the top level (ex: to h2) in cases
cases where an h1 is added externally. where an h1 is added externally.
If front matter is present and contains a [YAML](https://en.wikipedia.org/wiki/YAML)
`title` property (commonly used with blog posts), this rule will not report a
violation. To use a different property name in front matter, specify the text
of a regular expression via the `front_matter_title` parameter. To disable the
use of front matter by this rule, specify `""` for `front_matter_title`.
## MD042 - No empty links ## MD042 - No empty links

View file

@ -88,13 +88,17 @@ function lintContent(content, config, frontMatter, resultVersion) {
content = content.slice(1); content = content.slice(1);
} }
// Remove front matter (if present at beginning of content) // Remove front matter (if present at beginning of content)
var frontMatterLines = 0; var frontMatterLines = [];
if (frontMatter) { if (frontMatter) {
var frontMatterMatch = content.match(frontMatter); var frontMatterMatch = content.match(frontMatter);
if (frontMatterMatch && !frontMatterMatch.index) { if (frontMatterMatch && !frontMatterMatch.index) {
var contentMatched = frontMatterMatch[0]; var contentMatched = frontMatterMatch[0];
content = content.slice(contentMatched.length); content = content.slice(contentMatched.length);
frontMatterLines = contentMatched.split(shared.newLineRe).length - 1; frontMatterLines = contentMatched.split(shared.newLineRe);
if (frontMatterLines.length &&
(frontMatterLines[frontMatterLines.length - 1] === "")) {
frontMatterLines.length--;
}
} }
} }
// Parse content into tokens and lines // Parse content into tokens and lines
@ -184,7 +188,7 @@ function lintContent(content, config, frontMatter, resultVersion) {
} }
}); });
} }
var enabledRulesPerLineNumber = new Array(1 + frontMatterLines); var enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
lines.forEach(function forLine(line) { lines.forEach(function forLine(line) {
var match = shared.inlineCommentRe.exec(line); var match = shared.inlineCommentRe.exec(line);
if (match) { if (match) {
@ -200,7 +204,8 @@ function lintContent(content, config, frontMatter, resultVersion) {
var params = { var params = {
"tokens": tokens, "tokens": tokens,
"tokenLists": tokenLists, "tokenLists": tokenLists,
"lines": lines "lines": lines,
"frontMatterLines": frontMatterLines
}; };
// Run each rule // Run each rule
var result = (resultVersion === 1) ? [] : {}; var result = (resultVersion === 1) ? [] : {};
@ -210,7 +215,7 @@ function lintContent(content, config, frontMatter, resultVersion) {
var errors = []; var errors = [];
function addError(lineNumber, detail, context) { function addError(lineNumber, detail, context) {
errors.push({ errors.push({
"lineNumber": lineNumber + frontMatterLines, "lineNumber": lineNumber + frontMatterLines.length,
"detail": detail || null, "detail": detail || null,
"context": context || null "context": context || null
}); });
@ -255,7 +260,7 @@ function lintContent(content, config, frontMatter, resultVersion) {
if (typeof regexp === "function") { if (typeof regexp === "function") {
regexp = regexp(params.options); regexp = regexp(params.options);
} }
var lineIndex = error.lineNumber - frontMatterLines - 1; var lineIndex = error.lineNumber - frontMatterLines.length - 1;
var match = lines[lineIndex].match(regexp); var match = lines[lineIndex].match(regexp);
if (match) { if (match) {
var column = match.index + 1; var column = match.index + 1;

View file

@ -1029,7 +1029,10 @@ module.exports = [
"regexp": null, "regexp": null,
"func": function MD041(params, errors) { "func": function MD041(params, errors) {
var level = params.options.level || 1; var level = params.options.level || 1;
var frontMatterTitle = params.options.front_matter_title;
var tag = "h" + level; var tag = "h" + level;
var frontMatterTitleRe =
new RegExp(frontMatterTitle || "^\\s*title:", "i");
params.tokens.every(function forToken(token, index) { params.tokens.every(function forToken(token, index) {
if (token.type === "heading_open") { if (token.type === "heading_open") {
if (!((token.lineNumber === 1) || (index > 0)) || if (!((token.lineNumber === 1) || (index > 0)) ||
@ -1040,7 +1043,12 @@ module.exports = [
} else if (token.type === "html_block") { } else if (token.type === "html_block") {
return true; return true;
} }
errors.addContext(token.lineNumber, token.line); if (((frontMatterTitle !== undefined) && !frontMatterTitle) ||
!params.frontMatterLines.some(function forLine(line) {
return frontMatterTitleRe.test(line);
})) {
errors.addContext(token.lineNumber, token.line);
}
return false; return false;
}); });
} }

View file

@ -35,7 +35,6 @@ rules.forEach(function forRule(rule) {
switch (rule.name) { switch (rule.name) {
case "MD002": case "MD002":
case "MD025": case "MD025":
case "MD041":
scheme.properties = { scheme.properties = {
"level": { "level": {
"description": "Header level", "description": "Header level",
@ -205,6 +204,20 @@ rules.forEach(function forRule(rule) {
} }
}; };
break; break;
case "MD041":
scheme.properties = {
"level": {
"description": "Header level",
"type": "integer",
"default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title:"
}
};
break;
case "MD043": case "MD043":
scheme.properties = { scheme.properties = {
"headers": { "headers": {

View file

@ -813,6 +813,11 @@
"description": "Header level", "description": "Header level",
"type": "integer", "type": "integer",
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title:"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -829,6 +834,11 @@
"description": "Header level", "description": "Header level",
"type": "integer", "type": "integer",
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title:"
} }
}, },
"additionalProperties": false "additionalProperties": false

View file

@ -0,0 +1,7 @@
{
"default": true,
"MD013": false,
"MD041": {
"front_matter_title": "^\\s*alternate="
}
}

View file

@ -0,0 +1,4 @@
---
alternate="Welcome to Jekyll!"
---
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post).

View file

@ -0,0 +1,7 @@
{
"default": true,
"MD013": false,
"MD041": {
"front_matter_title": ""
}
}

View file

@ -0,0 +1,7 @@
---
layout: post
title: "Welcome to Jekyll!"
date: 2015-11-17 16:16:01 -0600
categories: jekyll update
---
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post). {MD041}

View file

@ -0,0 +1,5 @@
{
"default": true,
"MD013": false,
"MD041": true
}

View file

@ -0,0 +1,9 @@
---
layout: post
notitle: "Welcome to Jekyll!"
date: 2015-11-17 16:16:01 -0600
categories: jekyll update
---
# Top level header
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post).

View file

@ -0,0 +1,5 @@
{
"default": true,
"MD013": false,
"MD041": true
}

View file

@ -0,0 +1,7 @@
---
layout: post
notitle: "Welcome to Jekyll!"
date: 2015-11-17 16:16:01 -0600
categories: jekyll update
---
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post). {MD041}

View file

@ -0,0 +1,5 @@
{
"default": true,
"MD013": false,
"MD041": true
}

View file

@ -0,0 +1,9 @@
---
layout: post
title: "Welcome to Jekyll!"
date: 2015-11-17 16:16:01 -0600
categories: jekyll update
---
# Top level header
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post).

View file

@ -0,0 +1,5 @@
{
"default": true,
"MD013": false,
"MD041": true
}

View file

@ -0,0 +1,7 @@
---
layout: post
title: "Welcome to Jekyll!"
date: 2015-11-17 16:16:01 -0600
categories: jekyll update
---
Front matter from [Jekyll documentation](https://jekyllrb.com/docs/posts/#a-typical-post).