Update MD041/first-line-heading to add an allow_preamble parameter (fixes #1416).

This commit is contained in:
David Anson 2025-03-22 16:15:59 -07:00
parent c061888937
commit 62dc79864d
17 changed files with 538 additions and 163 deletions

View file

@ -1,37 +1,50 @@
This rule is intended to ensure documents have a title and is triggered when This rule is intended to ensure documents have a title and is triggered when
the first line in the file isn't a top-level (h1) heading: the first line in a document is not a top-level ([HTML][HTML] `h1`) heading:
```markdown ```markdown
This is a file without a heading This is a document without a heading
``` ```
To fix this, add a top-level heading to the beginning of the file: To fix this, add a top-level heading to the beginning of the document:
```markdown ```markdown
# File with heading # Document Heading
This is a file with a top-level heading This is a document with a top-level heading
``` ```
Because it is common for projects on GitHub to use an image for the heading of Because it is common for projects on GitHub to use an image for the heading of
`README.md` and that is not well-supported by Markdown, HTML headings are also `README.md` and that pattern is not well-supported by Markdown, HTML headings
permitted by this rule. For example: are also permitted by this rule. For example:
```markdown ```markdown
<h1 align="center"><img src="https://placekitten.com/300/150"/></h1> <h1 align="center"><img src="https://placekitten.com/300/150"/></h1>
This is a file with a top-level HTML heading This is a document with a top-level HTML heading
``` ```
Note: The `level` parameter can be used to change the top-level (ex: to h2) in In some cases, a document's title heading may be preceded by text like a table
cases where an h1 is added externally. of contents. This is not ideal for accessibility, but can be allowed by setting
the `allow_preamble` parameter to `true`.
If [YAML](https://en.wikipedia.org/wiki/YAML) front matter is present and ```markdown
contains a `title` property (commonly used with blog posts), this rule will not This is a document with preamble text
report a violation. To use a different property name in the front matter,
specify the text of a regular expression via the `front_matter_title` parameter. # Document Heading
To disable the use of front matter by this rule, specify `""` for ```
`front_matter_title`.
If [YAML][YAML] front matter is present and contains a `title` property
(commonly used with blog posts), this rule will not report a violation. To use a
different property name in the front matter, specify the text of a [regular
expression][RegExp] via the `front_matter_title` parameter. To disable the use
of front matter by this rule, specify `""` for `front_matter_title`.
The `level` parameter can be used to change the top-level heading (ex: to `h2`)
in cases where an `h1` is added externally.
Rationale: The top-level heading often acts as the title of a document. More Rationale: The top-level heading often acts as the title of a document. More
information: <https://cirosantilli.com/markdown-style-guide#top-level-header>. information: <https://cirosantilli.com/markdown-style-guide#top-level-header>.
[HTML]: https://en.wikipedia.org/wiki/HTML
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
[YAML]: https://en.wikipedia.org/wiki/YAML

View file

@ -1670,48 +1670,63 @@ Aliases: `first-line-h1`, `first-line-heading`
Parameters: Parameters:
- `allow_preamble`: Allow content before first heading (`boolean`, default
`false`)
- `front_matter_title`: RegExp for matching title in front matter (`string`, - `front_matter_title`: RegExp for matching title in front matter (`string`,
default `^\s*title\s*[:=]`) default `^\s*title\s*[:=]`)
- `level`: Heading level (`integer`, default `1`) - `level`: Heading level (`integer`, default `1`)
This rule is intended to ensure documents have a title and is triggered when This rule is intended to ensure documents have a title and is triggered when
the first line in the file isn't a top-level (h1) heading: the first line in a document is not a top-level ([HTML][HTML] `h1`) heading:
```markdown ```markdown
This is a file without a heading This is a document without a heading
``` ```
To fix this, add a top-level heading to the beginning of the file: To fix this, add a top-level heading to the beginning of the document:
```markdown ```markdown
# File with heading # Document Heading
This is a file with a top-level heading This is a document with a top-level heading
``` ```
Because it is common for projects on GitHub to use an image for the heading of Because it is common for projects on GitHub to use an image for the heading of
`README.md` and that is not well-supported by Markdown, HTML headings are also `README.md` and that pattern is not well-supported by Markdown, HTML headings
permitted by this rule. For example: are also permitted by this rule. For example:
```markdown ```markdown
<h1 align="center"><img src="https://placekitten.com/300/150"/></h1> <h1 align="center"><img src="https://placekitten.com/300/150"/></h1>
This is a file with a top-level HTML heading This is a document with a top-level HTML heading
``` ```
Note: The `level` parameter can be used to change the top-level (ex: to h2) in In some cases, a document's title heading may be preceded by text like a table
cases where an h1 is added externally. of contents. This is not ideal for accessibility, but can be allowed by setting
the `allow_preamble` parameter to `true`.
If [YAML](https://en.wikipedia.org/wiki/YAML) front matter is present and ```markdown
contains a `title` property (commonly used with blog posts), this rule will not This is a document with preamble text
report a violation. To use a different property name in the front matter,
specify the text of a regular expression via the `front_matter_title` parameter. # Document Heading
To disable the use of front matter by this rule, specify `""` for ```
`front_matter_title`.
If [YAML][YAML] front matter is present and contains a `title` property
(commonly used with blog posts), this rule will not report a violation. To use a
different property name in the front matter, specify the text of a [regular
expression][RegExp] via the `front_matter_title` parameter. To disable the use
of front matter by this rule, specify `""` for `front_matter_title`.
The `level` parameter can be used to change the top-level heading (ex: to `h2`)
in cases where an `h1` is added externally.
Rationale: The top-level heading often acts as the title of a document. More Rationale: The top-level heading often acts as the title of a document. More
information: <https://cirosantilli.com/markdown-style-guide#top-level-header>. information: <https://cirosantilli.com/markdown-style-guide#top-level-header>.
[HTML]: https://en.wikipedia.org/wiki/HTML
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
[YAML]: https://en.wikipedia.org/wiki/YAML
<a name="md042"></a> <a name="md042"></a>
## `MD042` - No empty links ## `MD042` - No empty links

View file

@ -6,44 +6,59 @@ Aliases: `first-line-h1`, `first-line-heading`
Parameters: Parameters:
- `allow_preamble`: Allow content before first heading (`boolean`, default
`false`)
- `front_matter_title`: RegExp for matching title in front matter (`string`, - `front_matter_title`: RegExp for matching title in front matter (`string`,
default `^\s*title\s*[:=]`) default `^\s*title\s*[:=]`)
- `level`: Heading level (`integer`, default `1`) - `level`: Heading level (`integer`, default `1`)
This rule is intended to ensure documents have a title and is triggered when This rule is intended to ensure documents have a title and is triggered when
the first line in the file isn't a top-level (h1) heading: the first line in a document is not a top-level ([HTML][HTML] `h1`) heading:
```markdown ```markdown
This is a file without a heading This is a document without a heading
``` ```
To fix this, add a top-level heading to the beginning of the file: To fix this, add a top-level heading to the beginning of the document:
```markdown ```markdown
# File with heading # Document Heading
This is a file with a top-level heading This is a document with a top-level heading
``` ```
Because it is common for projects on GitHub to use an image for the heading of Because it is common for projects on GitHub to use an image for the heading of
`README.md` and that is not well-supported by Markdown, HTML headings are also `README.md` and that pattern is not well-supported by Markdown, HTML headings
permitted by this rule. For example: are also permitted by this rule. For example:
```markdown ```markdown
<h1 align="center"><img src="https://placekitten.com/300/150"/></h1> <h1 align="center"><img src="https://placekitten.com/300/150"/></h1>
This is a file with a top-level HTML heading This is a document with a top-level HTML heading
``` ```
Note: The `level` parameter can be used to change the top-level (ex: to h2) in In some cases, a document's title heading may be preceded by text like a table
cases where an h1 is added externally. of contents. This is not ideal for accessibility, but can be allowed by setting
the `allow_preamble` parameter to `true`.
If [YAML](https://en.wikipedia.org/wiki/YAML) front matter is present and ```markdown
contains a `title` property (commonly used with blog posts), this rule will not This is a document with preamble text
report a violation. To use a different property name in the front matter,
specify the text of a regular expression via the `front_matter_title` parameter. # Document Heading
To disable the use of front matter by this rule, specify `""` for ```
`front_matter_title`.
If [YAML][YAML] front matter is present and contains a `title` property
(commonly used with blog posts), this rule will not report a violation. To use a
different property name in the front matter, specify the text of a [regular
expression][RegExp] via the `front_matter_title` parameter. To disable the use
of front matter by this rule, specify `""` for `front_matter_title`.
The `level` parameter can be used to change the top-level heading (ex: to `h2`)
in cases where an `h1` is added externally.
Rationale: The top-level heading often acts as the title of a document. More Rationale: The top-level heading often acts as the title of a document. More
information: <https://cirosantilli.com/markdown-style-guide#top-level-header>. information: <https://cirosantilli.com/markdown-style-guide#top-level-header>.
[HTML]: https://en.wikipedia.org/wiki/HTML
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
[YAML]: https://en.wikipedia.org/wiki/YAML

View file

@ -406,14 +406,14 @@ export interface ConfigurationStrict {
MD025?: MD025?:
| boolean | boolean
| { | {
/**
* Heading level
*/
level?: number;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md * MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md
@ -421,14 +421,14 @@ export interface ConfigurationStrict {
"single-title"?: "single-title"?:
| boolean | boolean
| { | {
/**
* Heading level
*/
level?: number;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md * MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md
@ -436,14 +436,14 @@ export interface ConfigurationStrict {
"single-h1"?: "single-h1"?:
| boolean | boolean
| { | {
/**
* Heading level
*/
level?: number;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md * MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md
@ -730,13 +730,17 @@ export interface ConfigurationStrict {
| boolean | boolean
| { | {
/** /**
* Heading level * Allow content before first heading
*/ */
level?: number; allow_preamble?: boolean;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md * MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md
@ -745,13 +749,17 @@ export interface ConfigurationStrict {
| boolean | boolean
| { | {
/** /**
* Heading level * Allow content before first heading
*/ */
level?: number; allow_preamble?: boolean;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md * MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md
@ -760,13 +768,17 @@ export interface ConfigurationStrict {
| boolean | boolean
| { | {
/** /**
* Heading level * Allow content before first heading
*/ */
level?: number; allow_preamble?: boolean;
/** /**
* RegExp for matching title in front matter * RegExp for matching title in front matter
*/ */
front_matter_title?: string; front_matter_title?: string;
/**
* Heading level
*/
level?: number;
}; };
/** /**
* MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md * MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md

View file

@ -3,6 +3,26 @@
import { addErrorContext, frontMatterHasTitle } from "../helpers/helpers.cjs"; import { addErrorContext, frontMatterHasTitle } from "../helpers/helpers.cjs";
import { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } from "../helpers/micromark-helpers.cjs"; import { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } from "../helpers/micromark-helpers.cjs";
const headingTagNameRe = /^h[1-6]$/;
/**
* Gets the HTML tag name of an htmlFlow token.
*
* @param {import("markdownlint").MicromarkToken} token Micromark Token.
* @returns {string | null} Tag name.
*/
function getHtmlFlowTagName(token) {
const { children, type } = token;
if (type === "htmlFlow") {
const htmlTexts = filterByTypes(children, [ "htmlText" ], true);
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]);
if (tagInfo) {
return tagInfo.name.toLowerCase();
}
}
return null;
}
/** @type {import("markdownlint").Rule} */ /** @type {import("markdownlint").Rule} */
export default { export default {
"names": [ "MD041", "first-line-heading", "first-line-h1" ], "names": [ "MD041", "first-line-heading", "first-line-h1" ],
@ -10,6 +30,7 @@ export default {
"tags": [ "headings" ], "tags": [ "headings" ],
"parser": "micromark", "parser": "micromark",
"function": function MD041(params, onError) { "function": function MD041(params, onError) {
const allowPreamble = !!params.config.allow_preamble;
const level = Number(params.config.level || 1); const level = Number(params.config.level || 1);
const { tokens } = params.parsers.micromark; const { tokens } = params.parsers.micromark;
if ( if (
@ -18,22 +39,33 @@ export default {
params.config.front_matter_title params.config.front_matter_title
) )
) { ) {
let errorLineNumber = 0;
for (const token of tokens) { for (const token of tokens) {
if (!nonContentTokens.has(token.type) && !isHtmlFlowComment(token)) { const { startLine, type } = token;
let isError = true; if (!nonContentTokens.has(type) && !isHtmlFlowComment(token)) {
if ((token.type === "atxHeading") || (token.type === "setextHeading")) { let tagName = null;
isError = (getHeadingLevel(token) !== level); if ((type === "atxHeading") || (type === "setextHeading")) {
} else if (token.type === "htmlFlow") { // First heading needs to have the expected level
const htmlTexts = filterByTypes(token.children, [ "htmlText" ], true); if (getHeadingLevel(token) !== level) {
const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]); errorLineNumber = startLine;
isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`); }
break;
} else if ((tagName = getHtmlFlowTagName(token)) && headingTagNameRe.test(tagName)) {
// First HTML element needs to have an <h?> with the expected level
if (tagName !== `h${level}`) {
errorLineNumber = startLine;
}
break;
} else if (!allowPreamble) {
// First non-content needs to be a heading with the expected level
errorLineNumber = startLine;
break;
} }
if (isError) {
addErrorContext(onError, token.startLine, params.lines[token.startLine - 1]);
}
break;
} }
} }
if (errorLineNumber > 0) {
addErrorContext(onError, errorLineNumber, params.lines[errorLineNumber - 1]);
}
} }
} }
}; };

View file

@ -118,10 +118,10 @@
// MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md // MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md
"MD025": { "MD025": {
// Heading level
"level": 1,
// RegExp for matching title in front matter // RegExp for matching title in front matter
"front_matter_title": "^\\s*title\\s*[:=]" "front_matter_title": "^\\s*title\\s*[:=]",
// Heading level
"level": 1
}, },
// MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md // MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md
@ -206,10 +206,12 @@
// MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md // MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md
"MD041": { "MD041": {
// Heading level // Allow content before first heading
"level": 1, "allow_preamble": false,
// RegExp for matching title in front matter // RegExp for matching title in front matter
"front_matter_title": "^\\s*title\\s*[:=]" "front_matter_title": "^\\s*title\\s*[:=]",
// Heading level
"level": 1
}, },
// MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md // MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md

View file

@ -108,10 +108,10 @@ MD024:
# MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md # MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md025.md
MD025: MD025:
# Heading level
level: 1
# RegExp for matching title in front matter # RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]" front_matter_title: "^\\s*title\\s*[:=]"
# Heading level
level: 1
# MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md # MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md026.md
MD026: MD026:
@ -186,10 +186,12 @@ MD040:
# MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md # MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md041.md
MD041: MD041:
# Heading level # Allow content before first heading
level: 1 allow_preamble: false
# RegExp for matching title in front matter # RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]" front_matter_title: "^\\s*title\\s*[:=]"
# Heading level
level: 1
# MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md # MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md042.md
MD042: true MD042: true

View file

@ -367,20 +367,32 @@ for (const rule of rules) {
break; break;
case "MD025": case "MD025":
case "MD041": case "MD041":
scheme.properties = { {
"level": { const md041Properties = (ruleName === "MD041") ?
"description": "Heading level", {
"type": "integer", "allow_preamble": {
"minimum": 1, "description": "Allow content before first heading",
"maximum": 6, "type": "boolean",
"default": 1 "default": false
}, }
"front_matter_title": { } :
"description": "RegExp for matching title in front matter", {};
"type": "string", scheme.properties = {
"default": "^\\s*title\\s*[:=]" ...md041Properties,
} "front_matter_title": {
}; "description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": {
"description": "Heading level",
"type": "integer",
"minimum": 1,
"maximum": 6,
"default": 1
}
};
}
break; break;
case "MD043": case "MD043":
scheme.properties = { scheme.properties = {

View file

@ -628,17 +628,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -651,17 +651,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -674,17 +674,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1117,17 +1117,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1140,17 +1145,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1163,17 +1173,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false

View file

@ -628,17 +628,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -651,17 +651,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -674,17 +674,17 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1117,17 +1117,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1140,17 +1145,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false
@ -1163,17 +1173,22 @@
], ],
"default": true, "default": true,
"properties": { "properties": {
"allow_preamble": {
"description": "Allow content before first heading",
"type": "boolean",
"default": false
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
},
"level": { "level": {
"description": "Heading level", "description": "Heading level",
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 6, "maximum": 6,
"default": 1 "default": 1
},
"front_matter_title": {
"description": "RegExp for matching title in front matter",
"type": "string",
"default": "^\\s*title\\s*[:=]"
} }
}, },
"additionalProperties": false "additionalProperties": false

View file

@ -0,0 +1,22 @@
Text {MD041}
<!-- Comment -->
Text
<p>HTML</p>
Text
- List item
# Heading
Text
<!-- markdownlint-configure-file {
"first-line-heading": {
"allow_preamble": false
},
"no-inline-html": false
} -->

View file

@ -0,0 +1,22 @@
Text
<!-- Comment -->
Text
<p>HTML</p>
Text
- List item
<h1>Heading</h1>
Text
<!-- markdownlint-configure-file {
"first-line-heading": {
"allow_preamble": true
},
"no-inline-html": false
} -->

View file

@ -0,0 +1,22 @@
Text
<!-- Comment -->
Text
<p>HTML</p>
Text
- List item
## Heading {MD041}
Text
<!-- markdownlint-configure-file {
"first-line-heading": {
"allow_preamble": true
},
"no-inline-html": false
} -->

View file

@ -0,0 +1,22 @@
Text
<!-- Comment -->
Text
<p>HTML</p>
Text
- List item
# Heading
Text
<!-- markdownlint-configure-file {
"first-line-heading": {
"allow_preamble": true
},
"no-inline-html": false
} -->

View file

@ -907,7 +907,7 @@ test("readme", async(t) => {
}); });
test("validateJsonUsingConfigSchemaStrict", async(t) => { test("validateJsonUsingConfigSchemaStrict", async(t) => {
t.plan(192); t.plan(196);
// @ts-ignore // @ts-ignore
const ajv = new Ajv(ajvOptions); const ajv = new Ajv(ajvOptions);
const validateSchemaStrict = ajv.compile(configSchemaStrict); const validateSchemaStrict = ajv.compile(configSchemaStrict);

View file

@ -13752,6 +13752,160 @@ Generated by [AVA](https://avajs.dev).
`, `,
} }
## first-line-heading-allow-preamble-false.md
> Snapshot 1
{
errors: [
{
errorContext: 'Text {MD041}',
errorDetail: null,
errorRange: null,
fixInfo: null,
lineNumber: 1,
ruleDescription: 'First line in a file should be a top-level heading',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md041.md',
ruleNames: [
'MD041',
'first-line-heading',
'first-line-h1',
],
},
],
fixed: `Text {MD041}␊
<!-- Comment -->
Text␊
<p>HTML</p>
Text␊
- List item␊
# Heading␊
Text␊
<!-- markdownlint-configure-file {␊
"first-line-heading": {␊
"allow_preamble": false␊
},␊
"no-inline-html": false␊
} -->␊
`,
}
## first-line-heading-allow-preamble-h1.md
> Snapshot 1
{
errors: [],
fixed: `Text␊
<!-- Comment -->
Text␊
<p>HTML</p>
Text␊
- List item␊
<h1>Heading</h1>
Text␊
<!-- markdownlint-configure-file {␊
"first-line-heading": {␊
"allow_preamble": true␊
},␊
"no-inline-html": false␊
} -->␊
`,
}
## first-line-heading-allow-preamble-violation.md
> Snapshot 1
{
errors: [
{
errorContext: '## Heading {MD041}',
errorDetail: null,
errorRange: null,
fixInfo: null,
lineNumber: 13,
ruleDescription: 'First line in a file should be a top-level heading',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md041.md',
ruleNames: [
'MD041',
'first-line-heading',
'first-line-h1',
],
},
],
fixed: `Text␊
<!-- Comment -->
Text␊
<p>HTML</p>
Text␊
- List item␊
## Heading {MD041}␊
Text␊
<!-- markdownlint-configure-file {␊
"first-line-heading": {␊
"allow_preamble": true␊
},␊
"no-inline-html": false␊
} -->␊
`,
}
## first-line-heading-allow-preamble.md
> Snapshot 1
{
errors: [],
fixed: `Text␊
<!-- Comment -->
Text␊
<p>HTML</p>
Text␊
- List item␊
# Heading␊
Text␊
<!-- markdownlint-configure-file {␊
"first-line-heading": {␊
"allow_preamble": true␊
},␊
"no-inline-html": false␊
} -->␊
`,
}
## first_heading_bad_atx.md ## first_heading_bad_atx.md
> Snapshot 1 > Snapshot 1