@alexlit/lint-kit 127.2.0 → 127.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/config-markdownlint/node_modules/markdownlint/CHANGELOG.md +457 -0
- package/packages/config-markdownlint/node_modules/markdownlint/CONTRIBUTING.md +93 -0
- package/packages/config-markdownlint/node_modules/markdownlint/LICENSE +21 -0
- package/packages/config-markdownlint/node_modules/markdownlint/README.md +1047 -0
- package/packages/config-markdownlint/node_modules/markdownlint/demo/markdownlint-browser.js +7094 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/CustomRules.md +388 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/Prettier.md +27 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/ReleaseProcess.md +20 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/Rules.md +2528 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md001.md +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md003.md +59 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md004.md +49 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md005.md +53 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md007.md +52 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md009.md +51 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md010.md +56 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md011.md +30 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md012.md +38 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md013.md +58 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md014.md +54 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md018.md +27 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md019.md +28 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md020.md +29 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md021.md +31 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md022.md +52 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md023.md +33 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md024.md +44 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md025.md +49 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md026.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md027.md +24 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md028.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md029.md +98 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md030.md +82 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md031.md +50 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md032.md +55 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md033.md +27 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md034.md +55 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md035.md +42 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md036.md +45 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md037.md +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md038.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md039.md +21 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md040.md +52 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md041.md +49 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md042.md +32 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md043.md +69 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md044.md +45 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md045.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md046.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md047.md +34 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md048.md +41 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md049.md +35 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md050.md +35 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md051.md +87 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md052.md +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md053.md +38 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md054.md +100 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md055.md +54 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md056.md +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/doc/md058.md +48 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/LICENSE +21 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/README.md +46 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/helpers.js +793 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/micromark.cjs +544 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/package.json +26 -0
- package/packages/config-markdownlint/node_modules/markdownlint/helpers/shared.js +10 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/cache.js +70 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/configuration-strict.d.ts +1185 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/configuration.d.ts +8 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/constants.js +15 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/markdownlint.d.ts +488 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/markdownlint.js +1572 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md001.js +31 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md003.js +50 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md004.js +86 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md005.js +72 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md007.js +88 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md009.js +95 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md010.js +78 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md011.js +57 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md012.js +43 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md013.js +105 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md014.js +54 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md018.js +46 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md019-md021.js +80 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md020.js +71 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md022.js +106 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md023.js +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md024.js +48 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md025.js +40 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md026.js +49 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md027.js +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md028.js +42 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md029.js +76 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md030.js +60 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md031.js +63 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md032.js +66 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md033.js +41 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md034.js +100 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md035.js +26 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md036.js +51 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md037.js +94 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md038.js +100 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md039.js +83 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md040.js +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md041.js +37 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md042.js +63 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md043.js +73 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md044.js +110 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md045.js +62 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md046.js +34 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md047.js +31 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md048.js +39 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md049-md050.js +103 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md051.js +170 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md052.js +42 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md053.js +62 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md054.js +125 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md055.js +79 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md056.js +56 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/md058.js +43 -0
- package/packages/config-markdownlint/node_modules/markdownlint/lib/rules.js +74 -0
- package/packages/config-markdownlint/node_modules/markdownlint/package.json +105 -0
- package/packages/config-markdownlint/node_modules/markdownlint/schema/.markdownlint.jsonc +307 -0
- package/packages/config-markdownlint/node_modules/markdownlint/schema/.markdownlint.yaml +275 -0
- package/packages/config-markdownlint/node_modules/markdownlint/schema/ValidatingConfiguration.md +26 -0
- package/packages/config-markdownlint/node_modules/markdownlint/schema/markdownlint-config-schema-strict.json +1819 -0
- package/packages/config-markdownlint/node_modules/markdownlint/schema/markdownlint-config-schema.json +1824 -0
- package/packages/config-markdownlint/node_modules/markdownlint/style/all.json +5 -0
- package/packages/config-markdownlint/node_modules/markdownlint/style/cirosantilli.json +22 -0
- package/packages/config-markdownlint/node_modules/markdownlint/style/prettier.json +27 -0
- package/packages/config-markdownlint/node_modules/markdownlint/style/relaxed.json +12 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/LICENSE +21 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/README.md +10 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/micromark-browser.js +2 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/micromark-html-browser.js +2 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/micromark.cjs +1 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/micromark.d.cts +1751 -0
- package/packages/config-markdownlint/node_modules/markdownlint-micromark/package.json +46 -0
- package/packages/config-markdownlint/package.json +2 -2
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addError, emphasisOrStrongStyleFor } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, tokenIfType } = require("../helpers/micromark.cjs");
|
|
7
|
+
|
|
8
|
+
const intrawordRe = /^\w$/;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {import("./markdownlint").RuleParams} params Rule parameters.
|
|
12
|
+
* @param {import("./markdownlint").RuleOnError} onError Error-reporting callback.
|
|
13
|
+
* @param {import("markdownlint-micromark").TokenType} type Token type.
|
|
14
|
+
* @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type.
|
|
15
|
+
* @param {"*" | "**"} asterisk Asterisk kind.
|
|
16
|
+
* @param {"_" | "__"} underline Underline kind.
|
|
17
|
+
* @param {"asterisk" | "consistent" | "underscore"} style Style string.
|
|
18
|
+
*/
|
|
19
|
+
const impl =
|
|
20
|
+
(params, onError, type, typeSequence, asterisk, underline, style = "consistent") => {
|
|
21
|
+
const { lines, parsers } = params;
|
|
22
|
+
const emphasisTokens = filterByPredicate(
|
|
23
|
+
parsers.micromark.tokens,
|
|
24
|
+
(token) => token.type === type,
|
|
25
|
+
(token) => ((token.type === "htmlFlow") ? [] : token.children)
|
|
26
|
+
);
|
|
27
|
+
for (const token of emphasisTokens) {
|
|
28
|
+
const { children } = token;
|
|
29
|
+
const startSequence = tokenIfType(children[0], typeSequence);
|
|
30
|
+
const endSequence = tokenIfType(children[children.length - 1], typeSequence);
|
|
31
|
+
if (startSequence && endSequence) {
|
|
32
|
+
const markupStyle = emphasisOrStrongStyleFor(startSequence.text);
|
|
33
|
+
if (style === "consistent") {
|
|
34
|
+
style = markupStyle;
|
|
35
|
+
}
|
|
36
|
+
if (style !== markupStyle) {
|
|
37
|
+
const underscoreIntraword = (style === "underscore") && (
|
|
38
|
+
intrawordRe.test(
|
|
39
|
+
lines[startSequence.startLine - 1][startSequence.startColumn - 2]
|
|
40
|
+
) ||
|
|
41
|
+
intrawordRe.test(
|
|
42
|
+
lines[endSequence.endLine - 1][endSequence.endColumn - 1]
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
if (!underscoreIntraword) {
|
|
46
|
+
for (const sequence of [ startSequence, endSequence ]) {
|
|
47
|
+
addError(
|
|
48
|
+
onError,
|
|
49
|
+
sequence.startLine,
|
|
50
|
+
`Expected: ${style}; Actual: ${markupStyle}`,
|
|
51
|
+
undefined,
|
|
52
|
+
[ sequence.startColumn, sequence.text.length ],
|
|
53
|
+
{
|
|
54
|
+
"editColumn": sequence.startColumn,
|
|
55
|
+
"deleteCount": sequence.text.length,
|
|
56
|
+
"insertText": (style === "asterisk") ? asterisk : underline
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
67
|
+
/** @type import("./markdownlint").Rule[] */
|
|
68
|
+
module.exports = [
|
|
69
|
+
{
|
|
70
|
+
"names": [ "MD049", "emphasis-style" ],
|
|
71
|
+
"description": "Emphasis style",
|
|
72
|
+
"tags": [ "emphasis" ],
|
|
73
|
+
"parser": "micromark",
|
|
74
|
+
"function": function MD049(params, onError) {
|
|
75
|
+
return impl(
|
|
76
|
+
params,
|
|
77
|
+
onError,
|
|
78
|
+
"emphasis",
|
|
79
|
+
"emphasisSequence",
|
|
80
|
+
"*",
|
|
81
|
+
"_",
|
|
82
|
+
params.config.style || undefined
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"names": [ "MD050", "strong-style" ],
|
|
88
|
+
"description": "Strong style",
|
|
89
|
+
"tags": [ "emphasis" ],
|
|
90
|
+
"parser": "micromark",
|
|
91
|
+
"function": function MD050(params, onError) {
|
|
92
|
+
return impl(
|
|
93
|
+
params,
|
|
94
|
+
onError,
|
|
95
|
+
"strong",
|
|
96
|
+
"strongSequence",
|
|
97
|
+
"**",
|
|
98
|
+
"__",
|
|
99
|
+
params.config.style || undefined
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
];
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addError, addErrorDetailIf, getHtmlAttributeRe } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
|
+
|
|
9
|
+
// Regular expression for identifying HTML anchor names
|
|
10
|
+
const idRe = getHtmlAttributeRe("id");
|
|
11
|
+
const nameRe = getHtmlAttributeRe("name");
|
|
12
|
+
const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu;
|
|
13
|
+
const lineFragmentRe = /^#(?:L\d+(?:C\d+)?-L\d+(?:C\d+)?|L\d+)$/;
|
|
14
|
+
|
|
15
|
+
// Sets for filtering heading tokens during conversion
|
|
16
|
+
const childrenExclude = new Set([ "image", "reference", "resource" ]);
|
|
17
|
+
const tokensInclude = new Set(
|
|
18
|
+
[ "characterEscapeValue", "codeTextData", "data", "mathTextData" ]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Converts a Markdown heading into an HTML fragment according to the rules
|
|
23
|
+
* used by GitHub.
|
|
24
|
+
*
|
|
25
|
+
* @param {import("../helpers/micromark.cjs").Token} headingText Heading text token.
|
|
26
|
+
* @returns {string} Fragment string for heading.
|
|
27
|
+
*/
|
|
28
|
+
function convertHeadingToHTMLFragment(headingText) {
|
|
29
|
+
const inlineText =
|
|
30
|
+
filterByPredicate(
|
|
31
|
+
headingText.children,
|
|
32
|
+
(token) => tokensInclude.has(token.type),
|
|
33
|
+
(token) => (childrenExclude.has(token.type) ? [] : token.children)
|
|
34
|
+
)
|
|
35
|
+
.map((token) => token.text)
|
|
36
|
+
.join("");
|
|
37
|
+
return "#" + encodeURIComponent(
|
|
38
|
+
inlineText
|
|
39
|
+
.toLowerCase()
|
|
40
|
+
// RegExp source with Ruby's \p{Word} expanded into its General Categories
|
|
41
|
+
// https://github.com/gjtorikian/html-pipeline/blob/main/lib/html/pipeline/toc_filter.rb
|
|
42
|
+
// https://ruby-doc.org/core-3.0.2/Regexp.html
|
|
43
|
+
.replace(
|
|
44
|
+
/[^\p{Letter}\p{Mark}\p{Number}\p{Connector_Punctuation}\- ]/gu,
|
|
45
|
+
""
|
|
46
|
+
)
|
|
47
|
+
.replace(/ /gu, "-")
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Unescapes the text of a String-type micromark Token.
|
|
53
|
+
*
|
|
54
|
+
* @param {import("../helpers/micromark.cjs").Token} token String-type micromark Token.
|
|
55
|
+
* @returns {string} Unescaped token text.
|
|
56
|
+
*/
|
|
57
|
+
function unescapeStringTokenText(token) {
|
|
58
|
+
return filterByTypes(token.children, [ "characterEscapeValue", "data" ])
|
|
59
|
+
.map((child) => child.text)
|
|
60
|
+
.join("");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
64
|
+
/** @type import("./markdownlint").Rule */
|
|
65
|
+
module.exports = {
|
|
66
|
+
"names": [ "MD051", "link-fragments" ],
|
|
67
|
+
"description": "Link fragments should be valid",
|
|
68
|
+
"tags": [ "links" ],
|
|
69
|
+
"parser": "micromark",
|
|
70
|
+
"function": function MD051(params, onError) {
|
|
71
|
+
const fragments = new Map();
|
|
72
|
+
|
|
73
|
+
// Process headings
|
|
74
|
+
const headingTexts = filterByTypesCached([ "atxHeadingText", "setextHeadingText" ]);
|
|
75
|
+
for (const headingText of headingTexts) {
|
|
76
|
+
const fragment = convertHeadingToHTMLFragment(headingText);
|
|
77
|
+
if (fragment !== "#") {
|
|
78
|
+
const count = fragments.get(fragment) || 0;
|
|
79
|
+
if (count) {
|
|
80
|
+
fragments.set(`${fragment}-${count}`, 0);
|
|
81
|
+
}
|
|
82
|
+
fragments.set(fragment, count + 1);
|
|
83
|
+
let match = null;
|
|
84
|
+
while ((match = anchorRe.exec(headingText.text)) !== null) {
|
|
85
|
+
const [ , anchor ] = match;
|
|
86
|
+
if (!fragments.has(anchor)) {
|
|
87
|
+
fragments.set(anchor, 1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Process HTML anchors
|
|
94
|
+
for (const token of filterByTypesCached([ "htmlText" ], true)) {
|
|
95
|
+
const htmlTagInfo = getHtmlTagInfo(token);
|
|
96
|
+
if (htmlTagInfo && !htmlTagInfo.close) {
|
|
97
|
+
const anchorMatch = idRe.exec(token.text) ||
|
|
98
|
+
(htmlTagInfo.name.toLowerCase() === "a" && nameRe.exec(token.text));
|
|
99
|
+
if (anchorMatch && anchorMatch.length > 0) {
|
|
100
|
+
fragments.set(`#${anchorMatch[1]}`, 0);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Process link and definition fragments
|
|
106
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
107
|
+
/** @type import("../helpers/micromark.cjs").TokenType[][] */
|
|
108
|
+
const parentChilds = [
|
|
109
|
+
[ "link", "resourceDestinationString" ],
|
|
110
|
+
[ "definition", "definitionDestinationString" ]
|
|
111
|
+
];
|
|
112
|
+
for (const [ parentType, definitionType ] of parentChilds) {
|
|
113
|
+
const links = filterByTypesCached([ parentType ]);
|
|
114
|
+
for (const link of links) {
|
|
115
|
+
const definitions = filterByTypes(link.children, [ definitionType ]);
|
|
116
|
+
for (const definition of definitions) {
|
|
117
|
+
const { endColumn, startColumn } = definition;
|
|
118
|
+
const text = unescapeStringTokenText(definition);
|
|
119
|
+
const encodedText = `#${encodeURIComponent(text.slice(1))}`;
|
|
120
|
+
if (
|
|
121
|
+
(text.length > 1) &&
|
|
122
|
+
text.startsWith("#") &&
|
|
123
|
+
!fragments.has(encodedText) &&
|
|
124
|
+
!lineFragmentRe.test(encodedText)
|
|
125
|
+
) {
|
|
126
|
+
// eslint-disable-next-line no-undef-init
|
|
127
|
+
let context = undefined;
|
|
128
|
+
// eslint-disable-next-line no-undef-init
|
|
129
|
+
let range = undefined;
|
|
130
|
+
// eslint-disable-next-line no-undef-init
|
|
131
|
+
let fixInfo = undefined;
|
|
132
|
+
if (link.startLine === link.endLine) {
|
|
133
|
+
context = link.text;
|
|
134
|
+
range = [ link.startColumn, link.endColumn - link.startColumn ];
|
|
135
|
+
fixInfo = {
|
|
136
|
+
"editColumn": startColumn,
|
|
137
|
+
"deleteCount": endColumn - startColumn
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const textLower = text.toLowerCase();
|
|
141
|
+
const mixedCaseKey = [ ...fragments.keys() ]
|
|
142
|
+
.find((key) => textLower === key.toLowerCase());
|
|
143
|
+
if (mixedCaseKey) {
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
(fixInfo || {}).insertText = mixedCaseKey;
|
|
146
|
+
addErrorDetailIf(
|
|
147
|
+
onError,
|
|
148
|
+
link.startLine,
|
|
149
|
+
mixedCaseKey,
|
|
150
|
+
text,
|
|
151
|
+
undefined,
|
|
152
|
+
context,
|
|
153
|
+
range,
|
|
154
|
+
fixInfo
|
|
155
|
+
);
|
|
156
|
+
} else {
|
|
157
|
+
addError(
|
|
158
|
+
onError,
|
|
159
|
+
link.startLine,
|
|
160
|
+
undefined,
|
|
161
|
+
context,
|
|
162
|
+
range
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addError } = require("../helpers");
|
|
6
|
+
const { getReferenceLinkImageData } = require("./cache");
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
10
|
+
module.exports = {
|
|
11
|
+
"names": [ "MD052", "reference-links-images" ],
|
|
12
|
+
"description":
|
|
13
|
+
"Reference links and images should use a label that is defined",
|
|
14
|
+
"tags": [ "images", "links" ],
|
|
15
|
+
"parser": "none",
|
|
16
|
+
"function": function MD052(params, onError) {
|
|
17
|
+
const { config, lines } = params;
|
|
18
|
+
const shortcutSyntax = config.shortcut_syntax || false;
|
|
19
|
+
const { definitions, references, shortcuts } = getReferenceLinkImageData();
|
|
20
|
+
const entries = shortcutSyntax ?
|
|
21
|
+
[ ...references.entries(), ...shortcuts.entries() ] :
|
|
22
|
+
references.entries();
|
|
23
|
+
// Look for links/images that use an undefined link reference
|
|
24
|
+
for (const reference of entries) {
|
|
25
|
+
const [ label, datas ] = reference;
|
|
26
|
+
if (!definitions.has(label)) {
|
|
27
|
+
for (const data of datas) {
|
|
28
|
+
const [ lineIndex, index, length ] = data;
|
|
29
|
+
// Context will be incomplete if reporting for a multi-line link
|
|
30
|
+
const context = lines[lineIndex].slice(index, index + length);
|
|
31
|
+
addError(
|
|
32
|
+
onError,
|
|
33
|
+
lineIndex + 1,
|
|
34
|
+
`Missing link or image reference definition: "${label}"`,
|
|
35
|
+
context,
|
|
36
|
+
[ index + 1, context.length ]
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addError, ellipsify, linkReferenceDefinitionRe } =
|
|
6
|
+
require("../helpers");
|
|
7
|
+
const { getReferenceLinkImageData } = require("./cache");
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
10
|
+
/** @type import("./markdownlint").Rule */
|
|
11
|
+
module.exports = {
|
|
12
|
+
"names": [ "MD053", "link-image-reference-definitions" ],
|
|
13
|
+
"description": "Link and image reference definitions should be needed",
|
|
14
|
+
"tags": [ "images", "links" ],
|
|
15
|
+
"parser": "none",
|
|
16
|
+
"function": function MD053(params, onError) {
|
|
17
|
+
const ignored = new Set(params.config.ignored_definitions || [ "//" ]);
|
|
18
|
+
const lines = params.lines;
|
|
19
|
+
const { references, shortcuts, definitions, duplicateDefinitions } =
|
|
20
|
+
getReferenceLinkImageData();
|
|
21
|
+
const singleLineDefinition = (line) => (
|
|
22
|
+
line.replace(linkReferenceDefinitionRe, "").trim().length > 0
|
|
23
|
+
);
|
|
24
|
+
const deleteFixInfo = {
|
|
25
|
+
"deleteCount": -1
|
|
26
|
+
};
|
|
27
|
+
// Look for unused link references (unreferenced by any link/image)
|
|
28
|
+
for (const definition of definitions.entries()) {
|
|
29
|
+
const [ label, [ lineIndex ] ] = definition;
|
|
30
|
+
if (
|
|
31
|
+
!ignored.has(label) &&
|
|
32
|
+
!references.has(label) &&
|
|
33
|
+
!shortcuts.has(label)
|
|
34
|
+
) {
|
|
35
|
+
const line = lines[lineIndex];
|
|
36
|
+
addError(
|
|
37
|
+
onError,
|
|
38
|
+
lineIndex + 1,
|
|
39
|
+
`Unused link or image reference definition: "${label}"`,
|
|
40
|
+
ellipsify(line),
|
|
41
|
+
[ 1, line.length ],
|
|
42
|
+
singleLineDefinition(line) ? deleteFixInfo : 0
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Look for duplicate link references (defined more than once)
|
|
47
|
+
for (const duplicateDefinition of duplicateDefinitions) {
|
|
48
|
+
const [ label, lineIndex ] = duplicateDefinition;
|
|
49
|
+
if (!ignored.has(label)) {
|
|
50
|
+
const line = lines[lineIndex];
|
|
51
|
+
addError(
|
|
52
|
+
onError,
|
|
53
|
+
lineIndex + 1,
|
|
54
|
+
`Duplicate link or image reference definition: "${label}"`,
|
|
55
|
+
ellipsify(line),
|
|
56
|
+
[ 1, line.length ],
|
|
57
|
+
singleLineDefinition(line) ? deleteFixInfo : 0
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContext, nextLinesRe } = require("../helpers");
|
|
6
|
+
const { filterByPredicate, getTokenTextByType } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { getReferenceLinkImageData, filterByTypesCached } = require("./cache");
|
|
8
|
+
|
|
9
|
+
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g;
|
|
10
|
+
const removeBackslashEscapes = (text) => text.replace(backslashEscapeRe, "$1");
|
|
11
|
+
const autolinkDisallowedRe = /[ <>]/;
|
|
12
|
+
const autolinkAble = (destination) => {
|
|
13
|
+
try {
|
|
14
|
+
// eslint-disable-next-line no-new
|
|
15
|
+
new URL(destination);
|
|
16
|
+
} catch {
|
|
17
|
+
// Not an absolute URL
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return !autolinkDisallowedRe.test(destination);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
24
|
+
/** @type import("./markdownlint").Rule */
|
|
25
|
+
module.exports = {
|
|
26
|
+
"names": [ "MD054", "link-image-style" ],
|
|
27
|
+
"description": "Link and image style",
|
|
28
|
+
"tags": [ "images", "links" ],
|
|
29
|
+
"parser": "micromark",
|
|
30
|
+
"function": (params, onError) => {
|
|
31
|
+
const config = params.config;
|
|
32
|
+
const autolink = (config.autolink === undefined) || !!config.autolink;
|
|
33
|
+
const inline = (config.inline === undefined) || !!config.inline;
|
|
34
|
+
const full = (config.full === undefined) || !!config.full;
|
|
35
|
+
const collapsed = (config.collapsed === undefined) || !!config.collapsed;
|
|
36
|
+
const shortcut = (config.shortcut === undefined) || !!config.shortcut;
|
|
37
|
+
const urlInline = (config.url_inline === undefined) || !!config.url_inline;
|
|
38
|
+
if (autolink && inline && full && collapsed && shortcut && urlInline) {
|
|
39
|
+
// Everything allowed, nothing to check
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const { definitions } = getReferenceLinkImageData();
|
|
43
|
+
const links = filterByTypesCached([ "autolink", "image", "link" ]);
|
|
44
|
+
for (const link of links) {
|
|
45
|
+
let label = null;
|
|
46
|
+
let destination = null;
|
|
47
|
+
const {
|
|
48
|
+
children, endColumn, endLine, startColumn, startLine, text, type
|
|
49
|
+
} = link;
|
|
50
|
+
const image = (type === "image");
|
|
51
|
+
let isError = false;
|
|
52
|
+
if (type === "autolink") {
|
|
53
|
+
// link kind is an autolink
|
|
54
|
+
destination = getTokenTextByType(children, "autolinkProtocol");
|
|
55
|
+
label = destination;
|
|
56
|
+
isError = !autolink;
|
|
57
|
+
} else {
|
|
58
|
+
// link type is "image" or "link"
|
|
59
|
+
const descendents = filterByPredicate(children);
|
|
60
|
+
label = getTokenTextByType(descendents, "labelText");
|
|
61
|
+
destination =
|
|
62
|
+
getTokenTextByType(descendents, "resourceDestinationString");
|
|
63
|
+
if (destination) {
|
|
64
|
+
// link kind is an inline link
|
|
65
|
+
const title = getTokenTextByType(descendents, "resourceTitleString");
|
|
66
|
+
isError = !inline || (
|
|
67
|
+
!urlInline &&
|
|
68
|
+
autolink &&
|
|
69
|
+
!image &&
|
|
70
|
+
!title &&
|
|
71
|
+
(label === destination) &&
|
|
72
|
+
autolinkAble(destination)
|
|
73
|
+
);
|
|
74
|
+
} else {
|
|
75
|
+
// link kind is a full/collapsed/shortcut reference link
|
|
76
|
+
const isShortcut = !children.some((t) => t.type === "reference");
|
|
77
|
+
const referenceString = getTokenTextByType(descendents, "referenceString");
|
|
78
|
+
const isCollapsed = (referenceString === null);
|
|
79
|
+
const definition = definitions.get(referenceString || label);
|
|
80
|
+
destination = definition && definition[1];
|
|
81
|
+
isError = destination &&
|
|
82
|
+
(isShortcut ? !shortcut : (isCollapsed ? !collapsed : !full));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (isError) {
|
|
86
|
+
// eslint-disable-next-line no-undef-init
|
|
87
|
+
let range = undefined;
|
|
88
|
+
let fixInfo = null;
|
|
89
|
+
if (startLine === endLine) {
|
|
90
|
+
range = [ startColumn, endColumn - startColumn ];
|
|
91
|
+
let insertText = null;
|
|
92
|
+
const canInline = (inline && label);
|
|
93
|
+
const canAutolink = (autolink && !image && autolinkAble(destination));
|
|
94
|
+
if (canInline && (urlInline || !canAutolink)) {
|
|
95
|
+
// Most useful form
|
|
96
|
+
const prefix = (image ? "!" : "");
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
const escapedLabel = label.replace(/[[\]]/g, "\\$&");
|
|
99
|
+
const escapedDestination = destination.replace(/[()]/g, "\\$&");
|
|
100
|
+
insertText = `${prefix}[${escapedLabel}](${escapedDestination})`;
|
|
101
|
+
} else if (canAutolink) {
|
|
102
|
+
// Simplest form
|
|
103
|
+
insertText = `<${removeBackslashEscapes(destination)}>`;
|
|
104
|
+
}
|
|
105
|
+
if (insertText) {
|
|
106
|
+
fixInfo = {
|
|
107
|
+
"editColumn": range[0],
|
|
108
|
+
insertText,
|
|
109
|
+
"deleteCount": range[1]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
addErrorContext(
|
|
114
|
+
onError,
|
|
115
|
+
startLine,
|
|
116
|
+
text.replace(nextLinesRe, ""),
|
|
117
|
+
undefined,
|
|
118
|
+
undefined,
|
|
119
|
+
range,
|
|
120
|
+
fixInfo
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
|
+
|
|
9
|
+
const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]);
|
|
10
|
+
const ignoreWhitespace = (tokens) => tokens.filter(
|
|
11
|
+
(token) => !whitespaceTypes.has(token.type)
|
|
12
|
+
);
|
|
13
|
+
const firstOrNothing = (items) => items[0];
|
|
14
|
+
const lastOrNothing = (items) => items[items.length - 1];
|
|
15
|
+
const makeRange = (start, end) => [ start, end - start + 1 ];
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
18
|
+
/** @type import("./markdownlint").Rule */
|
|
19
|
+
module.exports = {
|
|
20
|
+
"names": [ "MD055", "table-pipe-style" ],
|
|
21
|
+
"description": "Table pipe style",
|
|
22
|
+
"tags": [ "table" ],
|
|
23
|
+
"parser": "micromark",
|
|
24
|
+
"function": function MD055(params, onError) {
|
|
25
|
+
const style = String(params.config.style || "consistent");
|
|
26
|
+
let expectedStyle = style;
|
|
27
|
+
let expectedLeadingPipe =
|
|
28
|
+
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only"));
|
|
29
|
+
let expectedTrailingPipe =
|
|
30
|
+
((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only"));
|
|
31
|
+
const tables = filterByTypesCached([ "table" ]);
|
|
32
|
+
for (const table of tables) {
|
|
33
|
+
const rows = filterByTypes(
|
|
34
|
+
table.children,
|
|
35
|
+
[ "tableDelimiterRow", "tableRow" ]
|
|
36
|
+
);
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
// The following uses of first/lastOrNothing lack fallback handling
|
|
39
|
+
// because it seems not to be possible (i.e., 0% coverage)
|
|
40
|
+
const firstCell = firstOrNothing(row.children);
|
|
41
|
+
const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children));
|
|
42
|
+
const actualLeadingPipe = (leadingToken.type === "tableCellDivider");
|
|
43
|
+
const lastCell = lastOrNothing(row.children);
|
|
44
|
+
const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children));
|
|
45
|
+
const actualTrailingPipe = (trailingToken.type === "tableCellDivider");
|
|
46
|
+
const actualStyle = actualLeadingPipe ?
|
|
47
|
+
(actualTrailingPipe ? "leading_and_trailing" : "leading_only") :
|
|
48
|
+
(actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing");
|
|
49
|
+
if (expectedStyle === "consistent") {
|
|
50
|
+
expectedStyle = actualStyle;
|
|
51
|
+
expectedLeadingPipe = actualLeadingPipe;
|
|
52
|
+
expectedTrailingPipe = actualTrailingPipe;
|
|
53
|
+
}
|
|
54
|
+
if (actualLeadingPipe !== expectedLeadingPipe) {
|
|
55
|
+
addErrorDetailIf(
|
|
56
|
+
onError,
|
|
57
|
+
firstCell.startLine,
|
|
58
|
+
expectedStyle,
|
|
59
|
+
actualStyle,
|
|
60
|
+
`${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`,
|
|
61
|
+
undefined,
|
|
62
|
+
makeRange(row.startColumn, firstCell.startColumn)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (actualTrailingPipe !== expectedTrailingPipe) {
|
|
66
|
+
addErrorDetailIf(
|
|
67
|
+
onError,
|
|
68
|
+
lastCell.endLine,
|
|
69
|
+
expectedStyle,
|
|
70
|
+
actualStyle,
|
|
71
|
+
`${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`,
|
|
72
|
+
undefined,
|
|
73
|
+
makeRange(lastCell.endColumn - 1, row.endColumn - 1)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorDetailIf } = require("../helpers");
|
|
6
|
+
const { filterByTypes } = require("../helpers/micromark.cjs");
|
|
7
|
+
const { filterByTypesCached } = require("./cache");
|
|
8
|
+
|
|
9
|
+
const makeRange = (start, end) => [ start, end - start + 1 ];
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
12
|
+
/** @type import("./markdownlint").Rule */
|
|
13
|
+
module.exports = {
|
|
14
|
+
"names": [ "MD056", "table-column-count" ],
|
|
15
|
+
"description": "Table column count",
|
|
16
|
+
"tags": [ "table" ],
|
|
17
|
+
"parser": "micromark",
|
|
18
|
+
"function": function MD056(params, onError) {
|
|
19
|
+
const tables = filterByTypesCached([ "table" ]);
|
|
20
|
+
for (const table of tables) {
|
|
21
|
+
const rows = filterByTypes(
|
|
22
|
+
table.children,
|
|
23
|
+
[ "tableDelimiterRow", "tableRow" ]
|
|
24
|
+
);
|
|
25
|
+
let expectedCount = 0;
|
|
26
|
+
for (const row of rows) {
|
|
27
|
+
const cells = filterByTypes(
|
|
28
|
+
row.children,
|
|
29
|
+
[ "tableData", "tableDelimiter", "tableHeader" ]
|
|
30
|
+
);
|
|
31
|
+
const actualCount = cells.length;
|
|
32
|
+
expectedCount ||= actualCount;
|
|
33
|
+
// eslint-disable-next-line no-undef-init
|
|
34
|
+
let detail = undefined;
|
|
35
|
+
// eslint-disable-next-line no-undef-init
|
|
36
|
+
let range = undefined;
|
|
37
|
+
if (actualCount < expectedCount) {
|
|
38
|
+
detail = "Too few cells, row will be missing data";
|
|
39
|
+
range = [ row.endColumn - 1, 1 ];
|
|
40
|
+
} else if (expectedCount < actualCount) {
|
|
41
|
+
detail = "Too many cells, extra data will be missing";
|
|
42
|
+
range = makeRange(cells[expectedCount].startColumn, row.endColumn - 1);
|
|
43
|
+
}
|
|
44
|
+
addErrorDetailIf(
|
|
45
|
+
onError,
|
|
46
|
+
row.endLine,
|
|
47
|
+
expectedCount,
|
|
48
|
+
actualCount,
|
|
49
|
+
detail,
|
|
50
|
+
undefined,
|
|
51
|
+
range
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const { addErrorContextForLine, isBlankLine } = require("../helpers");
|
|
6
|
+
const { filterByTypesCached } = require("./cache");
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line jsdoc/valid-types
|
|
9
|
+
/** @type import("./markdownlint").Rule */
|
|
10
|
+
module.exports = {
|
|
11
|
+
"names": [ "MD058", "blanks-around-tables" ],
|
|
12
|
+
"description": "Tables should be surrounded by blank lines",
|
|
13
|
+
"tags": [ "table" ],
|
|
14
|
+
"parser": "micromark",
|
|
15
|
+
"function": function MD058(params, onError) {
|
|
16
|
+
const { lines } = params;
|
|
17
|
+
// For every table...
|
|
18
|
+
const tables = filterByTypesCached([ "table" ]);
|
|
19
|
+
for (const table of tables) {
|
|
20
|
+
// Look for a blank line above the table
|
|
21
|
+
const firstIndex = table.startLine - 1;
|
|
22
|
+
if (!isBlankLine(lines[firstIndex - 1])) {
|
|
23
|
+
addErrorContextForLine(
|
|
24
|
+
onError,
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
lines,
|
|
27
|
+
firstIndex
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
// Look for a blank line below the table
|
|
31
|
+
const lastIndex = table.endLine - 1;
|
|
32
|
+
if (!isBlankLine(lines[lastIndex + 1])) {
|
|
33
|
+
addErrorContextForLine(
|
|
34
|
+
onError,
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
lines,
|
|
37
|
+
lastIndex,
|
|
38
|
+
lastIndex + 2
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|