markdownlint 0.29.0 → 0.31.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/CHANGELOG.md +13 -0
- package/demo/markdownlint-browser.js +997 -891
- package/doc/CustomRules.md +2 -0
- package/doc/Rules.md +46 -23
- package/doc/md022.md +12 -6
- package/doc/md026.md +1 -2
- package/doc/md049.md +2 -2
- package/doc/md050.md +2 -2
- package/doc/md051.md +17 -6
- package/doc/md052.md +13 -6
- package/helpers/helpers.js +146 -235
- package/helpers/micromark.cjs +192 -53
- package/helpers/package.json +2 -2
- package/helpers/shared.js +7 -0
- package/lib/cache.js +0 -2
- package/lib/constants.js +1 -1
- package/lib/markdownlint.d.ts +10 -2
- package/lib/markdownlint.js +37 -13
- package/lib/md022.js +80 -40
- package/lib/md026.js +19 -12
- package/lib/md032.js +62 -31
- package/lib/md033.js +20 -45
- package/lib/md037.js +70 -164
- package/lib/md043.js +42 -40
- package/lib/md044.js +15 -41
- package/lib/md045.js +17 -5
- package/lib/md049-md050.js +6 -3
- package/lib/md051.js +123 -72
- package/lib/md052.js +7 -3
- package/package.json +25 -24
- package/schema/.markdownlint.jsonc +7 -4
- package/schema/.markdownlint.yaml +6 -4
- package/schema/markdownlint-config-schema.json +32 -9
package/helpers/micromark.cjs
CHANGED
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
// @ts-ignore
|
|
6
6
|
const {
|
|
7
|
-
gfmAutolinkLiteral, gfmFootnote, gfmTable, parse, postprocess,
|
|
7
|
+
gfmAutolinkLiteral, gfmFootnote, gfmTable, math, parse, postprocess,
|
|
8
|
+
preprocess
|
|
8
9
|
// @ts-ignore
|
|
9
10
|
} = require("markdownlint-micromark");
|
|
11
|
+
const { newLineRe } = require("./shared.js");
|
|
12
|
+
|
|
13
|
+
const flatTokensSymbol = Symbol("flat-tokens");
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* Markdown token.
|
|
@@ -21,25 +25,58 @@ const {
|
|
|
21
25
|
* @property {Token[]} children Child tokens.
|
|
22
26
|
*/
|
|
23
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Returns whether a token is an htmlFlow type containing an HTML comment.
|
|
30
|
+
*
|
|
31
|
+
* @param {Token} token Micromark token.
|
|
32
|
+
* @returns {boolean} True iff token is htmlFlow containing a comment.
|
|
33
|
+
*/
|
|
34
|
+
function isHtmlFlowComment(token) {
|
|
35
|
+
const { text, type } = token;
|
|
36
|
+
if (
|
|
37
|
+
(type === "htmlFlow") &&
|
|
38
|
+
text.startsWith("<!--") &&
|
|
39
|
+
text.endsWith("-->")
|
|
40
|
+
) {
|
|
41
|
+
const comment = text.slice(4, -3);
|
|
42
|
+
return (
|
|
43
|
+
!comment.startsWith(">") &&
|
|
44
|
+
!comment.startsWith("->") &&
|
|
45
|
+
!comment.endsWith("-") &&
|
|
46
|
+
!comment.includes("--")
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
24
52
|
/**
|
|
25
53
|
* Parses a Markdown document and returns Micromark events.
|
|
26
54
|
*
|
|
27
55
|
* @param {string} markdown Markdown document.
|
|
28
|
-
* @param {Object} [
|
|
29
|
-
* @param {boolean} [
|
|
56
|
+
* @param {Object} [micromarkOptions] Options for micromark.
|
|
57
|
+
* @param {boolean} [referencesDefined] Treat references as defined.
|
|
30
58
|
* @returns {Object[]} Micromark events.
|
|
31
59
|
*/
|
|
32
|
-
function getMicromarkEvents(
|
|
60
|
+
function getMicromarkEvents(
|
|
61
|
+
markdown,
|
|
62
|
+
micromarkOptions = {},
|
|
63
|
+
referencesDefined = true
|
|
64
|
+
) {
|
|
33
65
|
|
|
34
66
|
// Customize options object to add useful extensions
|
|
35
|
-
|
|
36
|
-
|
|
67
|
+
micromarkOptions.extensions = micromarkOptions.extensions || [];
|
|
68
|
+
micromarkOptions.extensions.push(
|
|
69
|
+
gfmAutolinkLiteral(),
|
|
70
|
+
gfmFootnote(),
|
|
71
|
+
gfmTable(),
|
|
72
|
+
math()
|
|
73
|
+
);
|
|
37
74
|
|
|
38
75
|
// Use micromark to parse document into Events
|
|
39
76
|
const encoding = undefined;
|
|
40
77
|
const eol = true;
|
|
41
|
-
const parseContext = parse(
|
|
42
|
-
if (
|
|
78
|
+
const parseContext = parse(micromarkOptions);
|
|
79
|
+
if (referencesDefined) {
|
|
43
80
|
// Customize ParseContext to treat all references as defined
|
|
44
81
|
parseContext.defined.includes = (searchElement) => searchElement.length > 0;
|
|
45
82
|
}
|
|
@@ -52,93 +89,171 @@ function getMicromarkEvents(markdown, options = {}, refsDefined = true) {
|
|
|
52
89
|
* Parses a Markdown document and returns (frozen) tokens.
|
|
53
90
|
*
|
|
54
91
|
* @param {string} markdown Markdown document.
|
|
55
|
-
* @param {Object}
|
|
56
|
-
* @param {boolean}
|
|
92
|
+
* @param {Object} micromarkOptions Options for micromark.
|
|
93
|
+
* @param {boolean} referencesDefined Treat references as defined.
|
|
94
|
+
* @param {number} lineDelta Offset to apply to start/end line.
|
|
57
95
|
* @returns {Token[]} Micromark tokens (frozen).
|
|
58
96
|
*/
|
|
59
|
-
function
|
|
60
|
-
|
|
97
|
+
function micromarkParseWithOffset(
|
|
98
|
+
markdown,
|
|
99
|
+
micromarkOptions,
|
|
100
|
+
referencesDefined,
|
|
101
|
+
lineDelta
|
|
102
|
+
) {
|
|
61
103
|
// Use micromark to parse document into Events
|
|
62
|
-
const events =
|
|
63
|
-
|
|
104
|
+
const events = getMicromarkEvents(
|
|
105
|
+
markdown, micromarkOptions, referencesDefined
|
|
106
|
+
);
|
|
64
107
|
|
|
65
108
|
// Create Token objects
|
|
66
109
|
const document = [];
|
|
110
|
+
let flatTokens = [];
|
|
67
111
|
let current = {
|
|
68
112
|
"children": document
|
|
69
113
|
};
|
|
70
114
|
const history = [ current ];
|
|
115
|
+
let reparseOptions = null;
|
|
116
|
+
let lines = null;
|
|
117
|
+
let skipHtmlFlowChildren = false;
|
|
71
118
|
for (const event of events) {
|
|
72
119
|
const [ kind, token, context ] = event;
|
|
73
120
|
const { type, start, end } = token;
|
|
74
121
|
const { "column": startColumn, "line": startLine } = start;
|
|
75
122
|
const { "column": endColumn, "line": endLine } = end;
|
|
76
123
|
const text = context.sliceSerialize(token);
|
|
77
|
-
if (kind === "enter") {
|
|
124
|
+
if ((kind === "enter") && !skipHtmlFlowChildren) {
|
|
78
125
|
const previous = current;
|
|
79
126
|
history.push(previous);
|
|
80
127
|
current = {
|
|
81
128
|
type,
|
|
82
|
-
startLine,
|
|
129
|
+
"startLine": startLine + lineDelta,
|
|
83
130
|
startColumn,
|
|
84
|
-
endLine,
|
|
131
|
+
"endLine": endLine + lineDelta,
|
|
85
132
|
endColumn,
|
|
86
133
|
text,
|
|
87
134
|
"children": []
|
|
88
135
|
};
|
|
89
136
|
previous.children.push(current);
|
|
90
|
-
|
|
91
|
-
Object.freeze(current.children);
|
|
92
|
-
Object.freeze(current);
|
|
137
|
+
flatTokens.push(current);
|
|
93
138
|
// @ts-ignore
|
|
94
|
-
current
|
|
139
|
+
if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) {
|
|
140
|
+
skipHtmlFlowChildren = true;
|
|
141
|
+
if (!reparseOptions || !lines) {
|
|
142
|
+
reparseOptions = {
|
|
143
|
+
...micromarkOptions,
|
|
144
|
+
"extensions": [
|
|
145
|
+
{
|
|
146
|
+
"disable": {
|
|
147
|
+
"null": [ "codeIndented", "htmlFlow" ]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
};
|
|
152
|
+
lines = markdown.split(newLineRe);
|
|
153
|
+
}
|
|
154
|
+
const reparseMarkdown = lines
|
|
155
|
+
.slice(current.startLine - 1, current.endLine)
|
|
156
|
+
.join("\n");
|
|
157
|
+
const tokens = micromarkParseWithOffset(
|
|
158
|
+
reparseMarkdown,
|
|
159
|
+
reparseOptions,
|
|
160
|
+
referencesDefined,
|
|
161
|
+
current.startLine - 1
|
|
162
|
+
);
|
|
163
|
+
current.children = tokens;
|
|
164
|
+
// Avoid stack overflow of Array.push(...spread)
|
|
165
|
+
// eslint-disable-next-line unicorn/prefer-spread
|
|
166
|
+
flatTokens = flatTokens.concat(tokens[flatTokensSymbol]);
|
|
167
|
+
}
|
|
168
|
+
} else if (kind === "exit") {
|
|
169
|
+
if (type === "htmlFlow") {
|
|
170
|
+
skipHtmlFlowChildren = false;
|
|
171
|
+
}
|
|
172
|
+
if (!skipHtmlFlowChildren) {
|
|
173
|
+
Object.freeze(current.children);
|
|
174
|
+
Object.freeze(current);
|
|
175
|
+
// @ts-ignore
|
|
176
|
+
current = history.pop();
|
|
177
|
+
}
|
|
95
178
|
}
|
|
96
179
|
}
|
|
97
180
|
|
|
98
181
|
// Return document
|
|
182
|
+
Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens });
|
|
99
183
|
Object.freeze(document);
|
|
100
184
|
return document;
|
|
101
185
|
}
|
|
102
186
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Parses a Markdown document and returns (frozen) tokens.
|
|
189
|
+
*
|
|
190
|
+
* @param {string} markdown Markdown document.
|
|
191
|
+
* @param {Object} [micromarkOptions] Options for micromark.
|
|
192
|
+
* @param {boolean} [referencesDefined] Treat references as defined.
|
|
193
|
+
* @returns {Token[]} Micromark tokens (frozen).
|
|
194
|
+
*/
|
|
195
|
+
function micromarkParse(
|
|
196
|
+
markdown,
|
|
197
|
+
micromarkOptions = {},
|
|
198
|
+
referencesDefined = true
|
|
199
|
+
) {
|
|
200
|
+
return micromarkParseWithOffset(
|
|
201
|
+
markdown,
|
|
202
|
+
micromarkOptions,
|
|
203
|
+
referencesDefined,
|
|
204
|
+
0
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @callback AllowedPredicate
|
|
210
|
+
* @param {Token} token Micromark token.
|
|
211
|
+
* @returns {boolean} True iff allowed.
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @callback TransformPredicate
|
|
216
|
+
* @param {Token} token Micromark token.
|
|
217
|
+
* @returns {Token[]} Child tokens.
|
|
218
|
+
*/
|
|
121
219
|
|
|
122
220
|
/**
|
|
123
221
|
* Filter a list of Micromark tokens by predicate.
|
|
124
222
|
*
|
|
125
223
|
* @param {Token[]} tokens Micromark tokens.
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
224
|
+
* @param {AllowedPredicate} allowed Allowed token predicate.
|
|
225
|
+
* @param {TransformPredicate} [transformChildren] Transform predicate.
|
|
128
226
|
* @returns {Token[]} Filtered tokens.
|
|
129
227
|
*/
|
|
130
228
|
function filterByPredicate(tokens, allowed, transformChildren) {
|
|
131
229
|
const result = [];
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
result.push(token);
|
|
230
|
+
const queue = [
|
|
231
|
+
{
|
|
232
|
+
"array": tokens,
|
|
233
|
+
"index": 0
|
|
137
234
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
235
|
+
];
|
|
236
|
+
while (queue.length > 0) {
|
|
237
|
+
const current = queue[queue.length - 1];
|
|
238
|
+
const { array, index } = current;
|
|
239
|
+
if (index < array.length) {
|
|
240
|
+
const token = array[current.index++];
|
|
241
|
+
if (allowed(token)) {
|
|
242
|
+
result.push(token);
|
|
243
|
+
}
|
|
244
|
+
const { children } = token;
|
|
245
|
+
if (children.length > 0) {
|
|
246
|
+
const transformed =
|
|
247
|
+
transformChildren ? transformChildren(token) : children;
|
|
248
|
+
queue.push(
|
|
249
|
+
{
|
|
250
|
+
"array": transformed,
|
|
251
|
+
"index": 0
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
queue.pop();
|
|
142
257
|
}
|
|
143
258
|
}
|
|
144
259
|
return result;
|
|
@@ -152,10 +267,33 @@ function filterByPredicate(tokens, allowed, transformChildren) {
|
|
|
152
267
|
* @returns {Token[]} Filtered tokens.
|
|
153
268
|
*/
|
|
154
269
|
function filterByTypes(tokens, allowed) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
270
|
+
const predicate = (token) => allowed.includes(token.type);
|
|
271
|
+
const flatTokens = tokens[flatTokensSymbol];
|
|
272
|
+
if (flatTokens) {
|
|
273
|
+
return flatTokens.filter(predicate);
|
|
274
|
+
}
|
|
275
|
+
return filterByPredicate(tokens, predicate);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Gets the heading level of a Micromark heading tokan.
|
|
280
|
+
*
|
|
281
|
+
* @param {Token} heading Micromark heading token.
|
|
282
|
+
* @returns {number} Heading level.
|
|
283
|
+
*/
|
|
284
|
+
function getHeadingLevel(heading) {
|
|
285
|
+
const headingSequence = filterByTypes(
|
|
286
|
+
heading.children,
|
|
287
|
+
[ "atxHeadingSequence", "setextHeadingLineSequence" ]
|
|
158
288
|
);
|
|
289
|
+
let level = 1;
|
|
290
|
+
const { text } = headingSequence[0];
|
|
291
|
+
if (text[0] === "#") {
|
|
292
|
+
level = Math.min(text.length, 6);
|
|
293
|
+
} else if (text[0] === "-") {
|
|
294
|
+
level = 2;
|
|
295
|
+
}
|
|
296
|
+
return level;
|
|
159
297
|
}
|
|
160
298
|
|
|
161
299
|
/**
|
|
@@ -232,6 +370,7 @@ module.exports = {
|
|
|
232
370
|
"parse": micromarkParse,
|
|
233
371
|
filterByPredicate,
|
|
234
372
|
filterByTypes,
|
|
373
|
+
getHeadingLevel,
|
|
235
374
|
getHtmlTagInfo,
|
|
236
375
|
getMicromarkEvents,
|
|
237
376
|
getTokenTextByType,
|
package/helpers/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdownlint-rule-helpers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "A collection of markdownlint helper functions for custom rules",
|
|
5
5
|
"main": "./helpers.js",
|
|
6
6
|
"exports": "./helpers.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"bugs": "https://github.com/DavidAnson/markdownlint/issues",
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=16"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"markdownlint-micromark": "0.1.2"
|
package/lib/cache.js
CHANGED
|
@@ -15,8 +15,6 @@ module.exports.codeBlockAndSpanRanges =
|
|
|
15
15
|
() => map.get("codeBlockAndSpanRanges");
|
|
16
16
|
module.exports.flattenedLists =
|
|
17
17
|
() => map.get("flattenedLists");
|
|
18
|
-
module.exports.htmlElementRanges =
|
|
19
|
-
() => map.get("htmlElementRanges");
|
|
20
18
|
module.exports.lineMetadata =
|
|
21
19
|
() => map.get("lineMetadata");
|
|
22
20
|
module.exports.referenceLinkImageData =
|
package/lib/constants.js
CHANGED
package/lib/markdownlint.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export = markdownlint;
|
|
|
8
8
|
*/
|
|
9
9
|
declare function markdownlint(options: Options | null, callback: LintCallback): void;
|
|
10
10
|
declare namespace markdownlint {
|
|
11
|
-
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
|
|
11
|
+
export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, RuleFunction, RuleParams, MarkdownItToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintContentCallback, LintCallback, Configuration, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback };
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Configuration options.
|
|
@@ -64,7 +64,7 @@ type Options = {
|
|
|
64
64
|
/**
|
|
65
65
|
* Called with the result of the lint function.
|
|
66
66
|
*/
|
|
67
|
-
type LintCallback = (
|
|
67
|
+
type LintCallback = (error: Error | null, results?: LintResults) => void;
|
|
68
68
|
/**
|
|
69
69
|
* Lint specified Markdown files synchronously.
|
|
70
70
|
*
|
|
@@ -218,6 +218,10 @@ type RuleOnErrorInfo = {
|
|
|
218
218
|
* Context for the error.
|
|
219
219
|
*/
|
|
220
220
|
context?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Link to more information.
|
|
223
|
+
*/
|
|
224
|
+
information?: URL;
|
|
221
225
|
/**
|
|
222
226
|
* Column number (1-based) and length.
|
|
223
227
|
*/
|
|
@@ -349,6 +353,10 @@ type FixInfo = {
|
|
|
349
353
|
*/
|
|
350
354
|
insertText?: string;
|
|
351
355
|
};
|
|
356
|
+
/**
|
|
357
|
+
* Called with the result of linting a string or document.
|
|
358
|
+
*/
|
|
359
|
+
type LintContentCallback = (error: Error | null, result?: LintError[]) => void;
|
|
352
360
|
/**
|
|
353
361
|
* Configuration object for linting rules. For a detailed schema, see
|
|
354
362
|
* {@link ../schema/markdownlint-config-schema.json}.
|
package/lib/markdownlint.js
CHANGED
|
@@ -59,7 +59,7 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
59
59
|
if (
|
|
60
60
|
!result &&
|
|
61
61
|
rule.information &&
|
|
62
|
-
|
|
62
|
+
!helpers.isUrl(rule.information)
|
|
63
63
|
) {
|
|
64
64
|
result = newError("information");
|
|
65
65
|
}
|
|
@@ -481,7 +481,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
481
481
|
applyEnableDisable(
|
|
482
482
|
action,
|
|
483
483
|
parameter,
|
|
484
|
-
enabledRulesPerLineNumber[nextLineNumber]
|
|
484
|
+
enabledRulesPerLineNumber[nextLineNumber]
|
|
485
485
|
);
|
|
486
486
|
}
|
|
487
487
|
}
|
|
@@ -520,7 +520,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
520
520
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
521
521
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
522
522
|
* @param {number} resultVersion Version of the LintResults object to return.
|
|
523
|
-
* @param {
|
|
523
|
+
* @param {LintContentCallback} callback Callback (err, result) function.
|
|
524
524
|
* @returns {void}
|
|
525
525
|
*/
|
|
526
526
|
function lintContent(
|
|
@@ -583,14 +583,11 @@ function lintContent(
|
|
|
583
583
|
helpers.codeBlockAndSpanRanges(paramsBase, lineMetadata);
|
|
584
584
|
const flattenedLists =
|
|
585
585
|
helpers.flattenLists(paramsBase.parsers.markdownit.tokens);
|
|
586
|
-
const htmlElementRanges =
|
|
587
|
-
helpers.htmlElementRanges(paramsBase, lineMetadata);
|
|
588
586
|
const referenceLinkImageData =
|
|
589
587
|
helpers.getReferenceLinkImageData(paramsBase);
|
|
590
588
|
cache.set({
|
|
591
589
|
codeBlockAndSpanRanges,
|
|
592
590
|
flattenedLists,
|
|
593
|
-
htmlElementRanges,
|
|
594
591
|
lineMetadata,
|
|
595
592
|
referenceLinkImageData
|
|
596
593
|
});
|
|
@@ -629,6 +626,10 @@ function lintContent(
|
|
|
629
626
|
!helpers.isString(errorInfo.context)) {
|
|
630
627
|
throwError("context");
|
|
631
628
|
}
|
|
629
|
+
if (errorInfo.information &&
|
|
630
|
+
!helpers.isUrl(errorInfo.information)) {
|
|
631
|
+
throwError("information");
|
|
632
|
+
}
|
|
632
633
|
if (errorInfo.range &&
|
|
633
634
|
(!Array.isArray(errorInfo.range) ||
|
|
634
635
|
(errorInfo.range.length !== 2) ||
|
|
@@ -681,12 +682,13 @@ function lintContent(
|
|
|
681
682
|
cleanFixInfo.insertText = fixInfo.insertText;
|
|
682
683
|
}
|
|
683
684
|
}
|
|
685
|
+
const information = errorInfo.information || rule.information;
|
|
684
686
|
results.push({
|
|
685
687
|
lineNumber,
|
|
686
688
|
"ruleName": rule.names[0],
|
|
687
689
|
"ruleNames": rule.names,
|
|
688
690
|
"ruleDescription": rule.description,
|
|
689
|
-
"ruleInformation":
|
|
691
|
+
"ruleInformation": information ? information.href : null,
|
|
690
692
|
"errorDetail": errorInfo.detail || null,
|
|
691
693
|
"errorContext": errorInfo.context || null,
|
|
692
694
|
"errorRange": errorInfo.range ? [ ...errorInfo.range ] : null,
|
|
@@ -807,7 +809,7 @@ function lintContent(
|
|
|
807
809
|
* @param {number} resultVersion Version of the LintResults object to return.
|
|
808
810
|
* @param {Object} fs File system implementation.
|
|
809
811
|
* @param {boolean} synchronous Whether to execute synchronously.
|
|
810
|
-
* @param {
|
|
812
|
+
* @param {LintContentCallback} callback Callback (err, result) function.
|
|
811
813
|
* @returns {void}
|
|
812
814
|
*/
|
|
813
815
|
function lintFile(
|
|
@@ -857,15 +859,26 @@ function lintFile(
|
|
|
857
859
|
*
|
|
858
860
|
* @param {Options | null} options Options object.
|
|
859
861
|
* @param {boolean} synchronous Whether to execute synchronously.
|
|
860
|
-
* @param {
|
|
862
|
+
* @param {LintCallback} callback Callback (err, result) function.
|
|
861
863
|
* @returns {void}
|
|
862
864
|
*/
|
|
863
865
|
function lintInput(options, synchronous, callback) {
|
|
864
866
|
// Normalize inputs
|
|
865
867
|
options = options || {};
|
|
866
868
|
callback = callback || function noop() {};
|
|
869
|
+
const customRuleList =
|
|
870
|
+
[ options.customRules || [] ]
|
|
871
|
+
.flat()
|
|
872
|
+
.map((rule) => ({
|
|
873
|
+
"names": helpers.cloneIfArray(rule.names),
|
|
874
|
+
"description": rule.description,
|
|
875
|
+
"information": helpers.cloneIfUrl(rule.information),
|
|
876
|
+
"tags": helpers.cloneIfArray(rule.tags),
|
|
877
|
+
"asynchronous": rule.asynchronous,
|
|
878
|
+
"function": rule.function
|
|
879
|
+
}));
|
|
867
880
|
// eslint-disable-next-line unicorn/prefer-spread
|
|
868
|
-
const ruleList = rules.concat(
|
|
881
|
+
const ruleList = rules.concat(customRuleList);
|
|
869
882
|
const ruleErr = validateRuleList(ruleList, synchronous);
|
|
870
883
|
if (ruleErr) {
|
|
871
884
|
callback(ruleErr);
|
|
@@ -1009,7 +1022,7 @@ function markdownlintPromise(options) {
|
|
|
1009
1022
|
* @returns {LintResults} Results object.
|
|
1010
1023
|
*/
|
|
1011
1024
|
function markdownlintSync(options) {
|
|
1012
|
-
let results =
|
|
1025
|
+
let results = null;
|
|
1013
1026
|
lintInput(options, true, function callback(error, res) {
|
|
1014
1027
|
if (error) {
|
|
1015
1028
|
throw error;
|
|
@@ -1163,6 +1176,7 @@ function readConfig(file, parsers, fs, callback) {
|
|
|
1163
1176
|
}
|
|
1164
1177
|
// Read file
|
|
1165
1178
|
file = helpers.expandTildePath(file, require("node:os"));
|
|
1179
|
+
// eslint-disable-next-line n/prefer-promises/fs
|
|
1166
1180
|
fs.readFile(file, "utf8", (err, content) => {
|
|
1167
1181
|
if (err) {
|
|
1168
1182
|
// @ts-ignore
|
|
@@ -1314,6 +1328,7 @@ module.exports = markdownlint;
|
|
|
1314
1328
|
* @property {number} lineNumber Line number (1-based).
|
|
1315
1329
|
* @property {string} [detail] Detail about the error.
|
|
1316
1330
|
* @property {string} [context] Context for the error.
|
|
1331
|
+
* @property {URL} [information] Link to more information.
|
|
1317
1332
|
* @property {number[]} [range] Column number (1-based) and length.
|
|
1318
1333
|
* @property {RuleOnErrorFixInfo} [fixInfo] Fix information.
|
|
1319
1334
|
*/
|
|
@@ -1402,12 +1417,21 @@ module.exports = markdownlint;
|
|
|
1402
1417
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
1403
1418
|
*/
|
|
1404
1419
|
|
|
1420
|
+
/**
|
|
1421
|
+
* Called with the result of linting a string or document.
|
|
1422
|
+
*
|
|
1423
|
+
* @callback LintContentCallback
|
|
1424
|
+
* @param {Error | null} error Error iff failed.
|
|
1425
|
+
* @param {LintError[]} [result] Result iff successful.
|
|
1426
|
+
* @returns {void}
|
|
1427
|
+
*/
|
|
1428
|
+
|
|
1405
1429
|
/**
|
|
1406
1430
|
* Called with the result of the lint function.
|
|
1407
1431
|
*
|
|
1408
1432
|
* @callback LintCallback
|
|
1409
|
-
* @param {Error | null}
|
|
1410
|
-
* @param {LintResults} [results] Lint results.
|
|
1433
|
+
* @param {Error | null} error Error object iff failed.
|
|
1434
|
+
* @param {LintResults} [results] Lint results iff succeeded.
|
|
1411
1435
|
* @returns {void}
|
|
1412
1436
|
*/
|
|
1413
1437
|
|