eslint-plugin-markdown-preferences 0.20.0 → 0.22.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/README.md +37 -30
- package/lib/index.d.ts +60 -1
- package/lib/index.js +1565 -204
- package/package.json +3 -2
package/lib/index.js
CHANGED
|
@@ -30,6 +30,12 @@ function createRule(ruleName, rule) {
|
|
|
30
30
|
//#endregion
|
|
31
31
|
//#region src/utils/ast.ts
|
|
32
32
|
/**
|
|
33
|
+
* Get the parent of a node.
|
|
34
|
+
*/
|
|
35
|
+
function getParent(sourceCode, node) {
|
|
36
|
+
return sourceCode.getParent(node);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
33
39
|
* Get the kind of heading.
|
|
34
40
|
*/
|
|
35
41
|
function getHeadingKind(sourceCode, node) {
|
|
@@ -150,6 +156,12 @@ function isSpaceOrTab(string) {
|
|
|
150
156
|
function isPunctuation(char) {
|
|
151
157
|
return /^[\p{P}\p{S}]+$/u.test(char);
|
|
152
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Check if the character is an ASCII control character
|
|
161
|
+
*/
|
|
162
|
+
function isAsciiControlCharacter(char) {
|
|
163
|
+
return /^[\x00-\x1f\x7f]+$/u.test(char);
|
|
164
|
+
}
|
|
153
165
|
|
|
154
166
|
//#endregion
|
|
155
167
|
//#region src/utils/atx-heading.ts
|
|
@@ -387,7 +399,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
387
399
|
type: "layout",
|
|
388
400
|
docs: {
|
|
389
401
|
description: "enforce consistent length for the closing sequence (trailing #s) in ATX headings.",
|
|
390
|
-
categories: [],
|
|
402
|
+
categories: ["standard"],
|
|
391
403
|
listCategory: "Stylistic"
|
|
392
404
|
},
|
|
393
405
|
fixable: "code",
|
|
@@ -413,7 +425,8 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
413
425
|
},
|
|
414
426
|
create(context) {
|
|
415
427
|
const sourceCode = context.sourceCode;
|
|
416
|
-
const option =
|
|
428
|
+
const option = context.options[0] || {};
|
|
429
|
+
const mode = option.mode || "match-opening";
|
|
417
430
|
/**
|
|
418
431
|
* Verify the closing sequence length of an ATX heading.
|
|
419
432
|
*/
|
|
@@ -433,12 +446,12 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
433
446
|
}
|
|
434
447
|
});
|
|
435
448
|
}
|
|
436
|
-
if (
|
|
449
|
+
if (mode === "match-opening") return { heading(node) {
|
|
437
450
|
const parsed = parseATXHeading(sourceCode, node);
|
|
438
451
|
if (!parsed || parsed.closingSequence == null) return;
|
|
439
452
|
verifyATXHeadingClosingSequenceLength(parsed, node, node.depth);
|
|
440
453
|
} };
|
|
441
|
-
if (
|
|
454
|
+
if (mode === "length") {
|
|
442
455
|
const expected = option.length || 2;
|
|
443
456
|
return { heading(node) {
|
|
444
457
|
const parsed = parseATXHeading(sourceCode, node);
|
|
@@ -446,7 +459,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
446
459
|
verifyATXHeadingClosingSequenceLength(parsed, node, expected);
|
|
447
460
|
} };
|
|
448
461
|
}
|
|
449
|
-
if (
|
|
462
|
+
if (mode === "fixed-line-length") {
|
|
450
463
|
const totalLength = option.length || 80;
|
|
451
464
|
return { heading(node) {
|
|
452
465
|
const parsed = parseATXHeading(sourceCode, node);
|
|
@@ -454,7 +467,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
454
467
|
verifyATXHeadingClosingSequenceLength(parsed, node, totalLength - getContentLength(parsed));
|
|
455
468
|
} };
|
|
456
469
|
}
|
|
457
|
-
if (
|
|
470
|
+
if (mode === "consistent") {
|
|
458
471
|
let expectedLength = null;
|
|
459
472
|
return { heading(node) {
|
|
460
473
|
const parsed = parseATXHeading(sourceCode, node);
|
|
@@ -463,7 +476,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
463
476
|
else verifyATXHeadingClosingSequenceLength(parsed, node, expectedLength);
|
|
464
477
|
} };
|
|
465
478
|
}
|
|
466
|
-
if (
|
|
479
|
+
if (mode === "consistent-line-length") {
|
|
467
480
|
const headings = [];
|
|
468
481
|
return {
|
|
469
482
|
heading(node) {
|
|
@@ -502,8 +515,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
502
515
|
* Get the content length of the heading.
|
|
503
516
|
*/
|
|
504
517
|
function getContentLength(parsed) {
|
|
505
|
-
const
|
|
506
|
-
const line = lines.get(parsed.closingSequence.loc.start.line);
|
|
518
|
+
const line = getParsedLines(sourceCode).get(parsed.closingSequence.loc.start.line);
|
|
507
519
|
const beforeClosing = sourceCode.text.slice(line.range[0], parsed.closingSequence.range[0]);
|
|
508
520
|
return getTextWidth(beforeClosing);
|
|
509
521
|
}
|
|
@@ -511,8 +523,7 @@ var atx_heading_closing_sequence_length_default = createRule("atx-heading-closin
|
|
|
511
523
|
* Get the line length of the heading.
|
|
512
524
|
*/
|
|
513
525
|
function getLineLength(parsed) {
|
|
514
|
-
const
|
|
515
|
-
const line = lines.get(parsed.closingSequence.loc.start.line);
|
|
526
|
+
const line = getParsedLines(sourceCode).get(parsed.closingSequence.loc.start.line);
|
|
516
527
|
const lineText = sourceCode.text.slice(line.range[0], parsed.closingSequence.range[1]);
|
|
517
528
|
return getTextWidth(lineText);
|
|
518
529
|
}
|
|
@@ -526,7 +537,7 @@ var atx_heading_closing_sequence_default = createRule("atx-heading-closing-seque
|
|
|
526
537
|
type: "layout",
|
|
527
538
|
docs: {
|
|
528
539
|
description: "enforce consistent use of closing sequence in ATX headings.",
|
|
529
|
-
categories: [],
|
|
540
|
+
categories: ["standard"],
|
|
530
541
|
listCategory: "Stylistic"
|
|
531
542
|
},
|
|
532
543
|
fixable: "code",
|
|
@@ -628,7 +639,7 @@ var blockquote_marker_alignment_default = createRule("blockquote-marker-alignmen
|
|
|
628
639
|
type: "layout",
|
|
629
640
|
docs: {
|
|
630
641
|
description: "enforce consistent alignment of blockquote markers",
|
|
631
|
-
categories: ["recommended"],
|
|
642
|
+
categories: ["recommended", "standard"],
|
|
632
643
|
listCategory: "Stylistic"
|
|
633
644
|
},
|
|
634
645
|
fixable: "whitespace",
|
|
@@ -677,8 +688,7 @@ var blockquote_marker_alignment_default = createRule("blockquote-marker-alignmen
|
|
|
677
688
|
},
|
|
678
689
|
messageId: "inconsistentAlignment",
|
|
679
690
|
fix(fixer) {
|
|
680
|
-
const
|
|
681
|
-
const line = lines.get(lineNumber);
|
|
691
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
682
692
|
if (marker.index < base.index) {
|
|
683
693
|
const addSpaces = " ".repeat(base.index - marker.index);
|
|
684
694
|
return fixer.insertTextBeforeRange([line.range[0] + marker.index, line.range[0] + marker.index], addSpaces);
|
|
@@ -687,8 +697,7 @@ var blockquote_marker_alignment_default = createRule("blockquote-marker-alignmen
|
|
|
687
697
|
const expectedSpaces = " ".repeat(base.index);
|
|
688
698
|
return fixer.replaceTextRange([line.range[0], line.range[0] + marker.index], expectedSpaces);
|
|
689
699
|
}
|
|
690
|
-
|
|
691
|
-
if (itemBefore.includes(" ")) return null;
|
|
700
|
+
if (line.text.slice(0, line.range[0] + marker.index).includes(" ")) return null;
|
|
692
701
|
let removeStartIndex = marker.index;
|
|
693
702
|
for (; removeStartIndex > base.index; removeStartIndex--) if (line.text[removeStartIndex - 1] !== " ") break;
|
|
694
703
|
return fixer.removeRange([line.range[0] + removeStartIndex, line.range[0] + marker.index]);
|
|
@@ -719,7 +728,7 @@ function getOtherMarker(unavailableMarker) {
|
|
|
719
728
|
/**
|
|
720
729
|
* Parse rule options.
|
|
721
730
|
*/
|
|
722
|
-
function parseOptions$
|
|
731
|
+
function parseOptions$2(options) {
|
|
723
732
|
const primary = options.primary || "-";
|
|
724
733
|
const secondary = options.secondary || getOtherMarker(primary);
|
|
725
734
|
if (primary === secondary) throw new Error(`\`primary\` and \`secondary\` cannot be the same (primary: "${primary}", secondary: "${secondary}").`);
|
|
@@ -750,7 +759,7 @@ var bullet_list_marker_style_default = createRule("bullet-list-marker-style", {
|
|
|
750
759
|
type: "layout",
|
|
751
760
|
docs: {
|
|
752
761
|
description: "enforce consistent bullet list (unordered list) marker style",
|
|
753
|
-
categories: [],
|
|
762
|
+
categories: ["standard"],
|
|
754
763
|
listCategory: "Stylistic"
|
|
755
764
|
},
|
|
756
765
|
fixable: "code",
|
|
@@ -787,7 +796,7 @@ var bullet_list_marker_style_default = createRule("bullet-list-marker-style", {
|
|
|
787
796
|
},
|
|
788
797
|
create(context) {
|
|
789
798
|
const sourceCode = context.sourceCode;
|
|
790
|
-
const options = parseOptions$
|
|
799
|
+
const options = parseOptions$2(context.options[0] || {});
|
|
791
800
|
let containerStack = {
|
|
792
801
|
node: sourceCode.ast,
|
|
793
802
|
level: 1,
|
|
@@ -831,8 +840,7 @@ var bullet_list_marker_style_default = createRule("bullet-list-marker-style", {
|
|
|
831
840
|
for (let index = nodeIndex + 1; index < containerStack.node.children.length; index++) {
|
|
832
841
|
const nextNode = containerStack.node.children[index];
|
|
833
842
|
if (nextNode.type !== "list") break;
|
|
834
|
-
|
|
835
|
-
if (nextMarker.kind !== prevMarker) break;
|
|
843
|
+
if (getListItemMarker(sourceCode, nextNode).kind !== prevMarker) break;
|
|
836
844
|
let expectedNextMarker = prevMarker === primary ? secondary : primary;
|
|
837
845
|
if (expectedNextMarker === "any") expectedNextMarker = getOtherMarker(prevMarker);
|
|
838
846
|
yield* fixMarkers(nextNode, expectedNextMarker);
|
|
@@ -902,15 +910,11 @@ function parseFencedCodeBlock(sourceCode, node) {
|
|
|
902
910
|
}
|
|
903
911
|
closingFenceText = closingFenceText.trimStart();
|
|
904
912
|
if (!closingFenceText || !closingFenceText.startsWith(fenceText)) return null;
|
|
905
|
-
const
|
|
906
|
-
const afterOpeningFence = lines.get(loc.start.line).text.slice(fenceText.length);
|
|
913
|
+
const afterOpeningFence = getParsedLines(sourceCode).get(loc.start.line).text.slice(fenceText.length);
|
|
907
914
|
const trimmedAfterOpeningFence = afterOpeningFence.trimStart();
|
|
908
915
|
const spaceAfterOpeningFenceLength = afterOpeningFence.length - trimmedAfterOpeningFence.length;
|
|
909
916
|
let languageText = "";
|
|
910
|
-
if (trimmedAfterOpeningFence)
|
|
911
|
-
const langMatch = RE_LANGUAGE.exec(trimmedAfterOpeningFence);
|
|
912
|
-
languageText = langMatch[1];
|
|
913
|
-
}
|
|
917
|
+
if (trimmedAfterOpeningFence) languageText = RE_LANGUAGE.exec(trimmedAfterOpeningFence)[1];
|
|
914
918
|
const afterLanguage = trimmedAfterOpeningFence.slice(languageText.length);
|
|
915
919
|
const trimmedAfterLanguage = afterLanguage.trimStart();
|
|
916
920
|
const spaceAfterLanguageLength = afterLanguage.length - trimmedAfterLanguage.length;
|
|
@@ -926,7 +930,7 @@ function parseFencedCodeBlock(sourceCode, node) {
|
|
|
926
930
|
}
|
|
927
931
|
}
|
|
928
932
|
};
|
|
929
|
-
const language$
|
|
933
|
+
const language$2 = languageText ? {
|
|
930
934
|
text: languageText,
|
|
931
935
|
range: [openingFence.range[1] + spaceAfterOpeningFenceLength, openingFence.range[1] + spaceAfterOpeningFenceLength + languageText.length],
|
|
932
936
|
loc: {
|
|
@@ -940,23 +944,23 @@ function parseFencedCodeBlock(sourceCode, node) {
|
|
|
940
944
|
}
|
|
941
945
|
}
|
|
942
946
|
} : null;
|
|
943
|
-
const meta = language$
|
|
947
|
+
const meta = language$2 && metaText ? {
|
|
944
948
|
text: metaText,
|
|
945
|
-
range: [language$
|
|
949
|
+
range: [language$2.range[1] + spaceAfterLanguageLength, language$2.range[1] + spaceAfterLanguageLength + metaText.length],
|
|
946
950
|
loc: {
|
|
947
951
|
start: {
|
|
948
|
-
line: language$
|
|
949
|
-
column: language$
|
|
952
|
+
line: language$2.loc.end.line,
|
|
953
|
+
column: language$2.loc.end.column + spaceAfterLanguageLength
|
|
950
954
|
},
|
|
951
955
|
end: {
|
|
952
|
-
line: language$
|
|
953
|
-
column: language$
|
|
956
|
+
line: language$2.loc.end.line,
|
|
957
|
+
column: language$2.loc.end.column + spaceAfterLanguageLength + metaText.length
|
|
954
958
|
}
|
|
955
959
|
}
|
|
956
960
|
} : null;
|
|
957
961
|
return {
|
|
958
962
|
openingFence,
|
|
959
|
-
language: language$
|
|
963
|
+
language: language$2,
|
|
960
964
|
meta,
|
|
961
965
|
closingFence: {
|
|
962
966
|
text: closingFenceText,
|
|
@@ -1054,7 +1058,7 @@ var code_fence_length_default = createRule("code-fence-length", {
|
|
|
1054
1058
|
type: "layout",
|
|
1055
1059
|
docs: {
|
|
1056
1060
|
description: "enforce consistent code fence length in fenced code blocks.",
|
|
1057
|
-
categories: [],
|
|
1061
|
+
categories: ["standard"],
|
|
1058
1062
|
listCategory: "Stylistic"
|
|
1059
1063
|
},
|
|
1060
1064
|
fixable: "code",
|
|
@@ -1104,7 +1108,7 @@ var code_fence_length_default = createRule("code-fence-length", {
|
|
|
1104
1108
|
* Get the effective options for the given code block node.
|
|
1105
1109
|
*/
|
|
1106
1110
|
function getOptionForCode(node) {
|
|
1107
|
-
const override = options.overrides
|
|
1111
|
+
const override = options.overrides ? [...options.overrides].reverse().find((o) => o.lang === node.lang) : null;
|
|
1108
1112
|
return {
|
|
1109
1113
|
length: override?.length ?? options.length ?? 3,
|
|
1110
1114
|
fallbackLength: override?.fallbackLength ?? options.fallbackLength ?? "minimum"
|
|
@@ -1158,8 +1162,7 @@ var code_fence_length_default = createRule("code-fence-length", {
|
|
|
1158
1162
|
* Get the expected fence string for the given length.
|
|
1159
1163
|
*/
|
|
1160
1164
|
function getExpectedFence(parsed, length) {
|
|
1161
|
-
|
|
1162
|
-
return fenceChar.repeat(Math.max(3, length));
|
|
1165
|
+
return parsed.openingFence.text[0].repeat(Math.max(3, length));
|
|
1163
1166
|
}
|
|
1164
1167
|
/**
|
|
1165
1168
|
* Verify that the opening and closing fence lengths match.
|
|
@@ -1192,7 +1195,7 @@ var code_fence_style_default = createRule("code-fence-style", {
|
|
|
1192
1195
|
type: "layout",
|
|
1193
1196
|
docs: {
|
|
1194
1197
|
description: "enforce a consistent code fence style (backtick or tilde) in Markdown fenced code blocks.",
|
|
1195
|
-
categories: [],
|
|
1198
|
+
categories: ["standard"],
|
|
1196
1199
|
listCategory: "Stylistic"
|
|
1197
1200
|
},
|
|
1198
1201
|
fixable: "code",
|
|
@@ -1209,8 +1212,7 @@ var code_fence_style_default = createRule("code-fence-style", {
|
|
|
1209
1212
|
},
|
|
1210
1213
|
create(context) {
|
|
1211
1214
|
const sourceCode = context.sourceCode;
|
|
1212
|
-
const
|
|
1213
|
-
const expectedChar = styleOption === "tilde" ? "~" : "`";
|
|
1215
|
+
const expectedChar = (context.options[0]?.style ?? "backtick") === "tilde" ? "~" : "`";
|
|
1214
1216
|
return { code(node) {
|
|
1215
1217
|
const parsed = parseFencedCodeBlock(sourceCode, node);
|
|
1216
1218
|
if (!parsed) return;
|
|
@@ -1262,8 +1264,7 @@ var definitions_last_default = createRule("definitions-last", {
|
|
|
1262
1264
|
*fix(fixer) {
|
|
1263
1265
|
let rangeStart = range[0];
|
|
1264
1266
|
for (let index = range[0] - 1; index >= 0; index--) {
|
|
1265
|
-
|
|
1266
|
-
if (c.trim()) break;
|
|
1267
|
+
if (sourceCode.text[index].trim()) break;
|
|
1267
1268
|
rangeStart = index;
|
|
1268
1269
|
}
|
|
1269
1270
|
yield fixer.removeRange([rangeStart, range[1]]);
|
|
@@ -3229,13 +3230,13 @@ var EmojiData = class {
|
|
|
3229
3230
|
get emojiToColon() {
|
|
3230
3231
|
if (this._emojiToColon) return this._emojiToColon;
|
|
3231
3232
|
const emojiToCode = this._emojiToColon = Object.create(null);
|
|
3232
|
-
for (const [name$
|
|
3233
|
+
for (const [name$3, unicode] of this.entries) emojiToCode[unicode] = `:${name$3}:`;
|
|
3233
3234
|
return emojiToCode;
|
|
3234
3235
|
}
|
|
3235
3236
|
get colonToEmoji() {
|
|
3236
3237
|
if (this._colonToEmoji) return this._colonToEmoji;
|
|
3237
3238
|
const colonToEmoji = this._colonToEmoji = Object.create(null);
|
|
3238
|
-
for (const [name$
|
|
3239
|
+
for (const [name$3, unicode] of this.entries) colonToEmoji[`:${name$3}:`] = unicode;
|
|
3239
3240
|
return colonToEmoji;
|
|
3240
3241
|
}
|
|
3241
3242
|
};
|
|
@@ -3284,7 +3285,7 @@ var emoji_notation_default = createRule("emoji-notation", {
|
|
|
3284
3285
|
const ignoreUnknown = options.ignoreUnknown ?? true;
|
|
3285
3286
|
const ignoreList = (options.ignoreList || []).map((s) => toRegExp(s)).flatMap((re) => {
|
|
3286
3287
|
const result = [re];
|
|
3287
|
-
for (const [name$
|
|
3288
|
+
for (const [name$3, unicode] of emojiData.entries) if (re.test(`:${name$3}:`) || re.test(unicode)) result.push(toRegExp(`:${name$3}:`), toRegExp(unicode));
|
|
3288
3289
|
return result;
|
|
3289
3290
|
});
|
|
3290
3291
|
const isIgnoreBase = (s) => ignoreList.some((re) => re.test(s));
|
|
@@ -3365,7 +3366,7 @@ var emphasis_delimiters_style_default = createRule("emphasis-delimiters-style",
|
|
|
3365
3366
|
type: "layout",
|
|
3366
3367
|
docs: {
|
|
3367
3368
|
description: "enforce a consistent delimiter style for emphasis and strong emphasis",
|
|
3368
|
-
categories: [],
|
|
3369
|
+
categories: ["standard"],
|
|
3369
3370
|
listCategory: "Stylistic"
|
|
3370
3371
|
},
|
|
3371
3372
|
fixable: "code",
|
|
@@ -3547,7 +3548,7 @@ var hard_linebreak_style_default = createRule("hard-linebreak-style", {
|
|
|
3547
3548
|
type: "layout",
|
|
3548
3549
|
docs: {
|
|
3549
3550
|
description: "enforce consistent hard linebreak style.",
|
|
3550
|
-
categories: ["recommended"],
|
|
3551
|
+
categories: ["recommended", "standard"],
|
|
3551
3552
|
listCategory: "Stylistic"
|
|
3552
3553
|
},
|
|
3553
3554
|
fixable: "code",
|
|
@@ -4159,10 +4160,7 @@ var PreserveWordsContext = class {
|
|
|
4159
4160
|
}
|
|
4160
4161
|
if (subWords.every((word, i) => word.toLowerCase() === phrase[i].toLowerCase())) {
|
|
4161
4162
|
let matchCount = 0;
|
|
4162
|
-
for (let i = 0; i < subWords.length; i++)
|
|
4163
|
-
const word = subWords[i];
|
|
4164
|
-
if (word === phrase[i]) matchCount++;
|
|
4165
|
-
}
|
|
4163
|
+
for (let i = 0; i < subWords.length; i++) if (subWords[i] === phrase[i]) matchCount++;
|
|
4166
4164
|
if (!returnCandidate || matchCount > returnCandidate.matchCount) returnCandidate = {
|
|
4167
4165
|
preservePhrase: phrase,
|
|
4168
4166
|
matchCount
|
|
@@ -4472,7 +4470,7 @@ var level1_heading_style_default = createRule("level1-heading-style", {
|
|
|
4472
4470
|
type: "layout",
|
|
4473
4471
|
docs: {
|
|
4474
4472
|
description: "enforce consistent style for level 1 headings",
|
|
4475
|
-
categories: [],
|
|
4473
|
+
categories: ["standard"],
|
|
4476
4474
|
listCategory: "Stylistic"
|
|
4477
4475
|
},
|
|
4478
4476
|
fixable: "code",
|
|
@@ -4503,8 +4501,7 @@ var level1_heading_style_default = createRule("level1-heading-style", {
|
|
|
4503
4501
|
if (headingKind !== "setext") return;
|
|
4504
4502
|
const parsed = parseSetextHeading(sourceCode, node);
|
|
4505
4503
|
if (!parsed) return;
|
|
4506
|
-
|
|
4507
|
-
if (isMultiline) {
|
|
4504
|
+
if (parsed.contentLines.length > 1) {
|
|
4508
4505
|
if (allowMultilineSetext) return;
|
|
4509
4506
|
context.report({
|
|
4510
4507
|
node,
|
|
@@ -4534,8 +4531,7 @@ var level1_heading_style_default = createRule("level1-heading-style", {
|
|
|
4534
4531
|
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4535
4532
|
const lines = getParsedLines(sourceCode);
|
|
4536
4533
|
const underline = "=".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4537
|
-
const
|
|
4538
|
-
const appendingText = `\n${prefix}${underline}`;
|
|
4534
|
+
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
4539
4535
|
yield fixer.insertTextAfter(node, appendingText);
|
|
4540
4536
|
}
|
|
4541
4537
|
});
|
|
@@ -4551,7 +4547,7 @@ var level2_heading_style_default = createRule("level2-heading-style", {
|
|
|
4551
4547
|
type: "layout",
|
|
4552
4548
|
docs: {
|
|
4553
4549
|
description: "enforce consistent style for level 2 headings",
|
|
4554
|
-
categories: [],
|
|
4550
|
+
categories: ["standard"],
|
|
4555
4551
|
listCategory: "Stylistic"
|
|
4556
4552
|
},
|
|
4557
4553
|
fixable: "code",
|
|
@@ -4582,8 +4578,7 @@ var level2_heading_style_default = createRule("level2-heading-style", {
|
|
|
4582
4578
|
if (headingKind !== "setext") return;
|
|
4583
4579
|
const parsed = parseSetextHeading(sourceCode, node);
|
|
4584
4580
|
if (!parsed) return;
|
|
4585
|
-
|
|
4586
|
-
if (isMultiline) {
|
|
4581
|
+
if (parsed.contentLines.length > 1) {
|
|
4587
4582
|
if (allowMultilineSetext) return;
|
|
4588
4583
|
context.report({
|
|
4589
4584
|
node,
|
|
@@ -4613,8 +4608,7 @@ var level2_heading_style_default = createRule("level2-heading-style", {
|
|
|
4613
4608
|
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4614
4609
|
const lines = getParsedLines(sourceCode);
|
|
4615
4610
|
const underline = "-".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4616
|
-
const
|
|
4617
|
-
const appendingText = `\n${prefix}${underline}`;
|
|
4611
|
+
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
4618
4612
|
yield fixer.insertTextAfter(node, appendingText);
|
|
4619
4613
|
}
|
|
4620
4614
|
});
|
|
@@ -4624,93 +4618,1197 @@ var level2_heading_style_default = createRule("level2-heading-style", {
|
|
|
4624
4618
|
});
|
|
4625
4619
|
|
|
4626
4620
|
//#endregion
|
|
4627
|
-
//#region src/
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4621
|
+
//#region src/utils/link.ts
|
|
4622
|
+
/**
|
|
4623
|
+
* Parse the inline link.
|
|
4624
|
+
*/
|
|
4625
|
+
function parseInlineLink(sourceCode, node) {
|
|
4626
|
+
if (getLinkKind(sourceCode, node) !== "inline") return null;
|
|
4627
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4628
|
+
let textRange;
|
|
4629
|
+
if (node.children.length === 0) textRange = [nodeRange[0], sourceCode.text.indexOf("]", nodeRange[0]) + 1];
|
|
4630
|
+
else {
|
|
4631
|
+
const lastChildRange = sourceCode.getRange(node.children[node.children.length - 1]);
|
|
4632
|
+
textRange = [nodeRange[0], sourceCode.text.indexOf("]", lastChildRange[1]) + 1];
|
|
4633
|
+
}
|
|
4634
|
+
const parsed = parseInlineLinkDestAndTitleFromText(sourceCode.text.slice(textRange[1], nodeRange[1]));
|
|
4635
|
+
if (!parsed) return null;
|
|
4636
|
+
const destinationRange = [textRange[1] + parsed.destination.range[0], textRange[1] + parsed.destination.range[1]];
|
|
4637
|
+
return {
|
|
4638
|
+
text: {
|
|
4639
|
+
range: textRange,
|
|
4640
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4641
|
+
},
|
|
4642
|
+
destination: {
|
|
4643
|
+
type: parsed.destination.type,
|
|
4644
|
+
text: parsed.destination.text,
|
|
4645
|
+
range: destinationRange,
|
|
4646
|
+
loc: getSourceLocationFromRange(sourceCode, node, destinationRange)
|
|
4647
|
+
},
|
|
4648
|
+
title: parsed.title ? {
|
|
4649
|
+
type: parsed.title.type,
|
|
4650
|
+
text: parsed.title.text,
|
|
4651
|
+
range: [textRange[1] + parsed.title.range[0], textRange[1] + parsed.title.range[1]],
|
|
4652
|
+
loc: getSourceLocationFromRange(sourceCode, node, [textRange[1] + parsed.title.range[0], textRange[1] + parsed.title.range[1]])
|
|
4653
|
+
} : null
|
|
4654
|
+
};
|
|
4655
|
+
}
|
|
4656
|
+
/**
|
|
4657
|
+
* Parse the inline link destination and link title from the given text.
|
|
4658
|
+
*/
|
|
4659
|
+
function parseInlineLinkDestAndTitleFromText(text) {
|
|
4660
|
+
let index = 0;
|
|
4661
|
+
if (text[index] !== "(") return null;
|
|
4662
|
+
index++;
|
|
4663
|
+
skipSpaces();
|
|
4664
|
+
let destination;
|
|
4665
|
+
const destinationStartIndex = index;
|
|
4666
|
+
if (text[index] === "<") {
|
|
4667
|
+
index++;
|
|
4668
|
+
if (!skipUntilEnd((c) => c === ">")) return null;
|
|
4669
|
+
index++;
|
|
4670
|
+
const destinationRange = [destinationStartIndex, index];
|
|
4671
|
+
destination = {
|
|
4672
|
+
type: "pointy-bracketed",
|
|
4673
|
+
text: text.slice(...destinationRange),
|
|
4674
|
+
range: destinationRange
|
|
4675
|
+
};
|
|
4676
|
+
} else {
|
|
4677
|
+
if (text.length <= index) return null;
|
|
4678
|
+
skipUntilEnd((c) => isWhitespace(c) || isAsciiControlCharacter(c) || c === ")");
|
|
4679
|
+
const destinationRange = [destinationStartIndex, index];
|
|
4680
|
+
destination = {
|
|
4681
|
+
type: "bare",
|
|
4682
|
+
text: text.slice(...destinationRange),
|
|
4683
|
+
range: destinationRange
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4686
|
+
skipSpaces();
|
|
4687
|
+
if (text[index] === ")") {
|
|
4688
|
+
index++;
|
|
4689
|
+
skipSpaces();
|
|
4690
|
+
if (index < text.length) return null;
|
|
4691
|
+
return {
|
|
4692
|
+
destination,
|
|
4693
|
+
title: null
|
|
4694
|
+
};
|
|
4695
|
+
}
|
|
4696
|
+
if (text.length <= index) return null;
|
|
4697
|
+
let title;
|
|
4698
|
+
const titleStartIndex = index;
|
|
4699
|
+
const startChar = text[index];
|
|
4700
|
+
if (startChar === "'" || startChar === "\"" || startChar === "(") {
|
|
4701
|
+
index++;
|
|
4702
|
+
const endChar = startChar === "(" ? ")" : startChar;
|
|
4703
|
+
if (!skipUntilEnd((c) => c === endChar)) return null;
|
|
4704
|
+
index++;
|
|
4705
|
+
const titleRange = [titleStartIndex, index];
|
|
4706
|
+
title = {
|
|
4707
|
+
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
4708
|
+
text: text.slice(...titleRange),
|
|
4709
|
+
range: titleRange
|
|
4710
|
+
};
|
|
4711
|
+
} else return null;
|
|
4712
|
+
skipSpaces();
|
|
4713
|
+
if (text[index] !== ")") return null;
|
|
4714
|
+
index++;
|
|
4715
|
+
skipSpaces();
|
|
4716
|
+
if (index < text.length) return null;
|
|
4717
|
+
return {
|
|
4718
|
+
destination,
|
|
4719
|
+
title
|
|
4720
|
+
};
|
|
4721
|
+
/**
|
|
4722
|
+
* Skip spaces
|
|
4723
|
+
*/
|
|
4724
|
+
function skipSpaces() {
|
|
4725
|
+
while (index < text.length && isWhitespace(text[index])) index++;
|
|
4726
|
+
}
|
|
4727
|
+
/**
|
|
4728
|
+
* Skip until the end by the given condition
|
|
4729
|
+
*/
|
|
4730
|
+
function skipUntilEnd(checkEnd) {
|
|
4731
|
+
while (index < text.length) {
|
|
4732
|
+
const c = text[index];
|
|
4733
|
+
if (checkEnd(c)) return true;
|
|
4734
|
+
index++;
|
|
4735
|
+
if (c !== "\\") continue;
|
|
4736
|
+
if (index < text.length && (text[index] === "\\" || checkEnd(text[index])) && !isWhitespace(text[index])) index++;
|
|
4737
|
+
}
|
|
4738
|
+
return false;
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
|
|
4742
|
+
//#endregion
|
|
4743
|
+
//#region src/utils/link-reference.ts
|
|
4744
|
+
/**
|
|
4745
|
+
* Parse the link reference.
|
|
4746
|
+
*/
|
|
4747
|
+
function parseLinkReference(sourceCode, node) {
|
|
4748
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4749
|
+
let textRange;
|
|
4750
|
+
if (node.children.length === 0) textRange = [nodeRange[0], sourceCode.text.indexOf("]", nodeRange[0]) + 1];
|
|
4751
|
+
else {
|
|
4752
|
+
const lastChildRange = sourceCode.getRange(node.children[node.children.length - 1]);
|
|
4753
|
+
textRange = [nodeRange[0], sourceCode.text.indexOf("]", lastChildRange[1]) + 1];
|
|
4754
|
+
}
|
|
4755
|
+
if (node.referenceType === "shortcut") return {
|
|
4756
|
+
text: {
|
|
4757
|
+
range: textRange,
|
|
4758
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4759
|
+
},
|
|
4760
|
+
label: null
|
|
4761
|
+
};
|
|
4762
|
+
if (node.referenceType === "collapsed") {
|
|
4763
|
+
const labelRange$1 = [textRange[1], textRange[1] + 1];
|
|
4764
|
+
return {
|
|
4765
|
+
text: {
|
|
4766
|
+
range: textRange,
|
|
4767
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4768
|
+
},
|
|
4769
|
+
label: {
|
|
4770
|
+
type: "collapsed",
|
|
4771
|
+
range: labelRange$1,
|
|
4772
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange$1)
|
|
4773
|
+
}
|
|
4774
|
+
};
|
|
4775
|
+
}
|
|
4776
|
+
let index = textRange[1] + 1;
|
|
4777
|
+
while (index < sourceCode.text.length) {
|
|
4778
|
+
const c = sourceCode.text[index];
|
|
4779
|
+
if (c === "]") break;
|
|
4780
|
+
index++;
|
|
4781
|
+
if (c !== "\\") continue;
|
|
4782
|
+
if (index < sourceCode.text.length && (sourceCode.text[index] === "\\" || sourceCode.text[index] === "]")) index++;
|
|
4783
|
+
}
|
|
4784
|
+
if (sourceCode.text[index] !== "]") return null;
|
|
4785
|
+
const labelRange = [textRange[1], index + 1];
|
|
4786
|
+
return {
|
|
4787
|
+
text: {
|
|
4788
|
+
range: textRange,
|
|
4789
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4790
|
+
},
|
|
4791
|
+
label: {
|
|
4792
|
+
type: "full",
|
|
4793
|
+
text: sourceCode.text.slice(...labelRange),
|
|
4794
|
+
range: labelRange,
|
|
4795
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange)
|
|
4796
|
+
}
|
|
4797
|
+
};
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4800
|
+
//#endregion
|
|
4801
|
+
//#region src/utils/image.ts
|
|
4802
|
+
/**
|
|
4803
|
+
* Parse the image.
|
|
4804
|
+
*/
|
|
4805
|
+
function parseImage(sourceCode, node) {
|
|
4806
|
+
const text = sourceCode.getText(node);
|
|
4807
|
+
const parsed = parseImageFromText(text);
|
|
4808
|
+
if (!parsed) return null;
|
|
4809
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4810
|
+
const textRange = [nodeRange[0] + parsed.text.range[0], nodeRange[0] + parsed.text.range[1]];
|
|
4811
|
+
const destinationRange = [nodeRange[0] + parsed.destination.range[0], nodeRange[0] + parsed.destination.range[1]];
|
|
4812
|
+
return {
|
|
4813
|
+
text: {
|
|
4814
|
+
range: textRange,
|
|
4815
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4816
|
+
},
|
|
4817
|
+
destination: {
|
|
4818
|
+
type: parsed.destination.type,
|
|
4819
|
+
text: parsed.destination.text,
|
|
4820
|
+
range: destinationRange,
|
|
4821
|
+
loc: getSourceLocationFromRange(sourceCode, node, destinationRange)
|
|
4822
|
+
},
|
|
4823
|
+
title: parsed.title ? {
|
|
4824
|
+
type: parsed.title.type,
|
|
4825
|
+
text: parsed.title.text,
|
|
4826
|
+
range: [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]],
|
|
4827
|
+
loc: getSourceLocationFromRange(sourceCode, node, [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]])
|
|
4828
|
+
} : null
|
|
4829
|
+
};
|
|
4830
|
+
}
|
|
4831
|
+
/**
|
|
4832
|
+
* Parse the image from the given text.
|
|
4833
|
+
*/
|
|
4834
|
+
function parseImageFromText(text) {
|
|
4835
|
+
if (!text.startsWith("![")) return null;
|
|
4836
|
+
let index = text.length - 1;
|
|
4837
|
+
skipSpaces();
|
|
4838
|
+
if (text[index] !== ")") return null;
|
|
4839
|
+
index--;
|
|
4840
|
+
skipSpaces();
|
|
4841
|
+
let title = null;
|
|
4842
|
+
const titleEndIndex = index + 1;
|
|
4843
|
+
const endChar = text[index];
|
|
4844
|
+
if (endChar === "'" || endChar === "\"" || endChar === ")") {
|
|
4845
|
+
index--;
|
|
4846
|
+
const startChar = endChar === ")" ? "(" : endChar;
|
|
4847
|
+
if (skipUntilStart((c) => c === startChar)) {
|
|
4848
|
+
const titleRange = [index, titleEndIndex];
|
|
4849
|
+
index--;
|
|
4850
|
+
title = {
|
|
4851
|
+
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
4852
|
+
text: text.slice(...titleRange),
|
|
4853
|
+
range: titleRange
|
|
4854
|
+
};
|
|
4855
|
+
skipSpaces();
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
if (title == null) index = titleEndIndex - 1;
|
|
4859
|
+
let destination;
|
|
4860
|
+
const destinationEndIndex = index + 1;
|
|
4861
|
+
if (text[index] === ">") {
|
|
4862
|
+
index--;
|
|
4863
|
+
if (!skipUntilStart((c) => c === "<")) return null;
|
|
4864
|
+
const destinationRange = [index, destinationEndIndex];
|
|
4865
|
+
index--;
|
|
4866
|
+
destination = {
|
|
4867
|
+
type: "pointy-bracketed",
|
|
4868
|
+
text: text.slice(...destinationRange),
|
|
4869
|
+
range: destinationRange
|
|
4870
|
+
};
|
|
4871
|
+
} else {
|
|
4872
|
+
if (text.length <= index) return null;
|
|
4873
|
+
skipUntilStart((c) => isWhitespace(c) || isAsciiControlCharacter(c) || c === "(");
|
|
4874
|
+
const destinationRange = [index + 1, destinationEndIndex];
|
|
4875
|
+
destination = {
|
|
4876
|
+
type: "bare",
|
|
4877
|
+
text: text.slice(...destinationRange),
|
|
4878
|
+
range: destinationRange
|
|
4879
|
+
};
|
|
4880
|
+
}
|
|
4881
|
+
skipSpaces();
|
|
4882
|
+
if (text[index] !== "(") return null;
|
|
4883
|
+
index--;
|
|
4884
|
+
if (text[index] !== "]") return null;
|
|
4885
|
+
return {
|
|
4886
|
+
text: { range: [1, index + 1] },
|
|
4887
|
+
destination,
|
|
4888
|
+
title
|
|
4889
|
+
};
|
|
4890
|
+
/**
|
|
4891
|
+
* Skip spaces
|
|
4892
|
+
*/
|
|
4893
|
+
function skipSpaces() {
|
|
4894
|
+
while (index >= 0 && isWhitespace(text[index])) index--;
|
|
4895
|
+
}
|
|
4896
|
+
/**
|
|
4897
|
+
* Skip until the start by the given condition
|
|
4898
|
+
*/
|
|
4899
|
+
function skipUntilStart(checkStart) {
|
|
4900
|
+
while (index >= 0) {
|
|
4901
|
+
const c = text[index];
|
|
4902
|
+
if (checkStart(c)) {
|
|
4903
|
+
if (index > 1 && !isWhitespace(c)) {
|
|
4904
|
+
let escapeText = "";
|
|
4905
|
+
while (text.endsWith(`${escapeText}\\`, index)) escapeText += "\\";
|
|
4906
|
+
if (escapeText.length % 2 === 1) {
|
|
4907
|
+
index -= escapeText.length + 1;
|
|
4908
|
+
continue;
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
return true;
|
|
4912
|
+
}
|
|
4913
|
+
index--;
|
|
4914
|
+
}
|
|
4915
|
+
return false;
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
|
|
4919
|
+
//#endregion
|
|
4920
|
+
//#region src/utils/image-reference.ts
|
|
4921
|
+
/**
|
|
4922
|
+
* Parse the image reference.
|
|
4923
|
+
*/
|
|
4924
|
+
function parseImageReference(sourceCode, node) {
|
|
4925
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4926
|
+
if (node.referenceType === "shortcut") {
|
|
4927
|
+
const textRange$1 = [nodeRange[0] + 1, nodeRange[1]];
|
|
4928
|
+
return {
|
|
4929
|
+
text: {
|
|
4930
|
+
range: textRange$1,
|
|
4931
|
+
text: sourceCode.text.slice(...textRange$1),
|
|
4932
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange$1)
|
|
4933
|
+
},
|
|
4934
|
+
label: null
|
|
4935
|
+
};
|
|
4936
|
+
}
|
|
4937
|
+
if (node.referenceType === "collapsed") {
|
|
4938
|
+
const textRange$1 = [nodeRange[0] + 1, nodeRange[1] - 2];
|
|
4939
|
+
const labelRange$1 = [textRange$1[1], nodeRange[1]];
|
|
4940
|
+
return {
|
|
4941
|
+
text: {
|
|
4942
|
+
range: textRange$1,
|
|
4943
|
+
text: sourceCode.text.slice(...textRange$1),
|
|
4944
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange$1)
|
|
4945
|
+
},
|
|
4946
|
+
label: {
|
|
4947
|
+
type: "collapsed",
|
|
4948
|
+
range: labelRange$1,
|
|
4949
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange$1)
|
|
4950
|
+
}
|
|
4951
|
+
};
|
|
4952
|
+
}
|
|
4953
|
+
const parsed = parseFullImageReferenceFromText(sourceCode.getText(node));
|
|
4954
|
+
if (!parsed) return null;
|
|
4955
|
+
const textRange = [nodeRange[0] + parsed.text.range[0], nodeRange[0] + parsed.text.range[1]];
|
|
4956
|
+
const labelRange = [nodeRange[0] + parsed.label.range[0], nodeRange[0] + parsed.label.range[1]];
|
|
4957
|
+
return {
|
|
4958
|
+
text: {
|
|
4959
|
+
range: textRange,
|
|
4960
|
+
text: parsed.text.text,
|
|
4961
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4962
|
+
},
|
|
4963
|
+
label: {
|
|
4964
|
+
type: "full",
|
|
4965
|
+
text: parsed.label.text,
|
|
4966
|
+
range: labelRange,
|
|
4967
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange)
|
|
4968
|
+
}
|
|
4969
|
+
};
|
|
4970
|
+
}
|
|
4971
|
+
/**
|
|
4972
|
+
* Parse the full image reference from the given text.
|
|
4973
|
+
*/
|
|
4974
|
+
function parseFullImageReferenceFromText(text) {
|
|
4975
|
+
if (!text.startsWith("![")) return null;
|
|
4976
|
+
let index = text.length - 1;
|
|
4977
|
+
skipSpaces();
|
|
4978
|
+
if (text[index] !== "]") return null;
|
|
4979
|
+
const labelEndIndex = index + 1;
|
|
4980
|
+
index--;
|
|
4981
|
+
skipSpaces();
|
|
4982
|
+
if (!skipUntilStart((c) => c === "[")) return null;
|
|
4983
|
+
const labelRange = [index, labelEndIndex];
|
|
4984
|
+
index--;
|
|
4985
|
+
const label = {
|
|
4986
|
+
text: text.slice(...labelRange),
|
|
4987
|
+
range: labelRange
|
|
4988
|
+
};
|
|
4989
|
+
if (text[index] !== "]") return null;
|
|
4990
|
+
const textRange = [1, index + 1];
|
|
4991
|
+
return {
|
|
4992
|
+
text: {
|
|
4993
|
+
text: text.slice(...textRange),
|
|
4994
|
+
range: textRange
|
|
4995
|
+
},
|
|
4996
|
+
label
|
|
4997
|
+
};
|
|
4998
|
+
/**
|
|
4999
|
+
* Skip spaces
|
|
5000
|
+
*/
|
|
5001
|
+
function skipSpaces() {
|
|
5002
|
+
while (index >= 0 && isWhitespace(text[index])) index--;
|
|
5003
|
+
}
|
|
5004
|
+
/**
|
|
5005
|
+
* Skip until the start by the given condition
|
|
5006
|
+
*/
|
|
5007
|
+
function skipUntilStart(checkStart) {
|
|
5008
|
+
while (index >= 0) {
|
|
5009
|
+
const c = text[index];
|
|
5010
|
+
if (checkStart(c)) {
|
|
5011
|
+
if (index > 1) {
|
|
5012
|
+
let escapeText = "";
|
|
5013
|
+
while (text.endsWith(`${escapeText}\\`, index)) escapeText += "\\";
|
|
5014
|
+
if (escapeText.length % 2 === 1) {
|
|
5015
|
+
index -= escapeText.length + 1;
|
|
5016
|
+
continue;
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
return true;
|
|
5020
|
+
}
|
|
5021
|
+
index--;
|
|
5022
|
+
}
|
|
5023
|
+
return false;
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
|
|
5027
|
+
//#endregion
|
|
5028
|
+
//#region src/utils/link-definition.ts
|
|
5029
|
+
/**
|
|
5030
|
+
* Parse the link definition.
|
|
5031
|
+
*/
|
|
5032
|
+
function parseLinkDefinition(sourceCode, node) {
|
|
5033
|
+
const text = sourceCode.getText(node);
|
|
5034
|
+
const parsed = parseLinkDefinitionFromText(text);
|
|
5035
|
+
if (!parsed) return null;
|
|
5036
|
+
const nodeRange = sourceCode.getRange(node);
|
|
5037
|
+
const labelRange = [nodeRange[0] + parsed.label.range[0], nodeRange[0] + parsed.label.range[1]];
|
|
5038
|
+
const destinationRange = [nodeRange[0] + parsed.destination.range[0], nodeRange[0] + parsed.destination.range[1]];
|
|
5039
|
+
return {
|
|
5040
|
+
label: {
|
|
5041
|
+
text: parsed.label.text,
|
|
5042
|
+
range: labelRange,
|
|
5043
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange)
|
|
5044
|
+
},
|
|
5045
|
+
destination: {
|
|
5046
|
+
type: parsed.destination.type,
|
|
5047
|
+
text: parsed.destination.text,
|
|
5048
|
+
range: destinationRange,
|
|
5049
|
+
loc: getSourceLocationFromRange(sourceCode, node, destinationRange)
|
|
5050
|
+
},
|
|
5051
|
+
title: parsed.title ? {
|
|
5052
|
+
type: parsed.title.type,
|
|
5053
|
+
text: parsed.title.text,
|
|
5054
|
+
range: [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]],
|
|
5055
|
+
loc: getSourceLocationFromRange(sourceCode, node, [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]])
|
|
5056
|
+
} : null
|
|
5057
|
+
};
|
|
5058
|
+
}
|
|
5059
|
+
/**
|
|
5060
|
+
* Parse the link definition from the given text.
|
|
5061
|
+
*/
|
|
5062
|
+
function parseLinkDefinitionFromText(text) {
|
|
5063
|
+
let index = 0;
|
|
5064
|
+
if (text[index] !== "[") return null;
|
|
5065
|
+
const labelStartIndex = index;
|
|
5066
|
+
index++;
|
|
5067
|
+
if (!skipUntilEnd((c) => c === "]")) return null;
|
|
5068
|
+
index++;
|
|
5069
|
+
const labelRange = [labelStartIndex, index];
|
|
5070
|
+
if (!text.slice(labelRange[0] + 1, labelRange[1] - 1).trim()) return null;
|
|
5071
|
+
if (text[index] !== ":") return null;
|
|
5072
|
+
const label = {
|
|
5073
|
+
text: text.slice(...labelRange),
|
|
5074
|
+
range: labelRange
|
|
5075
|
+
};
|
|
5076
|
+
index++;
|
|
5077
|
+
skipSpaces();
|
|
5078
|
+
let destination;
|
|
5079
|
+
const destinationStartIndex = index;
|
|
5080
|
+
if (text[index] === "<") {
|
|
5081
|
+
index++;
|
|
5082
|
+
if (!skipUntilEnd((c) => c === ">")) return null;
|
|
5083
|
+
index++;
|
|
5084
|
+
const destinationRange = [destinationStartIndex, index];
|
|
5085
|
+
destination = {
|
|
5086
|
+
type: "pointy-bracketed",
|
|
5087
|
+
text: text.slice(...destinationRange),
|
|
5088
|
+
range: destinationRange
|
|
5089
|
+
};
|
|
5090
|
+
} else {
|
|
5091
|
+
if (text.length <= index) return null;
|
|
5092
|
+
skipUntilEnd((c) => isWhitespace(c) || isAsciiControlCharacter(c));
|
|
5093
|
+
const destinationRange = [destinationStartIndex, index];
|
|
5094
|
+
destination = {
|
|
5095
|
+
type: "bare",
|
|
5096
|
+
text: text.slice(...destinationRange),
|
|
5097
|
+
range: destinationRange
|
|
5098
|
+
};
|
|
5099
|
+
}
|
|
5100
|
+
skipSpaces();
|
|
5101
|
+
if (text.length <= index) return {
|
|
5102
|
+
label,
|
|
5103
|
+
destination,
|
|
5104
|
+
title: null
|
|
5105
|
+
};
|
|
5106
|
+
let title;
|
|
5107
|
+
const titleStartIndex = index;
|
|
5108
|
+
const startChar = text[index];
|
|
5109
|
+
if (startChar === "'" || startChar === "\"" || startChar === "(") {
|
|
5110
|
+
index++;
|
|
5111
|
+
const endChar = startChar === "(" ? ")" : startChar;
|
|
5112
|
+
if (!skipUntilEnd((c) => c === endChar)) return null;
|
|
5113
|
+
index++;
|
|
5114
|
+
const titleRange = [titleStartIndex, index];
|
|
5115
|
+
title = {
|
|
5116
|
+
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
5117
|
+
text: text.slice(...titleRange),
|
|
5118
|
+
range: titleRange
|
|
5119
|
+
};
|
|
5120
|
+
} else return null;
|
|
5121
|
+
skipSpaces();
|
|
5122
|
+
if (index < text.length) return null;
|
|
5123
|
+
return {
|
|
5124
|
+
label,
|
|
5125
|
+
destination,
|
|
5126
|
+
title
|
|
5127
|
+
};
|
|
5128
|
+
/**
|
|
5129
|
+
* Skip spaces
|
|
5130
|
+
*/
|
|
5131
|
+
function skipSpaces() {
|
|
5132
|
+
while (index < text.length && isWhitespace(text[index])) index++;
|
|
5133
|
+
}
|
|
5134
|
+
/**
|
|
5135
|
+
* Skip until the end by the given condition
|
|
5136
|
+
*/
|
|
5137
|
+
function skipUntilEnd(checkEnd) {
|
|
5138
|
+
while (index < text.length) {
|
|
5139
|
+
const c = text[index];
|
|
5140
|
+
if (checkEnd(c)) return true;
|
|
5141
|
+
index++;
|
|
5142
|
+
if (c !== "\\") continue;
|
|
5143
|
+
if (index < text.length && (text[index] === "\\" || checkEnd(text[index])) && !isWhitespace(text[index])) index++;
|
|
5144
|
+
}
|
|
5145
|
+
return false;
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
|
|
5149
|
+
//#endregion
|
|
5150
|
+
//#region src/rules/link-bracket-newline.ts
|
|
5151
|
+
var link_bracket_newline_default = createRule("link-bracket-newline", {
|
|
4633
5152
|
meta: {
|
|
4634
5153
|
type: "layout",
|
|
4635
5154
|
docs: {
|
|
4636
|
-
description: "enforce
|
|
4637
|
-
categories: ["
|
|
5155
|
+
description: "enforce linebreaks after opening and before closing link brackets",
|
|
5156
|
+
categories: ["standard"],
|
|
4638
5157
|
listCategory: "Stylistic"
|
|
4639
5158
|
},
|
|
4640
5159
|
fixable: "whitespace",
|
|
4641
5160
|
hasSuggestions: false,
|
|
4642
5161
|
schema: [{
|
|
4643
5162
|
type: "object",
|
|
4644
|
-
properties: {
|
|
5163
|
+
properties: {
|
|
5164
|
+
newline: { enum: [
|
|
5165
|
+
"always",
|
|
5166
|
+
"never",
|
|
5167
|
+
"consistent"
|
|
5168
|
+
] },
|
|
5169
|
+
multiline: { type: "boolean" }
|
|
5170
|
+
},
|
|
4645
5171
|
additionalProperties: false
|
|
4646
5172
|
}],
|
|
4647
|
-
messages: {
|
|
5173
|
+
messages: {
|
|
5174
|
+
expectedNewlineAfterOpeningBracket: "Expected a linebreak after this opening bracket.",
|
|
5175
|
+
unexpectedNewlineAfterOpeningBracket: "Unexpected linebreak after this opening bracket.",
|
|
5176
|
+
expectedNewlineBeforeClosingBracket: "Expected a linebreak before this closing bracket.",
|
|
5177
|
+
unexpectedNewlineBeforeClosingBracket: "Unexpected linebreak before this closing bracket."
|
|
5178
|
+
}
|
|
4648
5179
|
},
|
|
4649
5180
|
create(context) {
|
|
4650
5181
|
const sourceCode = context.sourceCode;
|
|
4651
|
-
const
|
|
5182
|
+
const optionProvider = parseOptions$3(context.options[0]);
|
|
4652
5183
|
/**
|
|
4653
|
-
*
|
|
5184
|
+
* Parse the options.
|
|
4654
5185
|
*/
|
|
4655
|
-
function
|
|
4656
|
-
const
|
|
4657
|
-
const
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
5186
|
+
function parseOptions$3(option) {
|
|
5187
|
+
const newline = option?.newline ?? "never";
|
|
5188
|
+
const multiline = option?.multiline ?? false;
|
|
5189
|
+
return (bracketsRange) => {
|
|
5190
|
+
if (multiline) {
|
|
5191
|
+
if (sourceCode.text.slice(bracketsRange[0] + 1, bracketsRange[1] - 1).trim().includes("\n")) return "always";
|
|
5192
|
+
}
|
|
5193
|
+
return newline;
|
|
4663
5194
|
};
|
|
4664
5195
|
}
|
|
4665
5196
|
/**
|
|
4666
|
-
*
|
|
5197
|
+
* Verify the newline around the brackets.
|
|
4667
5198
|
*/
|
|
4668
|
-
function
|
|
4669
|
-
const
|
|
4670
|
-
|
|
4671
|
-
const
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
5199
|
+
function verifyNewlineAroundBrackets(node, bracketsRange) {
|
|
5200
|
+
const newline = optionProvider(bracketsRange);
|
|
5201
|
+
const openingBracketIndex = bracketsRange[0];
|
|
5202
|
+
const spaceAfterOpeningBracket = getSpaceAfterOpeningBracket(openingBracketIndex);
|
|
5203
|
+
verifyNewlineAfterOpeningBracket(node, spaceAfterOpeningBracket, openingBracketIndex, newline);
|
|
5204
|
+
const closingBracketIndex = bracketsRange[1] - 1;
|
|
5205
|
+
const newlineOptionBeforeClosingBracket = newline === "consistent" ? getSpaceAfterOpeningBracket(bracketsRange[0]).includes("\n") ? "always" : "never" : newline;
|
|
5206
|
+
verifyNewlineBeforeClosingBracket(node, getSpaceBeforeClosingBracket(closingBracketIndex), openingBracketIndex, closingBracketIndex, newlineOptionBeforeClosingBracket);
|
|
5207
|
+
}
|
|
5208
|
+
/**
|
|
5209
|
+
* Verify the newline after the opening bracket and before the closing bracket.
|
|
5210
|
+
*/
|
|
5211
|
+
function verifyNewlineAfterOpeningBracket(node, spaceAfterOpeningBracket, openingBracketIndex, newline) {
|
|
5212
|
+
if (newline === "always") {
|
|
5213
|
+
if (spaceAfterOpeningBracket.includes("\n")) return;
|
|
5214
|
+
const loc = getSourceLocationFromRange(sourceCode, node, [openingBracketIndex, openingBracketIndex + 1]);
|
|
4676
5215
|
context.report({
|
|
4677
|
-
node
|
|
4678
|
-
loc
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
return fixer.removeRange([removeStartIndex, removeEndIndex]);
|
|
4707
|
-
}
|
|
4708
|
-
return null;
|
|
5216
|
+
node,
|
|
5217
|
+
loc,
|
|
5218
|
+
messageId: "expectedNewlineAfterOpeningBracket",
|
|
5219
|
+
fix: (fixer) => fixer.insertTextAfterRange([openingBracketIndex, openingBracketIndex + 1], `\n${" ".repeat(loc.start.column)}${spaceAfterOpeningBracket}`)
|
|
5220
|
+
});
|
|
5221
|
+
} else if (newline === "never") {
|
|
5222
|
+
if (!spaceAfterOpeningBracket.includes("\n")) return;
|
|
5223
|
+
context.report({
|
|
5224
|
+
node,
|
|
5225
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingBracketIndex + 1, openingBracketIndex + 1 + spaceAfterOpeningBracket.length]),
|
|
5226
|
+
messageId: "unexpectedNewlineAfterOpeningBracket",
|
|
5227
|
+
fix: (fixer) => fixer.replaceTextRange([openingBracketIndex + 1, openingBracketIndex + 1 + spaceAfterOpeningBracket.length], " ")
|
|
5228
|
+
});
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
/**
|
|
5232
|
+
* Verify the newline before the closing bracket.
|
|
5233
|
+
*/
|
|
5234
|
+
function verifyNewlineBeforeClosingBracket(node, spaceBeforeClosingBracket, openingBracketIndex, closingBracketIndex, newline) {
|
|
5235
|
+
if (openingBracketIndex + 1 === closingBracketIndex - spaceBeforeClosingBracket.length) return;
|
|
5236
|
+
if (newline === "always") {
|
|
5237
|
+
if (spaceBeforeClosingBracket.includes("\n")) return;
|
|
5238
|
+
context.report({
|
|
5239
|
+
node,
|
|
5240
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingBracketIndex, closingBracketIndex + 1]),
|
|
5241
|
+
messageId: "expectedNewlineBeforeClosingBracket",
|
|
5242
|
+
fix: (fixer) => {
|
|
5243
|
+
const openingBracketLoc = getSourceLocationFromRange(sourceCode, node, [openingBracketIndex, openingBracketIndex + 1]);
|
|
5244
|
+
return fixer.insertTextBeforeRange([closingBracketIndex, closingBracketIndex + 1], `\n${" ".repeat(openingBracketLoc.start.column)}`);
|
|
4709
5245
|
}
|
|
4710
5246
|
});
|
|
5247
|
+
} else if (newline === "never") {
|
|
5248
|
+
if (!spaceBeforeClosingBracket.includes("\n")) return;
|
|
5249
|
+
context.report({
|
|
5250
|
+
node,
|
|
5251
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingBracketIndex - spaceBeforeClosingBracket.length, closingBracketIndex]),
|
|
5252
|
+
messageId: "unexpectedNewlineBeforeClosingBracket",
|
|
5253
|
+
fix: (fixer) => fixer.replaceTextRange([closingBracketIndex - spaceBeforeClosingBracket.length, closingBracketIndex], " ")
|
|
5254
|
+
});
|
|
4711
5255
|
}
|
|
4712
5256
|
}
|
|
4713
|
-
return {
|
|
5257
|
+
return {
|
|
5258
|
+
link(node) {
|
|
5259
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
5260
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5261
|
+
if (!parsed) return;
|
|
5262
|
+
verifyNewlineAroundBrackets(node, parsed.text.range);
|
|
5263
|
+
},
|
|
5264
|
+
linkReference(node) {
|
|
5265
|
+
const parsed = parseLinkReference(sourceCode, node);
|
|
5266
|
+
if (!parsed) return;
|
|
5267
|
+
verifyNewlineAroundBrackets(node, parsed.text.range);
|
|
5268
|
+
if (parsed.label?.type === "full") verifyNewlineAroundBrackets(node, parsed.label.range);
|
|
5269
|
+
},
|
|
5270
|
+
image(node) {
|
|
5271
|
+
const parsed = parseImage(sourceCode, node);
|
|
5272
|
+
if (!parsed) return;
|
|
5273
|
+
verifyNewlineAroundBrackets(node, parsed.text.range);
|
|
5274
|
+
},
|
|
5275
|
+
imageReference(node) {
|
|
5276
|
+
const parsed = parseImageReference(sourceCode, node);
|
|
5277
|
+
if (!parsed) return;
|
|
5278
|
+
verifyNewlineAroundBrackets(node, parsed.text.range);
|
|
5279
|
+
if (parsed.label?.type === "full") verifyNewlineAroundBrackets(node, parsed.label.range);
|
|
5280
|
+
},
|
|
5281
|
+
definition(node) {
|
|
5282
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5283
|
+
if (!parsed) return;
|
|
5284
|
+
verifyNewlineAroundBrackets(node, parsed.label.range);
|
|
5285
|
+
}
|
|
5286
|
+
};
|
|
5287
|
+
/**
|
|
5288
|
+
* Get the spaces after the opening bracket.
|
|
5289
|
+
*/
|
|
5290
|
+
function getSpaceAfterOpeningBracket(openingBracketIndex) {
|
|
5291
|
+
for (let i = openingBracketIndex + 1; i < sourceCode.text.length; i++) {
|
|
5292
|
+
const char = sourceCode.text[i];
|
|
5293
|
+
if (isWhitespace(char)) continue;
|
|
5294
|
+
return sourceCode.text.slice(openingBracketIndex + 1, i);
|
|
5295
|
+
}
|
|
5296
|
+
return sourceCode.text.slice(openingBracketIndex + 1);
|
|
5297
|
+
}
|
|
5298
|
+
/**
|
|
5299
|
+
* Get the spaces before the closing bracket.
|
|
5300
|
+
*/
|
|
5301
|
+
function getSpaceBeforeClosingBracket(closingBracketIndex) {
|
|
5302
|
+
for (let i = closingBracketIndex - 1; i >= 0; i--) {
|
|
5303
|
+
const char = sourceCode.text[i];
|
|
5304
|
+
if (isWhitespace(char)) continue;
|
|
5305
|
+
return sourceCode.text.slice(i + 1, closingBracketIndex);
|
|
5306
|
+
}
|
|
5307
|
+
return sourceCode.text.slice(0, closingBracketIndex);
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
5310
|
+
});
|
|
5311
|
+
|
|
5312
|
+
//#endregion
|
|
5313
|
+
//#region src/rules/link-bracket-spacing.ts
|
|
5314
|
+
/**
|
|
5315
|
+
* The basic option for links and images.
|
|
5316
|
+
*/
|
|
5317
|
+
function parseOptions$1(option) {
|
|
5318
|
+
const space = option?.space ?? "never";
|
|
5319
|
+
const imagesInLinks = option?.imagesInLinks;
|
|
5320
|
+
return {
|
|
5321
|
+
space,
|
|
5322
|
+
spaceForText: getOptionForText
|
|
5323
|
+
};
|
|
5324
|
+
/**
|
|
5325
|
+
* Get the spacing option for the given node.
|
|
5326
|
+
*/
|
|
5327
|
+
function getOptionForText(node) {
|
|
5328
|
+
if (imagesInLinks != null) {
|
|
5329
|
+
const children = [...node.children];
|
|
5330
|
+
let child;
|
|
5331
|
+
while (children.length && (child = children[0]) && child.type === "text" && isWhitespace(child.value)) children.shift();
|
|
5332
|
+
while (children.length && (child = children[children.length - 1]) && child.type === "text" && isWhitespace(child.value)) children.pop();
|
|
5333
|
+
const loneChild = children.length === 1 ? children[0] : null;
|
|
5334
|
+
if (loneChild?.type === "image" || loneChild?.type === "imageReference") return imagesInLinks ? "always" : "never";
|
|
5335
|
+
}
|
|
5336
|
+
if (node.children.length === 0 || node.children.length === 1 && node.children[0]?.type === "text" && isWhitespace(node.children[0].value)) return "ignore";
|
|
5337
|
+
return space;
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
var link_bracket_spacing_default = createRule("link-bracket-spacing", {
|
|
5341
|
+
meta: {
|
|
5342
|
+
type: "layout",
|
|
5343
|
+
docs: {
|
|
5344
|
+
description: "enforce consistent spacing inside link brackets",
|
|
5345
|
+
categories: ["standard"],
|
|
5346
|
+
listCategory: "Stylistic"
|
|
5347
|
+
},
|
|
5348
|
+
fixable: "whitespace",
|
|
5349
|
+
hasSuggestions: false,
|
|
5350
|
+
schema: [{
|
|
5351
|
+
type: "object",
|
|
5352
|
+
properties: {
|
|
5353
|
+
space: { enum: ["always", "never"] },
|
|
5354
|
+
imagesInLinks: { type: "boolean" }
|
|
5355
|
+
},
|
|
5356
|
+
additionalProperties: false
|
|
5357
|
+
}],
|
|
5358
|
+
messages: {
|
|
5359
|
+
unexpectedSpaceAfterOpeningBracket: "Unexpected space after opening bracket.",
|
|
5360
|
+
expectedSpaceAfterOpeningBracket: "Expected space after opening bracket.",
|
|
5361
|
+
unexpectedSpaceBeforeClosingBracket: "Unexpected space before closing bracket.",
|
|
5362
|
+
expectedSpaceBeforeClosingBracket: "Expected space before closing bracket."
|
|
5363
|
+
}
|
|
5364
|
+
},
|
|
5365
|
+
create(context) {
|
|
5366
|
+
const sourceCode = context.sourceCode;
|
|
5367
|
+
const options = parseOptions$1(context.options[0]);
|
|
5368
|
+
/**
|
|
5369
|
+
* Verify the space after the opening bracket and before the closing bracket.
|
|
5370
|
+
*/
|
|
5371
|
+
function verifySpaceAfterOpeningBracket(node, openingBracketIndex, spaceOption) {
|
|
5372
|
+
const space = getSpaceAfterOpeningBracket(openingBracketIndex);
|
|
5373
|
+
if (space.includes("\n")) return;
|
|
5374
|
+
if (spaceOption === "always") {
|
|
5375
|
+
if (space.length > 0) return;
|
|
5376
|
+
context.report({
|
|
5377
|
+
node,
|
|
5378
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingBracketIndex, openingBracketIndex + 1]),
|
|
5379
|
+
messageId: "expectedSpaceAfterOpeningBracket",
|
|
5380
|
+
fix: (fixer) => fixer.insertTextAfterRange([openingBracketIndex, openingBracketIndex + 1], " ")
|
|
5381
|
+
});
|
|
5382
|
+
} else if (spaceOption === "never") {
|
|
5383
|
+
if (space.length === 0) return;
|
|
5384
|
+
context.report({
|
|
5385
|
+
node,
|
|
5386
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingBracketIndex + 1, openingBracketIndex + 1 + space.length]),
|
|
5387
|
+
messageId: "unexpectedSpaceAfterOpeningBracket",
|
|
5388
|
+
fix: (fixer) => fixer.removeRange([openingBracketIndex + 1, openingBracketIndex + 1 + space.length])
|
|
5389
|
+
});
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
/**
|
|
5393
|
+
* Verify the space before the closing bracket.
|
|
5394
|
+
*/
|
|
5395
|
+
function verifySpaceBeforeClosingBracket(node, openingBracketIndex, closingBracketIndex, spaceOption) {
|
|
5396
|
+
const space = getSpaceBeforeClosingBracket(closingBracketIndex);
|
|
5397
|
+
if (openingBracketIndex + 1 === closingBracketIndex - space.length) return;
|
|
5398
|
+
if (space.includes("\n")) return;
|
|
5399
|
+
if (spaceOption === "always") {
|
|
5400
|
+
if (space.length > 0) return;
|
|
5401
|
+
context.report({
|
|
5402
|
+
node,
|
|
5403
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingBracketIndex, closingBracketIndex + 1]),
|
|
5404
|
+
messageId: "expectedSpaceBeforeClosingBracket",
|
|
5405
|
+
fix: (fixer) => fixer.insertTextBeforeRange([closingBracketIndex, closingBracketIndex + 1], " ")
|
|
5406
|
+
});
|
|
5407
|
+
} else if (spaceOption === "never") {
|
|
5408
|
+
if (space.length === 0) return;
|
|
5409
|
+
context.report({
|
|
5410
|
+
node,
|
|
5411
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingBracketIndex - space.length, closingBracketIndex]),
|
|
5412
|
+
messageId: "unexpectedSpaceBeforeClosingBracket",
|
|
5413
|
+
fix: (fixer) => fixer.removeRange([closingBracketIndex - space.length, closingBracketIndex])
|
|
5414
|
+
});
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
return {
|
|
5418
|
+
link(node) {
|
|
5419
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
5420
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5421
|
+
if (!parsed) return;
|
|
5422
|
+
const spaceForText = options.spaceForText(node);
|
|
5423
|
+
if (spaceForText === "ignore") return;
|
|
5424
|
+
verifySpaceAfterOpeningBracket(node, parsed.text.range[0], spaceForText);
|
|
5425
|
+
verifySpaceBeforeClosingBracket(node, parsed.text.range[0], parsed.text.range[1] - 1, spaceForText);
|
|
5426
|
+
},
|
|
5427
|
+
linkReference(node) {
|
|
5428
|
+
const parsed = parseLinkReference(sourceCode, node);
|
|
5429
|
+
if (!parsed) return;
|
|
5430
|
+
const spaceForText = options.spaceForText(node);
|
|
5431
|
+
if (spaceForText !== "ignore") {
|
|
5432
|
+
if (spaceForText !== "never" || !sourceCode.text.slice(parsed.text.range[0] + 1, parsed.text.range[1] - 1).trimStart().startsWith("^")) {
|
|
5433
|
+
verifySpaceAfterOpeningBracket(node, parsed.text.range[0], spaceForText);
|
|
5434
|
+
verifySpaceBeforeClosingBracket(node, parsed.text.range[0], parsed.text.range[1] - 1, spaceForText);
|
|
5435
|
+
}
|
|
5436
|
+
}
|
|
5437
|
+
if (parsed.label?.type === "full") {
|
|
5438
|
+
verifySpaceAfterOpeningBracket(node, parsed.label.range[0], options.space);
|
|
5439
|
+
verifySpaceBeforeClosingBracket(node, parsed.label.range[0], parsed.label.range[1] - 1, options.space);
|
|
5440
|
+
}
|
|
5441
|
+
},
|
|
5442
|
+
image(node) {
|
|
5443
|
+
const parsed = parseImage(sourceCode, node);
|
|
5444
|
+
if (!parsed) return;
|
|
5445
|
+
verifySpaceAfterOpeningBracket(node, parsed.text.range[0], options.space);
|
|
5446
|
+
verifySpaceBeforeClosingBracket(node, parsed.text.range[0], parsed.text.range[1] - 1, options.space);
|
|
5447
|
+
},
|
|
5448
|
+
imageReference(node) {
|
|
5449
|
+
const parsed = parseImageReference(sourceCode, node);
|
|
5450
|
+
if (!parsed) return;
|
|
5451
|
+
verifySpaceAfterOpeningBracket(node, parsed.text.range[0], options.space);
|
|
5452
|
+
verifySpaceBeforeClosingBracket(node, parsed.text.range[0], parsed.text.range[1] - 1, options.space);
|
|
5453
|
+
if (parsed.label?.type === "full") {
|
|
5454
|
+
verifySpaceAfterOpeningBracket(node, parsed.label.range[0], options.space);
|
|
5455
|
+
verifySpaceBeforeClosingBracket(node, parsed.label.range[0], parsed.label.range[1] - 1, options.space);
|
|
5456
|
+
}
|
|
5457
|
+
},
|
|
5458
|
+
definition(node) {
|
|
5459
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5460
|
+
if (!parsed) return;
|
|
5461
|
+
if (options.space !== "never" || !sourceCode.text.slice(parsed.label.range[0] + 1, parsed.label.range[1] - 1).trimStart().startsWith("^")) {
|
|
5462
|
+
verifySpaceAfterOpeningBracket(node, parsed.label.range[0], options.space);
|
|
5463
|
+
verifySpaceBeforeClosingBracket(node, parsed.label.range[0], parsed.label.range[1] - 1, options.space);
|
|
5464
|
+
}
|
|
5465
|
+
}
|
|
5466
|
+
};
|
|
5467
|
+
/**
|
|
5468
|
+
* Get the spaces after the opening bracket.
|
|
5469
|
+
*/
|
|
5470
|
+
function getSpaceAfterOpeningBracket(openingBracketIndex) {
|
|
5471
|
+
for (let i = openingBracketIndex + 1; i < sourceCode.text.length; i++) {
|
|
5472
|
+
const char = sourceCode.text[i];
|
|
5473
|
+
if (isWhitespace(char)) continue;
|
|
5474
|
+
return sourceCode.text.slice(openingBracketIndex + 1, i);
|
|
5475
|
+
}
|
|
5476
|
+
return sourceCode.text.slice(openingBracketIndex + 1);
|
|
5477
|
+
}
|
|
5478
|
+
/**
|
|
5479
|
+
* Get the spaces before the closing bracket.
|
|
5480
|
+
*/
|
|
5481
|
+
function getSpaceBeforeClosingBracket(closingBracketIndex) {
|
|
5482
|
+
for (let i = closingBracketIndex - 1; i >= 0; i--) {
|
|
5483
|
+
const char = sourceCode.text[i];
|
|
5484
|
+
if (isWhitespace(char)) continue;
|
|
5485
|
+
return sourceCode.text.slice(i + 1, closingBracketIndex);
|
|
5486
|
+
}
|
|
5487
|
+
return sourceCode.text.slice(0, closingBracketIndex);
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5490
|
+
});
|
|
5491
|
+
|
|
5492
|
+
//#endregion
|
|
5493
|
+
//#region src/rules/link-destination-style.ts
|
|
5494
|
+
const STYLES$1 = {
|
|
5495
|
+
bare: {
|
|
5496
|
+
messageId: "expectedBare",
|
|
5497
|
+
typeName: "bare"
|
|
5498
|
+
},
|
|
5499
|
+
"pointy-brackets": {
|
|
5500
|
+
messageId: "expectedPointyBrackets",
|
|
5501
|
+
typeName: "pointy-bracketed"
|
|
5502
|
+
}
|
|
5503
|
+
};
|
|
5504
|
+
var link_destination_style_default = createRule("link-destination-style", {
|
|
5505
|
+
meta: {
|
|
5506
|
+
type: "layout",
|
|
5507
|
+
docs: {
|
|
5508
|
+
description: "enforce a consistent style for link destinations",
|
|
5509
|
+
categories: ["standard"],
|
|
5510
|
+
listCategory: "Stylistic"
|
|
5511
|
+
},
|
|
5512
|
+
fixable: "code",
|
|
5513
|
+
hasSuggestions: false,
|
|
5514
|
+
schema: [{
|
|
5515
|
+
type: "object",
|
|
5516
|
+
properties: {
|
|
5517
|
+
style: { enum: ["bare", "pointy-brackets"] },
|
|
5518
|
+
avoidEscape: { type: "boolean" }
|
|
5519
|
+
}
|
|
5520
|
+
}],
|
|
5521
|
+
messages: {
|
|
5522
|
+
expectedBare: "Link destination should not be enclosed in pointy brackets.",
|
|
5523
|
+
expectedPointyBrackets: "Expected link destination to be pointy bracketed."
|
|
5524
|
+
}
|
|
5525
|
+
},
|
|
5526
|
+
create(context) {
|
|
5527
|
+
const sourceCode = context.sourceCode;
|
|
5528
|
+
const options = context.options[0] || {};
|
|
5529
|
+
const preferStyle = STYLES$1[options.style || "bare"];
|
|
5530
|
+
const avoidEscape = options.avoidEscape ?? true;
|
|
5531
|
+
/**
|
|
5532
|
+
* Verify destination style.
|
|
5533
|
+
*/
|
|
5534
|
+
function verifyDestination(node, destination) {
|
|
5535
|
+
if (preferStyle.typeName === destination.type) return;
|
|
5536
|
+
if (avoidEscape) {
|
|
5537
|
+
if (preferStyle.typeName === "bare") {
|
|
5538
|
+
if (hasWhitespaceOrControlCharacter(destination.text) || !isBalancedDestinationParentheses(destination.text)) return;
|
|
5539
|
+
} else if (preferStyle.typeName === "pointy-bracketed") {
|
|
5540
|
+
if (hasLoneLastBackslash(destination.text)) return;
|
|
5541
|
+
}
|
|
5542
|
+
}
|
|
5543
|
+
context.report({
|
|
5544
|
+
node,
|
|
5545
|
+
loc: destination.loc,
|
|
5546
|
+
messageId: preferStyle.messageId,
|
|
5547
|
+
*fix(fixer) {
|
|
5548
|
+
if (destination.type === "bare" && preferStyle.typeName === "pointy-bracketed") {
|
|
5549
|
+
yield fixer.insertTextBeforeRange([destination.range[0], destination.range[0]], "<");
|
|
5550
|
+
if (hasLoneLastBackslash(destination.text)) yield fixer.insertTextBeforeRange([destination.range[1] - 1, destination.range[1]], "\\");
|
|
5551
|
+
yield fixer.insertTextAfterRange([destination.range[1], destination.range[1]], ">");
|
|
5552
|
+
} else if (destination.type === "pointy-bracketed" && preferStyle.typeName === "bare") {
|
|
5553
|
+
yield fixer.removeRange([destination.range[0], destination.range[0] + 1]);
|
|
5554
|
+
const balancedParentheses = isBalancedDestinationParentheses(destination.text);
|
|
5555
|
+
const textStartIndex = destination.range[0] + 1;
|
|
5556
|
+
const textEndIndex = destination.range[1] - 1;
|
|
5557
|
+
for (let index = textStartIndex; index < textEndIndex; index++) {
|
|
5558
|
+
const c = sourceCode.text[index];
|
|
5559
|
+
if (c === "(" || c === ")") {
|
|
5560
|
+
if (!balancedParentheses) yield fixer.insertTextBeforeRange([index, index], "\\");
|
|
5561
|
+
} else if (isWhitespace(c) || isAsciiControlCharacter(c)) yield fixer.replaceTextRange([index, index + 1], encodeURI(c));
|
|
5562
|
+
else if (c === "\\") index++;
|
|
5563
|
+
}
|
|
5564
|
+
yield fixer.removeRange([destination.range[1] - 1, destination.range[1]]);
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
});
|
|
5568
|
+
}
|
|
5569
|
+
return {
|
|
5570
|
+
link(node) {
|
|
5571
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
5572
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5573
|
+
if (!parsed) return;
|
|
5574
|
+
verifyDestination(node, parsed.destination);
|
|
5575
|
+
},
|
|
5576
|
+
image(node) {
|
|
5577
|
+
const parsed = parseImage(sourceCode, node);
|
|
5578
|
+
if (!parsed) return;
|
|
5579
|
+
verifyDestination(node, parsed.destination);
|
|
5580
|
+
},
|
|
5581
|
+
definition(node) {
|
|
5582
|
+
if (!node.url && preferStyle.typeName === "bare") return;
|
|
5583
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5584
|
+
if (!parsed) return;
|
|
5585
|
+
verifyDestination(node, parsed.destination);
|
|
5586
|
+
}
|
|
5587
|
+
};
|
|
5588
|
+
}
|
|
5589
|
+
});
|
|
5590
|
+
/**
|
|
5591
|
+
* Checks if the text has whitespace or control characters.
|
|
5592
|
+
*/
|
|
5593
|
+
function hasWhitespaceOrControlCharacter(text) {
|
|
5594
|
+
for (let index = 0; index < text.length; index++) {
|
|
5595
|
+
const c = text[index];
|
|
5596
|
+
if (isWhitespace(c) || isAsciiControlCharacter(c)) return true;
|
|
5597
|
+
else if (c === "\\") index++;
|
|
5598
|
+
}
|
|
5599
|
+
return false;
|
|
5600
|
+
}
|
|
5601
|
+
/**
|
|
5602
|
+
* Checks if the destination text is balanced parentheses.
|
|
5603
|
+
*/
|
|
5604
|
+
function isBalancedDestinationParentheses(text) {
|
|
5605
|
+
let parentheses = 0;
|
|
5606
|
+
for (let index = 0; index < text.length; index++) {
|
|
5607
|
+
const c = text[index];
|
|
5608
|
+
if (c === "(") parentheses++;
|
|
5609
|
+
else if (c === ")") {
|
|
5610
|
+
parentheses--;
|
|
5611
|
+
if (parentheses < 0) return false;
|
|
5612
|
+
} else if (c === "\\") index++;
|
|
5613
|
+
}
|
|
5614
|
+
if (parentheses > 0) return false;
|
|
5615
|
+
return true;
|
|
5616
|
+
}
|
|
5617
|
+
/**
|
|
5618
|
+
* Checks if the text has a lone last backslash.
|
|
5619
|
+
*/
|
|
5620
|
+
function hasLoneLastBackslash(text) {
|
|
5621
|
+
if (!text.endsWith("\\")) return false;
|
|
5622
|
+
let escapeText = "";
|
|
5623
|
+
while (text.endsWith(`${escapeText}\\`)) escapeText += "\\";
|
|
5624
|
+
return escapeText.length % 2 === 1;
|
|
5625
|
+
}
|
|
5626
|
+
|
|
5627
|
+
//#endregion
|
|
5628
|
+
//#region src/rules/link-title-style.ts
|
|
5629
|
+
const STYLES = {
|
|
5630
|
+
double: {
|
|
5631
|
+
messageId: "expectedDouble",
|
|
5632
|
+
open: "\"",
|
|
5633
|
+
close: "\"",
|
|
5634
|
+
typeName: "double-quoted"
|
|
5635
|
+
},
|
|
5636
|
+
single: {
|
|
5637
|
+
messageId: "expectedSingle",
|
|
5638
|
+
open: "'",
|
|
5639
|
+
close: "'",
|
|
5640
|
+
typeName: "single-quoted"
|
|
5641
|
+
},
|
|
5642
|
+
parentheses: {
|
|
5643
|
+
messageId: "expectedParentheses",
|
|
5644
|
+
open: "(",
|
|
5645
|
+
close: ")",
|
|
5646
|
+
typeName: "parenthesized"
|
|
5647
|
+
}
|
|
5648
|
+
};
|
|
5649
|
+
var link_title_style_default = createRule("link-title-style", {
|
|
5650
|
+
meta: {
|
|
5651
|
+
type: "layout",
|
|
5652
|
+
docs: {
|
|
5653
|
+
description: "enforce a consistent style for link titles",
|
|
5654
|
+
categories: ["standard"],
|
|
5655
|
+
listCategory: "Stylistic"
|
|
5656
|
+
},
|
|
5657
|
+
fixable: "code",
|
|
5658
|
+
hasSuggestions: false,
|
|
5659
|
+
schema: [{
|
|
5660
|
+
type: "object",
|
|
5661
|
+
properties: {
|
|
5662
|
+
style: { enum: [
|
|
5663
|
+
"double",
|
|
5664
|
+
"single",
|
|
5665
|
+
"parentheses"
|
|
5666
|
+
] },
|
|
5667
|
+
avoidEscape: { type: "boolean" }
|
|
5668
|
+
}
|
|
5669
|
+
}],
|
|
5670
|
+
messages: {
|
|
5671
|
+
expectedDouble: "Expected link title to be double quoted.",
|
|
5672
|
+
expectedSingle: "Expected link title to be single quoted.",
|
|
5673
|
+
expectedParentheses: "Expected link title to be parenthesized."
|
|
5674
|
+
}
|
|
5675
|
+
},
|
|
5676
|
+
create(context) {
|
|
5677
|
+
const sourceCode = context.sourceCode;
|
|
5678
|
+
const options = context.options[0] || {};
|
|
5679
|
+
const preferStyle = STYLES[options.style || "double"];
|
|
5680
|
+
const avoidEscape = options.avoidEscape ?? true;
|
|
5681
|
+
/**
|
|
5682
|
+
* Verify title style.
|
|
5683
|
+
*/
|
|
5684
|
+
function verifyTitle(node, title) {
|
|
5685
|
+
if (preferStyle.typeName === title.type) return;
|
|
5686
|
+
if (avoidEscape) {
|
|
5687
|
+
if (title.text.slice(1, -1).includes(preferStyle.close)) return;
|
|
5688
|
+
}
|
|
5689
|
+
context.report({
|
|
5690
|
+
node,
|
|
5691
|
+
loc: title.loc,
|
|
5692
|
+
messageId: preferStyle.messageId,
|
|
5693
|
+
*fix(fixer) {
|
|
5694
|
+
yield fixer.replaceTextRange([title.range[0], title.range[0] + 1], preferStyle.open);
|
|
5695
|
+
for (let index = title.range[0] + 1; index < title.range[1] - 1; index++) {
|
|
5696
|
+
const c = sourceCode.text[index];
|
|
5697
|
+
if (c === preferStyle.close) yield fixer.insertTextBeforeRange([index, index], "\\");
|
|
5698
|
+
else if (c === "\\") index++;
|
|
5699
|
+
}
|
|
5700
|
+
yield fixer.replaceTextRange([title.range[1] - 1, title.range[1]], preferStyle.close);
|
|
5701
|
+
}
|
|
5702
|
+
});
|
|
5703
|
+
}
|
|
5704
|
+
return {
|
|
5705
|
+
link(node) {
|
|
5706
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
5707
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5708
|
+
if (!parsed || !parsed.title) return;
|
|
5709
|
+
verifyTitle(node, parsed.title);
|
|
5710
|
+
},
|
|
5711
|
+
image(node) {
|
|
5712
|
+
const parsed = parseImage(sourceCode, node);
|
|
5713
|
+
if (!parsed || !parsed.title) return;
|
|
5714
|
+
verifyTitle(node, parsed.title);
|
|
5715
|
+
},
|
|
5716
|
+
definition(node) {
|
|
5717
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5718
|
+
if (!parsed || !parsed.title) return;
|
|
5719
|
+
verifyTitle(node, parsed.title);
|
|
5720
|
+
}
|
|
5721
|
+
};
|
|
5722
|
+
}
|
|
5723
|
+
});
|
|
5724
|
+
|
|
5725
|
+
//#endregion
|
|
5726
|
+
//#region src/rules/list-marker-alignment.ts
|
|
5727
|
+
const ALIGN_TO_POSITION_NAME = {
|
|
5728
|
+
left: "start",
|
|
5729
|
+
right: "end"
|
|
5730
|
+
};
|
|
5731
|
+
var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
5732
|
+
meta: {
|
|
5733
|
+
type: "layout",
|
|
5734
|
+
docs: {
|
|
5735
|
+
description: "enforce consistent alignment of list markers",
|
|
5736
|
+
categories: ["recommended", "standard"],
|
|
5737
|
+
listCategory: "Stylistic"
|
|
5738
|
+
},
|
|
5739
|
+
fixable: "whitespace",
|
|
5740
|
+
hasSuggestions: false,
|
|
5741
|
+
schema: [{
|
|
5742
|
+
type: "object",
|
|
5743
|
+
properties: { align: { enum: ["left", "right"] } },
|
|
5744
|
+
additionalProperties: false
|
|
5745
|
+
}],
|
|
5746
|
+
messages: { incorrectAlignment: "List marker alignment is inconsistent. Expected {{expected}} characters of indentation, but got {{actual}}." }
|
|
5747
|
+
},
|
|
5748
|
+
create(context) {
|
|
5749
|
+
const sourceCode = context.sourceCode;
|
|
5750
|
+
const alignPositionName = ALIGN_TO_POSITION_NAME[context.options[0]?.align ?? "left"];
|
|
5751
|
+
/**
|
|
5752
|
+
* Get the marker location of a list item
|
|
5753
|
+
*/
|
|
5754
|
+
function getMarkerLocation(node) {
|
|
5755
|
+
const start = sourceCode.getLoc(node).start;
|
|
5756
|
+
const startColumnIndex = start.column - 1;
|
|
5757
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
5758
|
+
return {
|
|
5759
|
+
line: start.line,
|
|
5760
|
+
start: startColumnIndex,
|
|
5761
|
+
end: startColumnIndex + marker.raw.length
|
|
5762
|
+
};
|
|
5763
|
+
}
|
|
5764
|
+
/**
|
|
5765
|
+
* Check if list items have consistent alignment
|
|
5766
|
+
*/
|
|
5767
|
+
function checkListAlignment(listNode) {
|
|
5768
|
+
const items = listNode.children;
|
|
5769
|
+
if (items.length <= 1) return;
|
|
5770
|
+
const referenceMarkerLocation = getMarkerLocation(items[0]);
|
|
5771
|
+
for (const item of items.slice(1)) {
|
|
5772
|
+
const markerLocation = getMarkerLocation(item);
|
|
5773
|
+
const diff = markerLocation[alignPositionName] - referenceMarkerLocation[alignPositionName];
|
|
5774
|
+
if (diff === 0) continue;
|
|
5775
|
+
context.report({
|
|
5776
|
+
node: item,
|
|
5777
|
+
loc: {
|
|
5778
|
+
start: {
|
|
5779
|
+
line: markerLocation.line,
|
|
5780
|
+
column: markerLocation.start + 1
|
|
5781
|
+
},
|
|
5782
|
+
end: {
|
|
5783
|
+
line: markerLocation.line,
|
|
5784
|
+
column: markerLocation.end + 1
|
|
5785
|
+
}
|
|
5786
|
+
},
|
|
5787
|
+
messageId: "incorrectAlignment",
|
|
5788
|
+
data: {
|
|
5789
|
+
expected: String(markerLocation.start - diff),
|
|
5790
|
+
actual: String(markerLocation.start)
|
|
5791
|
+
},
|
|
5792
|
+
fix(fixer) {
|
|
5793
|
+
const lines = getParsedLines(sourceCode);
|
|
5794
|
+
const line = lines.get(markerLocation.line);
|
|
5795
|
+
if (diff < 0) {
|
|
5796
|
+
const addSpaces = " ".repeat(-diff);
|
|
5797
|
+
return fixer.insertTextBeforeRange([line.range[0] + markerLocation.start, line.range[0] + markerLocation.start], addSpaces);
|
|
5798
|
+
}
|
|
5799
|
+
const itemBefore = line.text.slice(0, markerLocation.start - diff);
|
|
5800
|
+
if (itemBefore.includes(" ")) return null;
|
|
5801
|
+
if (lines.get(referenceMarkerLocation.line).text.slice(0, referenceMarkerLocation.start) === itemBefore) {
|
|
5802
|
+
const removeEndIndex = line.range[0] + markerLocation.start;
|
|
5803
|
+
const removeStartIndex = removeEndIndex - diff;
|
|
5804
|
+
return fixer.removeRange([removeStartIndex, removeEndIndex]);
|
|
5805
|
+
}
|
|
5806
|
+
return null;
|
|
5807
|
+
}
|
|
5808
|
+
});
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
return { list: checkListAlignment };
|
|
4714
5812
|
}
|
|
4715
5813
|
});
|
|
4716
5814
|
|
|
@@ -4721,7 +5819,7 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
4721
5819
|
type: "problem",
|
|
4722
5820
|
docs: {
|
|
4723
5821
|
description: "disallow laziness in blockquotes",
|
|
4724
|
-
categories: ["recommended"],
|
|
5822
|
+
categories: ["recommended", "standard"],
|
|
4725
5823
|
listCategory: "Stylistic"
|
|
4726
5824
|
},
|
|
4727
5825
|
fixable: void 0,
|
|
@@ -4821,6 +5919,182 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
4821
5919
|
}
|
|
4822
5920
|
});
|
|
4823
5921
|
|
|
5922
|
+
//#endregion
|
|
5923
|
+
//#region src/rules/no-multi-spaces.ts
|
|
5924
|
+
var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
5925
|
+
meta: {
|
|
5926
|
+
type: "layout",
|
|
5927
|
+
docs: {
|
|
5928
|
+
description: "disallow multiple spaces",
|
|
5929
|
+
categories: ["standard"],
|
|
5930
|
+
listCategory: "Stylistic"
|
|
5931
|
+
},
|
|
5932
|
+
fixable: "whitespace",
|
|
5933
|
+
hasSuggestions: false,
|
|
5934
|
+
schema: [],
|
|
5935
|
+
messages: { multipleSpaces: "Multiple spaces are not allowed." }
|
|
5936
|
+
},
|
|
5937
|
+
create(context) {
|
|
5938
|
+
const sourceCode = context.sourceCode;
|
|
5939
|
+
return {
|
|
5940
|
+
definition: verifyLinkDefinition,
|
|
5941
|
+
footnoteDefinition: verifyFootnoteDefinition,
|
|
5942
|
+
heading: verifyHeading,
|
|
5943
|
+
image: verifyImage,
|
|
5944
|
+
imageReference: verifyImageReference,
|
|
5945
|
+
link: verifyLink,
|
|
5946
|
+
linkReference: verifyLinkReference,
|
|
5947
|
+
listItem: verifyListItem,
|
|
5948
|
+
text: verifyText
|
|
5949
|
+
};
|
|
5950
|
+
/**
|
|
5951
|
+
* Verify a text node.
|
|
5952
|
+
*/
|
|
5953
|
+
function verifyText(node) {
|
|
5954
|
+
verifyTextInNode(node);
|
|
5955
|
+
}
|
|
5956
|
+
/**
|
|
5957
|
+
* Verify a definition node.
|
|
5958
|
+
*/
|
|
5959
|
+
function verifyLinkDefinition(node) {
|
|
5960
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5961
|
+
if (!parsed) return;
|
|
5962
|
+
const nodeRange = sourceCode.getRange(node);
|
|
5963
|
+
verifyTextInRange(node, [nodeRange[0], parsed.destination.range[0]]);
|
|
5964
|
+
verifyTextInRange(node, [parsed.destination.range[1], nodeRange[1]]);
|
|
5965
|
+
}
|
|
5966
|
+
/**
|
|
5967
|
+
* Verify a footnote definition node
|
|
5968
|
+
*/
|
|
5969
|
+
function verifyFootnoteDefinition(node) {
|
|
5970
|
+
verifyTextOutsideChildren(node);
|
|
5971
|
+
}
|
|
5972
|
+
/**
|
|
5973
|
+
* Verify a heading node
|
|
5974
|
+
*/
|
|
5975
|
+
function verifyHeading(node) {
|
|
5976
|
+
verifyTextOutsideChildren(node);
|
|
5977
|
+
}
|
|
5978
|
+
/**
|
|
5979
|
+
* Verify an image node
|
|
5980
|
+
*/
|
|
5981
|
+
function verifyImage(node) {
|
|
5982
|
+
const parsed = parseImage(sourceCode, node);
|
|
5983
|
+
if (!parsed) return;
|
|
5984
|
+
const nodeRange = sourceCode.getRange(node);
|
|
5985
|
+
verifyTextInRange(node, [nodeRange[0], parsed.destination.range[0]]);
|
|
5986
|
+
verifyTextInRange(node, [parsed.destination.range[1], nodeRange[1]]);
|
|
5987
|
+
}
|
|
5988
|
+
/**
|
|
5989
|
+
* Verify an image reference node
|
|
5990
|
+
*/
|
|
5991
|
+
function verifyImageReference(node) {
|
|
5992
|
+
verifyTextInNode(node);
|
|
5993
|
+
}
|
|
5994
|
+
/**
|
|
5995
|
+
* Verify a link node
|
|
5996
|
+
*/
|
|
5997
|
+
function verifyLink(node) {
|
|
5998
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5999
|
+
if (!parsed) return;
|
|
6000
|
+
const nodeRange = sourceCode.getRange(node);
|
|
6001
|
+
if (node.children.length > 0) {
|
|
6002
|
+
const first = node.children[0];
|
|
6003
|
+
const last = node.children[node.children.length - 1];
|
|
6004
|
+
const firstRange = sourceCode.getRange(first);
|
|
6005
|
+
const lastRange = sourceCode.getRange(last);
|
|
6006
|
+
verifyTextInRange(node, [nodeRange[0], firstRange[0]]);
|
|
6007
|
+
verifyTextInRange(node, [lastRange[1], parsed.destination.range[0]]);
|
|
6008
|
+
} else verifyTextInRange(node, [nodeRange[0], parsed.destination.range[0]]);
|
|
6009
|
+
verifyTextInRange(node, [parsed.destination.range[1], nodeRange[1]]);
|
|
6010
|
+
}
|
|
6011
|
+
/**
|
|
6012
|
+
* Verify a link reference node
|
|
6013
|
+
*/
|
|
6014
|
+
function verifyLinkReference(node) {
|
|
6015
|
+
verifyTextOutsideChildren(node);
|
|
6016
|
+
}
|
|
6017
|
+
/**
|
|
6018
|
+
* Verify a list item node
|
|
6019
|
+
*/
|
|
6020
|
+
function verifyListItem(node) {
|
|
6021
|
+
verifyTextOutsideChildren(node);
|
|
6022
|
+
}
|
|
6023
|
+
/**
|
|
6024
|
+
* Verify spaces in a node
|
|
6025
|
+
*/
|
|
6026
|
+
function verifyTextInNode(node) {
|
|
6027
|
+
const nodeRange = sourceCode.getRange(node);
|
|
6028
|
+
verifyTextInRange(node, nodeRange);
|
|
6029
|
+
}
|
|
6030
|
+
/**
|
|
6031
|
+
* Verify spaces in a node excluding children
|
|
6032
|
+
*/
|
|
6033
|
+
function verifyTextOutsideChildren(node) {
|
|
6034
|
+
const nodeRange = sourceCode.getRange(node);
|
|
6035
|
+
if (node.children.length > 0) {
|
|
6036
|
+
const first = node.children[0];
|
|
6037
|
+
const last = node.children[node.children.length - 1];
|
|
6038
|
+
const firstRange = sourceCode.getRange(first);
|
|
6039
|
+
const lastRange = sourceCode.getRange(last);
|
|
6040
|
+
verifyTextInRange(node, [nodeRange[0], firstRange[0]]);
|
|
6041
|
+
verifyTextInRange(node, [lastRange[1], nodeRange[1]]);
|
|
6042
|
+
} else verifyTextInRange(node, nodeRange);
|
|
6043
|
+
}
|
|
6044
|
+
/**
|
|
6045
|
+
* Verify spaces in a node
|
|
6046
|
+
*/
|
|
6047
|
+
function verifyTextInRange(node, textRange) {
|
|
6048
|
+
const nodeRange = sourceCode.getRange(node);
|
|
6049
|
+
const text = sourceCode.text.slice(...textRange);
|
|
6050
|
+
const reSpaces = /\s{2,}|\n/gu;
|
|
6051
|
+
let match;
|
|
6052
|
+
while ((match = reSpaces.exec(text)) !== null) {
|
|
6053
|
+
const spaces = match[0];
|
|
6054
|
+
if (spaces.includes("\n")) {
|
|
6055
|
+
let c = "";
|
|
6056
|
+
while ((c = text[reSpaces.lastIndex]) && (c === ">" || !c.trim())) reSpaces.lastIndex++;
|
|
6057
|
+
continue;
|
|
6058
|
+
}
|
|
6059
|
+
if (spaces.length < 2) continue;
|
|
6060
|
+
const start = textRange[0] + match.index;
|
|
6061
|
+
const end = start + spaces.length;
|
|
6062
|
+
const range = [start, end];
|
|
6063
|
+
if (nodeRange[0] === range[0]) {
|
|
6064
|
+
let isIndentation = true;
|
|
6065
|
+
for (let index = nodeRange[0] - 1; index >= 0; index--) {
|
|
6066
|
+
const c = sourceCode.text[index];
|
|
6067
|
+
if (c === "\n") break;
|
|
6068
|
+
if (isWhitespace(c)) continue;
|
|
6069
|
+
isIndentation = false;
|
|
6070
|
+
break;
|
|
6071
|
+
}
|
|
6072
|
+
if (isIndentation) continue;
|
|
6073
|
+
}
|
|
6074
|
+
if (nodeRange[1] === range[1]) {
|
|
6075
|
+
let isTrailingSpaces = true;
|
|
6076
|
+
for (let index = nodeRange[1]; index < sourceCode.text.length; index++) {
|
|
6077
|
+
const c = sourceCode.text[index];
|
|
6078
|
+
if (c === "\n") break;
|
|
6079
|
+
if (isWhitespace(c)) continue;
|
|
6080
|
+
isTrailingSpaces = false;
|
|
6081
|
+
break;
|
|
6082
|
+
}
|
|
6083
|
+
if (isTrailingSpaces) continue;
|
|
6084
|
+
}
|
|
6085
|
+
context.report({
|
|
6086
|
+
node,
|
|
6087
|
+
messageId: "multipleSpaces",
|
|
6088
|
+
loc: getSourceLocationFromRange(sourceCode, node, range),
|
|
6089
|
+
fix(fixer) {
|
|
6090
|
+
return fixer.replaceTextRange(range, " ");
|
|
6091
|
+
}
|
|
6092
|
+
});
|
|
6093
|
+
}
|
|
6094
|
+
}
|
|
6095
|
+
}
|
|
6096
|
+
});
|
|
6097
|
+
|
|
4824
6098
|
//#endregion
|
|
4825
6099
|
//#region src/rules/no-multiple-empty-lines.ts
|
|
4826
6100
|
var no_multiple_empty_lines_default = createRule("no-multiple-empty-lines", {
|
|
@@ -4828,7 +6102,7 @@ var no_multiple_empty_lines_default = createRule("no-multiple-empty-lines", {
|
|
|
4828
6102
|
type: "layout",
|
|
4829
6103
|
docs: {
|
|
4830
6104
|
description: "disallow multiple empty lines in Markdown files.",
|
|
4831
|
-
categories:
|
|
6105
|
+
categories: ["standard"],
|
|
4832
6106
|
listCategory: "Stylistic"
|
|
4833
6107
|
},
|
|
4834
6108
|
fixable: "whitespace",
|
|
@@ -4987,7 +6261,7 @@ var no_text_backslash_linebreak_default = createRule("no-text-backslash-linebrea
|
|
|
4987
6261
|
type: "layout",
|
|
4988
6262
|
docs: {
|
|
4989
6263
|
description: "disallow text backslash at the end of a line.",
|
|
4990
|
-
categories: ["recommended"],
|
|
6264
|
+
categories: ["recommended", "standard"],
|
|
4991
6265
|
listCategory: "Stylistic"
|
|
4992
6266
|
},
|
|
4993
6267
|
fixable: void 0,
|
|
@@ -5032,7 +6306,7 @@ var no_trailing_spaces_default = createRule("no-trailing-spaces", {
|
|
|
5032
6306
|
type: "layout",
|
|
5033
6307
|
docs: {
|
|
5034
6308
|
description: "disallow trailing whitespace at the end of lines in Markdown files.",
|
|
5035
|
-
categories: [],
|
|
6309
|
+
categories: ["standard"],
|
|
5036
6310
|
listCategory: "Stylistic"
|
|
5037
6311
|
},
|
|
5038
6312
|
fixable: "whitespace",
|
|
@@ -5093,7 +6367,31 @@ var no_trailing_spaces_default = createRule("no-trailing-spaces", {
|
|
|
5093
6367
|
html(node) {
|
|
5094
6368
|
if (htmlComment.test(node.value)) comments.push(node);
|
|
5095
6369
|
},
|
|
5096
|
-
|
|
6370
|
+
break(node) {
|
|
6371
|
+
ignoreNodes.push(node);
|
|
6372
|
+
const range = sourceCode.getRange(node);
|
|
6373
|
+
let trailingSpaceCount = 0;
|
|
6374
|
+
for (let index = range[1] - 1; index >= range[0]; index--) {
|
|
6375
|
+
const c = sourceCode.text[index];
|
|
6376
|
+
if (c === "\n" || c === "\r") {
|
|
6377
|
+
trailingSpaceCount = 0;
|
|
6378
|
+
continue;
|
|
6379
|
+
}
|
|
6380
|
+
if (!isWhitespace(c)) return;
|
|
6381
|
+
trailingSpaceCount++;
|
|
6382
|
+
}
|
|
6383
|
+
const extraSpaces = trailingSpaceCount - 2;
|
|
6384
|
+
if (extraSpaces <= 0) return;
|
|
6385
|
+
context.report({
|
|
6386
|
+
node,
|
|
6387
|
+
loc: getSourceLocationFromRange(sourceCode, node, [range[0], range[0] + extraSpaces]),
|
|
6388
|
+
messageId: "trailingSpace",
|
|
6389
|
+
fix(fixer) {
|
|
6390
|
+
return fixer.removeRange([range[0], range[0] + extraSpaces]);
|
|
6391
|
+
}
|
|
6392
|
+
});
|
|
6393
|
+
},
|
|
6394
|
+
"code, inlineCode, text, yaml, toml, json"(node) {
|
|
5097
6395
|
ignoreNodes.push(node);
|
|
5098
6396
|
},
|
|
5099
6397
|
"root:exit"() {
|
|
@@ -5134,7 +6432,7 @@ var ordered_list_marker_sequence_default = createRule("ordered-list-marker-seque
|
|
|
5134
6432
|
type: "layout",
|
|
5135
6433
|
docs: {
|
|
5136
6434
|
description: "enforce that ordered list markers use sequential numbers",
|
|
5137
|
-
categories: [],
|
|
6435
|
+
categories: ["standard"],
|
|
5138
6436
|
listCategory: "Stylistic"
|
|
5139
6437
|
},
|
|
5140
6438
|
fixable: "code",
|
|
@@ -5250,7 +6548,7 @@ var ordered_list_marker_start_default = createRule("ordered-list-marker-start",
|
|
|
5250
6548
|
type: "layout",
|
|
5251
6549
|
docs: {
|
|
5252
6550
|
description: "enforce that ordered list markers start with 1 or 0",
|
|
5253
|
-
categories: [],
|
|
6551
|
+
categories: ["standard"],
|
|
5254
6552
|
listCategory: "Preference"
|
|
5255
6553
|
},
|
|
5256
6554
|
fixable: "code",
|
|
@@ -5267,8 +6565,7 @@ var ordered_list_marker_start_default = createRule("ordered-list-marker-start",
|
|
|
5267
6565
|
},
|
|
5268
6566
|
create(context) {
|
|
5269
6567
|
const sourceCode = context.sourceCode;
|
|
5270
|
-
const
|
|
5271
|
-
const expectedStart = option.start ?? 1;
|
|
6568
|
+
const expectedStart = (context.options[0] || {}).start ?? 1;
|
|
5272
6569
|
let scope = {
|
|
5273
6570
|
node: sourceCode.ast,
|
|
5274
6571
|
upper: null,
|
|
@@ -5376,7 +6673,7 @@ var ordered_list_marker_style_default = createRule("ordered-list-marker-style",
|
|
|
5376
6673
|
type: "layout",
|
|
5377
6674
|
docs: {
|
|
5378
6675
|
description: "enforce consistent ordered list marker style",
|
|
5379
|
-
categories: [],
|
|
6676
|
+
categories: ["standard"],
|
|
5380
6677
|
listCategory: "Stylistic"
|
|
5381
6678
|
},
|
|
5382
6679
|
fixable: "code",
|
|
@@ -5457,8 +6754,7 @@ var ordered_list_marker_style_default = createRule("ordered-list-marker-style",
|
|
|
5457
6754
|
for (let index = nodeIndex + 1; index < containerStack.node.children.length; index++) {
|
|
5458
6755
|
const nextNode = containerStack.node.children[index];
|
|
5459
6756
|
if (nextNode.type !== "list") break;
|
|
5460
|
-
|
|
5461
|
-
if (nextMarker.kind !== prevMarker) break;
|
|
6757
|
+
if (getListItemMarker(sourceCode, nextNode).kind !== prevMarker) break;
|
|
5462
6758
|
const expectedNextMarker = prevMarker === prefer ? getOtherMarkerKind(prefer) : prefer;
|
|
5463
6759
|
yield* fixMarkers(nextNode, expectedNextMarker);
|
|
5464
6760
|
prevMarker = expectedNextMarker;
|
|
@@ -5567,7 +6863,7 @@ const SELECTOR_SCHEMA = { oneOf: [...BLOCK_TYPE_SCHEMAS, {
|
|
|
5567
6863
|
required: ["type"],
|
|
5568
6864
|
additionalProperties: false
|
|
5569
6865
|
}] };
|
|
5570
|
-
const
|
|
6866
|
+
const BLOCK_TYPE_MAP = {
|
|
5571
6867
|
heading: "heading",
|
|
5572
6868
|
paragraph: "paragraph",
|
|
5573
6869
|
list: "list",
|
|
@@ -5582,7 +6878,6 @@ const BLOCK_TYPE_MAP0 = {
|
|
|
5582
6878
|
toml: "frontmatter",
|
|
5583
6879
|
yaml: "frontmatter"
|
|
5584
6880
|
};
|
|
5585
|
-
const BLOCK_TYPE_MAP = BLOCK_TYPE_MAP0;
|
|
5586
6881
|
/**
|
|
5587
6882
|
* Get the block type of a node
|
|
5588
6883
|
*/
|
|
@@ -5597,7 +6892,7 @@ var padding_line_between_blocks_default = createRule("padding-line-between-block
|
|
|
5597
6892
|
type: "layout",
|
|
5598
6893
|
docs: {
|
|
5599
6894
|
description: "require or disallow padding lines between blocks",
|
|
5600
|
-
categories: ["
|
|
6895
|
+
categories: ["standard"],
|
|
5601
6896
|
listCategory: "Stylistic"
|
|
5602
6897
|
},
|
|
5603
6898
|
fixable: "whitespace",
|
|
@@ -5633,7 +6928,31 @@ var padding_line_between_blocks_default = createRule("padding-line-between-block
|
|
|
5633
6928
|
},
|
|
5634
6929
|
create(context) {
|
|
5635
6930
|
const sourceCode = context.sourceCode;
|
|
5636
|
-
const options = [...context.options
|
|
6931
|
+
const options = [...context.options?.length ? context.options : [
|
|
6932
|
+
{
|
|
6933
|
+
prev: "*",
|
|
6934
|
+
next: "*",
|
|
6935
|
+
blankLine: "always"
|
|
6936
|
+
},
|
|
6937
|
+
{
|
|
6938
|
+
prev: "link-definition",
|
|
6939
|
+
next: "link-definition",
|
|
6940
|
+
blankLine: "never"
|
|
6941
|
+
},
|
|
6942
|
+
{
|
|
6943
|
+
prev: "footnote-definition",
|
|
6944
|
+
next: "footnote-definition",
|
|
6945
|
+
blankLine: "never"
|
|
6946
|
+
},
|
|
6947
|
+
{
|
|
6948
|
+
prev: "paragraph",
|
|
6949
|
+
next: {
|
|
6950
|
+
type: "list",
|
|
6951
|
+
in: "list"
|
|
6952
|
+
},
|
|
6953
|
+
blankLine: "never"
|
|
6954
|
+
}
|
|
6955
|
+
]].reverse();
|
|
5637
6956
|
const containerStack = [];
|
|
5638
6957
|
/**
|
|
5639
6958
|
* Check if the actual type matches the expected type pattern
|
|
@@ -5694,8 +7013,7 @@ var padding_line_between_blocks_default = createRule("padding-line-between-block
|
|
|
5694
7013
|
if (expected === null) continue;
|
|
5695
7014
|
const prevLoc = sourceCode.getLoc(prevBlock);
|
|
5696
7015
|
const nextLoc = sourceCode.getLoc(nextBlock);
|
|
5697
|
-
const
|
|
5698
|
-
const hasBlankLine = actualBlankLine > 0;
|
|
7016
|
+
const hasBlankLine = nextLoc.start.line - prevLoc.end.line - 1 > 0;
|
|
5699
7017
|
let messageId = "expectedBlankLine";
|
|
5700
7018
|
if (expected.blankLine === "always") {
|
|
5701
7019
|
if (hasBlankLine) continue;
|
|
@@ -5742,8 +7060,7 @@ var padding_line_between_blocks_default = createRule("padding-line-between-block
|
|
|
5742
7060
|
const blockquoteLoc = sourceCode.getLoc(blockquote);
|
|
5743
7061
|
text += getBlockquoteLevelFromLine(sourceCode, blockquoteLoc.start.line).prefix.trimEnd();
|
|
5744
7062
|
}
|
|
5745
|
-
const
|
|
5746
|
-
const startNext = nextRange[0] - nextLoc.start.column;
|
|
7063
|
+
const startNext = sourceCode.getRange(nextBlock)[0] - nextLoc.start.column;
|
|
5747
7064
|
return fixer.insertTextBeforeRange([startNext, startNext], text);
|
|
5748
7065
|
}
|
|
5749
7066
|
const lines = getParsedLines(sourceCode);
|
|
@@ -5773,7 +7090,7 @@ var prefer_autolinks_default = createRule("prefer-autolinks", {
|
|
|
5773
7090
|
type: "layout",
|
|
5774
7091
|
docs: {
|
|
5775
7092
|
description: "enforce the use of autolinks for URLs",
|
|
5776
|
-
categories: ["recommended"],
|
|
7093
|
+
categories: ["recommended", "standard"],
|
|
5777
7094
|
listCategory: "Stylistic"
|
|
5778
7095
|
},
|
|
5779
7096
|
fixable: "code",
|
|
@@ -5811,7 +7128,7 @@ var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks",
|
|
|
5811
7128
|
type: "layout",
|
|
5812
7129
|
docs: {
|
|
5813
7130
|
description: "enforce the use of fenced code blocks over indented code blocks",
|
|
5814
|
-
categories: ["recommended"],
|
|
7131
|
+
categories: ["recommended", "standard"],
|
|
5815
7132
|
listCategory: "Stylistic"
|
|
5816
7133
|
},
|
|
5817
7134
|
fixable: "code",
|
|
@@ -5871,8 +7188,7 @@ var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks",
|
|
|
5871
7188
|
const firstLine = lines.get(loc.start.line);
|
|
5872
7189
|
const codeBlockFirstLine = normalizePrefix(node.value.split(/\r?\n/u)[0]);
|
|
5873
7190
|
const startColumnOffset = loc.start.column - 1;
|
|
5874
|
-
|
|
5875
|
-
return normalizedFirstLine.startsWith(codeBlockFirstLine);
|
|
7191
|
+
return normalizePrefix(firstLine.text.slice(startColumnOffset)).startsWith(codeBlockFirstLine);
|
|
5876
7192
|
}
|
|
5877
7193
|
}
|
|
5878
7194
|
});
|
|
@@ -6061,8 +7377,7 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
|
|
|
6061
7377
|
},
|
|
6062
7378
|
create(context) {
|
|
6063
7379
|
const sourceCode = context.sourceCode;
|
|
6064
|
-
const
|
|
6065
|
-
const minLinks = options.minLinks ?? 2;
|
|
7380
|
+
const minLinks = (context.options[0] || {}).minLinks ?? 2;
|
|
6066
7381
|
const definitions = [];
|
|
6067
7382
|
const links = [];
|
|
6068
7383
|
const references = [];
|
|
@@ -6165,8 +7480,7 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
|
|
|
6165
7480
|
const range = sourceCode.getRange(link);
|
|
6166
7481
|
if (link.type === "link") {
|
|
6167
7482
|
const bracketsRange$1 = getLinkBracketsRange(link);
|
|
6168
|
-
const
|
|
6169
|
-
const linkLabelText$1 = linkBracketsText$1.slice(1, -1).trim();
|
|
7483
|
+
const linkLabelText$1 = sourceCode.text.slice(...bracketsRange$1).slice(1, -1).trim();
|
|
6170
7484
|
const urlStartIndex$1 = sourceCode.text.indexOf("(", bracketsRange$1[1]);
|
|
6171
7485
|
return {
|
|
6172
7486
|
label: linkLabelText$1,
|
|
@@ -6175,8 +7489,7 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
|
|
|
6175
7489
|
};
|
|
6176
7490
|
}
|
|
6177
7491
|
const bracketsRange = getImageBracketsRange(link);
|
|
6178
|
-
const
|
|
6179
|
-
const linkLabelText = linkBracketsText.slice(1, -1).trim();
|
|
7492
|
+
const linkLabelText = sourceCode.text.slice(...bracketsRange).slice(1, -1).trim();
|
|
6180
7493
|
const urlStartIndex = sourceCode.text.indexOf("(", bracketsRange[1]);
|
|
6181
7494
|
return {
|
|
6182
7495
|
label: linkLabelText,
|
|
@@ -6324,7 +7637,7 @@ var setext_heading_underline_length_default = createRule("setext-heading-underli
|
|
|
6324
7637
|
type: "layout",
|
|
6325
7638
|
docs: {
|
|
6326
7639
|
description: "enforce setext heading underline length",
|
|
6327
|
-
categories: [],
|
|
7640
|
+
categories: ["standard"],
|
|
6328
7641
|
listCategory: "Stylistic"
|
|
6329
7642
|
},
|
|
6330
7643
|
fixable: "whitespace",
|
|
@@ -6562,7 +7875,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6562
7875
|
type: "layout",
|
|
6563
7876
|
docs: {
|
|
6564
7877
|
description: "enforce a specific order for link definitions and footnote definitions",
|
|
6565
|
-
categories: [],
|
|
7878
|
+
categories: ["standard"],
|
|
6566
7879
|
listCategory: "Stylistic"
|
|
6567
7880
|
},
|
|
6568
7881
|
fixable: "code",
|
|
@@ -6650,8 +7963,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6650
7963
|
if (moveNode.type === "definition" && index > 0) {
|
|
6651
7964
|
if (movedNodes[index - 1].type === "footnoteDefinition") {
|
|
6652
7965
|
const footnoteLoc = sourceCode.getLoc(definitions[index - 1]);
|
|
6653
|
-
|
|
6654
|
-
if (linkLoc.start.line - footnoteLoc.end.line <= 1) text = `\n${text}`;
|
|
7966
|
+
if (sourceCode.getLoc(definitions[index]).start.line - footnoteLoc.end.line <= 1) text = `\n${text}`;
|
|
6655
7967
|
}
|
|
6656
7968
|
}
|
|
6657
7969
|
return fixer.replaceText(definitions[index], text);
|
|
@@ -6678,10 +7990,9 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6678
7990
|
return {
|
|
6679
7991
|
"*"(node) {
|
|
6680
7992
|
const last = group.at(-1);
|
|
6681
|
-
if (last && (node.type !== "definition" && node.type !== "footnoteDefinition" ||
|
|
7993
|
+
if (last && (node.type !== "definition" && node.type !== "footnoteDefinition" || getParent(sourceCode, node) !== getParent(sourceCode, last))) {
|
|
6682
7994
|
const range = sourceCode.getRange(node);
|
|
6683
|
-
|
|
6684
|
-
if (lastDefinitionRange[1] <= range[0]) {
|
|
7995
|
+
if (sourceCode.getRange(last)[1] <= range[0]) {
|
|
6685
7996
|
verify(group);
|
|
6686
7997
|
group.length = 0;
|
|
6687
7998
|
}
|
|
@@ -6694,14 +8005,13 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6694
8005
|
};
|
|
6695
8006
|
/** Parse options */
|
|
6696
8007
|
function parseOption(userOption) {
|
|
6697
|
-
const
|
|
8008
|
+
const compiled = (userOption?.order ?? [{
|
|
6698
8009
|
match: String.raw`!/^\[\\^/u`,
|
|
6699
8010
|
sort: "alphabetical"
|
|
6700
8011
|
}, {
|
|
6701
8012
|
match: String.raw`/./u`,
|
|
6702
8013
|
sort: "alphabetical"
|
|
6703
|
-
}];
|
|
6704
|
-
const compiled = order.map(compileOption);
|
|
8014
|
+
}]).map(compileOption);
|
|
6705
8015
|
return {
|
|
6706
8016
|
ignore: (node) => {
|
|
6707
8017
|
return !compiled.some((c) => c.match(node));
|
|
@@ -6743,20 +8053,14 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6743
8053
|
}
|
|
6744
8054
|
/** Compile order option without cache */
|
|
6745
8055
|
function compileOptionWithoutCache(orderOption) {
|
|
6746
|
-
if (typeof orderOption === "string") {
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
const match$1 = compileMatcher(orderOption);
|
|
6755
|
-
return {
|
|
6756
|
-
match: match$1,
|
|
6757
|
-
sort: "ignore"
|
|
6758
|
-
};
|
|
6759
|
-
}
|
|
8056
|
+
if (typeof orderOption === "string") return {
|
|
8057
|
+
match: compileMatcher([orderOption]),
|
|
8058
|
+
sort: "ignore"
|
|
8059
|
+
};
|
|
8060
|
+
if (Array.isArray(orderOption)) return {
|
|
8061
|
+
match: compileMatcher(orderOption),
|
|
8062
|
+
sort: "ignore"
|
|
8063
|
+
};
|
|
6760
8064
|
const { match } = compileOptionWithoutCache(orderOption.match);
|
|
6761
8065
|
return {
|
|
6762
8066
|
match,
|
|
@@ -6765,7 +8069,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6765
8069
|
}
|
|
6766
8070
|
/** Compile matcher */
|
|
6767
8071
|
function compileMatcher(pattern) {
|
|
6768
|
-
const rules$
|
|
8072
|
+
const rules$4 = [];
|
|
6769
8073
|
for (const p of pattern) {
|
|
6770
8074
|
let negative, patternStr;
|
|
6771
8075
|
if (p.startsWith("!")) {
|
|
@@ -6776,11 +8080,11 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6776
8080
|
patternStr = p;
|
|
6777
8081
|
}
|
|
6778
8082
|
const regex = toRegExp(patternStr);
|
|
6779
|
-
if (isRegExp(patternStr)) rules$
|
|
8083
|
+
if (isRegExp(patternStr)) rules$4.push({
|
|
6780
8084
|
negative,
|
|
6781
8085
|
match: (node) => regex.test(getDefinitionText(node))
|
|
6782
8086
|
});
|
|
6783
|
-
else rules$
|
|
8087
|
+
else rules$4.push({
|
|
6784
8088
|
negative,
|
|
6785
8089
|
match: (node) => {
|
|
6786
8090
|
if (node.label === patternStr || node.identifier === patternStr) return true;
|
|
@@ -6788,8 +8092,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6788
8092
|
if (node.url === patternStr) return true;
|
|
6789
8093
|
if (URL.canParse(patternStr) && URL.canParse(node.url)) {
|
|
6790
8094
|
const normalizedPattern = normalizedURL(patternStr);
|
|
6791
|
-
|
|
6792
|
-
if (normalizedUrl.startsWith(normalizedPattern)) return true;
|
|
8095
|
+
if (normalizedURL(node.url).startsWith(normalizedPattern)) return true;
|
|
6793
8096
|
}
|
|
6794
8097
|
}
|
|
6795
8098
|
return regex.test(getDefinitionText(node));
|
|
@@ -6797,8 +8100,8 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
6797
8100
|
});
|
|
6798
8101
|
}
|
|
6799
8102
|
return (node) => {
|
|
6800
|
-
let result = Boolean(rules$
|
|
6801
|
-
for (const { negative, match } of rules$
|
|
8103
|
+
let result = Boolean(rules$4[0]?.negative);
|
|
8104
|
+
for (const { negative, match } of rules$4) {
|
|
6802
8105
|
if (result === !negative) continue;
|
|
6803
8106
|
if (match(node)) result = !negative;
|
|
6804
8107
|
}
|
|
@@ -6845,7 +8148,7 @@ var strikethrough_delimiters_style_default = createRule("strikethrough-delimiter
|
|
|
6845
8148
|
type: "layout",
|
|
6846
8149
|
docs: {
|
|
6847
8150
|
description: "enforce a consistent delimiter style for strikethrough",
|
|
6848
|
-
categories: [],
|
|
8151
|
+
categories: ["standard"],
|
|
6849
8152
|
listCategory: "Stylistic"
|
|
6850
8153
|
},
|
|
6851
8154
|
fixable: "code",
|
|
@@ -6859,8 +8162,7 @@ var strikethrough_delimiters_style_default = createRule("strikethrough-delimiter
|
|
|
6859
8162
|
},
|
|
6860
8163
|
create(context) {
|
|
6861
8164
|
const sourceCode = context.sourceCode;
|
|
6862
|
-
const
|
|
6863
|
-
const delimiter = option.delimiter ?? "~~";
|
|
8165
|
+
const delimiter = (context.options[0] ?? {}).delimiter ?? "~~";
|
|
6864
8166
|
return { delete(node) {
|
|
6865
8167
|
const range = sourceCode.getRange(node);
|
|
6866
8168
|
const actualDelimiter = ["~~", "~"].find((d) => sourceCode.text.startsWith(d, range[0]) && sourceCode.text.endsWith(d, range[1]));
|
|
@@ -7021,7 +8323,7 @@ var thematic_break_character_style_default = createRule("thematic-break-characte
|
|
|
7021
8323
|
type: "layout",
|
|
7022
8324
|
docs: {
|
|
7023
8325
|
description: "enforce consistent character style for thematic breaks (horizontal rules) in Markdown.",
|
|
7024
|
-
categories: [],
|
|
8326
|
+
categories: ["standard"],
|
|
7025
8327
|
listCategory: "Stylistic"
|
|
7026
8328
|
},
|
|
7027
8329
|
fixable: "code",
|
|
@@ -7041,8 +8343,7 @@ var thematic_break_character_style_default = createRule("thematic-break-characte
|
|
|
7041
8343
|
messages: { unexpected: "Thematic break should use '{{expected}}' but found '{{actual}}'." }
|
|
7042
8344
|
},
|
|
7043
8345
|
create(context) {
|
|
7044
|
-
const
|
|
7045
|
-
const style = option?.style || "-";
|
|
8346
|
+
const style = context.options[0]?.style || "-";
|
|
7046
8347
|
return { thematicBreak(node) {
|
|
7047
8348
|
const marker = getThematicBreakMarker(context.sourceCode, node);
|
|
7048
8349
|
if (marker.kind !== style) context.report({
|
|
@@ -7054,8 +8355,7 @@ var thematic_break_character_style_default = createRule("thematic-break-characte
|
|
|
7054
8355
|
},
|
|
7055
8356
|
fix(fixer) {
|
|
7056
8357
|
const range = context.sourceCode.getRange(node);
|
|
7057
|
-
const
|
|
7058
|
-
const rep = text.replaceAll(marker.kind, style);
|
|
8358
|
+
const rep = context.sourceCode.getText(node).replaceAll(marker.kind, style);
|
|
7059
8359
|
return fixer.replaceTextRange(range, rep);
|
|
7060
8360
|
}
|
|
7061
8361
|
});
|
|
@@ -7102,7 +8402,7 @@ var thematic_break_length_default = createRule("thematic-break-length", {
|
|
|
7102
8402
|
type: "layout",
|
|
7103
8403
|
docs: {
|
|
7104
8404
|
description: "enforce consistent length for thematic breaks (horizontal rules) in Markdown.",
|
|
7105
|
-
categories: [],
|
|
8405
|
+
categories: ["standard"],
|
|
7106
8406
|
listCategory: "Stylistic"
|
|
7107
8407
|
},
|
|
7108
8408
|
fixable: "code",
|
|
@@ -7118,8 +8418,7 @@ var thematic_break_length_default = createRule("thematic-break-length", {
|
|
|
7118
8418
|
messages: { unexpected: "Thematic break should be {{expected}} characters, but found {{actual}}." }
|
|
7119
8419
|
},
|
|
7120
8420
|
create(context) {
|
|
7121
|
-
const
|
|
7122
|
-
const expectedLength = option.length ?? 3;
|
|
8421
|
+
const expectedLength = (context.options[0] || {}).length ?? 3;
|
|
7123
8422
|
const sourceCode = context.sourceCode;
|
|
7124
8423
|
return { thematicBreak(node) {
|
|
7125
8424
|
const marker = getThematicBreakMarker(sourceCode, node);
|
|
@@ -7169,7 +8468,7 @@ var thematic_break_sequence_pattern_default = createRule("thematic-break-sequenc
|
|
|
7169
8468
|
type: "layout",
|
|
7170
8469
|
docs: {
|
|
7171
8470
|
description: "enforce consistent repeating patterns for thematic breaks (horizontal rules) in Markdown.",
|
|
7172
|
-
categories: [],
|
|
8471
|
+
categories: ["standard"],
|
|
7173
8472
|
listCategory: "Stylistic"
|
|
7174
8473
|
},
|
|
7175
8474
|
fixable: "code",
|
|
@@ -7199,8 +8498,7 @@ var thematic_break_sequence_pattern_default = createRule("thematic-break-sequenc
|
|
|
7199
8498
|
messages: { inconsistentPattern: "Thematic break does not match the preferred repeating pattern '{{pattern}}'." }
|
|
7200
8499
|
},
|
|
7201
8500
|
create(context) {
|
|
7202
|
-
const
|
|
7203
|
-
const pattern = option.pattern ?? "-";
|
|
8501
|
+
const pattern = (context.options[0] || {}).pattern ?? "-";
|
|
7204
8502
|
const sourceCode = context.sourceCode;
|
|
7205
8503
|
const patterns = {
|
|
7206
8504
|
"-": pattern.replaceAll(/[*_]/gu, "-"),
|
|
@@ -7242,8 +8540,13 @@ const rules$1 = [
|
|
|
7242
8540
|
heading_casing_default,
|
|
7243
8541
|
level1_heading_style_default,
|
|
7244
8542
|
level2_heading_style_default,
|
|
8543
|
+
link_bracket_newline_default,
|
|
8544
|
+
link_bracket_spacing_default,
|
|
8545
|
+
link_destination_style_default,
|
|
8546
|
+
link_title_style_default,
|
|
7245
8547
|
list_marker_alignment_default,
|
|
7246
8548
|
no_laziness_blockquotes_default,
|
|
8549
|
+
no_multi_spaces_default,
|
|
7247
8550
|
no_multiple_empty_lines_default,
|
|
7248
8551
|
no_text_backslash_linebreak_default,
|
|
7249
8552
|
no_trailing_spaces_default,
|
|
@@ -7269,6 +8572,37 @@ const rules$1 = [
|
|
|
7269
8572
|
//#region src/configs/recommended.ts
|
|
7270
8573
|
var recommended_exports = {};
|
|
7271
8574
|
__export(recommended_exports, {
|
|
8575
|
+
files: () => files$1,
|
|
8576
|
+
language: () => language$1,
|
|
8577
|
+
languageOptions: () => languageOptions$1,
|
|
8578
|
+
name: () => name$2,
|
|
8579
|
+
plugins: () => plugins$1,
|
|
8580
|
+
rules: () => rules$3
|
|
8581
|
+
});
|
|
8582
|
+
const name$2 = "markdown-preferences/recommended";
|
|
8583
|
+
const files$1 = ["*.md", "**/*.md"];
|
|
8584
|
+
const language$1 = "markdown/gfm";
|
|
8585
|
+
const languageOptions$1 = { frontmatter: "yaml" };
|
|
8586
|
+
const plugins$1 = {
|
|
8587
|
+
markdown,
|
|
8588
|
+
get "markdown-preferences"() {
|
|
8589
|
+
return src_default;
|
|
8590
|
+
}
|
|
8591
|
+
};
|
|
8592
|
+
const rules$3 = {
|
|
8593
|
+
"markdown-preferences/blockquote-marker-alignment": "error",
|
|
8594
|
+
"markdown-preferences/hard-linebreak-style": "error",
|
|
8595
|
+
"markdown-preferences/list-marker-alignment": "error",
|
|
8596
|
+
"markdown-preferences/no-laziness-blockquotes": "error",
|
|
8597
|
+
"markdown-preferences/no-text-backslash-linebreak": "error",
|
|
8598
|
+
"markdown-preferences/prefer-autolinks": "error",
|
|
8599
|
+
"markdown-preferences/prefer-fenced-code-blocks": "error"
|
|
8600
|
+
};
|
|
8601
|
+
|
|
8602
|
+
//#endregion
|
|
8603
|
+
//#region src/configs/standard.ts
|
|
8604
|
+
var standard_exports = {};
|
|
8605
|
+
__export(standard_exports, {
|
|
7272
8606
|
files: () => files,
|
|
7273
8607
|
language: () => language,
|
|
7274
8608
|
languageOptions: () => languageOptions,
|
|
@@ -7287,14 +8621,38 @@ const plugins = {
|
|
|
7287
8621
|
}
|
|
7288
8622
|
};
|
|
7289
8623
|
const rules$2 = {
|
|
8624
|
+
"markdown-preferences/atx-heading-closing-sequence-length": "error",
|
|
8625
|
+
"markdown-preferences/atx-heading-closing-sequence": "error",
|
|
7290
8626
|
"markdown-preferences/blockquote-marker-alignment": "error",
|
|
8627
|
+
"markdown-preferences/bullet-list-marker-style": "error",
|
|
8628
|
+
"markdown-preferences/code-fence-length": "error",
|
|
8629
|
+
"markdown-preferences/code-fence-style": "error",
|
|
8630
|
+
"markdown-preferences/emphasis-delimiters-style": "error",
|
|
7291
8631
|
"markdown-preferences/hard-linebreak-style": "error",
|
|
8632
|
+
"markdown-preferences/level1-heading-style": "error",
|
|
8633
|
+
"markdown-preferences/level2-heading-style": "error",
|
|
8634
|
+
"markdown-preferences/link-bracket-newline": "error",
|
|
8635
|
+
"markdown-preferences/link-bracket-spacing": "error",
|
|
8636
|
+
"markdown-preferences/link-destination-style": "error",
|
|
8637
|
+
"markdown-preferences/link-title-style": "error",
|
|
7292
8638
|
"markdown-preferences/list-marker-alignment": "error",
|
|
7293
8639
|
"markdown-preferences/no-laziness-blockquotes": "error",
|
|
8640
|
+
"markdown-preferences/no-multi-spaces": "error",
|
|
8641
|
+
"markdown-preferences/no-multiple-empty-lines": "error",
|
|
7294
8642
|
"markdown-preferences/no-text-backslash-linebreak": "error",
|
|
8643
|
+
"markdown-preferences/no-trailing-spaces": "error",
|
|
8644
|
+
"markdown-preferences/ordered-list-marker-sequence": "error",
|
|
8645
|
+
"markdown-preferences/ordered-list-marker-start": "error",
|
|
8646
|
+
"markdown-preferences/ordered-list-marker-style": "error",
|
|
7295
8647
|
"markdown-preferences/padding-line-between-blocks": "error",
|
|
7296
8648
|
"markdown-preferences/prefer-autolinks": "error",
|
|
7297
|
-
"markdown-preferences/prefer-fenced-code-blocks": "error"
|
|
8649
|
+
"markdown-preferences/prefer-fenced-code-blocks": "error",
|
|
8650
|
+
"markdown-preferences/setext-heading-underline-length": "error",
|
|
8651
|
+
"markdown-preferences/sort-definitions": "error",
|
|
8652
|
+
"markdown-preferences/strikethrough-delimiters-style": "error",
|
|
8653
|
+
"markdown-preferences/thematic-break-character-style": "error",
|
|
8654
|
+
"markdown-preferences/thematic-break-length": "error",
|
|
8655
|
+
"markdown-preferences/thematic-break-sequence-pattern": "error"
|
|
7298
8656
|
};
|
|
7299
8657
|
|
|
7300
8658
|
//#endregion
|
|
@@ -7305,11 +8663,14 @@ __export(meta_exports, {
|
|
|
7305
8663
|
version: () => version
|
|
7306
8664
|
});
|
|
7307
8665
|
const name = "eslint-plugin-markdown-preferences";
|
|
7308
|
-
const version = "0.
|
|
8666
|
+
const version = "0.22.0";
|
|
7309
8667
|
|
|
7310
8668
|
//#endregion
|
|
7311
8669
|
//#region src/index.ts
|
|
7312
|
-
const configs = {
|
|
8670
|
+
const configs = {
|
|
8671
|
+
recommended: recommended_exports,
|
|
8672
|
+
standard: standard_exports
|
|
8673
|
+
};
|
|
7313
8674
|
const rules = rules$1.reduce((obj, r) => {
|
|
7314
8675
|
obj[r.meta.docs.ruleName] = r;
|
|
7315
8676
|
return obj;
|