markdownlint
Advanced tools
Comparing version 0.22.0 to 0.23.0
159
doc/Rules.md
# Rules | ||
This document contains a description of all rules, what they are checking for, | ||
as well as an examples of documents that break the rule and corrected | ||
as well as examples of documents that break the rule and corrected | ||
versions of the examples. Any rule whose heading is ~~struck through~~ is | ||
@@ -50,3 +50,3 @@ deprecated, but still provided for backward-compatibility. | ||
## ~~MD002 - First heading should be a top level heading~~ | ||
## ~~MD002 - First heading should be a top-level heading~~ | ||
@@ -63,6 +63,6 @@ Tags: headings, headers | ||
This rule is intended to ensure document headings start at the top level and | ||
is triggered when the first heading in the document isn't a h1 heading: | ||
is triggered when the first heading in the document isn't an h1 heading: | ||
```markdown | ||
## This isn't a H1 heading | ||
## This isn't an H1 heading | ||
@@ -72,6 +72,6 @@ ### Another heading | ||
The first heading in the document should be a h1 heading: | ||
The first heading in the document should be an h1 heading: | ||
```markdown | ||
# Start with a H1 heading | ||
# Start with an H1 heading | ||
@@ -81,6 +81,6 @@ ## Then use an H2 for subsections | ||
Note: The `level` parameter can be used to change the top level (ex: to h2) in | ||
cases where a h1 is added externally. | ||
Note: The `level` parameter can be used to change the top-level (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>. | ||
@@ -134,3 +134,3 @@ | ||
atx_closed, setext, setext_with_atx, setext_with_atx_closed), or simply require | ||
that the usage be consistent within the document. | ||
that the usage is consistent within the document. | ||
@@ -150,2 +150,4 @@ Rationale: Consistent formatting makes it easier to understand a document. | ||
Fixable: Most violations can be fixed by tooling | ||
This rule is triggered when the symbols used in the document for unordered | ||
@@ -170,7 +172,8 @@ list items do not match the configured unordered list style: | ||
The configured list style can be a specific symbol to use (asterisk, plus, dash), | ||
can require that usage be consistent within the document, or can require that each | ||
sublist have a consistent symbol that is different from its parent list. | ||
to ensure that all list styling is consistent, or to ensure that each | ||
sublist has a consistent symbol that differs from its parent list. | ||
For example, the following is valid for the `sublist` style because the outer-most | ||
indent uses asterisk, the middle indent uses plus, and the inner-most indent uses dash: | ||
indent uses asterisk, the middle indent uses plus, and the inner-most indent uses | ||
dash: | ||
@@ -208,3 +211,3 @@ ```markdown | ||
Usually this rule will be triggered because of a typo. Correct the indentation | ||
Usually, this rule will be triggered because of a typo. Correct the indentation | ||
for the list to fix it: | ||
@@ -255,3 +258,3 @@ | ||
This rule is triggered when top level lists don't start at the beginning of a | ||
This rule is triggered when top-level lists don't start at the beginning of a | ||
line: | ||
@@ -266,3 +269,3 @@ | ||
To fix, ensure that top level list items are not indented: | ||
To fix, ensure that top-level list items are not indented: | ||
@@ -335,3 +338,3 @@ ```markdown | ||
and simpler for editors to implement. Additionally, this can be a compatibility | ||
issue for multi-markdown parsers, which require a 4-space indents. More information: | ||
issue for multi-markdown parsers, which require 4-space indents. More information: | ||
<https://cirosantilli.com/markdown-style-guide#indentation-of-content-inside-lists> | ||
@@ -348,4 +351,8 @@ and <http://support.markedapp.com/discussions/problems/21-sub-lists-not-indenting>. | ||
<!-- markdownlint-disable line-length --> | ||
Parameters: br_spaces, list_item_empty_lines, strict (number; default 2, boolean; default false, boolean; default false) | ||
<!-- markdownlint-restore --> | ||
Fixable: Most violations can be fixed by tooling | ||
@@ -414,3 +421,3 @@ | ||
<!-- markdownlint-enable no-hard-tabs --> | ||
<!-- markdownlint-restore --> | ||
@@ -456,3 +463,4 @@ Corrected example: | ||
Note: [Markdown Extra](https://en.wikipedia.org/wiki/Markdown_Extra)-style footnotes do not trigger this rule: | ||
Note: [Markdown Extra](https://en.wikipedia.org/wiki/Markdown_Extra)-style | ||
footnotes do not trigger this rule: | ||
@@ -516,3 +524,3 @@ ```markdown | ||
<!-- markdownlint-enable line-length --> | ||
<!-- markdownlint-restore --> | ||
@@ -544,3 +552,3 @@ > If `headings` is not provided, `headers` (deprecated) will be used. | ||
In `strict` or `stern` modes, the two middle lines above are a violation. The | ||
third line is a violation in `strict` mode, but allowed in `stern` mode. | ||
third line is a violation in `strict` mode but allowed in `stern` mode. | ||
@@ -578,3 +586,3 @@ You have the option to exclude this rule for code blocks, tables, or headings. | ||
<!-- markdownlint-enable commands-show-output --> | ||
<!-- markdownlint-restore --> | ||
@@ -784,3 +792,3 @@ The dollar signs are unnecessary in this situation, and should not be | ||
Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will | ||
Rationale: Aside from aesthetic reasons, some parsers, including `kramdown`, will | ||
not parse headings that don't have a blank line before, and will parse them as | ||
@@ -847,3 +855,3 @@ regular text. | ||
set to `true`, heading duplication is allowed for non-sibling headings (common | ||
in change logs): | ||
in changelogs): | ||
@@ -867,3 +875,3 @@ ```markdown | ||
## MD025 - Multiple top level headings in the same document | ||
## MD025 - Multiple top-level headings in the same document | ||
@@ -876,4 +884,4 @@ Tags: headings, headers | ||
This rule is triggered when a top level heading is in use (the first line of | ||
the file is a h1 heading), and more than one h1 heading is in use in the | ||
This rule is triggered when a top-level heading is in use (the first line of | ||
the file is an h1 heading), and more than one h1 heading is in use in the | ||
document: | ||
@@ -884,8 +892,8 @@ | ||
# Another top level heading | ||
# Another top-level heading | ||
``` | ||
To fix, structure your document so that there is a single h1 heading that is | ||
the title for the document, and all later headings are h2 or lower level | ||
headings: | ||
To fix, structure your document so there is a single h1 heading that is | ||
the title for the document. Subsequent headings must be | ||
lower-level headings (h2, h3, etc.): | ||
@@ -900,13 +908,13 @@ ```markdown | ||
Note: The `level` parameter can be used to change the top level (ex: to h2) in | ||
cases where a h1 is added externally. | ||
Note: The `level` parameter can be used to change the top-level (ex: to h2) in | ||
cases where an h1 is added externally. | ||
If [YAML](https://en.wikipedia.org/wiki/YAML) front matter is present and contains | ||
a `title` property (commonly used with blog posts), this rule treats that as a top | ||
level heading and will report a violation for any subsequent top level headings. | ||
To use a different property name in front matter, specify the text of a regular | ||
level heading and will report a violation for any subsequent top-level headings. | ||
To use a different property name in the 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`. | ||
Rationale: A top level heading is a h1 on the first line of the file, and | ||
Rationale: A top-level heading is an h1 on the first line of the file, and | ||
serves as the title for the document. If this convention is in use, then there | ||
@@ -943,3 +951,3 @@ can not be more than one title for the document, and the entire document | ||
as punctuation at the end of a heading. For example, you can change it to | ||
`".,;:"` to allow headings that end with an exclamation point. Question mark is | ||
`".,;:"` to allow headings that end with an exclamation point. `?` is | ||
allowed by default because of how common it is in headings of FAQ-style documents. | ||
@@ -970,3 +978,3 @@ Setting the `punctuation` parameter to `""` allows all characters - and is | ||
```markdown | ||
> This is a block quote with bad indentation | ||
> This is a blockquote with bad indentation | ||
> there should only be one. | ||
@@ -1039,3 +1047,3 @@ ``` | ||
do not have a prefix that increases in numerical order (depending on the | ||
configured style). The less-common patterns of using '0.' as a first prefix or | ||
configured style). The less-common pattern of using '0.' as a first prefix or | ||
for all prefixes is also supported. | ||
@@ -1093,4 +1101,5 @@ | ||
Note: This rule will report violations for cases like the following where an improperly-indented code block (or similar) appears between two list | ||
items and "breaks" the list in two: | ||
Note: This rule will report violations for cases like the following where an | ||
improperly-indented code block (or similar) appears between two list items and | ||
"breaks" the list in two: | ||
@@ -1109,3 +1118,4 @@ <!-- markdownlint-disable code-fence-style --> | ||
The fix is to indent the code block so it becomes part of the preceding list item as intended: | ||
The fix is to indent the code block so it becomes part of the preceding list | ||
item as intended: | ||
@@ -1122,3 +1132,3 @@ ~~~markdown | ||
<!-- markdownlint-enable code-fence-style --> | ||
<!-- markdownlint-restore --> | ||
@@ -1161,3 +1171,3 @@ Rationale: Consistent formatting makes it easier to understand a document. | ||
and ordered list items independently, as well as based on whether the content | ||
of every item in the list consists of a single paragraph, or multiple | ||
of every item in the list consists of a single paragraph or multiple | ||
paragraphs (including sub-lists and code blocks). | ||
@@ -1198,3 +1208,3 @@ | ||
To fix this, ensure the correct number of spaces are used after list marker | ||
To fix this, ensure the correct number of spaces are used after the list marker | ||
for your selected document style. | ||
@@ -1407,3 +1417,3 @@ | ||
Note: by default, this rule is configured to just require that all horizontal | ||
rules in the document are the same, and will trigger if any of the horizontal | ||
rules in the document are the same and will trigger if any of the horizontal | ||
rules are different than the first one encountered in the document. If you | ||
@@ -1452,3 +1462,3 @@ want to configure the rule to match a specific style, the parameter given to | ||
Note: This rule looks for single line paragraphs that consist entirely | ||
Note: This rule looks for single-line paragraphs that consist entirely | ||
of emphasized text. It won't fire on emphasis used within regular text, | ||
@@ -1499,3 +1509,3 @@ multi-line emphasized paragraphs, or paragraphs ending in punctuation | ||
Rationale: Emphasis is only parsed as such when the asterisks/underscores | ||
aren't completely surrounded by spaces. This rule attempts to detect where | ||
aren't surrounded by spaces. This rule attempts to detect where | ||
they were surrounded by spaces, but it appears that emphasized text was | ||
@@ -1536,3 +1546,3 @@ intended by the author. | ||
Note: A single leading or trailing space is allowed if used to separate codespan | ||
Note: A single leading or trailing space is allowed if used to separate code span | ||
markers from an embedded backtick: | ||
@@ -1603,3 +1613,3 @@ | ||
## MD041 - First line in file should be a top level heading | ||
## MD041 - First line in a file should be a top-level heading | ||
@@ -1613,3 +1623,3 @@ Tags: headings, headers | ||
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 the file isn't a top-level (h1) heading: | ||
@@ -1620,3 +1630,3 @@ ```markdown | ||
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 file: | ||
@@ -1626,15 +1636,25 @@ ```markdown | ||
This is a file with a top level heading | ||
This is a file with a top-level heading | ||
``` | ||
Note: The `level` parameter can be used to change the top level (ex: to h2) in cases | ||
where a h1 is added externally. | ||
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 | ||
permitted by this rule. For example: | ||
If [YAML](https://en.wikipedia.org/wiki/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 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`. | ||
```markdown | ||
<h1 align="center"><img src="https://placekitten.com/300/150"/></h1> | ||
Rationale: The top level heading often acts as the title of a document. More | ||
This is a file with a top-level HTML heading | ||
``` | ||
Note: The `level` parameter can be used to change the top-level (ex: to h2) in cases | ||
where an h1 is added externally. | ||
If [YAML](https://en.wikipedia.org/wiki/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 via the `front_matter_title` parameter. | ||
To disable the use of front matter by this rule, specify `""` for `front_matter_title`. | ||
Rationale: The top-level heading often acts as the title of a document. More | ||
information: <https://cirosantilli.com/markdown-style-guide#top-level-header>. | ||
@@ -1835,8 +1855,9 @@ | ||
<!-- markdownlint-enable code-block-style --> | ||
<!-- markdownlint-restore --> | ||
To fix violations of this rule, use a consistent style (either indenting or code fences). | ||
To fix violations of this rule, use a consistent style (either indenting or code | ||
fences). | ||
The specified style can be specific (`fenced`, `indented`) or simply require that usage | ||
be consistent within the document (`consistent`). | ||
The specified style can be specific (`fenced`, `indented`) or simply require | ||
that usage be consistent within the document (`consistent`). | ||
@@ -1855,5 +1876,6 @@ Rationale: Consistent formatting makes it easier to understand a document. | ||
This rule is triggered when there is not a single newline character at the end of a file. | ||
This rule is triggered when there is not a single newline character at the end | ||
of a file. | ||
Example that triggers the rule: | ||
An example that triggers the rule: | ||
@@ -1888,3 +1910,4 @@ ```markdown | ||
This rule is triggered when the symbols used in the document for fenced code blocks do not match the configured code fence style: | ||
This rule is triggered when the symbols used in the document for fenced code | ||
blocks do not match the configured code fence style: | ||
@@ -1891,0 +1914,0 @@ ````markdown |
@@ -102,6 +102,6 @@ // @ts-check | ||
// Replaces the text of all properly-formatted HTML comments with whitespace | ||
// Replaces the content of properly-formatted CommonMark comments with "." | ||
// This preserves the line/column information for the rest of the document | ||
// Trailing whitespace is avoided with a '\' character in the last column | ||
// See https://www.w3.org/TR/html5/syntax.html#comments for details | ||
// https://spec.commonmark.org/0.29/#html-blocks | ||
// https://spec.commonmark.org/0.29/#html-comment | ||
const htmlCommentBegin = "<!--"; | ||
@@ -112,3 +112,3 @@ const htmlCommentEnd = "-->"; | ||
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) { | ||
const j = text.indexOf(htmlCommentEnd, i); | ||
const j = text.indexOf(htmlCommentEnd, i + 2); | ||
if (j === -1) { | ||
@@ -118,14 +118,29 @@ // Un-terminated comments are treated as text | ||
} | ||
const comment = text.slice(i + htmlCommentBegin.length, j); | ||
if ((comment.length > 0) && | ||
(comment[0] !== ">") && | ||
(comment[comment.length - 1] !== "-") && | ||
!comment.includes("--") && | ||
(text.slice(i, j + htmlCommentEnd.length) | ||
.search(inlineCommentRe) === -1)) { | ||
const blanks = comment | ||
.replace(/[^\r\n]/g, " ") | ||
.replace(/ ([\r\n])/g, "\\$1"); | ||
text = text.slice(0, i + htmlCommentBegin.length) + | ||
blanks + text.slice(j); | ||
// If the comment has content... | ||
if (j > i + htmlCommentBegin.length) { | ||
let k = i - 1; | ||
while (text[k] === " ") { | ||
k--; | ||
} | ||
// If comment is not within an indented code block... | ||
if (k >= i - 4) { | ||
const content = text.slice(i + htmlCommentBegin.length, j); | ||
const isBlock = (k < 0) || (text[k] === "\n"); | ||
const isValid = isBlock || | ||
(!content.startsWith(">") && !content.startsWith("->") && | ||
!content.endsWith("-") && !content.includes("--")); | ||
// If a valid block/inline comment... | ||
if (isValid) { | ||
const inlineCommentIndex = text | ||
.slice(i, j + htmlCommentEnd.length) | ||
.search(inlineCommentRe); | ||
// If not a markdownlint inline directive... | ||
if (inlineCommentIndex === -1) { | ||
text = | ||
text.slice(0, i + htmlCommentBegin.length) + | ||
content.replace(/[^\r\n]/g, ".") + | ||
text.slice(j); | ||
} | ||
} | ||
} | ||
} | ||
@@ -179,3 +194,3 @@ i = j + htmlCommentEnd.length; | ||
const line = token.line.replace(/^[\s>]*(> |>)/, ""); | ||
return line.length - line.trimLeft().length; | ||
return line.length - line.trimStart().length; | ||
} | ||
@@ -230,8 +245,22 @@ module.exports.indentFor = indentFor; | ||
/** | ||
* Returns whether a token is a math block (created by markdown-it-texmath). | ||
* | ||
* @param {Object} token MarkdownItToken instance. | ||
* @returns {boolean} True iff token is a math block. | ||
*/ | ||
function isMathBlock(token) { | ||
return ( | ||
(token.tag === "math") && | ||
token.type.startsWith("math_block") && | ||
!token.type.endsWith("_end") | ||
); | ||
} | ||
// Get line metadata array | ||
module.exports.getLineMetadata = function getLineMetadata(params) { | ||
const lineMetadata = params.lines.map(function mapLine(line, index) { | ||
return [ line, index, false, 0, false, false ]; | ||
}); | ||
filterTokens(params, "fence", function forToken(token) { | ||
const lineMetadata = params.lines.map( | ||
(line, index) => [ line, index, false, 0, false, false, false, false ] | ||
); | ||
filterTokens(params, "fence", (token) => { | ||
lineMetadata[token.map[0]][3] = 1; | ||
@@ -243,3 +272,3 @@ lineMetadata[token.map[1] - 1][3] = -1; | ||
}); | ||
filterTokens(params, "code_block", function forToken(token) { | ||
filterTokens(params, "code_block", (token) => { | ||
for (let i = token.map[0]; i < token.map[1]; i++) { | ||
@@ -249,3 +278,3 @@ lineMetadata[i][2] = true; | ||
}); | ||
filterTokens(params, "table_open", function forToken(token) { | ||
filterTokens(params, "table_open", (token) => { | ||
for (let i = token.map[0]; i < token.map[1]; i++) { | ||
@@ -255,3 +284,3 @@ lineMetadata[i][4] = true; | ||
}); | ||
filterTokens(params, "list_item_open", function forToken(token) { | ||
filterTokens(params, "list_item_open", (token) => { | ||
let count = 1; | ||
@@ -263,5 +292,10 @@ for (let i = token.map[0]; i < token.map[1]; i++) { | ||
}); | ||
filterTokens(params, "hr", function forToken(token) { | ||
filterTokens(params, "hr", (token) => { | ||
lineMetadata[token.map[0]][6] = true; | ||
}); | ||
params.tokens.filter(isMathBlock).forEach((token) => { | ||
for (let i = token.map[0]; i < token.map[1]; i++) { | ||
lineMetadata[i][7] = true; | ||
} | ||
}); | ||
return lineMetadata; | ||
@@ -273,3 +307,4 @@ }; | ||
lineMetadata.forEach(function forMetadata(metadata) { | ||
// Parameters: line, lineIndex, inCode, onFence, inTable, inItem, inBreak | ||
// Parameters: | ||
// line, lineIndex, inCode, onFence, inTable, inItem, inBreak, inMath | ||
handler(...metadata); | ||
@@ -287,9 +322,5 @@ }); | ||
let lastWithMap = { "map": [ 0, 1 ] }; | ||
params.tokens.forEach(function forToken(token) { | ||
if ( | ||
(token.type === "math_block") && | ||
(token.tag === "math") && | ||
token.map[1] | ||
) { | ||
// markdown-it-texmath package does not account for math_block_end | ||
params.tokens.forEach((token) => { | ||
if (isMathBlock(token) && token.map[1]) { | ||
// markdown-it-texmath plugin does not account for math_block_end | ||
token.map[1]++; | ||
@@ -706,4 +737,5 @@ } | ||
(lineIndex !== lastLineIndex) || | ||
((editIndex + deleteCount) < lastEditIndex) || | ||
(deleteCount === -1) | ||
(deleteCount === -1) || | ||
((editIndex + deleteCount) <= | ||
(lastEditIndex - ((deleteCount > 0) ? 0 : 1))) | ||
) { | ||
@@ -710,0 +742,0 @@ lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding); |
{ | ||
"name": "markdownlint-rule-helpers", | ||
"version": "0.13.0", | ||
"version": "0.14.0", | ||
"description": "A collection of markdownlint helper functions for custom rules", | ||
@@ -5,0 +5,0 @@ "main": "helpers.js", |
@@ -313,3 +313,3 @@ export = markdownlint; | ||
*/ | ||
fixInfo: FixInfo; | ||
fixInfo?: FixInfo; | ||
}; | ||
@@ -316,0 +316,0 @@ /** |
@@ -54,6 +54,8 @@ // @ts-check | ||
}); | ||
if (!result && rule.information) { | ||
if (Object.getPrototypeOf(rule.information) !== URL.prototype) { | ||
result = newError("information"); | ||
} | ||
if ( | ||
!result && | ||
rule.information && | ||
(Object.getPrototypeOf(rule.information) !== URL.prototype) | ||
) { | ||
result = newError("information"); | ||
} | ||
@@ -725,2 +727,3 @@ if (!result) { | ||
callback = callback || function noop() {}; | ||
// eslint-disable-next-line unicorn/prefer-spread | ||
const ruleList = rules.concat(options.customRules || []); | ||
@@ -858,3 +861,3 @@ const ruleErr = validateRuleList(ruleList); | ||
const markdownlintPromisify = promisify(markdownlint); | ||
const markdownlintPromisify = promisify && promisify(markdownlint); | ||
@@ -991,3 +994,3 @@ /** | ||
const readConfigPromisify = promisify(readConfig); | ||
const readConfigPromisify = promisify && promisify(readConfig); | ||
@@ -1185,3 +1188,3 @@ /** | ||
* @property {number[]} errorRange Column number (1-based) and length. | ||
* @property {FixInfo} fixInfo Fix information. | ||
* @property {FixInfo} [fixInfo] Fix information. | ||
*/ | ||
@@ -1188,0 +1191,0 @@ |
@@ -9,3 +9,3 @@ // @ts-check | ||
"names": [ "MD002", "first-heading-h1", "first-header-h1" ], | ||
"description": "First heading should be a top level heading", | ||
"description": "First heading should be a top-level heading", | ||
"tags": [ "headings", "headers" ], | ||
@@ -12,0 +12,0 @@ "function": function MD002(params, onError) { |
@@ -5,6 +5,18 @@ // @ts-check | ||
const { addErrorDetailIf, listItemMarkerRe, | ||
rangeFromRegExp, unorderedListStyleFor } = require("../helpers"); | ||
const { addErrorDetailIf, listItemMarkerRe, unorderedListStyleFor } = | ||
require("../helpers"); | ||
const { flattenedLists } = require("./cache"); | ||
const expectedStyleToMarker = { | ||
"dash": "-", | ||
"plus": "+", | ||
"asterisk": "*" | ||
}; | ||
const differentItemStyle = { | ||
"dash": "plus", | ||
"plus": "asterisk", | ||
"asterisk": "dash" | ||
}; | ||
const validStyles = Object.keys(expectedStyleToMarker); | ||
module.exports = { | ||
@@ -27,15 +39,36 @@ "names": [ "MD004", "ul-style" ], | ||
const nesting = list.nesting; | ||
if (!nestingStyles[nesting] && | ||
(itemStyle !== nestingStyles[nesting - 1])) { | ||
nestingStyles[nesting] = itemStyle; | ||
} else { | ||
addErrorDetailIf(onError, item.lineNumber, | ||
nestingStyles[nesting], itemStyle, null, null, | ||
rangeFromRegExp(item.line, listItemMarkerRe)); | ||
if (!nestingStyles[nesting]) { | ||
nestingStyles[nesting] = | ||
(itemStyle === nestingStyles[nesting - 1]) ? | ||
differentItemStyle[itemStyle] : | ||
itemStyle; | ||
} | ||
} else { | ||
addErrorDetailIf(onError, item.lineNumber, | ||
expectedStyle, itemStyle, null, null, | ||
rangeFromRegExp(item.line, listItemMarkerRe)); | ||
expectedStyle = nestingStyles[nesting]; | ||
} | ||
if (!validStyles.includes(expectedStyle)) { | ||
expectedStyle = validStyles[0]; | ||
} | ||
let range = null; | ||
let fixInfo = null; | ||
const match = item.line.match(listItemMarkerRe); | ||
if (match) { | ||
const column = match.index + 1; | ||
const length = match[0].length; | ||
range = [ column, length ]; | ||
fixInfo = { | ||
"editColumn": match[1].length + 1, | ||
"deleteCount": 1, | ||
"insertText": expectedStyleToMarker[expectedStyle] | ||
}; | ||
} | ||
addErrorDetailIf( | ||
onError, | ||
item.lineNumber, | ||
expectedStyle, | ||
itemStyle, | ||
null, | ||
null, | ||
range, | ||
fixInfo | ||
); | ||
}); | ||
@@ -42,0 +75,0 @@ } |
@@ -28,3 +28,3 @@ // @ts-check | ||
{ | ||
"deleteCount": line.length - line.trimLeft().length | ||
"deleteCount": line.length - line.trimStart().length | ||
}); | ||
@@ -31,0 +31,0 @@ }); |
@@ -52,22 +52,26 @@ // @ts-check | ||
const lineNumber = lineIndex + 1; | ||
const trailingSpaces = line.length - line.trimRight().length; | ||
if (trailingSpaces && !inCode && | ||
!includesSorted(listItemLineNumbers, lineNumber)) { | ||
if ((expected !== trailingSpaces) || | ||
(strict && | ||
(!includesSorted(paragraphLineNumbers, lineNumber) || | ||
includesSorted(codeInlineLineNumbers, lineNumber)))) { | ||
const column = line.length - trailingSpaces + 1; | ||
addError( | ||
onError, | ||
lineNumber, | ||
"Expected: " + (expected === 0 ? "" : "0 or ") + | ||
expected + "; Actual: " + trailingSpaces, | ||
null, | ||
[ column, trailingSpaces ], | ||
{ | ||
"editColumn": column, | ||
"deleteCount": trailingSpaces | ||
}); | ||
} | ||
const trailingSpaces = line.length - line.trimEnd().length; | ||
if ( | ||
trailingSpaces && | ||
!inCode && | ||
!includesSorted(listItemLineNumbers, lineNumber) && | ||
( | ||
(expected !== trailingSpaces) || | ||
(strict && | ||
(!includesSorted(paragraphLineNumbers, lineNumber) || | ||
includesSorted(codeInlineLineNumbers, lineNumber))) | ||
) | ||
) { | ||
const column = line.length - trailingSpaces + 1; | ||
addError( | ||
onError, | ||
lineNumber, | ||
"Expected: " + (expected === 0 ? "" : "0 or ") + | ||
expected + "; Actual: " + trailingSpaces, | ||
null, | ||
[ column, trailingSpaces ], | ||
{ | ||
"editColumn": column, | ||
"deleteCount": trailingSpaces | ||
}); | ||
} | ||
@@ -74,0 +78,0 @@ }); |
@@ -15,3 +15,3 @@ // @ts-check | ||
if (!inCode && | ||
/^#+[^#\s]/.test(line) && | ||
/^#+[^# \t]/.test(line) && | ||
!/#\s*$/.test(line) && | ||
@@ -18,0 +18,0 @@ !line.startsWith("#️⃣")) { |
@@ -16,3 +16,3 @@ // @ts-check | ||
const { line, lineNumber } = token; | ||
const match = /^(#+)(\s{2,})(?:\S)/.exec(line); | ||
const match = /^(#+)([ \t]{2,})(?:\S)/.exec(line); | ||
if (match) { | ||
@@ -19,0 +19,0 @@ const [ |
@@ -16,3 +16,3 @@ // @ts-check | ||
const match = | ||
/^(#+)(\s*)([^#]*?[^#\\])(\s*)((?:\\#)?)(#+)(\s*)$/.exec(line); | ||
/^(#+)([ \t]*)([^#]*?[^#\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line); | ||
if (match) { | ||
@@ -19,0 +19,0 @@ const [ |
@@ -16,3 +16,3 @@ // @ts-check | ||
const { line, lineNumber } = token; | ||
const match = /^(#+)(\s+)([^#]+?)(\s+)(#+)(\s*)$/.exec(line); | ||
const match = /^(#+)([ \t]+)([^#]+?)([ \t]+)(#+)(\s*)$/.exec(line); | ||
if (match) { | ||
@@ -19,0 +19,0 @@ const [ |
@@ -20,3 +20,3 @@ // @ts-check | ||
let deleteCount = prefix.length; | ||
const prefixLengthNoSpace = prefix.trimRight().length; | ||
const prefixLengthNoSpace = prefix.trimEnd().length; | ||
if (prefixLengthNoSpace) { | ||
@@ -23,0 +23,0 @@ deleteCount -= prefixLengthNoSpace - 1; |
@@ -10,3 +10,3 @@ // @ts-check | ||
"names": [ "MD025", "single-title", "single-h1" ], | ||
"description": "Multiple top level headings in the same document", | ||
"description": "Multiple top-level headings in the same document", | ||
"tags": [ "headings", "headers" ], | ||
@@ -13,0 +13,0 @@ "function": function MD025(params, onError) { |
@@ -20,3 +20,3 @@ // @ts-check | ||
const line = lines[firstIndex]; | ||
const quotePrefix = line.match(quotePrefixRe)[0].trimRight(); | ||
const quotePrefix = line.match(quotePrefixRe)[0].trimEnd(); | ||
addErrorContext( | ||
@@ -36,3 +36,3 @@ onError, | ||
const line = lines[lastIndex]; | ||
const quotePrefix = line.match(quotePrefixRe)[0].trimRight(); | ||
const quotePrefix = line.match(quotePrefixRe)[0].trimEnd(); | ||
addErrorContext( | ||
@@ -39,0 +39,0 @@ onError, |
@@ -13,2 +13,3 @@ // @ts-check | ||
const rightSpaceRe = /\s+$/; | ||
const tablePipeRe = /\|/; | ||
@@ -32,14 +33,19 @@ module.exports = { | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
function handleRunEnd(line, lineIndex, contextLength, match, matchIndex) { | ||
function handleRunEnd( | ||
line, lineIndex, contextLength, match, matchIndex, inTable | ||
) { | ||
// Close current run | ||
let content = line.substring(emphasisIndex, matchIndex); | ||
if (!emphasisLength) { | ||
content = content.trimLeft(); | ||
content = content.trimStart(); | ||
} | ||
if (!match) { | ||
content = content.trimRight(); | ||
content = content.trimEnd(); | ||
} | ||
const leftSpace = leftSpaceRe.test(content); | ||
const rightSpace = rightSpaceRe.test(content); | ||
if (leftSpace || rightSpace) { | ||
if ( | ||
(leftSpace || rightSpace) && | ||
(!inTable || !tablePipeRe.test(content)) | ||
) { | ||
// Report the violation | ||
@@ -75,3 +81,3 @@ const contextStart = emphasisIndex - emphasisLength; | ||
lineMetadata(), | ||
(line, lineIndex, inCode, onFence, inTable, inItem, onBreak) => { | ||
(line, lineIndex, inCode, onFence, inTable, inItem, onBreak, inMath) => { | ||
const onItemStart = (inItem === 1); | ||
@@ -82,3 +88,3 @@ if (inCode || inTable || onBreak || onItemStart || isBlankLine(line)) { | ||
} | ||
if (inCode || onBreak) { | ||
if (inCode || onBreak || inMath) { | ||
// Emphasis has no meaning here | ||
@@ -113,2 +119,3 @@ return; | ||
if (pendingError) { | ||
// @ts-ignore | ||
addErrorContext(...pendingError); | ||
@@ -118,4 +125,11 @@ pendingError = null; | ||
const error = handleRunEnd( | ||
line, lineIndex, effectiveEmphasisLength, match, matchIndex); | ||
line, | ||
lineIndex, | ||
effectiveEmphasisLength, | ||
match, | ||
matchIndex, | ||
inTable | ||
); | ||
if (error) { | ||
// @ts-ignore | ||
addErrorContext(...error); | ||
@@ -148,3 +162,3 @@ } | ||
pendingError = pendingError || | ||
handleRunEnd(line, lineIndex, 0, null, line.length); | ||
handleRunEnd(line, lineIndex, 0, null, line.length, inTable); | ||
// Adjust for pending run on new line | ||
@@ -151,0 +165,0 @@ emphasisIndex = 0; |
@@ -27,4 +27,4 @@ // @ts-check | ||
inLink = false; | ||
const left = linkText.trimLeft().length !== linkText.length; | ||
const right = linkText.trimRight().length !== linkText.length; | ||
const left = linkText.trimStart().length !== linkText.length; | ||
const right = linkText.trimEnd().length !== linkText.length; | ||
if (left || right) { | ||
@@ -31,0 +31,0 @@ const line = params.lines[lineNumber - 1]; |
@@ -9,3 +9,3 @@ // @ts-check | ||
"names": [ "MD041", "first-line-heading", "first-line-h1" ], | ||
"description": "First line in file should be a top level heading", | ||
"description": "First line in a file should be a top-level heading", | ||
"tags": [ "headings", "headers" ], | ||
@@ -21,7 +21,18 @@ "function": function MD041(params, onError) { | ||
if (!foundFrontMatterTitle) { | ||
const htmlHeadingRe = new RegExp(`^<h${level}[ />]`, "i"); | ||
params.tokens.every((token) => { | ||
let isError = false; | ||
if (token.type === "html_block") { | ||
return true; | ||
if (token.content.startsWith("<!--")) { | ||
// Ignore leading HTML comments | ||
return true; | ||
} else if (!htmlHeadingRe.test(token.content)) { | ||
// Something other than an HTML heading | ||
isError = true; | ||
} | ||
} else if ((token.type !== "heading_open") || (token.tag !== tag)) { | ||
// Something other than a Markdown heading | ||
isError = true; | ||
} | ||
if ((token.type !== "heading_open") || (token.tag !== tag)) { | ||
if (isError) { | ||
addErrorContext(onError, token.lineNumber, token.line); | ||
@@ -28,0 +39,0 @@ } |
@@ -29,6 +29,6 @@ // @ts-check | ||
const actual = levels[heading.tag] + " " + content; | ||
let expected = getExpected(); | ||
const expected = getExpected(); | ||
if (expected === "*") { | ||
matchAny = true; | ||
expected = getExpected(); | ||
getExpected(); | ||
} else if (expected === "+") { | ||
@@ -35,0 +35,0 @@ matchAny = true; |
@@ -57,5 +57,6 @@ // @ts-check | ||
const name = rule.names[0].toLowerCase(); | ||
rule.information = | ||
// eslint-disable-next-line dot-notation | ||
rule["information"] = | ||
new URL(`${homepage}/blob/v${version}/doc/Rules.md#${name}`); | ||
}); | ||
module.exports = rules; |
{ | ||
"name": "markdownlint", | ||
"version": "0.22.0", | ||
"version": "0.23.0", | ||
"description": "A Node.js style checker and lint tool for Markdown/CommonMark files.", | ||
@@ -16,17 +16,20 @@ "main": "lib/markdownlint.js", | ||
"scripts": { | ||
"test": "tape test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js", | ||
"test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 tape test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js", | ||
"test-declaration": "cd example/typescript && tsc && node type-check.js", | ||
"test-extra": "node test/markdownlint-test-extra.js", | ||
"lint": "eslint --max-warnings 0 lib helpers test schema && eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0, no-console: 0, no-var: 0, unicorn/prefer-add-event-listener: 0, unicorn/prefer-query-selector: 0, unicorn/prefer-replace-all: 0\" demo && eslint --rule \"no-console: 0, no-invalid-this: 0, no-shadow: 0, object-property-newline: 0, node/no-missing-require: 0, node/no-extraneous-require: 0\" example", | ||
"ci": "npm run test-cover && npm run lint && npm run test-declaration", | ||
"build-config": "npm run build-config-schema && npm run build-config-example", | ||
"build-config-example": "node schema/build-config-example.js", | ||
"build-config-schema": "node schema/build-config-schema.js", | ||
"build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'", | ||
"build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && cpy file-header.js . --rename=markdownlint-browser.js && tsc --allowJs --resolveJsonModule --outDir ../lib-es3 ../lib/markdownlint.js && cpy ../helpers/package.json ../lib-es3/helpers && browserify ../lib-es3/lib/markdownlint.js --standalone markdownlint >> markdownlint-browser.js && browserify ../lib-es3/helpers/helpers.js --standalone helpers >> markdownlint-rule-helpers-browser.js && uglifyjs markdownlint-browser.js markdownlint-rule-helpers-browser.js --compress --mangle --comments --output markdownlint-browser.min.js", | ||
"build-demo": "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats", | ||
"build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2", | ||
"ci": "npm-run-all --continue-on-error --parallel test-cover lint declaration build-config build-demo && git diff --exit-code", | ||
"clean-test-repos": "rimraf test-repos", | ||
"clone-test-repos": "mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet", | ||
"clone-test-repos-large": "npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet", | ||
"declaration": "npm run build-declaration && npm run test-declaration", | ||
"example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint", | ||
"clone-test-repos": "make-dir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet", | ||
"clone-test-repos-large": "npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet", | ||
"lint-test-repos": "node test/markdownlint-test-repos.js", | ||
"clean-test-repos": "rimraf test-repos" | ||
"lint": "eslint --max-warnings 0 .", | ||
"lint-test-repos": "ava --timeout=5m test/markdownlint-test-repos.js", | ||
"test": "ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js", | ||
"test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test", | ||
"test-declaration": "cd example/typescript && tsc && node type-check.js", | ||
"test-extra": "ava --timeout=5m test/markdownlint-test-extra.js" | ||
}, | ||
@@ -37,16 +40,14 @@ "engines": { | ||
"dependencies": { | ||
"markdown-it": "12.0.2" | ||
"markdown-it": "12.0.4" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "~14.14.9", | ||
"browserify": "~17.0.0", | ||
"c8": "~7.3.5", | ||
"ava": "~3.15.0", | ||
"c8": "~7.5.0", | ||
"cpy-cli": "~3.1.1", | ||
"eslint": "~7.14.0", | ||
"eslint-plugin-jsdoc": "~30.7.8", | ||
"eslint": "~7.19.0", | ||
"eslint-plugin-jsdoc": "~31.6.0", | ||
"eslint-plugin-node": "~11.1.0", | ||
"eslint-plugin-unicorn": "~23.0.0", | ||
"globby": "~11.0.1", | ||
"js-yaml": "~3.14.0", | ||
"make-dir-cli": "~2.0.0", | ||
"eslint-plugin-unicorn": "~27.0.0", | ||
"globby": "~11.0.2", | ||
"js-yaml": "~4.0.0", | ||
"markdown-it-for-inline": "~0.1.1", | ||
@@ -56,11 +57,12 @@ "markdown-it-sub": "~1.0.0", | ||
"markdown-it-texmath": "~0.8.0", | ||
"markdownlint-rule-helpers": "~0.12.0", | ||
"markdownlint-rule-helpers": "~0.13.0", | ||
"npm-run-all": "~4.1.5", | ||
"rimraf": "~3.0.2", | ||
"strip-json-comments": "~3.1.1", | ||
"tape": "~5.0.1", | ||
"tape-player": "~0.1.1", | ||
"toml": "~3.0.0", | ||
"ts-loader": "~8.0.15", | ||
"tv4": "~1.3.0", | ||
"typescript": "~4.1.2", | ||
"uglify-js": "~3.12.0" | ||
"typescript": "~4.1.3", | ||
"webpack": "~5.21.1", | ||
"webpack-cli": "~4.5.0" | ||
}, | ||
@@ -73,6 +75,3 @@ "keywords": [ | ||
"markdownlint" | ||
], | ||
"browser": { | ||
"markdown-it": "../demo/markdown-it-stub.js" | ||
} | ||
] | ||
} |
155
README.md
@@ -17,8 +17,9 @@ # markdownlint | ||
The [Markdown](https://en.wikipedia.org/wiki/Markdown) markup language is | ||
designed to be easy to read, write, and understand. It succeeds - and its | ||
flexibility is both a benefit and a drawback. Many styles are possible, so | ||
formatting can be inconsistent. Some constructs don't work well in all | ||
parsers and should be avoided. The [CommonMark](https://commonmark.org/) | ||
specification standardizes parsers - but not authors. | ||
The [Markdown](https://en.wikipedia.org/wiki/Markdown) markup language | ||
is designed to be easy to read, write, and understand. It succeeds - | ||
and its flexibility is both a benefit and a drawback. Many styles are | ||
possible, so formatting can be inconsistent. Some constructs don't | ||
work well in all parsers and should be avoided. The | ||
[CommonMark](https://commonmark.org/) specification standardizes | ||
parsers - but not authors. | ||
@@ -43,3 +44,3 @@ `markdownlint` is a | ||
* Editor | ||
* [vscode-markdownlint extension for VS Code](https://marketplace.visualstudio.com/items/DavidAnson.vscode-markdownlint) | ||
* [vscode-markdownlint extension for VS Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) | ||
* [Sublime Text markdownlint for Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint) | ||
@@ -61,4 +62,6 @@ * [linter-node-markdownlint extension for Atom](https://atom.io/packages/linter-node-markdownlint) | ||
<!-- markdownlint-disable line-length --> | ||
* **[MD001](doc/Rules.md#md001)** *heading-increment/header-increment* - Heading levels should only increment by one level at a time | ||
* ~~**[MD002](doc/Rules.md#md002)** *first-heading-h1/first-header-h1* - First heading should be a top level heading~~ | ||
* ~~**[MD002](doc/Rules.md#md002)** *first-heading-h1/first-header-h1* - First heading should be a top-level heading~~ | ||
* **[MD003](doc/Rules.md#md003)** *heading-style/header-style* - Heading style | ||
@@ -82,3 +85,3 @@ * **[MD004](doc/Rules.md#md004)** *ul-style* - Unordered list style | ||
* **[MD024](doc/Rules.md#md024)** *no-duplicate-heading/no-duplicate-header* - Multiple headings with the same content | ||
* **[MD025](doc/Rules.md#md025)** *single-title/single-h1* - Multiple top level headings in the same document | ||
* **[MD025](doc/Rules.md#md025)** *single-title/single-h1* - Multiple top-level headings in the same document | ||
* **[MD026](doc/Rules.md#md026)** *no-trailing-punctuation* - Trailing punctuation in heading | ||
@@ -99,3 +102,3 @@ * **[MD027](doc/Rules.md#md027)** *no-multiple-space-blockquote* - Multiple spaces after blockquote symbol | ||
* **[MD040](doc/Rules.md#md040)** *fenced-code-language* - Fenced code blocks should have a language specified | ||
* **[MD041](doc/Rules.md#md041)** *first-line-heading/first-line-h1* - First line in file should be a top level heading | ||
* **[MD041](doc/Rules.md#md041)** *first-line-heading/first-line-h1* - First line in a file should be a top-level heading | ||
* **[MD042](doc/Rules.md#md042)** *no-empty-links* - No empty links | ||
@@ -109,2 +112,4 @@ * **[MD043](doc/Rules.md#md043)** *required-headings/required-headers* - Required heading structure | ||
<!-- markdownlint-restore --> | ||
See [Rules.md](doc/Rules.md) for more details. | ||
@@ -114,4 +119,4 @@ | ||
> All rules with `heading` as part of their name are also available as `header` | ||
> aliases (e.g. `heading-increment` is also available as `header-increment`). | ||
> All rules with `heading` as part of their name are also available as | ||
> `header` aliases (e.g. `heading-increment` is also available as `header-increment`). | ||
> The use of `header` is deprecated and provided for backward-compatibility. | ||
@@ -121,3 +126,4 @@ | ||
Tags group related rules and can be used to enable/disable multiple rules at once. | ||
Tags group related rules and can be used to enable/disable multiple | ||
rules at once. | ||
@@ -133,6 +139,6 @@ * **accessibility** - MD045 | ||
* **hard_tab** - MD010 | ||
* **headers** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023, | ||
MD024, MD025, MD026, MD036, MD041, MD043 | ||
* **headings** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, MD023, | ||
MD024, MD025, MD026, MD036, MD041, MD043 | ||
* **headers** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, | ||
MD023, MD024, MD025, MD026, MD036, MD041, MD043 | ||
* **headings** - MD001, MD002, MD003, MD018, MD019, MD020, MD021, MD022, | ||
MD023, MD024, MD025, MD026, MD036, MD041, MD043 | ||
* **hr** - MD035 | ||
@@ -150,16 +156,19 @@ * **html** - MD033 | ||
* **url** - MD034 | ||
* **whitespace** - MD009, MD010, MD012, MD027, MD028, MD030, MD037, MD038, MD039 | ||
* **whitespace** - MD009, MD010, MD012, MD027, MD028, MD030, MD037, | ||
MD038, MD039 | ||
## Configuration | ||
Text passed to `markdownlint` is parsed as Markdown, analyzed, and any issues reported. | ||
Two kinds of text are ignored: | ||
Text passed to `markdownlint` is parsed as Markdown, analyzed, and any | ||
issues reported. Two kinds of text are ignored: | ||
* [HTML comments](https://www.w3.org/TR/html5/syntax.html#comments) | ||
* [Front matter](https://jekyllrb.com/docs/frontmatter/) (see `options.frontMatter` below) | ||
* [Front matter](https://jekyllrb.com/docs/frontmatter/) (see | ||
`options.frontMatter` below) | ||
Rules can be enabled, disabled, and configured via `options.config` (described | ||
below) to define the expected behavior for a set of inputs. To enable or disable | ||
rules at a particular location within a file, add one of these markers to the | ||
appropriate place (HTML comments don't appear in the final markup): | ||
Rules can be enabled, disabled, and configured via `options.config` | ||
(described below) to define the expected behavior for a set of inputs. | ||
To enable or disable rules at a particular location within a file, add | ||
one of these markers to the appropriate place (HTML comments don't | ||
appear in the final markup): | ||
@@ -199,5 +208,5 @@ * Disable all rules: `<!-- markdownlint-disable -->` | ||
The initial configuration is captured by default (as if every document began | ||
with `<!-- markdownlint-capture -->`), so the pattern above can be expressed | ||
more simply: | ||
The initial configuration is captured by default (as if every document | ||
began with `<!-- markdownlint-capture -->`), so the pattern above can | ||
be expressed more simply: | ||
@@ -227,4 +236,4 @@ ```markdown | ||
In cases where it is desirable to change the configuration of one or more rules | ||
for a file, the following more advanced syntax is supported: | ||
In cases where it is desirable to change the configuration of one or | ||
more rules for a file, the following more advanced syntax is supported: | ||
@@ -252,4 +261,4 @@ * Configure: `<!-- markdownlint-configure-file { options.config JSON } -->` | ||
These changes apply to the entire file regardless of where the comment is | ||
located. Multiple such comments (if present) are applied top-to-bottom. | ||
These changes apply to the entire file regardless of where the comment | ||
is located. Multiple such comments (if present) are applied top-to-bottom. | ||
@@ -310,4 +319,5 @@ ## API | ||
Each array element should define a rule. Rules are typically exported by another | ||
package, but can be defined locally. Custom rules are identified by the | ||
Each array element should define a rule. Rules are typically exported | ||
by another package, but can be defined locally. Custom rules are | ||
identified by the | ||
[keyword `markdownlint-rule` on npm](https://www.npmjs.com/search?q=keywords:markdownlint-rule). | ||
@@ -324,3 +334,4 @@ | ||
See [CustomRules.md](doc/CustomRules.md) for details about authoring custom rules. | ||
See [CustomRules.md](doc/CustomRules.md) for details about authoring | ||
custom rules. | ||
@@ -334,4 +345,4 @@ ##### options.files | ||
Each array element should be a single file (via relative or absolute path); | ||
[globbing](https://en.wikipedia.org/wiki/Glob_%28programming%29) is the caller's | ||
responsibility. | ||
[globbing](https://en.wikipedia.org/wiki/Glob_%28programming%29) is the | ||
caller's responsibility. | ||
@@ -346,5 +357,5 @@ Example: `[ "one.md", "dir/two.md" ]` | ||
When Markdown content is not available as files, it can be passed as strings. | ||
The keys of the `strings` object are used to identify each input value in the | ||
`result` summary. | ||
When Markdown content is not available as files, it can be passed as | ||
strings. The keys of the `strings` object are used to identify each | ||
input value in the `result` summary. | ||
@@ -369,8 +380,9 @@ Example: | ||
and passing an object customizes its settings. Setting the special `default` | ||
rule to `true` or `false` includes/excludes all rules by default. Enabling or | ||
disabling a tag name (ex: `whitespace`) affects all rules having that tag. | ||
rule to `true` or `false` includes/excludes all rules by default. Enabling | ||
or disabling a tag name (ex: `whitespace`) affects all rules having that | ||
tag. | ||
The `default` rule is applied first, then keys are processed in order from top | ||
to bottom with later values overriding earlier ones. Keys (including rule names, | ||
aliases, tags, and `default`) are not case-sensitive. | ||
The `default` rule is applied first, then keys are processed in order | ||
from top to bottom with later values overriding earlier ones. Keys | ||
(including rule names, aliases, tags, and `default`) are not case-sensitive. | ||
@@ -389,5 +401,9 @@ Example: | ||
Sets of rules (known as a "style") can be stored separately and loaded as | ||
[JSON](https://en.wikipedia.org/wiki/JSON). | ||
See [.markdownlint.jsonc](schema/.markdownlint.jsonc) and/or | ||
[.markdownlint.yaml](schema/.markdownlint.yaml) for an example | ||
configuration object with all properties set to the default value. | ||
Sets of rules (known as a "style") can be stored separately and loaded | ||
as [JSON](https://en.wikipedia.org/wiki/JSON). | ||
Example: | ||
@@ -405,6 +421,8 @@ | ||
See [markdownlint-config-schema.json](schema/markdownlint-config-schema.json) | ||
for the [JSON Schema](https://json-schema.org/) of the `options.config` object. | ||
for the [JSON Schema](https://json-schema.org/) of the `options.config` | ||
object. | ||
For more advanced scenarios, styles can reference and extend other styles. The | ||
`readConfig` and `readConfigSync` functions can be used to read such styles. | ||
For more advanced scenarios, styles can reference and extend other styles. | ||
The `readConfig` and `readConfigSync` functions can be used to read such | ||
styles. | ||
@@ -451,8 +469,8 @@ For example, assuming a `base.json` configuration file: | ||
Matches any [front matter](https://jekyllrb.com/docs/frontmatter/) found at the | ||
beginning of a file. | ||
Matches any [front matter](https://jekyllrb.com/docs/frontmatter/) | ||
found at the beginning of a file. | ||
Some Markdown content begins with metadata; the default `RegExp` for this option | ||
ignores common forms of "front matter". To match differently, specify a custom | ||
`RegExp` or use the value `null` to disable the feature. | ||
Some Markdown content begins with metadata; the default `RegExp` for | ||
this option ignores common forms of "front matter". To match differently, | ||
specify a custom `RegExp` or use the value `null` to disable the feature. | ||
@@ -482,12 +500,12 @@ The default value: | ||
Catches exceptions thrown during rule processing and reports the problem as a | ||
rule violation. | ||
Catches exceptions thrown during rule processing and reports the problem | ||
as a rule violation. | ||
By default, exceptions thrown by rules (or the library itself) are unhandled | ||
and bubble up the stack to the caller in the conventional manner. By setting | ||
`handleRuleFailures` to `true`, exceptions thrown by failing rules will be | ||
handled by the library and the exception message logged as a rule violation. | ||
`handleRuleFailures` to `true`, exceptions thrown by failing rules will | ||
be handled by the library and the exception message logged as a rule violation. | ||
This setting can be useful in the presence of (custom) rules that encounter | ||
unexpected syntax and fail. By enabling this option, the linting process is | ||
allowed to continue and report any violations that were found. | ||
unexpected syntax and fail. By enabling this option, the linting process | ||
is allowed to continue and report any violations that were found. | ||
@@ -632,3 +650,3 @@ ##### options.noInlineConfig | ||
```js | ||
[ JSON.parse, require("toml").parse, require("js-yaml").safeLoad ] | ||
[ JSON.parse, require("toml").parse, require("js-yaml").load ] | ||
``` | ||
@@ -676,7 +694,7 @@ | ||
bad.string: 3: MD018/no-missing-space-atx No space after hash on atx style heading [Context: "#This string fails some rules."] | ||
bad.string: 1: MD041/first-line-heading/first-line-h1 First line in file should be a top level heading [Context: "#bad.string"] | ||
bad.string: 1: MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "#bad.string"] | ||
bad.md: 3: MD010/no-hard-tabs Hard tabs [Column: 17] | ||
bad.md: 1: MD018/no-missing-space-atx No space after hash on atx style heading [Context: "#bad.md"] | ||
bad.md: 3: MD018/no-missing-space-atx No space after hash on atx style heading [Context: "#This file fails some rules."] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in file should be a top level heading [Context: "#bad.md"] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "#bad.md"] | ||
``` | ||
@@ -730,3 +748,3 @@ | ||
"ruleNames": [ "MD041", "first-line-heading", "first-line-h1" ], | ||
"ruleDescription": "First line in file should be a top level heading", | ||
"ruleDescription": "First line in a file should be a top-level heading", | ||
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md041", | ||
@@ -770,3 +788,3 @@ "errorDetail": null, | ||
bad.md: 3: MD018/no-missing-space-atx No space after hash on atx style heading [Context: "#This file fails some rules."] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in file should be a top level heading [Context: "#bad.md"] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "#bad.md"] | ||
[00:00:00] Finished 'markdownlint' after 10 ms | ||
@@ -812,3 +830,3 @@ ``` | ||
bad.md: 3: MD018/no-missing-space-atx No space after hash on atx style heading [Context: "#This file fails some rules."] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in file should be a top level heading [Context: "#bad.md"] | ||
bad.md: 1: MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "#bad.md"] | ||
Use --force to continue. | ||
@@ -949,2 +967,5 @@ ``` | ||
MD009/MD026/MD028/MD043, update dependencies (including `markdown-it` to v12). | ||
* 0.23.0 - Add comprehensive example `.markdownlint.jsonc`/`.markdownlint.yaml` files, add fix | ||
information for MD004/ul-style, improve MD018/MD019/MD020/MD021/MD037/MD041, improve | ||
HTML comment handling, update test runner and test suite, update dependencies. | ||
@@ -951,0 +972,0 @@ [npm-image]: https://img.shields.io/npm/v/markdownlint.svg |
@@ -21,3 +21,6 @@ // @ts-check | ||
"description": "Path to configuration file to extend", | ||
"type": "string", | ||
"type": [ | ||
"string", | ||
"null" | ||
], | ||
"default": null | ||
@@ -335,3 +338,3 @@ }, | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -344,3 +347,3 @@ "headers": { | ||
}, | ||
"default": null | ||
"default": [] | ||
} | ||
@@ -357,3 +360,3 @@ }; | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -360,0 +363,0 @@ "code_blocks": { |
@@ -12,3 +12,6 @@ { | ||
"description": "Path to configuration file to extend", | ||
"type": "string", | ||
"type": [ | ||
"string", | ||
"null" | ||
], | ||
"default": null | ||
@@ -37,3 +40,3 @@ }, | ||
"MD002": { | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top level heading", | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading", | ||
"type": [ | ||
@@ -54,3 +57,3 @@ "boolean", | ||
"first-heading-h1": { | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top level heading", | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading", | ||
"type": [ | ||
@@ -71,3 +74,3 @@ "boolean", | ||
"first-header-h1": { | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top level heading", | ||
"description": "MD002/first-heading-h1/first-header-h1 - First heading should be a top-level heading", | ||
"type": [ | ||
@@ -697,3 +700,3 @@ "boolean", | ||
"MD025": { | ||
"description": "MD025/single-title/single-h1 - Multiple top level headings in the same document", | ||
"description": "MD025/single-title/single-h1 - Multiple top-level headings in the same document", | ||
"type": [ | ||
@@ -719,3 +722,3 @@ "boolean", | ||
"single-title": { | ||
"description": "MD025/single-title/single-h1 - Multiple top level headings in the same document", | ||
"description": "MD025/single-title/single-h1 - Multiple top-level headings in the same document", | ||
"type": [ | ||
@@ -741,3 +744,3 @@ "boolean", | ||
"single-h1": { | ||
"description": "MD025/single-title/single-h1 - Multiple top level headings in the same document", | ||
"description": "MD025/single-title/single-h1 - Multiple top-level headings in the same document", | ||
"type": [ | ||
@@ -1131,3 +1134,3 @@ "boolean", | ||
"MD041": { | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in file should be a top level heading", | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading", | ||
"type": [ | ||
@@ -1153,3 +1156,3 @@ "boolean", | ||
"first-line-heading": { | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in file should be a top level heading", | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading", | ||
"type": [ | ||
@@ -1175,3 +1178,3 @@ "boolean", | ||
"first-line-h1": { | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in file should be a top level heading", | ||
"description": "MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading", | ||
"type": [ | ||
@@ -1220,3 +1223,3 @@ "boolean", | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -1229,3 +1232,3 @@ "headers": { | ||
}, | ||
"default": null | ||
"default": [] | ||
} | ||
@@ -1249,3 +1252,3 @@ }, | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -1258,3 +1261,3 @@ "headers": { | ||
}, | ||
"default": null | ||
"default": [] | ||
} | ||
@@ -1278,3 +1281,3 @@ }, | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -1287,3 +1290,3 @@ "headers": { | ||
}, | ||
"default": null | ||
"default": [] | ||
} | ||
@@ -1307,3 +1310,3 @@ }, | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -1332,3 +1335,3 @@ "code_blocks": { | ||
}, | ||
"default": null | ||
"default": [] | ||
}, | ||
@@ -1335,0 +1338,0 @@ "code_blocks": { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
23
67
950
4
0
473183
10279
+ Addedentities@2.1.0(transitive)
+ Addedmarkdown-it@12.0.4(transitive)
- Removedentities@2.0.3(transitive)
- Removedmarkdown-it@12.0.2(transitive)
Updatedmarkdown-it@12.0.4