markdownlint 0.37.4 → 0.39.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 +20 -0
- package/CONTRIBUTING.md +2 -3
- package/README.md +175 -87
- package/doc/Rules.md +273 -47
- package/doc/md001.md +14 -0
- package/doc/md009.md +8 -9
- package/doc/md010.md +6 -0
- package/doc/md027.md +8 -0
- package/doc/md029.md +2 -0
- package/doc/md033.md +7 -1
- package/doc/md038.md +23 -11
- package/doc/md041.md +31 -16
- package/doc/md043.md +22 -4
- package/doc/md045.md +9 -1
- package/doc/md051.md +17 -0
- package/doc/md052.md +12 -0
- package/doc/md053.md +3 -3
- package/doc/md055.md +1 -1
- package/doc/md056.md +1 -1
- package/doc/md059.md +33 -0
- package/doc/md060.md +70 -0
- package/helpers/README.md +2 -2
- package/helpers/helpers.cjs +174 -20
- package/helpers/micromark-helpers.cjs +37 -7
- package/helpers/package.json +1 -1
- package/lib/cache.mjs +25 -7
- package/lib/configuration-strict.d.ts +1494 -292
- package/lib/constants.mjs +6 -5
- package/lib/defer-require.cjs +2 -0
- package/lib/exports.d.mts +2 -2
- package/lib/exports.mjs +2 -2
- package/lib/markdownit.cjs +8 -14
- package/lib/markdownlint.d.mts +136 -52
- package/lib/markdownlint.mjs +469 -409
- package/lib/md001.mjs +6 -2
- package/lib/md004.mjs +7 -18
- package/lib/md007.mjs +2 -1
- package/lib/md009.mjs +9 -5
- package/lib/md010.mjs +1 -1
- package/lib/md022.mjs +5 -2
- package/lib/md025.mjs +23 -15
- package/lib/md027.mjs +11 -1
- package/lib/md029.mjs +25 -14
- package/lib/md031.mjs +0 -1
- package/lib/md032.mjs +3 -1
- package/lib/md033.mjs +28 -20
- package/lib/md034.mjs +2 -1
- package/lib/md036.mjs +16 -4
- package/lib/md037.mjs +10 -7
- package/lib/md038.mjs +52 -71
- package/lib/md041.mjs +54 -16
- package/lib/md042.mjs +4 -2
- package/lib/md043.mjs +4 -2
- package/lib/md044.mjs +1 -1
- package/lib/md045.mjs +3 -1
- package/lib/md046.mjs +6 -6
- package/lib/md051.mjs +13 -5
- package/lib/md052.mjs +2 -1
- package/lib/md053.mjs +1 -1
- package/lib/md054.mjs +7 -5
- package/lib/md055.mjs +7 -6
- package/lib/md056.mjs +1 -1
- package/lib/md059.mjs +71 -0
- package/lib/md060.mjs +121 -0
- package/lib/micromark-parse.mjs +17 -3
- package/lib/node-imports-browser.mjs +2 -0
- package/lib/parse-configuration.mjs +47 -0
- package/lib/rules.mjs +5 -1
- package/package.json +32 -30
- package/schema/.markdownlint.jsonc +97 -62
- package/schema/.markdownlint.yaml +86 -57
- package/schema/markdownlint-config-schema-strict.json +4713 -1436
- package/schema/markdownlint-config-schema.json +4713 -1436
package/lib/markdownlint.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { requireMarkdownItCjs } from "./defer-require.cjs";
|
|
|
8
8
|
import { resolveModule } from "./resolve-module.cjs";
|
|
9
9
|
import rules from "./rules.mjs";
|
|
10
10
|
import { parse as micromarkParse } from "./micromark-parse.mjs";
|
|
11
|
+
import parseConfiguration from "./parse-configuration.mjs";
|
|
11
12
|
import * as helpers from "../helpers/helpers.cjs";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -23,15 +24,17 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
23
24
|
// No need to validate if only using built-in rules
|
|
24
25
|
return result;
|
|
25
26
|
}
|
|
27
|
+
/** @type {Object.<string, boolean>} */
|
|
26
28
|
const allIds = {};
|
|
27
29
|
for (const [ index, rule ] of ruleList.entries()) {
|
|
28
30
|
const customIndex = index - rules.length;
|
|
29
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
30
|
-
function newError(property, value) {
|
|
31
|
+
// eslint-disable-next-line jsdoc/reject-any-type, jsdoc/require-jsdoc
|
|
32
|
+
function newError(/** @type {string} */ property, /** @type {any} */ value) {
|
|
31
33
|
return new Error(
|
|
32
34
|
`Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`);
|
|
33
35
|
}
|
|
34
36
|
for (const property of [ "names", "tags" ]) {
|
|
37
|
+
// @ts-ignore
|
|
35
38
|
const value = rule[property];
|
|
36
39
|
if (!result &&
|
|
37
40
|
(!value || !Array.isArray(value) || (value.length === 0) ||
|
|
@@ -44,6 +47,7 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
44
47
|
[ "function", "function" ]
|
|
45
48
|
]) {
|
|
46
49
|
const property = propertyInfo[0];
|
|
50
|
+
// @ts-ignore
|
|
47
51
|
const value = rule[property];
|
|
48
52
|
if (!result && (!value || (typeof value !== propertyInfo[1]))) {
|
|
49
53
|
result = newError(property, value);
|
|
@@ -107,9 +111,17 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
107
111
|
* @returns {LintResults} New LintResults instance.
|
|
108
112
|
*/
|
|
109
113
|
function newResults(ruleList) {
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Returns the string representation of a LintResults instance.
|
|
116
|
+
*
|
|
117
|
+
* @param {boolean} useAlias True if rule alias should be used instead of name.
|
|
118
|
+
* @returns {string} String representation of the instance.
|
|
119
|
+
* @this {LintResults}
|
|
120
|
+
*/
|
|
112
121
|
function toString(useAlias) {
|
|
122
|
+
// eslint-disable-next-line consistent-this, unicorn/no-this-assignment
|
|
123
|
+
const lintResults = this;
|
|
124
|
+
/** @type {Object.<string, Rule> | null} */
|
|
113
125
|
let ruleNameToRule = null;
|
|
114
126
|
const results = [];
|
|
115
127
|
const keys = Object.keys(lintResults);
|
|
@@ -120,6 +132,7 @@ function newResults(ruleList) {
|
|
|
120
132
|
for (const result of fileResults) {
|
|
121
133
|
const ruleMoniker = result.ruleNames ?
|
|
122
134
|
result.ruleNames.join("/") :
|
|
135
|
+
// @ts-ignore
|
|
123
136
|
(result.ruleName + "/" + result.ruleAlias);
|
|
124
137
|
results.push(
|
|
125
138
|
file + ": " +
|
|
@@ -160,19 +173,29 @@ function newResults(ruleList) {
|
|
|
160
173
|
}
|
|
161
174
|
return results.join("\n");
|
|
162
175
|
}
|
|
176
|
+
const lintResults = {};
|
|
163
177
|
Object.defineProperty(lintResults, "toString", { "value": toString });
|
|
164
178
|
// @ts-ignore
|
|
165
179
|
return lintResults;
|
|
166
180
|
}
|
|
167
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Result object for removeFrontMatter.
|
|
184
|
+
*
|
|
185
|
+
* @typedef {Object} RemoveFrontMatterResult
|
|
186
|
+
* @property {string} content Markdown content.
|
|
187
|
+
* @property {string[]} frontMatterLines Front matter lines.
|
|
188
|
+
*/
|
|
189
|
+
|
|
168
190
|
/**
|
|
169
191
|
* Remove front matter (if present at beginning of content).
|
|
170
192
|
*
|
|
171
193
|
* @param {string} content Markdown content.
|
|
172
194
|
* @param {RegExp | null} frontMatter Regular expression to match front matter.
|
|
173
|
-
* @returns {
|
|
195
|
+
* @returns {RemoveFrontMatterResult} Trimmed content and front matter lines.
|
|
174
196
|
*/
|
|
175
197
|
function removeFrontMatter(content, frontMatter) {
|
|
198
|
+
/** @type {string[]} */
|
|
176
199
|
let frontMatterLines = [];
|
|
177
200
|
if (frontMatter) {
|
|
178
201
|
const frontMatterMatch = content.match(frontMatter);
|
|
@@ -199,6 +222,7 @@ function removeFrontMatter(content, frontMatter) {
|
|
|
199
222
|
* @returns {Object.<string, string[]>} Map of alias to rule name.
|
|
200
223
|
*/
|
|
201
224
|
function mapAliasToRuleNames(ruleList) {
|
|
225
|
+
/** @type {Object.<string, string[]>} */
|
|
202
226
|
const aliasToRuleNames = {};
|
|
203
227
|
// const tagToRuleNames = {};
|
|
204
228
|
for (const rule of ruleList) {
|
|
@@ -228,78 +252,98 @@ function mapAliasToRuleNames(ruleList) {
|
|
|
228
252
|
return aliasToRuleNames;
|
|
229
253
|
}
|
|
230
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Result object for getEffectiveConfig.
|
|
257
|
+
*
|
|
258
|
+
* @typedef {Object} GetEffectiveConfigResult
|
|
259
|
+
* @property {Configuration} effectiveConfig Effective configuration.
|
|
260
|
+
* @property {Map<string, boolean>} rulesEnabled Rules enabled.
|
|
261
|
+
* @property {Map<string, "error" | "warning">} rulesSeverity Rules severity.
|
|
262
|
+
*/
|
|
263
|
+
|
|
231
264
|
/**
|
|
232
265
|
* Apply (and normalize) configuration object.
|
|
233
266
|
*
|
|
234
267
|
* @param {Rule[]} ruleList List of rules.
|
|
235
268
|
* @param {Configuration} config Configuration object.
|
|
236
|
-
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
237
|
-
*
|
|
238
|
-
* @returns {Configuration} Effective configuration.
|
|
269
|
+
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule names.
|
|
270
|
+
* @returns {GetEffectiveConfigResult} Effective configuration and rule severities.
|
|
239
271
|
*/
|
|
240
272
|
function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
273
|
+
let ruleDefaultEnable = true;
|
|
274
|
+
/** @type {"error" | "warning"} */
|
|
275
|
+
let ruleDefaultSeverity = "error";
|
|
276
|
+
Object.entries(config).every(([ key, value ]) => {
|
|
277
|
+
if (key.toUpperCase() === "DEFAULT") {
|
|
278
|
+
ruleDefaultEnable = !!value;
|
|
279
|
+
if (value === "warning") {
|
|
280
|
+
ruleDefaultSeverity = "warning";
|
|
281
|
+
}
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
});
|
|
245
286
|
/** @type {Configuration} */
|
|
246
287
|
const effectiveConfig = {};
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
288
|
+
/** @type {Map<string, boolean>} */
|
|
289
|
+
const rulesEnabled = new Map();
|
|
290
|
+
/** @type {Map<string, "error" | "warning">} */
|
|
291
|
+
const rulesSeverity = new Map();
|
|
292
|
+
const emptyObject = Object.freeze({});
|
|
293
|
+
for (const ruleName of ruleList.map((rule) => rule.names[0].toUpperCase())) {
|
|
294
|
+
effectiveConfig[ruleName] = emptyObject;
|
|
295
|
+
rulesEnabled.set(ruleName, ruleDefaultEnable);
|
|
296
|
+
rulesSeverity.set(ruleName, ruleDefaultSeverity);
|
|
250
297
|
}
|
|
251
298
|
// for (const ruleName of deprecatedRuleNames) {
|
|
252
299
|
// effectiveConfig[ruleName] = false;
|
|
253
300
|
// }
|
|
254
|
-
for (const key of Object.
|
|
255
|
-
|
|
301
|
+
for (const [ key, value ] of Object.entries(config)) {
|
|
302
|
+
const keyUpper = key.toUpperCase();
|
|
303
|
+
/** @type {boolean} */
|
|
304
|
+
let enabled = false;
|
|
305
|
+
/** @type {"error" | "warning"} */
|
|
306
|
+
let severity = "error";
|
|
307
|
+
let effectiveValue = {};
|
|
256
308
|
if (value) {
|
|
257
|
-
if (
|
|
258
|
-
|
|
309
|
+
if (value instanceof Object) {
|
|
310
|
+
/** @type {{ enabled?: boolean, severity?: "error" | "warning" }} */
|
|
311
|
+
const valueObject = value;
|
|
312
|
+
enabled = (valueObject.enabled === undefined) ? true : !!valueObject.enabled;
|
|
313
|
+
severity = (valueObject.severity === "warning") ? "warning" : "error";
|
|
314
|
+
effectiveValue = Object.fromEntries(
|
|
315
|
+
Object.entries(value).filter(
|
|
316
|
+
([ k ]) => (k !== "enabled") && (k !== "severity")
|
|
317
|
+
)
|
|
318
|
+
);
|
|
319
|
+
} else {
|
|
320
|
+
enabled = true;
|
|
321
|
+
severity = (value === "warning") ? "warning" : "error";
|
|
259
322
|
}
|
|
260
|
-
} else {
|
|
261
|
-
value = false;
|
|
262
323
|
}
|
|
263
|
-
const keyUpper = key.toUpperCase();
|
|
264
324
|
for (const ruleName of (aliasToRuleNames[keyUpper] || [])) {
|
|
265
|
-
|
|
325
|
+
Object.freeze(effectiveValue);
|
|
326
|
+
effectiveConfig[ruleName] = effectiveValue;
|
|
327
|
+
rulesEnabled.set(ruleName, enabled);
|
|
328
|
+
rulesSeverity.set(ruleName, severity);
|
|
266
329
|
}
|
|
267
330
|
}
|
|
268
|
-
return
|
|
331
|
+
return {
|
|
332
|
+
effectiveConfig,
|
|
333
|
+
rulesEnabled,
|
|
334
|
+
rulesSeverity
|
|
335
|
+
};
|
|
269
336
|
}
|
|
270
337
|
|
|
271
338
|
/**
|
|
272
|
-
*
|
|
339
|
+
* Result object for getEnabledRulesPerLineNumber.
|
|
273
340
|
*
|
|
274
|
-
* @
|
|
275
|
-
* @
|
|
276
|
-
* @
|
|
277
|
-
* @
|
|
341
|
+
* @typedef {Object} EnabledRulesPerLineNumberResult
|
|
342
|
+
* @property {Configuration} effectiveConfig Effective configuration.
|
|
343
|
+
* @property {Map<string, boolean>[]} enabledRulesPerLineNumber Enabled rules per line number.
|
|
344
|
+
* @property {Rule[]} enabledRuleList Enabled rule list.
|
|
345
|
+
* @property {Map<string, "error" | "warning">} rulesSeverity Rules severity.
|
|
278
346
|
*/
|
|
279
|
-
function parseConfiguration(name, content, parsers) {
|
|
280
|
-
let config = null;
|
|
281
|
-
let message = "";
|
|
282
|
-
const errors = [];
|
|
283
|
-
let index = 0;
|
|
284
|
-
// Try each parser
|
|
285
|
-
(parsers || [ JSON.parse ]).every((parser) => {
|
|
286
|
-
try {
|
|
287
|
-
config = parser(content);
|
|
288
|
-
} catch (error) {
|
|
289
|
-
errors.push(`Parser ${index++}: ${error.message}`);
|
|
290
|
-
}
|
|
291
|
-
return !config;
|
|
292
|
-
});
|
|
293
|
-
// Message if unable to parse
|
|
294
|
-
if (!config) {
|
|
295
|
-
errors.unshift(`Unable to parse '${name}'`);
|
|
296
|
-
message = errors.join("; ");
|
|
297
|
-
}
|
|
298
|
-
return {
|
|
299
|
-
config,
|
|
300
|
-
message
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
347
|
|
|
304
348
|
/**
|
|
305
349
|
* Create a mapping of enabled rules per line.
|
|
@@ -309,10 +353,9 @@ function parseConfiguration(name, content, parsers) {
|
|
|
309
353
|
* @param {string[]} frontMatterLines List of front matter lines.
|
|
310
354
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
311
355
|
* @param {Configuration} config Configuration object.
|
|
312
|
-
* @param {ConfigurationParser[] |
|
|
313
|
-
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
314
|
-
*
|
|
315
|
-
* @returns {Object} Effective configuration and enabled rules per line number.
|
|
356
|
+
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
357
|
+
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule names.
|
|
358
|
+
* @returns {EnabledRulesPerLineNumberResult} Effective configuration and enabled rules per line number.
|
|
316
359
|
*/
|
|
317
360
|
function getEnabledRulesPerLineNumber(
|
|
318
361
|
ruleList,
|
|
@@ -323,13 +366,14 @@ function getEnabledRulesPerLineNumber(
|
|
|
323
366
|
configParsers,
|
|
324
367
|
aliasToRuleNames) {
|
|
325
368
|
// Shared variables
|
|
326
|
-
|
|
327
|
-
let
|
|
328
|
-
|
|
369
|
+
/** @type {Map<string, boolean>} */
|
|
370
|
+
let enabledRules = new Map();
|
|
371
|
+
/** @type {Map<string, boolean>} */
|
|
372
|
+
let capturedRules = enabledRules;
|
|
329
373
|
const enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length);
|
|
330
374
|
// Helper functions
|
|
331
375
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
332
|
-
function handleInlineConfig(input, forEachMatch, forEachLine) {
|
|
376
|
+
function handleInlineConfig(/** @type {string[]} */ input, /** @type {(act: string, par: string, ind: number) => void} */ forEachMatch, /** @type {(() => void)|undefined} */ forEachLine = undefined) {
|
|
333
377
|
for (const [ lineIndex, line ] of input.entries()) {
|
|
334
378
|
if (!noInlineConfig) {
|
|
335
379
|
let match = null;
|
|
@@ -350,7 +394,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
350
394
|
}
|
|
351
395
|
}
|
|
352
396
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
353
|
-
function configureFile(action, parameter) {
|
|
397
|
+
function configureFile(/** @type {string} */ action, /** @type {string} */ parameter) {
|
|
354
398
|
if (action === "CONFIGURE-FILE") {
|
|
355
399
|
const { "config": parsed } = parseConfiguration(
|
|
356
400
|
"CONFIGURE-FILE", parameter, configParsers
|
|
@@ -364,26 +408,27 @@ function getEnabledRulesPerLineNumber(
|
|
|
364
408
|
}
|
|
365
409
|
}
|
|
366
410
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
367
|
-
function applyEnableDisable(action, parameter, state) {
|
|
368
|
-
state =
|
|
411
|
+
function applyEnableDisable(/** @type {string} */ action, /** @type {string} */ parameter, /** @type {Map<string, boolean>} */ state) {
|
|
412
|
+
state = new Map(state);
|
|
369
413
|
const enabled = (action.startsWith("ENABLE"));
|
|
370
414
|
const trimmed = parameter && parameter.trim();
|
|
415
|
+
// eslint-disable-next-line no-use-before-define
|
|
371
416
|
const items = trimmed ? trimmed.toUpperCase().split(/\s+/) : allRuleNames;
|
|
372
417
|
for (const nameUpper of items) {
|
|
373
418
|
for (const ruleName of (aliasToRuleNames[nameUpper] || [])) {
|
|
374
|
-
state
|
|
419
|
+
state.set(ruleName, enabled);
|
|
375
420
|
}
|
|
376
421
|
}
|
|
377
422
|
return state;
|
|
378
423
|
}
|
|
379
424
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
380
|
-
function enableDisableFile(action, parameter) {
|
|
425
|
+
function enableDisableFile(/** @type {string} */ action, /** @type {string} */ parameter) {
|
|
381
426
|
if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) {
|
|
382
427
|
enabledRules = applyEnableDisable(action, parameter, enabledRules);
|
|
383
428
|
}
|
|
384
429
|
}
|
|
385
430
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
386
|
-
function captureRestoreEnableDisable(action, parameter) {
|
|
431
|
+
function captureRestoreEnableDisable(/** @type {string} */ action, /** @type {string} */ parameter) {
|
|
387
432
|
if (action === "CAPTURE") {
|
|
388
433
|
capturedRules = enabledRules;
|
|
389
434
|
} else if (action === "RESTORE") {
|
|
@@ -397,7 +442,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
397
442
|
enabledRulesPerLineNumber.push(enabledRules);
|
|
398
443
|
}
|
|
399
444
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
400
|
-
function disableLineNextLine(action, parameter, lineNumber) {
|
|
445
|
+
function disableLineNextLine(/** @type {string} */ action, /** @type {string} */ parameter, /** @type {number} */ lineNumber) {
|
|
401
446
|
const disableLine = (action === "DISABLE-LINE");
|
|
402
447
|
const disableNextLine = (action === "DISABLE-NEXT-LINE");
|
|
403
448
|
if (disableLine || disableNextLine) {
|
|
@@ -413,29 +458,24 @@ function getEnabledRulesPerLineNumber(
|
|
|
413
458
|
}
|
|
414
459
|
// Handle inline comments
|
|
415
460
|
handleInlineConfig([ lines.join("\n") ], configureFile);
|
|
416
|
-
const effectiveConfig = getEffectiveConfig(
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const ruleName = rule.names[0].toUpperCase();
|
|
420
|
-
allRuleNames.push(ruleName);
|
|
421
|
-
enabledRules[ruleName] = !!effectiveConfig[ruleName];
|
|
422
|
-
}
|
|
461
|
+
const { effectiveConfig, rulesEnabled, rulesSeverity } = getEffectiveConfig(ruleList, config, aliasToRuleNames);
|
|
462
|
+
const allRuleNames = [ ...rulesEnabled.keys() ];
|
|
463
|
+
enabledRules = new Map(rulesEnabled);
|
|
423
464
|
capturedRules = enabledRules;
|
|
424
465
|
handleInlineConfig(lines, enableDisableFile);
|
|
425
466
|
handleInlineConfig(lines, captureRestoreEnableDisable, updateLineState);
|
|
426
467
|
handleInlineConfig(lines, disableLineNextLine);
|
|
427
468
|
// Create the list of rules that are used at least once
|
|
428
|
-
const enabledRuleList =
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
}
|
|
469
|
+
const enabledRuleList = ruleList.filter((rule) => {
|
|
470
|
+
const ruleName = rule.names[0].toUpperCase();
|
|
471
|
+
return enabledRulesPerLineNumber.some((enabledRulesForLine) => enabledRulesForLine.get(ruleName));
|
|
472
|
+
});
|
|
434
473
|
// Return results
|
|
435
474
|
return {
|
|
436
475
|
effectiveConfig,
|
|
437
476
|
enabledRulesPerLineNumber,
|
|
438
|
-
enabledRuleList
|
|
477
|
+
enabledRuleList,
|
|
478
|
+
rulesSeverity
|
|
439
479
|
};
|
|
440
480
|
}
|
|
441
481
|
|
|
@@ -443,17 +483,16 @@ function getEnabledRulesPerLineNumber(
|
|
|
443
483
|
* Lints a string containing Markdown content.
|
|
444
484
|
*
|
|
445
485
|
* @param {Rule[]} ruleList List of rules.
|
|
446
|
-
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
447
|
-
* names.
|
|
486
|
+
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule names.
|
|
448
487
|
* @param {string} name Identifier for the content.
|
|
449
488
|
* @param {string} content Markdown content.
|
|
450
|
-
* @param {
|
|
489
|
+
* @param {MarkdownItFactory} markdownItFactory Function to create a markdown-it parser.
|
|
451
490
|
* @param {Configuration} config Configuration object.
|
|
452
|
-
* @param {ConfigurationParser[] |
|
|
491
|
+
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
453
492
|
* @param {RegExp | null} frontMatter Regular expression for front matter.
|
|
454
493
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
455
494
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
456
|
-
* @param {
|
|
495
|
+
* @param {boolean} synchronous Whether to execute synchronously.
|
|
457
496
|
* @param {LintContentCallback} callback Callback (err, result) function.
|
|
458
497
|
* @returns {void}
|
|
459
498
|
*/
|
|
@@ -462,14 +501,17 @@ function lintContent(
|
|
|
462
501
|
aliasToRuleNames,
|
|
463
502
|
name,
|
|
464
503
|
content,
|
|
465
|
-
|
|
504
|
+
markdownItFactory,
|
|
466
505
|
config,
|
|
467
506
|
configParsers,
|
|
468
507
|
frontMatter,
|
|
469
508
|
handleRuleFailures,
|
|
470
509
|
noInlineConfig,
|
|
471
|
-
|
|
510
|
+
synchronous,
|
|
472
511
|
callback) {
|
|
512
|
+
// Provide a consistent error-reporting callback
|
|
513
|
+
// eslint-disable-next-line jsdoc/reject-any-type
|
|
514
|
+
const callbackError = (/** @type {any} */ error) => callback(error instanceof Error ? error : new Error(error));
|
|
473
515
|
// Remove UTF-8 byte order marker (if present)
|
|
474
516
|
content = content.replace(/^\uFEFF/, "");
|
|
475
517
|
// Remove front matter
|
|
@@ -477,7 +519,7 @@ function lintContent(
|
|
|
477
519
|
const { frontMatterLines } = removeFrontMatterResult;
|
|
478
520
|
content = removeFrontMatterResult.content;
|
|
479
521
|
// Get enabled rules per line (with HTML comments present)
|
|
480
|
-
const { effectiveConfig, enabledRulesPerLineNumber, enabledRuleList } =
|
|
522
|
+
const { effectiveConfig, enabledRulesPerLineNumber, enabledRuleList, rulesSeverity } =
|
|
481
523
|
getEnabledRulesPerLineNumber(
|
|
482
524
|
ruleList,
|
|
483
525
|
content.split(helpers.newLineRe),
|
|
@@ -490,263 +532,248 @@ function lintContent(
|
|
|
490
532
|
const needMarkdownItTokens = enabledRuleList.some(
|
|
491
533
|
(rule) => (rule.parser === "markdownit") || (rule.parser === undefined)
|
|
492
534
|
);
|
|
535
|
+
const needMicromarkTokens = enabledRuleList.some(
|
|
536
|
+
(rule) => (rule.parser === "micromark")
|
|
537
|
+
);
|
|
493
538
|
const customRulesPresent = (ruleList.length !== rules.length);
|
|
494
539
|
// Parse content into parser tokens
|
|
495
|
-
const micromarkTokens =
|
|
496
|
-
content,
|
|
497
|
-
|
|
498
|
-
);
|
|
540
|
+
const micromarkTokens = needMicromarkTokens ?
|
|
541
|
+
micromarkParse(content, { "freezeTokens": customRulesPresent }) :
|
|
542
|
+
[];
|
|
499
543
|
// Hide the content of HTML comments from rules
|
|
500
544
|
const preClearedContent = content;
|
|
501
545
|
content = helpers.clearHtmlCommentText(content);
|
|
502
546
|
// Parse content into lines and get markdown-it tokens
|
|
503
547
|
const lines = content.split(helpers.newLineRe);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
"frontMatterLines": Object.freeze(frontMatterLines)
|
|
530
|
-
};
|
|
531
|
-
cacheInitialize({
|
|
532
|
-
...paramsBase,
|
|
533
|
-
"parsers": parsersMicromark,
|
|
534
|
-
"config": null
|
|
535
|
-
});
|
|
536
|
-
// Function to run for each rule
|
|
537
|
-
let results = [];
|
|
538
|
-
/**
|
|
539
|
-
* @param {Rule} rule Rule.
|
|
540
|
-
* @returns {Promise<void> | null} Promise.
|
|
541
|
-
*/
|
|
542
|
-
const forRule = (rule) => {
|
|
543
|
-
// Configure rule
|
|
544
|
-
const ruleName = rule.names[0].toUpperCase();
|
|
545
|
-
const tokens = {};
|
|
546
|
-
let parsers = parsersNone;
|
|
547
|
-
if (rule.parser === undefined) {
|
|
548
|
-
tokens.tokens = markdownitTokens;
|
|
549
|
-
parsers = parsersMarkdownIt;
|
|
550
|
-
} else if (rule.parser === "markdownit") {
|
|
551
|
-
parsers = parsersMarkdownIt;
|
|
552
|
-
} else if (rule.parser === "micromark") {
|
|
553
|
-
parsers = parsersMicromark;
|
|
554
|
-
}
|
|
555
|
-
const params = {
|
|
556
|
-
...paramsBase,
|
|
557
|
-
...tokens,
|
|
558
|
-
parsers,
|
|
559
|
-
"config": effectiveConfig[ruleName]
|
|
548
|
+
// Function to run after fetching markdown-it tokens (when needed)
|
|
549
|
+
const lintContentInternal = (/** @type {MarkdownItToken[]} */ markdownitTokens) => {
|
|
550
|
+
// Create (frozen) parameters for rules
|
|
551
|
+
/** @type {MarkdownParsers} */
|
|
552
|
+
// @ts-ignore
|
|
553
|
+
const parsersMarkdownIt = Object.freeze({
|
|
554
|
+
"markdownit": Object.freeze({
|
|
555
|
+
"tokens": markdownitTokens
|
|
556
|
+
})
|
|
557
|
+
});
|
|
558
|
+
/** @type {MarkdownParsers} */
|
|
559
|
+
// @ts-ignore
|
|
560
|
+
const parsersMicromark = Object.freeze({
|
|
561
|
+
"micromark": Object.freeze({
|
|
562
|
+
"tokens": micromarkTokens
|
|
563
|
+
})
|
|
564
|
+
});
|
|
565
|
+
/** @type {MarkdownParsers} */
|
|
566
|
+
// @ts-ignore
|
|
567
|
+
const parsersNone = Object.freeze({});
|
|
568
|
+
const paramsBase = {
|
|
569
|
+
name,
|
|
570
|
+
version,
|
|
571
|
+
"lines": Object.freeze(lines),
|
|
572
|
+
"frontMatterLines": Object.freeze(frontMatterLines)
|
|
560
573
|
};
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
//
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
if (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
if (errorInfo.information &&
|
|
587
|
-
!helpers.isUrl(errorInfo.information)) {
|
|
588
|
-
throwError("information");
|
|
574
|
+
cacheInitialize({
|
|
575
|
+
...paramsBase,
|
|
576
|
+
"parsers": parsersMicromark,
|
|
577
|
+
"config": null
|
|
578
|
+
});
|
|
579
|
+
// Function to run for each rule
|
|
580
|
+
/** @type {LintError[]} */
|
|
581
|
+
const results = [];
|
|
582
|
+
/**
|
|
583
|
+
* @param {Rule} rule Rule.
|
|
584
|
+
* @returns {Promise<void> | null} Promise.
|
|
585
|
+
*/
|
|
586
|
+
const forRule = (rule) => {
|
|
587
|
+
// Configure rule
|
|
588
|
+
const ruleName = rule.names[0].toUpperCase();
|
|
589
|
+
const tokens = {};
|
|
590
|
+
let parsers = parsersNone;
|
|
591
|
+
if (rule.parser === undefined) {
|
|
592
|
+
tokens.tokens = markdownitTokens;
|
|
593
|
+
parsers = parsersMarkdownIt;
|
|
594
|
+
} else if (rule.parser === "markdownit") {
|
|
595
|
+
parsers = parsersMarkdownIt;
|
|
596
|
+
} else if (rule.parser === "micromark") {
|
|
597
|
+
parsers = parsersMicromark;
|
|
589
598
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
599
|
+
const params = Object.freeze({
|
|
600
|
+
...paramsBase,
|
|
601
|
+
...tokens,
|
|
602
|
+
parsers,
|
|
603
|
+
/** @type {RuleConfiguration} */
|
|
604
|
+
// @ts-ignore
|
|
605
|
+
"config": effectiveConfig[ruleName]
|
|
606
|
+
});
|
|
607
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
608
|
+
function throwError(/** @type {string} */ property) {
|
|
609
|
+
throw new Error(
|
|
610
|
+
`Value of '${property}' passed to onError by '${ruleName}' is incorrect for '${name}'.`);
|
|
600
611
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
612
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
613
|
+
function onError(/** @type {RuleOnErrorInfo} */ errorInfo) {
|
|
614
|
+
if (!errorInfo ||
|
|
615
|
+
!helpers.isNumber(errorInfo.lineNumber) ||
|
|
616
|
+
(errorInfo.lineNumber < 1) ||
|
|
617
|
+
(errorInfo.lineNumber > lines.length)) {
|
|
618
|
+
throwError("lineNumber");
|
|
606
619
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
(fixInfo.lineNumber > lines.length))) {
|
|
611
|
-
throwError("fixInfo.lineNumber");
|
|
612
|
-
}
|
|
613
|
-
cleanFixInfo.lineNumber =
|
|
614
|
-
fixInfo.lineNumber + frontMatterLines.length;
|
|
620
|
+
const lineNumber = errorInfo.lineNumber + frontMatterLines.length;
|
|
621
|
+
if (!enabledRulesPerLineNumber[lineNumber].get(ruleName)) {
|
|
622
|
+
return;
|
|
615
623
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
(fixInfo.editColumn < 1) ||
|
|
620
|
-
(fixInfo.editColumn >
|
|
621
|
-
lines[effectiveLineNumber - 1].length + 1))) {
|
|
622
|
-
throwError("fixInfo.editColumn");
|
|
623
|
-
}
|
|
624
|
-
cleanFixInfo.editColumn = fixInfo.editColumn;
|
|
624
|
+
if (errorInfo.detail &&
|
|
625
|
+
!helpers.isString(errorInfo.detail)) {
|
|
626
|
+
throwError("detail");
|
|
625
627
|
}
|
|
626
|
-
if (
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
(fixInfo.deleteCount >
|
|
630
|
-
lines[effectiveLineNumber - 1].length))) {
|
|
631
|
-
throwError("fixInfo.deleteCount");
|
|
632
|
-
}
|
|
633
|
-
cleanFixInfo.deleteCount = fixInfo.deleteCount;
|
|
628
|
+
if (errorInfo.context &&
|
|
629
|
+
!helpers.isString(errorInfo.context)) {
|
|
630
|
+
throwError("context");
|
|
634
631
|
}
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
632
|
+
if (errorInfo.information &&
|
|
633
|
+
!helpers.isUrl(errorInfo.information)) {
|
|
634
|
+
throwError("information");
|
|
635
|
+
}
|
|
636
|
+
if (errorInfo.range &&
|
|
637
|
+
(!Array.isArray(errorInfo.range) ||
|
|
638
|
+
(errorInfo.range.length !== 2) ||
|
|
639
|
+
!helpers.isNumber(errorInfo.range[0]) ||
|
|
640
|
+
(errorInfo.range[0] < 1) ||
|
|
641
|
+
!helpers.isNumber(errorInfo.range[1]) ||
|
|
642
|
+
(errorInfo.range[1] < 1) ||
|
|
643
|
+
((errorInfo.range[0] + errorInfo.range[1] - 1) >
|
|
644
|
+
lines[errorInfo.lineNumber - 1].length))) {
|
|
645
|
+
throwError("range");
|
|
646
|
+
}
|
|
647
|
+
const fixInfo = errorInfo.fixInfo;
|
|
648
|
+
const cleanFixInfo = {};
|
|
649
|
+
if (fixInfo) {
|
|
650
|
+
if (!helpers.isObject(fixInfo)) {
|
|
651
|
+
throwError("fixInfo");
|
|
652
|
+
}
|
|
653
|
+
if (fixInfo.lineNumber !== undefined) {
|
|
654
|
+
if ((!helpers.isNumber(fixInfo.lineNumber) ||
|
|
655
|
+
(fixInfo.lineNumber < 1) ||
|
|
656
|
+
(fixInfo.lineNumber > lines.length))) {
|
|
657
|
+
throwError("fixInfo.lineNumber");
|
|
658
|
+
}
|
|
659
|
+
cleanFixInfo.lineNumber =
|
|
660
|
+
fixInfo.lineNumber + frontMatterLines.length;
|
|
661
|
+
}
|
|
662
|
+
const effectiveLineNumber = fixInfo.lineNumber || errorInfo.lineNumber;
|
|
663
|
+
if (fixInfo.editColumn !== undefined) {
|
|
664
|
+
if ((!helpers.isNumber(fixInfo.editColumn) ||
|
|
665
|
+
(fixInfo.editColumn < 1) ||
|
|
666
|
+
(fixInfo.editColumn >
|
|
667
|
+
lines[effectiveLineNumber - 1].length + 1))) {
|
|
668
|
+
throwError("fixInfo.editColumn");
|
|
669
|
+
}
|
|
670
|
+
cleanFixInfo.editColumn = fixInfo.editColumn;
|
|
671
|
+
}
|
|
672
|
+
if (fixInfo.deleteCount !== undefined) {
|
|
673
|
+
if ((!helpers.isNumber(fixInfo.deleteCount) ||
|
|
674
|
+
(fixInfo.deleteCount < -1) ||
|
|
675
|
+
(fixInfo.deleteCount >
|
|
676
|
+
lines[effectiveLineNumber - 1].length))) {
|
|
677
|
+
throwError("fixInfo.deleteCount");
|
|
678
|
+
}
|
|
679
|
+
cleanFixInfo.deleteCount = fixInfo.deleteCount;
|
|
680
|
+
}
|
|
681
|
+
if (fixInfo.insertText !== undefined) {
|
|
682
|
+
if (!helpers.isString(fixInfo.insertText)) {
|
|
683
|
+
throwError("fixInfo.insertText");
|
|
684
|
+
}
|
|
685
|
+
cleanFixInfo.insertText = fixInfo.insertText;
|
|
638
686
|
}
|
|
639
|
-
cleanFixInfo.insertText = fixInfo.insertText;
|
|
640
687
|
}
|
|
688
|
+
const information = errorInfo.information || rule.information;
|
|
689
|
+
results.push({
|
|
690
|
+
lineNumber,
|
|
691
|
+
"ruleNames": rule.names,
|
|
692
|
+
"ruleDescription": rule.description,
|
|
693
|
+
"ruleInformation": information ? information.href : null,
|
|
694
|
+
"errorDetail": errorInfo.detail?.replace(helpers.newLineRe, " ") || null,
|
|
695
|
+
"errorContext": errorInfo.context?.replace(helpers.newLineRe, " ") || null,
|
|
696
|
+
"errorRange": errorInfo.range ? [ ...errorInfo.range ] : null,
|
|
697
|
+
"fixInfo": fixInfo ? cleanFixInfo : null,
|
|
698
|
+
// @ts-ignore
|
|
699
|
+
"severity": rulesSeverity.get(ruleName)
|
|
700
|
+
});
|
|
641
701
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
"
|
|
646
|
-
"
|
|
647
|
-
"ruleDescription": rule.description,
|
|
648
|
-
"ruleInformation": information ? information.href : null,
|
|
649
|
-
"errorDetail": errorInfo.detail || null,
|
|
650
|
-
"errorContext": errorInfo.context || null,
|
|
651
|
-
"errorRange": errorInfo.range ? [ ...errorInfo.range ] : null,
|
|
652
|
-
"fixInfo": fixInfo ? cleanFixInfo : null
|
|
702
|
+
// Call (possibly external) rule function to report errors
|
|
703
|
+
// @ts-ignore
|
|
704
|
+
const catchCallsOnError = (error) => onError({
|
|
705
|
+
"lineNumber": 1,
|
|
706
|
+
"detail": `This rule threw an exception: ${error.message || error}`
|
|
653
707
|
});
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
708
|
+
const invokeRuleFunction = () => rule.function(params, onError);
|
|
709
|
+
if (rule.asynchronous) {
|
|
710
|
+
// Asynchronous rule, ensure it returns a Promise
|
|
711
|
+
const ruleFunctionPromise =
|
|
712
|
+
Promise.resolve().then(invokeRuleFunction);
|
|
713
|
+
return handleRuleFailures ?
|
|
714
|
+
ruleFunctionPromise.catch(catchCallsOnError) :
|
|
715
|
+
ruleFunctionPromise;
|
|
716
|
+
}
|
|
717
|
+
// Synchronous rule
|
|
718
|
+
try {
|
|
719
|
+
invokeRuleFunction();
|
|
720
|
+
} catch(error) {
|
|
721
|
+
if (handleRuleFailures) {
|
|
722
|
+
catchCallsOnError(error);
|
|
723
|
+
} else {
|
|
724
|
+
throw error;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
return null;
|
|
728
|
+
};
|
|
729
|
+
const formatResults = () => {
|
|
730
|
+
// Sort results by rule name by line number
|
|
731
|
+
results.sort((a, b) => (
|
|
732
|
+
a.ruleNames[0].localeCompare(b.ruleNames[0]) ||
|
|
733
|
+
a.lineNumber - b.lineNumber
|
|
734
|
+
));
|
|
735
|
+
return results;
|
|
736
|
+
};
|
|
737
|
+
// Run all rules
|
|
738
|
+
const ruleListAsync = enabledRuleList.filter((rule) => rule.asynchronous);
|
|
739
|
+
const ruleListSync = enabledRuleList.filter((rule) => !rule.asynchronous);
|
|
740
|
+
const ruleListAsyncFirst = [
|
|
741
|
+
...ruleListAsync,
|
|
742
|
+
...ruleListSync
|
|
743
|
+
];
|
|
744
|
+
const callbackSuccess = () => callback(null, formatResults());
|
|
670
745
|
try {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
746
|
+
const ruleResults = ruleListAsyncFirst.map(forRule);
|
|
747
|
+
if (ruleListAsync.length > 0) {
|
|
748
|
+
Promise.all(ruleResults.slice(0, ruleListAsync.length))
|
|
749
|
+
.then(callbackSuccess)
|
|
750
|
+
.catch(callbackError);
|
|
675
751
|
} else {
|
|
676
|
-
|
|
752
|
+
callbackSuccess();
|
|
677
753
|
}
|
|
754
|
+
} catch(error) {
|
|
755
|
+
callbackError(error);
|
|
756
|
+
} finally {
|
|
757
|
+
cacheInitialize();
|
|
678
758
|
}
|
|
679
|
-
return null;
|
|
680
759
|
};
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
(error.ruleName !== previous.ruleName) ||
|
|
699
|
-
(error.lineNumber !== previous.lineNumber)
|
|
700
|
-
);
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
if (resultVersion === 0) {
|
|
704
|
-
// Return a dictionary of rule->[line numbers]
|
|
705
|
-
const dictionary = {};
|
|
706
|
-
for (const error of results) {
|
|
707
|
-
const ruleLines = dictionary[error.ruleName] || [];
|
|
708
|
-
ruleLines.push(error.lineNumber);
|
|
709
|
-
dictionary[error.ruleName] = ruleLines;
|
|
710
|
-
}
|
|
711
|
-
// @ts-ignore
|
|
712
|
-
results = dictionary;
|
|
713
|
-
} else if (resultVersion === 1) {
|
|
714
|
-
// Use ruleAlias instead of ruleNames
|
|
715
|
-
for (const error of results) {
|
|
716
|
-
error.ruleAlias = error.ruleNames[1] || error.ruleName;
|
|
717
|
-
delete error.ruleNames;
|
|
718
|
-
}
|
|
719
|
-
} else {
|
|
720
|
-
// resultVersion 2 or 3: Remove unwanted ruleName
|
|
721
|
-
for (const error of results) {
|
|
722
|
-
delete error.ruleName;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
return results;
|
|
726
|
-
}
|
|
727
|
-
// Run all rules
|
|
728
|
-
const ruleListAsync = enabledRuleList.filter((rule) => rule.asynchronous);
|
|
729
|
-
const ruleListSync = enabledRuleList.filter((rule) => !rule.asynchronous);
|
|
730
|
-
const ruleListAsyncFirst = [
|
|
731
|
-
...ruleListAsync,
|
|
732
|
-
...ruleListSync
|
|
733
|
-
];
|
|
734
|
-
const callbackSuccess = () => callback(null, formatResults());
|
|
735
|
-
const callbackError =
|
|
736
|
-
(error) => callback(error instanceof Error ? error : new Error(error));
|
|
737
|
-
try {
|
|
738
|
-
const ruleResults = ruleListAsyncFirst.map(forRule);
|
|
739
|
-
if (ruleListAsync.length > 0) {
|
|
740
|
-
Promise.all(ruleResults.slice(0, ruleListAsync.length))
|
|
741
|
-
.then(callbackSuccess)
|
|
742
|
-
.catch(callbackError);
|
|
743
|
-
} else {
|
|
744
|
-
callbackSuccess();
|
|
745
|
-
}
|
|
746
|
-
} catch (error) {
|
|
747
|
-
callbackError(error);
|
|
748
|
-
} finally {
|
|
749
|
-
cacheInitialize();
|
|
760
|
+
if (!needMarkdownItTokens || synchronous) {
|
|
761
|
+
// Need/able to call into markdown-it and lintContentInternal synchronously
|
|
762
|
+
const markdownItTokens = needMarkdownItTokens ?
|
|
763
|
+
requireMarkdownItCjs().getMarkdownItTokens(markdownItFactory(), preClearedContent, lines) :
|
|
764
|
+
[];
|
|
765
|
+
lintContentInternal(markdownItTokens);
|
|
766
|
+
} else {
|
|
767
|
+
// Need to call into markdown-it and lintContentInternal asynchronously
|
|
768
|
+
Promise.all([
|
|
769
|
+
// eslint-disable-next-line no-inline-comments
|
|
770
|
+
import(/* webpackMode: "eager" */ "./markdownit.cjs"),
|
|
771
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
772
|
+
new Promise((resolve) => resolve(markdownItFactory()))
|
|
773
|
+
]).then(([ markdownitCjs, markdownIt ]) => {
|
|
774
|
+
const markdownItTokens = markdownitCjs.getMarkdownItTokens(markdownIt, preClearedContent, lines);
|
|
775
|
+
lintContentInternal(markdownItTokens);
|
|
776
|
+
}).catch(callbackError);
|
|
750
777
|
}
|
|
751
778
|
}
|
|
752
779
|
|
|
@@ -754,17 +781,15 @@ function lintContent(
|
|
|
754
781
|
* Lints a file containing Markdown content.
|
|
755
782
|
*
|
|
756
783
|
* @param {Rule[]} ruleList List of rules.
|
|
757
|
-
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule
|
|
758
|
-
* names.
|
|
784
|
+
* @param {Object.<string, string[]>} aliasToRuleNames Map of alias to rule names.
|
|
759
785
|
* @param {string} file Path of file to lint.
|
|
760
|
-
* @param {
|
|
786
|
+
* @param {MarkdownItFactory} markdownItFactory Function to create a markdown-it parser.
|
|
761
787
|
* @param {Configuration} config Configuration object.
|
|
762
|
-
* @param {ConfigurationParser[] |
|
|
788
|
+
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
763
789
|
* @param {RegExp | null} frontMatter Regular expression for front matter.
|
|
764
790
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
765
791
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
766
|
-
* @param {
|
|
767
|
-
* @param {Object} fs File system implementation.
|
|
792
|
+
* @param {FsLike} fs File system implementation.
|
|
768
793
|
* @param {boolean} synchronous Whether to execute synchronously.
|
|
769
794
|
* @param {LintContentCallback} callback Callback (err, result) function.
|
|
770
795
|
* @returns {void}
|
|
@@ -773,18 +798,17 @@ function lintFile(
|
|
|
773
798
|
ruleList,
|
|
774
799
|
aliasToRuleNames,
|
|
775
800
|
file,
|
|
776
|
-
|
|
801
|
+
markdownItFactory,
|
|
777
802
|
config,
|
|
778
803
|
configParsers,
|
|
779
804
|
frontMatter,
|
|
780
805
|
handleRuleFailures,
|
|
781
806
|
noInlineConfig,
|
|
782
|
-
resultVersion,
|
|
783
807
|
fs,
|
|
784
808
|
synchronous,
|
|
785
809
|
callback) {
|
|
786
810
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
787
|
-
function lintContentWrapper(err, content) {
|
|
811
|
+
function lintContentWrapper(/** @type {Error | null} */ err, /** @type {string} */ content) {
|
|
788
812
|
if (err) {
|
|
789
813
|
return callback(err);
|
|
790
814
|
}
|
|
@@ -793,13 +817,13 @@ function lintFile(
|
|
|
793
817
|
aliasToRuleNames,
|
|
794
818
|
file,
|
|
795
819
|
content,
|
|
796
|
-
|
|
820
|
+
markdownItFactory,
|
|
797
821
|
config,
|
|
798
822
|
configParsers,
|
|
799
823
|
frontMatter,
|
|
800
824
|
handleRuleFailures,
|
|
801
825
|
noInlineConfig,
|
|
802
|
-
|
|
826
|
+
synchronous,
|
|
803
827
|
callback
|
|
804
828
|
);
|
|
805
829
|
}
|
|
@@ -823,6 +847,8 @@ function lintInput(options, synchronous, callback) {
|
|
|
823
847
|
// Normalize inputs
|
|
824
848
|
options = options || {};
|
|
825
849
|
callback = callback || function noop() {};
|
|
850
|
+
/** @type {Rule[]} */
|
|
851
|
+
// @ts-ignore
|
|
826
852
|
const customRuleList =
|
|
827
853
|
[ options.customRules || [] ]
|
|
828
854
|
.flat()
|
|
@@ -842,6 +868,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
842
868
|
callback(ruleErr);
|
|
843
869
|
return;
|
|
844
870
|
}
|
|
871
|
+
/** @type {string[]} */
|
|
845
872
|
let files = [];
|
|
846
873
|
if (Array.isArray(options.files)) {
|
|
847
874
|
files = [ ...options.files ];
|
|
@@ -851,16 +878,20 @@ function lintInput(options, synchronous, callback) {
|
|
|
851
878
|
const strings = options.strings || {};
|
|
852
879
|
const stringsKeys = Object.keys(strings);
|
|
853
880
|
const config = options.config || { "default": true };
|
|
854
|
-
const configParsers = options.configParsers ||
|
|
881
|
+
const configParsers = options.configParsers || undefined;
|
|
855
882
|
const frontMatter = (options.frontMatter === undefined) ?
|
|
856
883
|
helpers.frontMatterRe :
|
|
857
884
|
options.frontMatter;
|
|
858
885
|
const handleRuleFailures = !!options.handleRuleFailures;
|
|
859
886
|
const noInlineConfig = !!options.noInlineConfig;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
const
|
|
887
|
+
// @ts-ignore
|
|
888
|
+
// eslint-disable-next-line dot-notation
|
|
889
|
+
const resultVersion = (options["resultVersion"] === undefined) ? 3 : options["resultVersion"];
|
|
890
|
+
const markdownItFactory =
|
|
891
|
+
options.markdownItFactory ||
|
|
892
|
+
(() => { throw new Error("The option 'markdownItFactory' was required (due to the option 'customRules' including a rule requiring the 'markdown-it' parser), but 'markdownItFactory' was not set."); });
|
|
893
|
+
/** @type {FsLike} */
|
|
894
|
+
// @ts-ignore
|
|
864
895
|
const fs = options.fs || nodeFs;
|
|
865
896
|
const aliasToRuleNames = mapAliasToRuleNames(ruleList);
|
|
866
897
|
const results = newResults(ruleList);
|
|
@@ -868,14 +899,16 @@ function lintInput(options, synchronous, callback) {
|
|
|
868
899
|
let concurrency = 0;
|
|
869
900
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
870
901
|
function lintWorker() {
|
|
871
|
-
|
|
902
|
+
/** @type {string | undefined} */
|
|
903
|
+
let currentItem = undefined;
|
|
872
904
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
873
|
-
function lintWorkerCallback(err, result) {
|
|
905
|
+
function lintWorkerCallback(/** @type {Error | null} */ err, /** @type {LintError[] | undefined} */ result) {
|
|
874
906
|
concurrency--;
|
|
875
907
|
if (err) {
|
|
876
908
|
done = true;
|
|
877
909
|
return callback(err);
|
|
878
910
|
}
|
|
911
|
+
// @ts-ignore
|
|
879
912
|
results[currentItem] = result;
|
|
880
913
|
if (!synchronous) {
|
|
881
914
|
lintWorker();
|
|
@@ -884,21 +917,19 @@ function lintInput(options, synchronous, callback) {
|
|
|
884
917
|
}
|
|
885
918
|
if (done) {
|
|
886
919
|
// Abort for error or nothing left to do
|
|
887
|
-
} else if (files.
|
|
920
|
+
} else if ((currentItem = files.shift())) {
|
|
888
921
|
// Lint next file
|
|
889
922
|
concurrency++;
|
|
890
|
-
currentItem = files.shift();
|
|
891
923
|
lintFile(
|
|
892
924
|
ruleList,
|
|
893
925
|
aliasToRuleNames,
|
|
894
926
|
currentItem,
|
|
895
|
-
|
|
927
|
+
markdownItFactory,
|
|
896
928
|
config,
|
|
897
929
|
configParsers,
|
|
898
930
|
frontMatter,
|
|
899
931
|
handleRuleFailures,
|
|
900
932
|
noInlineConfig,
|
|
901
|
-
resultVersion,
|
|
902
933
|
fs,
|
|
903
934
|
synchronous,
|
|
904
935
|
lintWorkerCallback
|
|
@@ -911,19 +942,28 @@ function lintInput(options, synchronous, callback) {
|
|
|
911
942
|
aliasToRuleNames,
|
|
912
943
|
currentItem,
|
|
913
944
|
strings[currentItem] || "",
|
|
914
|
-
|
|
945
|
+
markdownItFactory,
|
|
915
946
|
config,
|
|
916
947
|
configParsers,
|
|
917
948
|
frontMatter,
|
|
918
949
|
handleRuleFailures,
|
|
919
950
|
noInlineConfig,
|
|
920
|
-
|
|
951
|
+
synchronous,
|
|
921
952
|
lintWorkerCallback
|
|
922
953
|
);
|
|
923
954
|
} else if (concurrency === 0) {
|
|
924
955
|
// Finish
|
|
925
956
|
done = true;
|
|
926
|
-
|
|
957
|
+
// Deprecated: Convert results to specified resultVersion
|
|
958
|
+
let convertedResults = results;
|
|
959
|
+
if (resultVersion === 0) {
|
|
960
|
+
convertedResults = helpers.convertToResultVersion0(results);
|
|
961
|
+
} else if (resultVersion === 1) {
|
|
962
|
+
convertedResults = helpers.convertToResultVersion1(results);
|
|
963
|
+
} else if (resultVersion === 2) {
|
|
964
|
+
convertedResults = helpers.convertToResultVersion2(results);
|
|
965
|
+
}
|
|
966
|
+
return callback(null, convertedResults);
|
|
927
967
|
}
|
|
928
968
|
return null;
|
|
929
969
|
}
|
|
@@ -993,15 +1033,24 @@ export function lintSync(options) {
|
|
|
993
1033
|
return results;
|
|
994
1034
|
}
|
|
995
1035
|
|
|
1036
|
+
/**
|
|
1037
|
+
* Node fs instance (or compatible object).
|
|
1038
|
+
*
|
|
1039
|
+
* @typedef FsLike
|
|
1040
|
+
* @property {(path: string, callback: (err: Error) => void) => void} access access method.
|
|
1041
|
+
* @property {(path: string) => void} accessSync accessSync method.
|
|
1042
|
+
* @property {(path: string, encoding: string, callback: (err: Error, data: string) => void) => void} readFile readFile method.
|
|
1043
|
+
* @property {(path: string, encoding: string) => string} readFileSync readFileSync method.
|
|
1044
|
+
*/
|
|
1045
|
+
|
|
996
1046
|
/**
|
|
997
1047
|
* Resolve referenced "extends" path in a configuration file
|
|
998
1048
|
* using path.resolve() with require.resolve() as a fallback.
|
|
999
1049
|
*
|
|
1000
1050
|
* @param {string} configFile Configuration file name.
|
|
1001
1051
|
* @param {string} referenceId Referenced identifier to resolve.
|
|
1002
|
-
* @param {
|
|
1003
|
-
* @param {ResolveConfigExtendsCallback} callback Callback (err, result)
|
|
1004
|
-
* function.
|
|
1052
|
+
* @param {FsLike} fs File system implementation.
|
|
1053
|
+
* @param {ResolveConfigExtendsCallback} callback Callback (err, result) function.
|
|
1005
1054
|
* @returns {void}
|
|
1006
1055
|
*/
|
|
1007
1056
|
function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
|
@@ -1029,7 +1078,7 @@ function resolveConfigExtends(configFile, referenceId, fs, callback) {
|
|
|
1029
1078
|
*
|
|
1030
1079
|
* @param {string} configFile Configuration file name.
|
|
1031
1080
|
* @param {string} referenceId Referenced identifier to resolve.
|
|
1032
|
-
* @param {
|
|
1081
|
+
* @param {FsLike} fs File system implementation.
|
|
1033
1082
|
* @returns {string} Resolved path to file.
|
|
1034
1083
|
*/
|
|
1035
1084
|
function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
|
@@ -1054,9 +1103,8 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
|
|
1054
1103
|
*
|
|
1055
1104
|
* @param {Configuration} config Configuration object.
|
|
1056
1105
|
* @param {string} file Configuration file name.
|
|
1057
|
-
* @param {ConfigurationParser[] | undefined} parsers Parsing
|
|
1058
|
-
*
|
|
1059
|
-
* @param {Object} fs File system implementation.
|
|
1106
|
+
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
|
1107
|
+
* @param {FsLike} fs File system implementation.
|
|
1060
1108
|
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
|
1061
1109
|
* @returns {void}
|
|
1062
1110
|
*/
|
|
@@ -1096,7 +1144,7 @@ function extendConfig(config, file, parsers, fs, callback) {
|
|
|
1096
1144
|
* @param {Configuration} config Configuration object.
|
|
1097
1145
|
* @param {string} file Configuration file name.
|
|
1098
1146
|
* @param {ConfigurationParser[] | undefined} parsers Parsing function(s).
|
|
1099
|
-
* @param {
|
|
1147
|
+
* @param {FsLike} fs File system implementation.
|
|
1100
1148
|
* @returns {Promise<Configuration>} Configuration object.
|
|
1101
1149
|
*/
|
|
1102
1150
|
export function extendConfigPromise(config, file, parsers, fs) {
|
|
@@ -1115,16 +1163,17 @@ export function extendConfigPromise(config, file, parsers, fs) {
|
|
|
1115
1163
|
* Read specified configuration file.
|
|
1116
1164
|
*
|
|
1117
1165
|
* @param {string} file Configuration file name.
|
|
1118
|
-
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing
|
|
1119
|
-
*
|
|
1120
|
-
* @param {Object} [fs] File system implementation.
|
|
1166
|
+
* @param {ConfigurationParser[] | ReadConfigCallback} [parsers] Parsing function(s).
|
|
1167
|
+
* @param {FsLike | ReadConfigCallback} [fs] File system implementation.
|
|
1121
1168
|
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
|
1122
1169
|
* @returns {void}
|
|
1123
1170
|
*/
|
|
1124
1171
|
export function readConfigAsync(file, parsers, fs, callback) {
|
|
1125
1172
|
if (!callback) {
|
|
1126
1173
|
if (fs) {
|
|
1174
|
+
// @ts-ignore
|
|
1127
1175
|
callback = fs;
|
|
1176
|
+
// @ts-ignore
|
|
1128
1177
|
fs = null;
|
|
1129
1178
|
} else {
|
|
1130
1179
|
// @ts-ignore
|
|
@@ -1133,12 +1182,12 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
|
|
1133
1182
|
parsers = null;
|
|
1134
1183
|
}
|
|
1135
1184
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1185
|
+
/** @type {FsLike} */
|
|
1186
|
+
// @ts-ignore
|
|
1187
|
+
const fsLike = fs || nodeFs;
|
|
1139
1188
|
// Read file
|
|
1140
1189
|
file = helpers.expandTildePath(file, os);
|
|
1141
|
-
|
|
1190
|
+
fsLike.readFile(file, "utf8", (err, content) => {
|
|
1142
1191
|
if (err) {
|
|
1143
1192
|
// @ts-ignore
|
|
1144
1193
|
return callback(err);
|
|
@@ -1152,7 +1201,7 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
|
|
1152
1201
|
}
|
|
1153
1202
|
// Extend configuration
|
|
1154
1203
|
// @ts-ignore
|
|
1155
|
-
return extendConfig(config, file, parsers,
|
|
1204
|
+
return extendConfig(config, file, parsers, fsLike, callback);
|
|
1156
1205
|
});
|
|
1157
1206
|
}
|
|
1158
1207
|
|
|
@@ -1161,7 +1210,7 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
|
|
1161
1210
|
*
|
|
1162
1211
|
* @param {string} file Configuration file name.
|
|
1163
1212
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
1164
|
-
* @param {
|
|
1213
|
+
* @param {FsLike} [fs] File system implementation.
|
|
1165
1214
|
* @returns {Promise<Configuration>} Configuration object.
|
|
1166
1215
|
*/
|
|
1167
1216
|
export function readConfigPromise(file, parsers, fs) {
|
|
@@ -1181,19 +1230,20 @@ export function readConfigPromise(file, parsers, fs) {
|
|
|
1181
1230
|
*
|
|
1182
1231
|
* @param {string} file Configuration file name.
|
|
1183
1232
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
|
1184
|
-
* @param {
|
|
1233
|
+
* @param {FsLike} [fs] File system implementation.
|
|
1185
1234
|
* @returns {Configuration} Configuration object.
|
|
1186
1235
|
*/
|
|
1187
1236
|
export function readConfigSync(file, parsers, fs) {
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1237
|
+
/** @type {FsLike} */
|
|
1238
|
+
// @ts-ignore
|
|
1239
|
+
const fsLike = fs || nodeFs;
|
|
1191
1240
|
// Read file
|
|
1192
1241
|
file = helpers.expandTildePath(file, os);
|
|
1193
|
-
const content =
|
|
1242
|
+
const content = fsLike.readFileSync(file, "utf8");
|
|
1194
1243
|
// Try to parse file
|
|
1195
1244
|
const { config, message } = parseConfiguration(file, content, parsers);
|
|
1196
1245
|
if (!config) {
|
|
1246
|
+
// @ts-ignore
|
|
1197
1247
|
throw new Error(message);
|
|
1198
1248
|
}
|
|
1199
1249
|
// Extend configuration
|
|
@@ -1203,7 +1253,7 @@ export function readConfigSync(file, parsers, fs) {
|
|
|
1203
1253
|
const resolvedExtends = resolveConfigExtendsSync(
|
|
1204
1254
|
file,
|
|
1205
1255
|
helpers.expandTildePath(configExtends, os),
|
|
1206
|
-
|
|
1256
|
+
fsLike
|
|
1207
1257
|
);
|
|
1208
1258
|
return {
|
|
1209
1259
|
...readConfigSync(resolvedExtends, parsers, fs),
|
|
@@ -1216,9 +1266,9 @@ export function readConfigSync(file, parsers, fs) {
|
|
|
1216
1266
|
/**
|
|
1217
1267
|
* Normalizes the fields of a RuleOnErrorFixInfo instance.
|
|
1218
1268
|
*
|
|
1219
|
-
* @param {
|
|
1269
|
+
* @param {FixInfo} fixInfo RuleOnErrorFixInfo instance.
|
|
1220
1270
|
* @param {number} [lineNumber] Line number.
|
|
1221
|
-
* @returns {
|
|
1271
|
+
* @returns {FixInfoNormalized} Normalized RuleOnErrorFixInfo instance.
|
|
1222
1272
|
*/
|
|
1223
1273
|
function normalizeFixInfo(fixInfo, lineNumber = 0) {
|
|
1224
1274
|
return {
|
|
@@ -1233,7 +1283,7 @@ function normalizeFixInfo(fixInfo, lineNumber = 0) {
|
|
|
1233
1283
|
* Applies the specified fix to a Markdown content line.
|
|
1234
1284
|
*
|
|
1235
1285
|
* @param {string} line Line of Markdown content.
|
|
1236
|
-
* @param {
|
|
1286
|
+
* @param {FixInfo} fixInfo FixInfo instance.
|
|
1237
1287
|
* @param {string} [lineEnding] Line ending to use.
|
|
1238
1288
|
* @returns {string | null} Fixed content or null if deleted.
|
|
1239
1289
|
*/
|
|
@@ -1249,7 +1299,7 @@ export function applyFix(line, fixInfo, lineEnding = "\n") {
|
|
|
1249
1299
|
* Applies as many of the specified fixes as possible to Markdown content.
|
|
1250
1300
|
*
|
|
1251
1301
|
* @param {string} input Lines of Markdown content.
|
|
1252
|
-
* @param {
|
|
1302
|
+
* @param {LintError[]} errors LintError instances.
|
|
1253
1303
|
* @returns {string} Fixed content.
|
|
1254
1304
|
*/
|
|
1255
1305
|
export function applyFixes(input, errors) {
|
|
@@ -1345,8 +1395,6 @@ export function getVersion() {
|
|
|
1345
1395
|
* @returns {void}
|
|
1346
1396
|
*/
|
|
1347
1397
|
|
|
1348
|
-
/* eslint-disable jsdoc/valid-types */
|
|
1349
|
-
|
|
1350
1398
|
/**
|
|
1351
1399
|
* Rule parameters.
|
|
1352
1400
|
*
|
|
@@ -1359,8 +1407,6 @@ export function getVersion() {
|
|
|
1359
1407
|
* @property {string} version Version of the markdownlint library.
|
|
1360
1408
|
*/
|
|
1361
1409
|
|
|
1362
|
-
/* eslint-enable jsdoc/valid-types */
|
|
1363
|
-
|
|
1364
1410
|
/**
|
|
1365
1411
|
* Markdown parser data.
|
|
1366
1412
|
*
|
|
@@ -1450,16 +1496,6 @@ export function getVersion() {
|
|
|
1450
1496
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
1451
1497
|
*/
|
|
1452
1498
|
|
|
1453
|
-
/**
|
|
1454
|
-
* RuleOnErrorInfo with all optional properties present.
|
|
1455
|
-
*
|
|
1456
|
-
* @typedef {Object} RuleOnErrorFixInfoNormalized
|
|
1457
|
-
* @property {number} lineNumber Line number (1-based).
|
|
1458
|
-
* @property {number} editColumn Column of the fix (1-based).
|
|
1459
|
-
* @property {number} deleteCount Count of characters to delete.
|
|
1460
|
-
* @property {string} insertText Text to insert (after deleting).
|
|
1461
|
-
*/
|
|
1462
|
-
|
|
1463
1499
|
/**
|
|
1464
1500
|
* Rule definition.
|
|
1465
1501
|
*
|
|
@@ -1473,6 +1509,29 @@ export function getVersion() {
|
|
|
1473
1509
|
* @property {RuleFunction} function Rule implementation.
|
|
1474
1510
|
*/
|
|
1475
1511
|
|
|
1512
|
+
/**
|
|
1513
|
+
* Method used by the markdown-it parser to parse input.
|
|
1514
|
+
*
|
|
1515
|
+
* @callback MarkdownItParse
|
|
1516
|
+
* @param {string} src Source string.
|
|
1517
|
+
* @param {Object} env Environment sandbox.
|
|
1518
|
+
* @returns {import("markdown-it").Token[]} Tokens.
|
|
1519
|
+
*/
|
|
1520
|
+
|
|
1521
|
+
/**
|
|
1522
|
+
* Instance of the markdown-it parser.
|
|
1523
|
+
*
|
|
1524
|
+
* @typedef MarkdownIt
|
|
1525
|
+
* @property {MarkdownItParse} parse Method to parse input.
|
|
1526
|
+
*/
|
|
1527
|
+
|
|
1528
|
+
/**
|
|
1529
|
+
* Gets an instance of the markdown-it parser. Any plugins should already have been loaded.
|
|
1530
|
+
*
|
|
1531
|
+
* @callback MarkdownItFactory
|
|
1532
|
+
* @returns {MarkdownIt|Promise<MarkdownIt>} Instance of the markdown-it parser.
|
|
1533
|
+
*/
|
|
1534
|
+
|
|
1476
1535
|
/**
|
|
1477
1536
|
* Configuration options.
|
|
1478
1537
|
*
|
|
@@ -1482,33 +1541,23 @@ export function getVersion() {
|
|
|
1482
1541
|
* @property {Rule[] | Rule} [customRules] Custom rules.
|
|
1483
1542
|
* @property {string[] | string} [files] Files to lint.
|
|
1484
1543
|
* @property {RegExp | null} [frontMatter] Front matter pattern.
|
|
1485
|
-
* @property {
|
|
1544
|
+
* @property {FsLike} [fs] File system implementation.
|
|
1486
1545
|
* @property {boolean} [handleRuleFailures] True to catch exceptions.
|
|
1487
|
-
* @property {
|
|
1546
|
+
* @property {MarkdownItFactory} [markdownItFactory] Function to create a markdown-it parser.
|
|
1488
1547
|
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
|
1489
|
-
* @property {number} [resultVersion] Results object version.
|
|
1490
1548
|
* @property {Object.<string, string>} [strings] Strings to lint.
|
|
1491
1549
|
*/
|
|
1492
1550
|
|
|
1493
1551
|
/**
|
|
1494
1552
|
* A markdown-it plugin.
|
|
1495
1553
|
*
|
|
1496
|
-
* @typedef {
|
|
1554
|
+
* @typedef {Object[]} Plugin
|
|
1497
1555
|
*/
|
|
1498
1556
|
|
|
1499
1557
|
/**
|
|
1500
|
-
*
|
|
1501
|
-
*
|
|
1502
|
-
* @callback ToStringCallback
|
|
1503
|
-
* @param {boolean} [ruleAliases] True to use rule aliases.
|
|
1504
|
-
* @returns {string}
|
|
1505
|
-
*/
|
|
1506
|
-
|
|
1507
|
-
/**
|
|
1508
|
-
* Lint results (for resultVersion 3).
|
|
1558
|
+
* Lint results.
|
|
1509
1559
|
*
|
|
1510
1560
|
* @typedef {Object.<string, LintError[]>} LintResults
|
|
1511
|
-
* @property {ToStringCallback} toString String representation.
|
|
1512
1561
|
*/
|
|
1513
1562
|
|
|
1514
1563
|
/**
|
|
@@ -1518,11 +1567,12 @@ export function getVersion() {
|
|
|
1518
1567
|
* @property {number} lineNumber Line number (1-based).
|
|
1519
1568
|
* @property {string[]} ruleNames Rule name(s).
|
|
1520
1569
|
* @property {string} ruleDescription Rule description.
|
|
1521
|
-
* @property {string} ruleInformation Link to more information.
|
|
1522
|
-
* @property {string} errorDetail Detail about the error.
|
|
1523
|
-
* @property {string} errorContext Context for the error.
|
|
1524
|
-
* @property {number[]} errorRange Column number (1-based) and length.
|
|
1525
|
-
* @property {FixInfo}
|
|
1570
|
+
* @property {string | null} ruleInformation Link to more information.
|
|
1571
|
+
* @property {string | null} errorDetail Detail about the error.
|
|
1572
|
+
* @property {string | null} errorContext Context for the error.
|
|
1573
|
+
* @property {number[] | null} errorRange Column number (1-based) and length.
|
|
1574
|
+
* @property {FixInfo | null} fixInfo Fix information.
|
|
1575
|
+
* @property {"error" | "warning"} severity Severity of the error.
|
|
1526
1576
|
*/
|
|
1527
1577
|
|
|
1528
1578
|
/**
|
|
@@ -1535,6 +1585,16 @@ export function getVersion() {
|
|
|
1535
1585
|
* @property {string} [insertText] Text to insert (after deleting).
|
|
1536
1586
|
*/
|
|
1537
1587
|
|
|
1588
|
+
/**
|
|
1589
|
+
* FixInfo with all optional properties present.
|
|
1590
|
+
*
|
|
1591
|
+
* @typedef {Object} FixInfoNormalized
|
|
1592
|
+
* @property {number} lineNumber Line number (1-based).
|
|
1593
|
+
* @property {number} editColumn Column of the fix (1-based).
|
|
1594
|
+
* @property {number} deleteCount Count of characters to delete.
|
|
1595
|
+
* @property {string} insertText Text to insert (after deleting).
|
|
1596
|
+
*/
|
|
1597
|
+
|
|
1538
1598
|
/**
|
|
1539
1599
|
* Called with the result of linting a string or document.
|
|
1540
1600
|
*
|