markdownlint 0.38.0 → 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 +10 -0
- package/README.md +136 -66
- package/doc/Rules.md +116 -13
- package/doc/md001.md +14 -0
- package/doc/md009.md +8 -9
- package/doc/md010.md +6 -0
- package/doc/md029.md +2 -0
- package/doc/md033.md +7 -1
- package/doc/md055.md +1 -1
- package/doc/md056.md +1 -1
- package/doc/md059.md +4 -1
- package/doc/md060.md +70 -0
- package/helpers/README.md +2 -2
- package/helpers/helpers.cjs +171 -15
- package/helpers/micromark-helpers.cjs +11 -7
- package/helpers/package.json +1 -1
- package/lib/cache.mjs +6 -2
- package/lib/configuration-strict.d.ts +1344 -206
- package/lib/constants.mjs +6 -5
- package/lib/defer-require.cjs +2 -0
- package/lib/exports.d.mts +1 -2
- package/lib/exports.mjs +1 -2
- package/lib/markdownit.cjs +2 -1
- package/lib/markdownlint.d.mts +101 -51
- package/lib/markdownlint.mjs +217 -181
- 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/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 +5 -3
- package/lib/md037.mjs +10 -7
- package/lib/md042.mjs +4 -2
- package/lib/md043.mjs +2 -2
- package/lib/md044.mjs +1 -1
- package/lib/md046.mjs +6 -6
- 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/md060.mjs +121 -0
- package/lib/micromark-parse.mjs +3 -0
- package/lib/node-imports-browser.mjs +2 -0
- package/lib/parse-configuration.mjs +5 -4
- package/lib/rules.mjs +3 -1
- package/package.json +15 -16
- package/schema/.markdownlint.jsonc +67 -54
- package/schema/.markdownlint.yaml +64 -53
- package/schema/markdownlint-config-schema-strict.json +4699 -1537
- package/schema/markdownlint-config-schema.json +4699 -1537
package/doc/md059.md
CHANGED
|
@@ -27,4 +27,7 @@ translations for every language.
|
|
|
27
27
|
|
|
28
28
|
Note: This rule checks Markdown links; HTML links are ignored.
|
|
29
29
|
|
|
30
|
-
More information:
|
|
30
|
+
More information:
|
|
31
|
+
|
|
32
|
+
- <https://webaim.org/techniques/hypertext/>
|
|
33
|
+
- <https://www.w3.org/WAI/WCAG21/Understanding/link-purpose-link-only.html>
|
package/doc/md060.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# `MD060` - Table column style
|
|
2
|
+
|
|
3
|
+
Tags: `table`
|
|
4
|
+
|
|
5
|
+
Aliases: `table-column-style`
|
|
6
|
+
|
|
7
|
+
Parameters:
|
|
8
|
+
|
|
9
|
+
- `style`: Table column style (`string`, default `any`, values `aligned` /
|
|
10
|
+
`any` / `compact` / `tight`)
|
|
11
|
+
|
|
12
|
+
This rule is triggered when the column separators of a
|
|
13
|
+
[GitHub Flavored Markdown table][gfm-table-060] are used inconsistently.
|
|
14
|
+
|
|
15
|
+
This rule recognizes three table column styles based on popular use:
|
|
16
|
+
|
|
17
|
+
Style `aligned` looks the most like a table:
|
|
18
|
+
|
|
19
|
+
```markdown
|
|
20
|
+
| Character | Meaning |
|
|
21
|
+
| --------- | ------- |
|
|
22
|
+
| Y | Yes |
|
|
23
|
+
| N | No |
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Style `compact` uses a single space to pad cell content:
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
| Character | Meaning |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| Y | Yes |
|
|
32
|
+
| N | No |
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Style `tight` uses no padding for cell content:
|
|
36
|
+
|
|
37
|
+
```markdown
|
|
38
|
+
|Character|Meaning|
|
|
39
|
+
|---|---|
|
|
40
|
+
|Y|Yes|
|
|
41
|
+
|N|No|
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
When this rule's `style` parameter is set to `aligned`, `compact`, or `tight`,
|
|
45
|
+
every table must match the corresponding pattern and errors will be reported for
|
|
46
|
+
any violations. By default, or when the `any` style is used, each table is
|
|
47
|
+
analyzed to see if it satisfies any supported style. If so, no errors are
|
|
48
|
+
reported. If not, errors are be reported for whichever style would produce the
|
|
49
|
+
*fewest* errors (i.e., whichever style is the closest match).
|
|
50
|
+
|
|
51
|
+
Note: Pipe alignment for the `aligned` style is based on character count, so
|
|
52
|
+
wide characters and multi-character encodings can produce unexpected results.
|
|
53
|
+
The following table is correctly aligned based on character count, though some
|
|
54
|
+
editors render the emoji wider:
|
|
55
|
+
|
|
56
|
+
<!-- markdownlint-capture -->
|
|
57
|
+
<!-- markdownlint-disable extended-ascii -->
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
| Response | Emoji |
|
|
61
|
+
| -------- | ----- |
|
|
62
|
+
| Yes | ✅ |
|
|
63
|
+
| No | ❎ |
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
<!-- markdownlint-restore -->
|
|
67
|
+
|
|
68
|
+
Rationale: Consistent formatting makes it easier to understand a document.
|
|
69
|
+
|
|
70
|
+
[gfm-table-060]: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables
|
package/helpers/README.md
CHANGED
|
@@ -22,8 +22,8 @@ be useful to custom rule authors and may avoid duplicating code.
|
|
|
22
22
|
*None* - The entire body of code is tested to 100% coverage by the core
|
|
23
23
|
`markdownlint` project, so there are no additional tests here.
|
|
24
24
|
|
|
25
|
-
[custom-rules]: https://github.com/DavidAnson/markdownlint/blob/v0.
|
|
25
|
+
[custom-rules]: https://github.com/DavidAnson/markdownlint/blob/v0.39.0/doc/CustomRules.md
|
|
26
26
|
[jsdoc]: https://en.m.wikipedia.org/wiki/JSDoc
|
|
27
27
|
[markdown]: https://en.wikipedia.org/wiki/Markdown
|
|
28
28
|
[markdownlint]: https://github.com/DavidAnson/markdownlint
|
|
29
|
-
[rules]: https://github.com/DavidAnson/markdownlint/blob/v0.
|
|
29
|
+
[rules]: https://github.com/DavidAnson/markdownlint/blob/v0.39.0/doc/Rules.md
|
package/helpers/helpers.cjs
CHANGED
|
@@ -111,10 +111,11 @@ module.exports.cloneIfArray = cloneIfArray;
|
|
|
111
111
|
/**
|
|
112
112
|
* Clones the input if it is a URL.
|
|
113
113
|
*
|
|
114
|
-
* @param {Object} url Object of unknown type.
|
|
114
|
+
* @param {Object | undefined} url Object of unknown type.
|
|
115
115
|
* @returns {Object} Clone of obj iff obj is a URL.
|
|
116
116
|
*/
|
|
117
117
|
function cloneIfUrl(url) {
|
|
118
|
+
// @ts-ignore
|
|
118
119
|
return isUrl(url) ? new URL(url) : url;
|
|
119
120
|
}
|
|
120
121
|
module.exports.cloneIfUrl = cloneIfUrl;
|
|
@@ -139,7 +140,7 @@ module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) {
|
|
|
139
140
|
function isBlankLine(line) {
|
|
140
141
|
const startComment = "<!--";
|
|
141
142
|
const endComment = "-->";
|
|
142
|
-
const removeComments = (s) => {
|
|
143
|
+
const removeComments = (/** @type {string} */ s) => {
|
|
143
144
|
while (true) {
|
|
144
145
|
const start = s.indexOf(startComment);
|
|
145
146
|
const end = s.indexOf(endComment);
|
|
@@ -177,8 +178,8 @@ const startsWithPipeRe = /^ *\|/;
|
|
|
177
178
|
const notCrLfRe = /[^\r\n]/g;
|
|
178
179
|
const notSpaceCrLfRe = /[^ \r\n]/g;
|
|
179
180
|
const trailingSpaceRe = / +[\r\n]/g;
|
|
180
|
-
const replaceTrailingSpace = (s) => s.replace(notCrLfRe, safeCommentCharacter);
|
|
181
|
-
module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
|
181
|
+
const replaceTrailingSpace = (/** @type {string} */ s) => s.replace(notCrLfRe, safeCommentCharacter);
|
|
182
|
+
module.exports.clearHtmlCommentText = function clearHtmlCommentText(/** @type {string} */ text) {
|
|
182
183
|
let i = 0;
|
|
183
184
|
while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) {
|
|
184
185
|
const j = text.indexOf(htmlCommentEnd, i + 2);
|
|
@@ -220,7 +221,7 @@ module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) {
|
|
|
220
221
|
};
|
|
221
222
|
|
|
222
223
|
// Escapes a string for use in a RegExp
|
|
223
|
-
module.exports.escapeForRegExp = function escapeForRegExp(str) {
|
|
224
|
+
module.exports.escapeForRegExp = function escapeForRegExp(/** @type {string} */ str) {
|
|
224
225
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
225
226
|
};
|
|
226
227
|
|
|
@@ -308,8 +309,8 @@ module.exports.addErrorDetailIf = addErrorDetailIf;
|
|
|
308
309
|
* @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance.
|
|
309
310
|
* @returns {void}
|
|
310
311
|
*/
|
|
311
|
-
function addErrorContext(
|
|
312
|
-
|
|
312
|
+
function addErrorContext(onError, lineNumber, context, start, end, range, fixInfo) {
|
|
313
|
+
// Normalize new line characters so Linux and Windows trim consistently
|
|
313
314
|
context = ellipsify(context.replace(newLineRe, "\n"), start, end);
|
|
314
315
|
addError(onError, lineNumber, undefined, context, range, fixInfo);
|
|
315
316
|
}
|
|
@@ -355,7 +356,7 @@ module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) {
|
|
|
355
356
|
|
|
356
357
|
// Determines if the front matter includes a title
|
|
357
358
|
module.exports.frontMatterHasTitle =
|
|
358
|
-
function frontMatterHasTitle(frontMatterLines, frontMatterTitlePattern) {
|
|
359
|
+
function frontMatterHasTitle(/** @type {readonly string[]} */ frontMatterLines, /** @type {string} */ frontMatterTitlePattern) {
|
|
359
360
|
const ignoreFrontMatter =
|
|
360
361
|
(frontMatterTitlePattern !== undefined) && !frontMatterTitlePattern;
|
|
361
362
|
const frontMatterTitleRe =
|
|
@@ -367,18 +368,31 @@ module.exports.frontMatterHasTitle =
|
|
|
367
368
|
frontMatterLines.some((line) => frontMatterTitleRe.test(line));
|
|
368
369
|
};
|
|
369
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Result object for getReferenceLinkImageData.
|
|
373
|
+
*
|
|
374
|
+
* @typedef {Object} GetReferenceLinkImageDataResult
|
|
375
|
+
* @property {Map<string, number[][]>} references References.
|
|
376
|
+
* @property {Map<string, number[][]>} shortcuts Shortcuts.
|
|
377
|
+
* @property {Map<string, [number, string]>} definitions Definitions.
|
|
378
|
+
* @property {[string, number][]} duplicateDefinitions Duplicate definitions.
|
|
379
|
+
* @property {number[]} definitionLineIndices Definition line indices.
|
|
380
|
+
*/
|
|
381
|
+
|
|
370
382
|
/**
|
|
371
383
|
* Returns an object with information about reference links and images.
|
|
372
384
|
*
|
|
373
385
|
* @param {MicromarkToken[]} tokens Micromark tokens.
|
|
374
|
-
* @returns {
|
|
386
|
+
* @returns {GetReferenceLinkImageDataResult} Reference link/image data.
|
|
375
387
|
*/
|
|
376
388
|
function getReferenceLinkImageData(tokens) {
|
|
377
|
-
const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
378
|
-
const getText = (t) => t?.children.filter((c) => c.type !== "blockQuotePrefix").map((c) => c.text).join("");
|
|
389
|
+
const normalizeReference = (/** @type {string} */ s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
390
|
+
const getText = (/** @type {MicromarkToken} */ t) => t?.children.filter((c) => c.type !== "blockQuotePrefix").map((c) => c.text).join("");
|
|
391
|
+
/** @type {Map<string, number[][]>} */
|
|
379
392
|
const references = new Map();
|
|
393
|
+
/** @type {Map<string, number[][]>} */
|
|
380
394
|
const shortcuts = new Map();
|
|
381
|
-
const addReferenceToDictionary = (token, label, isShortcut) => {
|
|
395
|
+
const addReferenceToDictionary = (/** @type {MicromarkToken} */ token, /** @type {string} */ label, /** @type {boolean} */ isShortcut) => {
|
|
382
396
|
const referenceDatum = [
|
|
383
397
|
token.startLine - 1,
|
|
384
398
|
token.startColumn - 1,
|
|
@@ -390,8 +404,11 @@ function getReferenceLinkImageData(tokens) {
|
|
|
390
404
|
referenceData.push(referenceDatum);
|
|
391
405
|
dictionary.set(reference, referenceData);
|
|
392
406
|
};
|
|
407
|
+
/** @type {Map<string, [number, string]>} */
|
|
393
408
|
const definitions = new Map();
|
|
409
|
+
/** @type {number[]} */
|
|
394
410
|
const definitionLineIndices = [];
|
|
411
|
+
/** @type {[string, number][]} */
|
|
395
412
|
const duplicateDefinitions = [];
|
|
396
413
|
const filteredTokens =
|
|
397
414
|
micromark.filterByTypes(
|
|
@@ -433,7 +450,7 @@ function getReferenceLinkImageData(tokens) {
|
|
|
433
450
|
micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text;
|
|
434
451
|
definitions.set(
|
|
435
452
|
reference,
|
|
436
|
-
[ token.startLine - 1, destinationString ]
|
|
453
|
+
[ token.startLine - 1, destinationString || "" ]
|
|
437
454
|
);
|
|
438
455
|
}
|
|
439
456
|
}
|
|
@@ -490,7 +507,7 @@ module.exports.getReferenceLinkImageData = getReferenceLinkImageData;
|
|
|
490
507
|
* Gets the most common line ending, falling back to the platform default.
|
|
491
508
|
*
|
|
492
509
|
* @param {string} input Markdown content to analyze.
|
|
493
|
-
* @param {
|
|
510
|
+
* @param {{EOL: string}} [os] Node.js "os" module.
|
|
494
511
|
* @returns {string} Preferred line ending.
|
|
495
512
|
*/
|
|
496
513
|
function getPreferredLineEnding(input, os) {
|
|
@@ -530,7 +547,7 @@ module.exports.getPreferredLineEnding = getPreferredLineEnding;
|
|
|
530
547
|
* Expands a path with a tilde to an absolute path.
|
|
531
548
|
*
|
|
532
549
|
* @param {string} file Path that may begin with a tilde.
|
|
533
|
-
* @param {
|
|
550
|
+
* @param {{homedir: () => string}} os Node.js "os" module.
|
|
534
551
|
* @returns {string} Absolute path (or original path).
|
|
535
552
|
*/
|
|
536
553
|
function expandTildePath(file, os) {
|
|
@@ -538,3 +555,142 @@ function expandTildePath(file, os) {
|
|
|
538
555
|
return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file;
|
|
539
556
|
}
|
|
540
557
|
module.exports.expandTildePath = expandTildePath;
|
|
558
|
+
|
|
559
|
+
/** @typedef {import("../lib/markdownlint.mjs").LintError[]} LintErrors */
|
|
560
|
+
/** @typedef {import("../lib/markdownlint.mjs").LintResults} LintResults */
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Converts lint errors from resultVersion 3 to 2.
|
|
564
|
+
*
|
|
565
|
+
* @param {LintErrors} errors Lint errors (v3).
|
|
566
|
+
* @returns {LintErrors} Lint errors (v2).
|
|
567
|
+
*/
|
|
568
|
+
function convertLintErrorsVersion3To2(errors) {
|
|
569
|
+
const noPrevious = {
|
|
570
|
+
"ruleNames": [],
|
|
571
|
+
"lineNumber": -1
|
|
572
|
+
};
|
|
573
|
+
return errors.filter((error, index, array) => {
|
|
574
|
+
// @ts-ignore
|
|
575
|
+
delete error.fixInfo;
|
|
576
|
+
// @ts-ignore
|
|
577
|
+
delete error.severity;
|
|
578
|
+
const previous = array[index - 1] || noPrevious;
|
|
579
|
+
return (
|
|
580
|
+
(error.ruleNames[0] !== previous.ruleNames[0]) ||
|
|
581
|
+
(error.lineNumber !== previous.lineNumber)
|
|
582
|
+
);
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Converts lint errors from resultVersion 2 to 1.
|
|
588
|
+
*
|
|
589
|
+
* @param {LintErrors} errors Lint errors (v2).
|
|
590
|
+
* @returns {LintErrors} Lint errors (v1).
|
|
591
|
+
*/
|
|
592
|
+
function convertLintErrorsVersion2To1(errors) {
|
|
593
|
+
for (const error of errors) {
|
|
594
|
+
// @ts-ignore
|
|
595
|
+
error.ruleName = error.ruleNames[0];
|
|
596
|
+
// @ts-ignore
|
|
597
|
+
error.ruleAlias = error.ruleNames[1] || error.ruleName;
|
|
598
|
+
// @ts-ignore
|
|
599
|
+
delete error.ruleNames;
|
|
600
|
+
}
|
|
601
|
+
return errors;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Converts lint errors from resultVersion 2 to 0.
|
|
606
|
+
*
|
|
607
|
+
* @param {LintErrors} errors Lint errors (v2).
|
|
608
|
+
* @returns {LintErrors} Lint errors (v0).
|
|
609
|
+
*/
|
|
610
|
+
function convertLintErrorsVersion2To0(errors) {
|
|
611
|
+
/** @type {Object.<string, number[]>} */
|
|
612
|
+
const dictionary = {};
|
|
613
|
+
for (const error of errors) {
|
|
614
|
+
const ruleName = error.ruleNames[0];
|
|
615
|
+
const ruleLines = dictionary[ruleName] || [];
|
|
616
|
+
ruleLines.push(error.lineNumber);
|
|
617
|
+
dictionary[ruleName] = ruleLines;
|
|
618
|
+
}
|
|
619
|
+
// @ts-ignore
|
|
620
|
+
return dictionary;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Copies and transforms lint results from resultVersion 3 to ?.
|
|
625
|
+
*
|
|
626
|
+
* @param {LintResults} results Lint results (v3).
|
|
627
|
+
* @param {(errors: LintErrors) => LintErrors} transform Lint errors (v?).
|
|
628
|
+
* @returns {LintResults} Lint results (v?).
|
|
629
|
+
*/
|
|
630
|
+
function copyAndTransformResults(results, transform) {
|
|
631
|
+
/** @type {Object.<string, LintErrors>} */
|
|
632
|
+
const newResults = {};
|
|
633
|
+
Object.defineProperty(newResults, "toString", { "value": results.toString });
|
|
634
|
+
for (const key of Object.keys(results)) {
|
|
635
|
+
const arr = results[key].map((r) => ({ ...r }));
|
|
636
|
+
newResults[key] = transform(arr);
|
|
637
|
+
}
|
|
638
|
+
// @ts-ignore
|
|
639
|
+
return newResults;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Converts lint results from resultVersion 3 to 0.
|
|
644
|
+
*
|
|
645
|
+
* @param {LintResults} results Lint results (v3).
|
|
646
|
+
* @returns {LintResults} Lint results (v0).
|
|
647
|
+
*/
|
|
648
|
+
module.exports.convertToResultVersion0 = function convertToResultVersion0(results) {
|
|
649
|
+
return copyAndTransformResults(results, (r) => convertLintErrorsVersion2To0(convertLintErrorsVersion3To2(r)));
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Converts lint results from resultVersion 3 to 1.
|
|
654
|
+
*
|
|
655
|
+
* @param {LintResults} results Lint results (v3).
|
|
656
|
+
* @returns {LintResults} Lint results (v1).
|
|
657
|
+
*/
|
|
658
|
+
module.exports.convertToResultVersion1 = function convertToResultVersion1(results) {
|
|
659
|
+
return copyAndTransformResults(results, (r) => convertLintErrorsVersion2To1(convertLintErrorsVersion3To2(r)));
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Converts lint results from resultVersion 3 to 2.
|
|
664
|
+
*
|
|
665
|
+
* @param {LintResults} results Lint results (v3).
|
|
666
|
+
* @returns {LintResults} Lint results (v2).
|
|
667
|
+
*/
|
|
668
|
+
module.exports.convertToResultVersion2 = function convertToResultVersion2(results) {
|
|
669
|
+
return copyAndTransformResults(results, convertLintErrorsVersion3To2);
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Formats lint results to an array of strings.
|
|
674
|
+
*
|
|
675
|
+
* @param {LintResults|undefined} lintResults Lint results.
|
|
676
|
+
* @returns {string[]} Lint error strings.
|
|
677
|
+
*/
|
|
678
|
+
module.exports.formatLintResults = function formatLintResults(lintResults) {
|
|
679
|
+
const results = [];
|
|
680
|
+
const entries = Object.entries(lintResults || {});
|
|
681
|
+
entries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
682
|
+
for (const [ source, lintErrors ] of entries) {
|
|
683
|
+
for (const lintError of lintErrors) {
|
|
684
|
+
const { lineNumber, ruleNames, ruleDescription, errorDetail, errorContext, errorRange, severity } = lintError;
|
|
685
|
+
const rule = ruleNames.join("/");
|
|
686
|
+
const line = `:${lineNumber}`;
|
|
687
|
+
const rangeStart = (errorRange && errorRange[0]) || 0;
|
|
688
|
+
const column = rangeStart ? `:${rangeStart}` : "";
|
|
689
|
+
const description = ruleDescription;
|
|
690
|
+
const detail = (errorDetail ? ` [${errorDetail}]` : "");
|
|
691
|
+
const context = (errorContext ? ` [Context: "${errorContext}"]` : "");
|
|
692
|
+
results.push(`${source}${line}${column} ${severity} ${rule} ${description}${detail}${context}`);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return results;
|
|
696
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
const { flatTokensSymbol, htmlFlowSymbol } = require("./shared.cjs");
|
|
5
|
+
const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = require("./shared.cjs");
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line jsdoc/valid-types
|
|
8
8
|
/** @typedef {import("micromark-util-types", { with: { "resolution-mode": "import" } }).TokenType} TokenType */
|
|
@@ -17,6 +17,7 @@ const { flatTokensSymbol, htmlFlowSymbol } = require("./shared.cjs");
|
|
|
17
17
|
* @returns {boolean} True iff the token is within an htmlFlow type.
|
|
18
18
|
*/
|
|
19
19
|
function inHtmlFlow(token) {
|
|
20
|
+
// @ts-ignore
|
|
20
21
|
return Boolean(token[htmlFlowSymbol]);
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -126,8 +127,11 @@ function filterByPredicate(tokens, allowed, transformChildren) {
|
|
|
126
127
|
* @returns {Token[]} Filtered tokens.
|
|
127
128
|
*/
|
|
128
129
|
function filterByTypes(tokens, types, htmlFlow) {
|
|
129
|
-
const predicate = (token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token));
|
|
130
|
-
|
|
130
|
+
const predicate = (/** @type {Token} */ token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token));
|
|
131
|
+
/** @type {Token[]} */
|
|
132
|
+
const flatTokens =
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
tokens[flatTokensSymbol];
|
|
131
135
|
if (flatTokens) {
|
|
132
136
|
return flatTokens.filter(predicate);
|
|
133
137
|
}
|
|
@@ -163,7 +167,7 @@ function getBlockQuotePrefixText(tokens, lineNumber, count = 1) {
|
|
|
163
167
|
function getDescendantsByType(parent, typePath) {
|
|
164
168
|
let tokens = Array.isArray(parent) ? parent : [ parent ];
|
|
165
169
|
for (const type of typePath) {
|
|
166
|
-
const predicate = (token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type);
|
|
170
|
+
const predicate = (/** @type {Token} */ token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type);
|
|
167
171
|
tokens = tokens.flatMap((t) => t.children.filter(predicate));
|
|
168
172
|
}
|
|
169
173
|
return tokens;
|
|
@@ -216,12 +220,11 @@ function getHeadingStyle(heading) {
|
|
|
216
220
|
* @returns {string} Heading text.
|
|
217
221
|
*/
|
|
218
222
|
function getHeadingText(heading) {
|
|
219
|
-
|
|
223
|
+
return getDescendantsByType(heading, [ [ "atxHeadingText", "setextHeadingText" ] ])
|
|
220
224
|
.flatMap((descendant) => descendant.children.filter((child) => child.type !== "htmlText"))
|
|
221
225
|
.map((data) => data.text)
|
|
222
226
|
.join("")
|
|
223
|
-
.replace(
|
|
224
|
-
return headingText || "";
|
|
227
|
+
.replace(newLineRe, " ");
|
|
225
228
|
}
|
|
226
229
|
|
|
227
230
|
/**
|
|
@@ -299,6 +302,7 @@ const nonContentTokens = new Set([
|
|
|
299
302
|
"blockQuoteMarker",
|
|
300
303
|
"blockQuotePrefix",
|
|
301
304
|
"blockQuotePrefixWhitespace",
|
|
305
|
+
"gfmFootnoteDefinitionIndent",
|
|
302
306
|
"lineEnding",
|
|
303
307
|
"lineEndingBlank",
|
|
304
308
|
"linePrefix",
|
package/helpers/package.json
CHANGED
package/lib/cache.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { filterByTypes } from "../helpers/micromark-helpers.cjs";
|
|
|
6
6
|
/** @typedef {import("markdownlint").RuleParams} RuleParams */
|
|
7
7
|
/** @typedef {import("markdownlint").MicromarkToken} MicromarkToken */
|
|
8
8
|
/** @typedef {import("markdownlint").MicromarkTokenType} MicromarkTokenType */
|
|
9
|
+
/** @typedef {import("../helpers/helpers.cjs").GetReferenceLinkImageDataResult} GetReferenceLinkImageDataResult */
|
|
9
10
|
|
|
10
11
|
/** @type {Map<string, object>} */
|
|
11
12
|
const map = new Map();
|
|
@@ -36,11 +37,12 @@ export function micromarkTokens() {
|
|
|
36
37
|
* Gets a cached object value - computes it and caches it.
|
|
37
38
|
*
|
|
38
39
|
* @param {string} name Cache object name.
|
|
39
|
-
* @param {
|
|
40
|
+
* @param {() => Object} getValue Getter for object value.
|
|
40
41
|
* @returns {Object} Object value.
|
|
41
42
|
*/
|
|
42
43
|
function getCached(name, getValue) {
|
|
43
44
|
if (map.has(name)) {
|
|
45
|
+
// @ts-ignore
|
|
44
46
|
return map.get(name);
|
|
45
47
|
}
|
|
46
48
|
const value = getValue();
|
|
@@ -56,6 +58,7 @@ function getCached(name, getValue) {
|
|
|
56
58
|
* @returns {MicromarkToken[]} Filtered tokens.
|
|
57
59
|
*/
|
|
58
60
|
export function filterByTypesCached(types, htmlFlow) {
|
|
61
|
+
// @ts-ignore
|
|
59
62
|
return getCached(
|
|
60
63
|
// eslint-disable-next-line prefer-rest-params
|
|
61
64
|
JSON.stringify(arguments),
|
|
@@ -66,9 +69,10 @@ export function filterByTypesCached(types, htmlFlow) {
|
|
|
66
69
|
/**
|
|
67
70
|
* Gets a reference link and image data object.
|
|
68
71
|
*
|
|
69
|
-
* @returns {
|
|
72
|
+
* @returns {GetReferenceLinkImageDataResult} Reference link and image data object.
|
|
70
73
|
*/
|
|
71
74
|
export function getReferenceLinkImageData() {
|
|
75
|
+
// @ts-ignore
|
|
72
76
|
return getCached(
|
|
73
77
|
getReferenceLinkImageData.name,
|
|
74
78
|
() => helpersGetReferenceLinkImageData(micromarkTokens())
|