markdownlint 0.41.1 → 0.42.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 +18 -0
- package/CONTRIBUTING.md +62 -77
- package/README.md +7 -7
- package/doc/CustomRules.md +6 -4
- package/doc/Rules.md +76 -35
- package/doc/md010.md +0 -1
- package/doc/md024.md +1 -1
- package/doc/md043.md +47 -9
- package/doc/md051.md +19 -19
- package/doc/md055.md +6 -3
- package/doc/md060.md +3 -2
- package/helpers/README.md +2 -2
- package/helpers/helpers.cjs +16 -7
- package/helpers/micromark-helpers.cjs +7 -10
- package/helpers/package.json +1 -5
- package/lib/configuration-strict.d.ts +124 -112
- package/lib/constants.mjs +1 -1
- package/lib/defer-require.cjs +1 -0
- package/lib/exports.d.mts +29 -1
- package/lib/markdownit.cjs +8 -1
- package/lib/markdownlint.d.mts +337 -195
- package/lib/markdownlint.mjs +78 -85
- package/lib/md007.mjs +2 -2
- package/lib/md009.mjs +2 -3
- package/lib/md010.mjs +1 -1
- package/lib/md011.mjs +10 -7
- package/lib/md012.mjs +1 -1
- package/lib/md013.mjs +13 -9
- package/lib/md018.mjs +1 -1
- package/lib/md020.mjs +1 -1
- package/lib/md022.mjs +5 -6
- package/lib/md025.mjs +1 -1
- package/lib/md027.mjs +1 -1
- package/lib/md028.mjs +1 -2
- package/lib/md029.mjs +1 -2
- package/lib/md030.mjs +4 -4
- package/lib/md031.mjs +1 -1
- package/lib/md033.mjs +1 -1
- package/lib/md034.mjs +1 -1
- package/lib/md039.mjs +5 -1
- package/lib/md041.mjs +1 -1
- package/lib/md043.mjs +98 -44
- package/lib/md044.mjs +2 -2
- package/lib/md048.mjs +1 -3
- package/lib/md051.mjs +2 -3
- package/lib/md055.mjs +11 -1
- package/lib/md056.mjs +1 -1
- package/lib/md058.mjs +1 -1
- package/lib/md060.mjs +24 -4
- package/lib/micromark-parse.mjs +1 -1
- package/lib/resolve-module.d.cts +15 -10
- package/package.json +31 -34
- package/schema/.markdownlint.jsonc +54 -54
- package/schema/.markdownlint.yaml +54 -54
- package/schema/markdownlint-config-schema-strict.json +126 -118
- package/schema/markdownlint-config-schema.json +126 -118
package/lib/markdownlint.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import { fs as nodeFs, os, path } from "#node-imports";
|
|
5
|
+
import { RE2JS } from "re2js";
|
|
5
6
|
import { initialize as cacheInitialize } from "./cache.mjs";
|
|
6
7
|
import { version } from "./constants.mjs";
|
|
7
8
|
import { requireMarkdownItCjs } from "./defer-require.cjs";
|
|
@@ -76,7 +77,7 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
76
77
|
) {
|
|
77
78
|
result = newError("asynchronous", rule.asynchronous);
|
|
78
79
|
}
|
|
79
|
-
if (!result && rule.asynchronous
|
|
80
|
+
if (!result && synchronous && rule.asynchronous) {
|
|
80
81
|
result = new Error(
|
|
81
82
|
"Custom rule " + rule.names.join("/") + " at index " + customIndex +
|
|
82
83
|
" is asynchronous and can not be used in a synchronous context."
|
|
@@ -117,14 +118,15 @@ function validateRuleList(ruleList, synchronous) {
|
|
|
117
118
|
* Remove front matter (if present at beginning of content).
|
|
118
119
|
*
|
|
119
120
|
* @param {string} content Markdown content.
|
|
120
|
-
* @param {
|
|
121
|
+
* @param {RE2JS | null} frontMatterRe2 Regular expression to match front matter.
|
|
121
122
|
* @returns {RemoveFrontMatterResult} Trimmed content and front matter lines.
|
|
122
123
|
*/
|
|
123
|
-
function removeFrontMatter(content,
|
|
124
|
+
function removeFrontMatter(content, frontMatterRe2) {
|
|
124
125
|
/** @type {string[]} */
|
|
125
126
|
let frontMatterLines = [];
|
|
126
|
-
if (
|
|
127
|
-
const frontMatterMatch =
|
|
127
|
+
if (frontMatterRe2) {
|
|
128
|
+
const frontMatterMatch = frontMatterRe2.exec(content);
|
|
129
|
+
// @ts-ignore
|
|
128
130
|
if (frontMatterMatch && !frontMatterMatch.index) {
|
|
129
131
|
const contentMatched = frontMatterMatch[0];
|
|
130
132
|
content = content.slice(contentMatched.length);
|
|
@@ -199,7 +201,7 @@ function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
|
|
199
201
|
let ruleDefaultEnable = true;
|
|
200
202
|
/** @type {"error" | "warning"} */
|
|
201
203
|
let ruleDefaultSeverity = "error";
|
|
202
|
-
// eslint-disable-next-line unicorn/no-unused-
|
|
204
|
+
// eslint-disable-next-line unicorn/no-unused-builtin-method-return
|
|
203
205
|
Object.entries(config).every(([ key, value ]) => {
|
|
204
206
|
if (key.toUpperCase() === "DEFAULT") {
|
|
205
207
|
ruleDefaultEnable = !!value;
|
|
@@ -236,7 +238,7 @@ function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
|
|
236
238
|
if (value instanceof Object) {
|
|
237
239
|
/** @type {{ enabled?: boolean, severity?: "error" | "warning" }} */
|
|
238
240
|
const valueObject = value;
|
|
239
|
-
enabled = (valueObject.enabled === undefined)
|
|
241
|
+
enabled = (valueObject.enabled === undefined) || !!valueObject.enabled;
|
|
240
242
|
severity = (valueObject.severity === "warning") ? "warning" : "error";
|
|
241
243
|
effectiveValue = Object.fromEntries(
|
|
242
244
|
Object.entries(value).filter(
|
|
@@ -277,7 +279,6 @@ function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
|
|
277
279
|
*
|
|
278
280
|
* @param {Rule[]} ruleList List of rules.
|
|
279
281
|
* @param {string[]} lines List of content lines.
|
|
280
|
-
* @param {string[]} frontMatterLines List of front matter lines.
|
|
281
282
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
282
283
|
* @param {Configuration} config Configuration object.
|
|
283
284
|
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
@@ -287,7 +288,6 @@ function getEffectiveConfig(ruleList, config, aliasToRuleNames) {
|
|
|
287
288
|
function getEnabledRulesPerLineNumber(
|
|
288
289
|
ruleList,
|
|
289
290
|
lines,
|
|
290
|
-
frontMatterLines,
|
|
291
291
|
noInlineConfig,
|
|
292
292
|
config,
|
|
293
293
|
configParsers,
|
|
@@ -297,7 +297,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
297
297
|
let enabledRules = new Map();
|
|
298
298
|
/** @type {Map<string, boolean>} */
|
|
299
299
|
let capturedRules = enabledRules;
|
|
300
|
-
const enabledRulesPerLineNumber = new Array(1
|
|
300
|
+
const enabledRulesPerLineNumber = new Array(1);
|
|
301
301
|
// Helper functions
|
|
302
302
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
303
303
|
function handleInlineConfig(/** @type {string[]} */ input, /** @type {(act: string, par: string, ind: number) => void} */ forEachMatch, /** @type {(() => void)|undefined} */ forEachLine = undefined) {
|
|
@@ -373,8 +373,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
373
373
|
const disableLine = (action === "DISABLE-LINE");
|
|
374
374
|
const disableNextLine = (action === "DISABLE-NEXT-LINE");
|
|
375
375
|
if (disableLine || disableNextLine) {
|
|
376
|
-
const nextLineNumber =
|
|
377
|
-
frontMatterLines.length + lineNumber + (disableNextLine ? 1 : 0);
|
|
376
|
+
const nextLineNumber = lineNumber + (disableNextLine ? 1 : 0);
|
|
378
377
|
enabledRulesPerLineNumber[nextLineNumber] =
|
|
379
378
|
applyEnableDisable(
|
|
380
379
|
action,
|
|
@@ -416,7 +415,7 @@ function getEnabledRulesPerLineNumber(
|
|
|
416
415
|
* @param {MarkdownItFactory} markdownItFactory Function to create a markdown-it parser.
|
|
417
416
|
* @param {Configuration} config Configuration object.
|
|
418
417
|
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
419
|
-
* @param {
|
|
418
|
+
* @param {RE2JS | null} frontMatterRe2 Regular expression for front matter.
|
|
420
419
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
421
420
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
422
421
|
* @param {boolean} synchronous Whether to execute synchronously.
|
|
@@ -431,7 +430,7 @@ function lintContent(
|
|
|
431
430
|
markdownItFactory,
|
|
432
431
|
config,
|
|
433
432
|
configParsers,
|
|
434
|
-
|
|
433
|
+
frontMatterRe2,
|
|
435
434
|
handleRuleFailures,
|
|
436
435
|
noInlineConfig,
|
|
437
436
|
synchronous,
|
|
@@ -441,17 +440,16 @@ function lintContent(
|
|
|
441
440
|
const callbackError = (/** @type {any} */ error) => callback(error instanceof Error ? error : new Error(error));
|
|
442
441
|
// Remove UTF-8 byte order marker (if present)
|
|
443
442
|
// eslint-disable-next-line unicorn/prefer-unicode-code-point-escapes
|
|
444
|
-
|
|
443
|
+
const fullContent = content.replace(/^\uFEFF/, "");
|
|
444
|
+
const fullContentLines = fullContent.split(helpers.newLineRe);
|
|
445
|
+
const fullContentNormalized = fullContentLines.join("\n");
|
|
445
446
|
// Remove front matter
|
|
446
|
-
const
|
|
447
|
-
const { frontMatterLines } = removeFrontMatterResult;
|
|
448
|
-
content = removeFrontMatterResult.content;
|
|
447
|
+
const { "content": markdownContentNormalized, frontMatterLines } = removeFrontMatter(fullContentNormalized, frontMatterRe2);
|
|
449
448
|
// Get enabled rules per line (with HTML comments present)
|
|
450
449
|
const { effectiveConfig, enabledRulesPerLineNumber, enabledRuleList, rulesSeverity } =
|
|
451
450
|
getEnabledRulesPerLineNumber(
|
|
452
451
|
ruleList,
|
|
453
|
-
|
|
454
|
-
frontMatterLines,
|
|
452
|
+
fullContentLines,
|
|
455
453
|
noInlineConfig,
|
|
456
454
|
config,
|
|
457
455
|
configParsers,
|
|
@@ -466,13 +464,12 @@ function lintContent(
|
|
|
466
464
|
const customRulesPresent = (ruleList.length !== rules.length);
|
|
467
465
|
// Parse content into parser tokens
|
|
468
466
|
const micromarkTokens = needMicromarkTokens ?
|
|
469
|
-
micromarkParse(
|
|
467
|
+
micromarkParse(markdownContentNormalized, { "freezeTokens": customRulesPresent }) :
|
|
470
468
|
[];
|
|
471
469
|
// Hide the content of HTML comments from rules
|
|
472
|
-
const
|
|
473
|
-
content = helpers.clearHtmlCommentText(content);
|
|
470
|
+
const markdownContentNormalizedSanitized = helpers.clearHtmlCommentText(markdownContentNormalized);
|
|
474
471
|
// Parse content into lines and get markdown-it tokens
|
|
475
|
-
const lines =
|
|
472
|
+
const lines = markdownContentNormalizedSanitized.split(helpers.newLineRe);
|
|
476
473
|
// Function to run after fetching markdown-it tokens (when needed)
|
|
477
474
|
const lintContentInternal = (/** @type {MarkdownItToken[]} */ markdownitTokens) => {
|
|
478
475
|
// Create (frozen) parameters for rules
|
|
@@ -539,37 +536,45 @@ function lintContent(
|
|
|
539
536
|
}
|
|
540
537
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
541
538
|
function onError(/** @type {RuleOnErrorInfo} */ errorInfo) {
|
|
542
|
-
if (!errorInfo
|
|
543
|
-
|
|
539
|
+
if (!errorInfo) {
|
|
540
|
+
throwError("onErrorInfo");
|
|
541
|
+
}
|
|
542
|
+
if ((errorInfo.frontMatter !== undefined) &&
|
|
543
|
+
!helpers.isBoolean(errorInfo.frontMatter)) {
|
|
544
|
+
throwError("frontMatter");
|
|
545
|
+
}
|
|
546
|
+
const useFrontMatter = Boolean(errorInfo.frontMatter);
|
|
547
|
+
const contentLines = useFrontMatter ? frontMatterLines : lines;
|
|
548
|
+
const lineOffset = useFrontMatter ? 0 : frontMatterLines.length;
|
|
549
|
+
if (!helpers.isNumber(errorInfo.lineNumber) ||
|
|
544
550
|
(errorInfo.lineNumber < 1) ||
|
|
545
|
-
(errorInfo.lineNumber >
|
|
551
|
+
(errorInfo.lineNumber > contentLines.length)) {
|
|
546
552
|
throwError("lineNumber");
|
|
547
553
|
}
|
|
548
|
-
const lineNumber = errorInfo.lineNumber +
|
|
554
|
+
const lineNumber = errorInfo.lineNumber + lineOffset;
|
|
549
555
|
if (!enabledRulesPerLineNumber[lineNumber].get(ruleName)) {
|
|
550
556
|
return;
|
|
551
557
|
}
|
|
552
|
-
if (errorInfo.detail &&
|
|
558
|
+
if ((errorInfo.detail !== undefined) &&
|
|
553
559
|
!helpers.isString(errorInfo.detail)) {
|
|
554
560
|
throwError("detail");
|
|
555
561
|
}
|
|
556
|
-
if (errorInfo.context &&
|
|
562
|
+
if ((errorInfo.context !== undefined) &&
|
|
557
563
|
!helpers.isString(errorInfo.context)) {
|
|
558
564
|
throwError("context");
|
|
559
565
|
}
|
|
560
|
-
if (errorInfo.information &&
|
|
566
|
+
if ((errorInfo.information !== undefined) &&
|
|
561
567
|
!helpers.isUrl(errorInfo.information)) {
|
|
562
568
|
throwError("information");
|
|
563
569
|
}
|
|
564
|
-
if (errorInfo.range &&
|
|
570
|
+
if ((errorInfo.range !== undefined) &&
|
|
565
571
|
(!Array.isArray(errorInfo.range) ||
|
|
566
572
|
(errorInfo.range.length !== 2) ||
|
|
567
573
|
!helpers.isNumber(errorInfo.range[0]) ||
|
|
568
574
|
(errorInfo.range[0] < 1) ||
|
|
569
575
|
!helpers.isNumber(errorInfo.range[1]) ||
|
|
570
576
|
(errorInfo.range[1] < 1) ||
|
|
571
|
-
((errorInfo.range[0] + errorInfo.range[1] - 1) >
|
|
572
|
-
lines[errorInfo.lineNumber - 1].length))) {
|
|
577
|
+
((errorInfo.range[0] + errorInfo.range[1] - 1) > contentLines[errorInfo.lineNumber - 1].length))) {
|
|
573
578
|
throwError("range");
|
|
574
579
|
}
|
|
575
580
|
const fixInfo = errorInfo.fixInfo;
|
|
@@ -581,18 +586,16 @@ function lintContent(
|
|
|
581
586
|
if (fixInfo.lineNumber !== undefined) {
|
|
582
587
|
if ((!helpers.isNumber(fixInfo.lineNumber) ||
|
|
583
588
|
(fixInfo.lineNumber < 1) ||
|
|
584
|
-
(fixInfo.lineNumber >
|
|
589
|
+
(fixInfo.lineNumber > contentLines.length))) {
|
|
585
590
|
throwError("fixInfo.lineNumber");
|
|
586
591
|
}
|
|
587
|
-
cleanFixInfo.lineNumber =
|
|
588
|
-
fixInfo.lineNumber + frontMatterLines.length;
|
|
592
|
+
cleanFixInfo.lineNumber = fixInfo.lineNumber + lineOffset;
|
|
589
593
|
}
|
|
590
594
|
const effectiveLineNumber = fixInfo.lineNumber || errorInfo.lineNumber;
|
|
591
595
|
if (fixInfo.editColumn !== undefined) {
|
|
592
596
|
if ((!helpers.isNumber(fixInfo.editColumn) ||
|
|
593
597
|
(fixInfo.editColumn < 1) ||
|
|
594
|
-
(fixInfo.editColumn >
|
|
595
|
-
lines[effectiveLineNumber - 1].length + 1))) {
|
|
598
|
+
(fixInfo.editColumn > contentLines[effectiveLineNumber - 1].length + 1))) {
|
|
596
599
|
throwError("fixInfo.editColumn");
|
|
597
600
|
}
|
|
598
601
|
cleanFixInfo.editColumn = fixInfo.editColumn;
|
|
@@ -600,8 +603,7 @@ function lintContent(
|
|
|
600
603
|
if (fixInfo.deleteCount !== undefined) {
|
|
601
604
|
if ((!helpers.isNumber(fixInfo.deleteCount) ||
|
|
602
605
|
(fixInfo.deleteCount < -1) ||
|
|
603
|
-
(fixInfo.deleteCount >
|
|
604
|
-
lines[effectiveLineNumber - 1].length))) {
|
|
606
|
+
(((fixInfo.editColumn ?? 1) + fixInfo.deleteCount - 1) > contentLines[effectiveLineNumber - 1].length))) {
|
|
605
607
|
throwError("fixInfo.deleteCount");
|
|
606
608
|
}
|
|
607
609
|
cleanFixInfo.deleteCount = fixInfo.deleteCount;
|
|
@@ -688,7 +690,7 @@ function lintContent(
|
|
|
688
690
|
if (!needMarkdownItTokens || synchronous) {
|
|
689
691
|
// Need/able to call into markdown-it and lintContentInternal synchronously
|
|
690
692
|
const markdownItTokens = needMarkdownItTokens ?
|
|
691
|
-
requireMarkdownItCjs().getMarkdownItTokens(markdownItFactory(),
|
|
693
|
+
requireMarkdownItCjs().getMarkdownItTokens(markdownItFactory(), markdownContentNormalized, lines) :
|
|
692
694
|
[];
|
|
693
695
|
lintContentInternal(markdownItTokens);
|
|
694
696
|
} else {
|
|
@@ -699,7 +701,7 @@ function lintContent(
|
|
|
699
701
|
// eslint-disable-next-line no-promise-executor-return
|
|
700
702
|
new Promise((resolve) => resolve(markdownItFactory()))
|
|
701
703
|
]).then(([ markdownitCjs, markdownIt ]) => {
|
|
702
|
-
const markdownItTokens = markdownitCjs.getMarkdownItTokens(markdownIt,
|
|
704
|
+
const markdownItTokens = markdownitCjs.getMarkdownItTokens(markdownIt, markdownContentNormalized, lines);
|
|
703
705
|
lintContentInternal(markdownItTokens);
|
|
704
706
|
}).catch(callbackError);
|
|
705
707
|
}
|
|
@@ -714,7 +716,7 @@ function lintContent(
|
|
|
714
716
|
* @param {MarkdownItFactory} markdownItFactory Function to create a markdown-it parser.
|
|
715
717
|
* @param {Configuration} config Configuration object.
|
|
716
718
|
* @param {ConfigurationParser[] | undefined} configParsers Configuration parsers.
|
|
717
|
-
* @param {
|
|
719
|
+
* @param {RE2JS | null} frontMatterRe2 Regular expression for front matter.
|
|
718
720
|
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
|
719
721
|
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
|
720
722
|
* @param {FsLike} fs File system implementation.
|
|
@@ -729,7 +731,7 @@ function lintFile(
|
|
|
729
731
|
markdownItFactory,
|
|
730
732
|
config,
|
|
731
733
|
configParsers,
|
|
732
|
-
|
|
734
|
+
frontMatterRe2,
|
|
733
735
|
handleRuleFailures,
|
|
734
736
|
noInlineConfig,
|
|
735
737
|
fs,
|
|
@@ -737,23 +739,22 @@ function lintFile(
|
|
|
737
739
|
callback) {
|
|
738
740
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
739
741
|
function lintContentWrapper(/** @type {Error | null} */ err, /** @type {string} */ content) {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
);
|
|
742
|
+
return err ?
|
|
743
|
+
callback(err) :
|
|
744
|
+
lintContent(
|
|
745
|
+
ruleList,
|
|
746
|
+
aliasToRuleNames,
|
|
747
|
+
file,
|
|
748
|
+
content,
|
|
749
|
+
markdownItFactory,
|
|
750
|
+
config,
|
|
751
|
+
configParsers,
|
|
752
|
+
frontMatterRe2,
|
|
753
|
+
handleRuleFailures,
|
|
754
|
+
noInlineConfig,
|
|
755
|
+
synchronous,
|
|
756
|
+
callback
|
|
757
|
+
);
|
|
757
758
|
}
|
|
758
759
|
// Make a/synchronous call to read file
|
|
759
760
|
if (synchronous) {
|
|
@@ -807,9 +808,8 @@ function lintInput(options, synchronous, callback) {
|
|
|
807
808
|
const stringsKeys = Object.keys(strings);
|
|
808
809
|
const config = options.config || { "default": true };
|
|
809
810
|
const configParsers = options.configParsers || undefined;
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
options.frontMatter;
|
|
811
|
+
const frontMatterRe = (options.frontMatter === undefined) ? helpers.frontMatterRe : options.frontMatter;
|
|
812
|
+
const frontMatterRe2 = frontMatterRe && RE2JS.compile(RE2JS.translateRegExp(frontMatterRe));
|
|
813
813
|
const handleRuleFailures = !!options.handleRuleFailures;
|
|
814
814
|
const noInlineConfig = !!options.noInlineConfig;
|
|
815
815
|
const markdownItFactory =
|
|
@@ -852,7 +852,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
852
852
|
markdownItFactory,
|
|
853
853
|
config,
|
|
854
854
|
configParsers,
|
|
855
|
-
|
|
855
|
+
frontMatterRe2,
|
|
856
856
|
handleRuleFailures,
|
|
857
857
|
noInlineConfig,
|
|
858
858
|
fs,
|
|
@@ -870,7 +870,7 @@ function lintInput(options, synchronous, callback) {
|
|
|
870
870
|
markdownItFactory,
|
|
871
871
|
config,
|
|
872
872
|
configParsers,
|
|
873
|
-
|
|
873
|
+
frontMatterRe2,
|
|
874
874
|
handleRuleFailures,
|
|
875
875
|
noInlineConfig,
|
|
876
876
|
synchronous,
|
|
@@ -1029,8 +1029,8 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
|
|
1029
1029
|
*/
|
|
1030
1030
|
function extendConfig(config, file, parsers, fs, callback) {
|
|
1031
1031
|
const configExtends = config.extends;
|
|
1032
|
-
|
|
1033
|
-
|
|
1032
|
+
return configExtends ?
|
|
1033
|
+
resolveConfigExtends(
|
|
1034
1034
|
file,
|
|
1035
1035
|
helpers.expandTildePath(configExtends, os),
|
|
1036
1036
|
fs,
|
|
@@ -1052,9 +1052,8 @@ function extendConfig(config, file, parsers, fs, callback) {
|
|
|
1052
1052
|
return callback(null, result);
|
|
1053
1053
|
}
|
|
1054
1054
|
)
|
|
1055
|
-
)
|
|
1056
|
-
|
|
1057
|
-
return callback(null, config);
|
|
1055
|
+
) :
|
|
1056
|
+
callback(null, config);
|
|
1058
1057
|
}
|
|
1059
1058
|
|
|
1060
1059
|
/**
|
|
@@ -1114,13 +1113,11 @@ export function readConfigAsync(file, parsers, fs, callback) {
|
|
|
1114
1113
|
// Try to parse file
|
|
1115
1114
|
// @ts-ignore
|
|
1116
1115
|
const { config, message } = parseConfiguration(file, content, parsers);
|
|
1117
|
-
|
|
1116
|
+
return config ?
|
|
1118
1117
|
// @ts-ignore
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
// @ts-ignore
|
|
1123
|
-
return extendConfig(config, file, parsers, fsLike, callback);
|
|
1118
|
+
extendConfig(config, file, parsers, fsLike, callback) :
|
|
1119
|
+
// @ts-ignore
|
|
1120
|
+
callback(new Error(message));
|
|
1124
1121
|
});
|
|
1125
1122
|
}
|
|
1126
1123
|
|
|
@@ -1411,6 +1408,7 @@ export function getVersion() {
|
|
|
1411
1408
|
* Fix information for RuleOnError callback.
|
|
1412
1409
|
*
|
|
1413
1410
|
* @typedef {Object} RuleOnErrorInfo
|
|
1411
|
+
* @property {boolean} [frontMatter] True if applies to front matter.
|
|
1414
1412
|
* @property {number} lineNumber Line number (1-based).
|
|
1415
1413
|
* @property {string} [detail] Detail about the error.
|
|
1416
1414
|
* @property {string} [context] Context for the error.
|
|
@@ -1451,12 +1449,7 @@ export function getVersion() {
|
|
|
1451
1449
|
* @returns {MarkdownItBaseToken[]} Tokens.
|
|
1452
1450
|
*/
|
|
1453
1451
|
|
|
1454
|
-
/**
|
|
1455
|
-
* Instance of the markdown-it parser.
|
|
1456
|
-
*
|
|
1457
|
-
* @typedef MarkdownIt
|
|
1458
|
-
* @property {MarkdownItParse} parse Method to parse input.
|
|
1459
|
-
*/
|
|
1452
|
+
/** @typedef {import("markdown-it").MarkdownIt} MarkdownIt */
|
|
1460
1453
|
|
|
1461
1454
|
/**
|
|
1462
1455
|
* Gets an instance of the markdown-it parser. Any plugins should already have been loaded.
|
|
@@ -1490,7 +1483,7 @@ export function getVersion() {
|
|
|
1490
1483
|
/**
|
|
1491
1484
|
* Lint results.
|
|
1492
1485
|
*
|
|
1493
|
-
* @typedef {
|
|
1486
|
+
* @typedef {{[k: string]: LintError[]}} LintResults
|
|
1494
1487
|
*/
|
|
1495
1488
|
|
|
1496
1489
|
/**
|
package/lib/md007.mjs
CHANGED
|
@@ -18,9 +18,9 @@ export default {
|
|
|
18
18
|
"tags": [ "bullet", "ul", "indentation" ],
|
|
19
19
|
"parser": "micromark",
|
|
20
20
|
"function": function MD007(params, onError) {
|
|
21
|
-
const indent = Number(params.config.indent
|
|
21
|
+
const indent = Number(params.config.indent ?? 2);
|
|
22
22
|
const startIndented = !!params.config.start_indented;
|
|
23
|
-
const startIndent = Number(params.config.start_indent
|
|
23
|
+
const startIndent = Number(params.config.start_indent ?? indent);
|
|
24
24
|
const unorderedListNesting = new Map();
|
|
25
25
|
let lastBlockQuotePrefix = null;
|
|
26
26
|
const tokens = filterByTypesCached(unorderedListTypes);
|
package/lib/md009.mjs
CHANGED
|
@@ -11,10 +11,9 @@ export default {
|
|
|
11
11
|
"tags": [ "whitespace" ],
|
|
12
12
|
"parser": "micromark",
|
|
13
13
|
"function": function MD009(params, onError) {
|
|
14
|
-
|
|
15
|
-
brSpaces = Number((brSpaces === undefined) ? 2 : brSpaces);
|
|
14
|
+
const brSpaces = Number(params.config.br_spaces ?? 2);
|
|
16
15
|
const codeBlocks = params.config.code_blocks;
|
|
17
|
-
const includeCode = (codeBlocks
|
|
16
|
+
const includeCode = (codeBlocks !== undefined) && !!codeBlocks;
|
|
18
17
|
const listItemEmptyLines = !!params.config.list_item_empty_lines;
|
|
19
18
|
const strict = !!params.config.strict;
|
|
20
19
|
const codeBlockLineNumbers = new Set();
|
package/lib/md010.mjs
CHANGED
|
@@ -14,7 +14,7 @@ export default {
|
|
|
14
14
|
"parser": "micromark",
|
|
15
15
|
"function": function MD010(params, onError) {
|
|
16
16
|
const codeBlocks = params.config.code_blocks;
|
|
17
|
-
const includeCode = (codeBlocks === undefined)
|
|
17
|
+
const includeCode = (codeBlocks === undefined) || !!codeBlocks;
|
|
18
18
|
const ignoreCodeLanguages = new Set(
|
|
19
19
|
(params.config.ignore_code_languages || [])
|
|
20
20
|
.map((/** @type {void} */ language) => String(language).toLowerCase())
|
package/lib/md011.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { re } from "re2js";
|
|
3
4
|
import { addError, hasOverlap } from "../helpers/helpers.cjs";
|
|
4
5
|
import { addRangeToSet } from "../helpers/micromark-helpers.cjs";
|
|
5
6
|
import { filterByTypesCached } from "./cache.mjs";
|
|
6
7
|
|
|
7
|
-
/** @typedef {import("micromark-extension-math")} */
|
|
8
|
+
/** @typedef {typeof import("micromark-extension-math")} _ambient_ */
|
|
8
9
|
|
|
9
|
-
const reversedLinkRe =
|
|
10
|
+
const reversedLinkRe = re`(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\]`;
|
|
10
11
|
|
|
11
12
|
/** @type {import("markdownlint").Rule} */
|
|
12
13
|
export default {
|
|
@@ -16,22 +17,24 @@ export default {
|
|
|
16
17
|
"parser": "micromark",
|
|
17
18
|
"function": function MD011(params, onError) {
|
|
18
19
|
const ignoreBlockLineNumbers = new Set();
|
|
19
|
-
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "mathFlow" ])) {
|
|
20
|
+
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow", "mathFlow" ])) {
|
|
20
21
|
addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine);
|
|
21
22
|
}
|
|
22
23
|
const ignoreTexts = filterByTypesCached([ "codeText", "mathText" ]);
|
|
23
24
|
for (const [ lineIndex, line ] of params.lines.entries()) {
|
|
24
25
|
const lineNumber = lineIndex + 1;
|
|
25
26
|
if (!ignoreBlockLineNumbers.has(lineNumber)) {
|
|
26
|
-
|
|
27
|
-
while ((match = reversedLinkRe.exec(line)) !== null) {
|
|
27
|
+
for (const match of reversedLinkRe.matchAll(line)) {
|
|
28
28
|
const [ reversedLink, preChar, linkText, linkDestination ] = match;
|
|
29
|
+
const matchIndex = match.index ?? 0;
|
|
30
|
+
const matchLength = match[0].length;
|
|
29
31
|
if (
|
|
32
|
+
(line[matchIndex + matchLength] !== "(") &&
|
|
30
33
|
!linkText.endsWith("\\") &&
|
|
31
34
|
!linkDestination.endsWith("\\")
|
|
32
35
|
) {
|
|
33
|
-
const column =
|
|
34
|
-
const length =
|
|
36
|
+
const column = matchIndex + preChar.length + 1;
|
|
37
|
+
const length = matchLength - preChar.length;
|
|
35
38
|
/** @type {import("../helpers/helpers.cjs").FileRange} */
|
|
36
39
|
const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 };
|
|
37
40
|
if (!ignoreTexts.some((ignoreText) => hasOverlap(ignoreText, range))) {
|
package/lib/md012.mjs
CHANGED
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
"tags": [ "whitespace", "blank_lines" ],
|
|
12
12
|
"parser": "micromark",
|
|
13
13
|
"function": function MD012(params, onError) {
|
|
14
|
-
const maximum = Number(params.config.maximum
|
|
14
|
+
const maximum = Number(params.config.maximum ?? 1);
|
|
15
15
|
const { lines } = params;
|
|
16
16
|
const codeBlockLineNumbers = new Set();
|
|
17
17
|
for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) {
|
package/lib/md013.mjs
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { re } from "re2js";
|
|
3
4
|
import { addErrorDetailIf } from "../helpers/helpers.cjs";
|
|
4
5
|
import { filterByTypesCached, getReferenceLinkImageData } from "./cache.mjs";
|
|
5
6
|
import { addRangeToSet, getDescendantsByType } from "../helpers/micromark-helpers.cjs";
|
|
6
7
|
|
|
8
|
+
/** @typedef {typeof import("micromark-extension-gfm-autolink-literal")} _ambient_ */
|
|
9
|
+
/** @typedef {typeof import("micromark-extension-gfm-table")} _ambient_2_ */
|
|
10
|
+
|
|
7
11
|
// Regular expression for a line that is not wrappable
|
|
8
12
|
const notWrappableRe = /^(?:[#>\s]*\s)?\S*$/;
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
// Regular expression for the last run of non-whitespace
|
|
15
|
+
const lastRunRe = re`\S*$`;
|
|
12
16
|
|
|
13
17
|
/** @type {import("markdownlint").Rule} */
|
|
14
18
|
export default {
|
|
@@ -17,17 +21,17 @@ export default {
|
|
|
17
21
|
"tags": [ "line_length" ],
|
|
18
22
|
"parser": "micromark",
|
|
19
23
|
"function": function MD013(params, onError) {
|
|
20
|
-
const lineLength = Number(params.config.line_length
|
|
21
|
-
const headingLineLength = Number(params.config.heading_line_length
|
|
22
|
-
const codeLineLength = Number(params.config.code_block_line_length
|
|
24
|
+
const lineLength = Number(params.config.line_length ?? 80);
|
|
25
|
+
const headingLineLength = Number(params.config.heading_line_length ?? lineLength);
|
|
26
|
+
const codeLineLength = Number(params.config.code_block_line_length ?? lineLength);
|
|
23
27
|
const strict = !!params.config.strict;
|
|
24
28
|
const stern = !!params.config.stern;
|
|
25
29
|
const codeBlocks = params.config.code_blocks;
|
|
26
|
-
const includeCodeBlocks = (codeBlocks === undefined)
|
|
30
|
+
const includeCodeBlocks = (codeBlocks === undefined) || !!codeBlocks;
|
|
27
31
|
const tables = params.config.tables;
|
|
28
|
-
const includeTables = (tables === undefined)
|
|
32
|
+
const includeTables = (tables === undefined) || !!tables;
|
|
29
33
|
const headings = params.config.headings;
|
|
30
|
-
const includeHeadings = (headings === undefined)
|
|
34
|
+
const includeHeadings = (headings === undefined) || !!headings;
|
|
31
35
|
const headingLineNumbers = new Set();
|
|
32
36
|
for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) {
|
|
33
37
|
addRangeToSet(headingLineNumbers, heading.startLine, heading.endLine);
|
|
@@ -66,7 +70,7 @@ export default {
|
|
|
66
70
|
const maxLength = inCode ? codeLineLength : (isHeading ? headingLineLength : lineLength);
|
|
67
71
|
// If not strict/stern, the last run of non-whitespace is allowed to go
|
|
68
72
|
// beyond the limit as long as it begins within the limit
|
|
69
|
-
const text = (strict || stern) ? line : line.
|
|
73
|
+
const text = (strict || stern) ? line : lastRunRe.matcher(line).replaceFirst("#");
|
|
70
74
|
if ((maxLength > 0) &&
|
|
71
75
|
(includeCodeBlocks || !inCode) &&
|
|
72
76
|
(includeTables || !inTable) &&
|
package/lib/md018.mjs
CHANGED
|
@@ -13,7 +13,7 @@ export default {
|
|
|
13
13
|
"function": function MD018(params, onError) {
|
|
14
14
|
const { lines } = params;
|
|
15
15
|
const ignoreBlockLineNumbers = new Set();
|
|
16
|
-
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow" ])) {
|
|
16
|
+
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow", "mathFlow" ])) {
|
|
17
17
|
addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine);
|
|
18
18
|
}
|
|
19
19
|
for (const [ lineIndex, line ] of lines.entries()) {
|
package/lib/md020.mjs
CHANGED
|
@@ -13,7 +13,7 @@ export default {
|
|
|
13
13
|
"function": function MD020(params, onError) {
|
|
14
14
|
const { lines } = params;
|
|
15
15
|
const ignoreBlockLineNumbers = new Set();
|
|
16
|
-
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow" ])) {
|
|
16
|
+
for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow", "mathFlow" ])) {
|
|
17
17
|
addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine);
|
|
18
18
|
}
|
|
19
19
|
for (const [ lineIndex, line ] of lines.entries()) {
|
package/lib/md022.mjs
CHANGED
|
@@ -13,13 +13,13 @@ const getLinesFunction = (/** @type {any} */ linesParam) => {
|
|
|
13
13
|
if (Array.isArray(linesParam)) {
|
|
14
14
|
// eslint-disable-next-line unicorn/no-unreadable-new-expression
|
|
15
15
|
const linesArray = new Array(6).fill(defaultLines);
|
|
16
|
-
for (const [ index, value ] of
|
|
16
|
+
for (const [ index, value ] of linesParam.slice(0, 6).entries()) {
|
|
17
17
|
linesArray[index] = value;
|
|
18
18
|
}
|
|
19
19
|
return (/** @type {MicromarkToken} */ heading) => linesArray[getHeadingLevel(heading) - 1];
|
|
20
20
|
}
|
|
21
21
|
// Coerce linesParam to a number
|
|
22
|
-
const lines = (linesParam
|
|
22
|
+
const lines = Number(linesParam ?? defaultLines);
|
|
23
23
|
return () => lines;
|
|
24
24
|
};
|
|
25
25
|
|
|
@@ -27,10 +27,9 @@ const getLine = (/** @type {readonly string[]} */ lines, /** @type {number} */ i
|
|
|
27
27
|
if ((index >= 0) && (index < lines.length)) {
|
|
28
28
|
return lines[index];
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return "";
|
|
30
|
+
return (includeFrontMatter && (frontMatterLines.length > 0) && (index < 0) && (index >= -frontMatterLines.length)) ?
|
|
31
|
+
frontMatterLines[frontMatterLines.length + index] :
|
|
32
|
+
"";
|
|
34
33
|
};
|
|
35
34
|
|
|
36
35
|
/** @type {import("markdownlint").Rule} */
|
package/lib/md025.mjs
CHANGED
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
"tags": [ "headings" ],
|
|
12
12
|
"parser": "micromark",
|
|
13
13
|
"function": function MD025(params, onError) {
|
|
14
|
-
const level = Number(params.config.level
|
|
14
|
+
const level = Number(params.config.level ?? 1);
|
|
15
15
|
const { tokens } = params.parsers.micromark;
|
|
16
16
|
const matchingHeadings = filterByTypesCached([ "atxHeading", "setextHeading" ])
|
|
17
17
|
.filter((heading) => (level === getHeadingLevel(heading)) && !isDocfxTab(heading));
|
package/lib/md027.mjs
CHANGED
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
"parser": "micromark",
|
|
16
16
|
"function": function MD027(params, onError) {
|
|
17
17
|
const listItems = params.config.list_items;
|
|
18
|
-
const includeListItems = (listItems === undefined)
|
|
18
|
+
const includeListItems = (listItems === undefined) || !!listItems;
|
|
19
19
|
const { tokens } = params.parsers.micromark;
|
|
20
20
|
for (const token of filterByTypesCached([ "linePrefix" ])) {
|
|
21
21
|
const parent = token.parent;
|
package/lib/md028.mjs
CHANGED
|
@@ -16,8 +16,7 @@ export default {
|
|
|
16
16
|
const errorLineNumbers = [];
|
|
17
17
|
const siblings = token.parent?.children || params.parsers.micromark.tokens;
|
|
18
18
|
for (let i = siblings.indexOf(token) + 1; i < siblings.length; i++) {
|
|
19
|
-
const
|
|
20
|
-
const { startLine, type } = sibling;
|
|
19
|
+
const { startLine, type } = siblings[i];
|
|
21
20
|
if (type === "lineEndingBlank") {
|
|
22
21
|
// Possible blank between blockquotes
|
|
23
22
|
errorLineNumbers.push(startLine);
|
package/lib/md029.mjs
CHANGED
|
@@ -18,8 +18,7 @@ const listStyles = Object.keys(listStyleExamples);
|
|
|
18
18
|
* @returns {{startColumn: number, endColumn: number, text: string, number: number}} List item value column and text.
|
|
19
19
|
*/
|
|
20
20
|
function getOrderedListItemValue(listItemPrefix) {
|
|
21
|
-
const
|
|
22
|
-
const { startColumn, endColumn, text } = listItemValue;
|
|
21
|
+
const { startColumn, endColumn, text } = getDescendantsByType(listItemPrefix, [ "listItemValue" ])[0];
|
|
23
22
|
return {
|
|
24
23
|
startColumn,
|
|
25
24
|
endColumn,
|