eslint-plugin-markdown-preferences 0.22.0 → 0.24.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 +3 -0
- package/lib/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
- package/lib/index.d.ts +30 -1
- package/lib/index.js +1997 -655
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __export } from "./chunk-
|
|
1
|
+
import { __export } from "./chunk-CTAAG5j7.js";
|
|
2
2
|
import stringWidth from "string-width";
|
|
3
3
|
import emojiRegex from "emoji-regex-xs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -186,47 +186,48 @@ function parseATXHeading(sourceCode, node) {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
};
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
loc: {
|
|
193
|
-
start: openingSequence.loc.end,
|
|
194
|
-
end: {
|
|
195
|
-
line: openingSequence.loc.end.line,
|
|
196
|
-
column: openingSequence.loc.end.column + parsedOpening.rawAfter.length
|
|
197
|
-
}
|
|
198
|
-
}
|
|
189
|
+
const contentLocStart = {
|
|
190
|
+
line: openingSequence.loc.end.line,
|
|
191
|
+
column: openingSequence.loc.end.column + parsedOpening.after.length
|
|
199
192
|
};
|
|
200
193
|
const parsedClosing = parseATXHeadingClosingSequenceFromText(text);
|
|
201
194
|
if (parsedClosing == null) {
|
|
202
|
-
const textAfterOpening = sourceCode.text.slice(
|
|
195
|
+
const textAfterOpening = sourceCode.text.slice(openingSequence.range[1] + parsedOpening.after.length, range[1]);
|
|
203
196
|
const contentText$1 = textAfterOpening.trimEnd();
|
|
197
|
+
const contentRange$1 = [openingSequence.range[1] + parsedOpening.after.length, openingSequence.range[1] + parsedOpening.after.length + contentText$1.length];
|
|
198
|
+
const contentLocEnd = {
|
|
199
|
+
line: loc.end.line,
|
|
200
|
+
column: loc.end.column - (textAfterOpening.length - contentText$1.length)
|
|
201
|
+
};
|
|
202
|
+
const after = contentText$1 === textAfterOpening ? null : {
|
|
203
|
+
text: textAfterOpening.slice(contentText$1.length),
|
|
204
|
+
range: [contentRange$1[1], range[1]],
|
|
205
|
+
loc: {
|
|
206
|
+
start: contentLocEnd,
|
|
207
|
+
end: loc.end
|
|
208
|
+
}
|
|
209
|
+
};
|
|
204
210
|
return {
|
|
205
|
-
openingSequence
|
|
206
|
-
...openingSequence,
|
|
207
|
-
raws: { spaceAfter: spaceAfterOpening }
|
|
208
|
-
},
|
|
211
|
+
openingSequence,
|
|
209
212
|
content: {
|
|
210
213
|
text: contentText$1,
|
|
211
|
-
range:
|
|
214
|
+
range: contentRange$1,
|
|
212
215
|
loc: {
|
|
213
|
-
start:
|
|
214
|
-
end:
|
|
215
|
-
line: loc.end.line,
|
|
216
|
-
column: loc.end.column - (textAfterOpening.length - contentText$1.length)
|
|
217
|
-
}
|
|
216
|
+
start: contentLocStart,
|
|
217
|
+
end: contentLocEnd
|
|
218
218
|
}
|
|
219
219
|
},
|
|
220
|
-
closingSequence: null
|
|
220
|
+
closingSequence: null,
|
|
221
|
+
after
|
|
221
222
|
};
|
|
222
223
|
}
|
|
223
224
|
const spaceAfterClosing = {
|
|
224
|
-
text: parsedClosing.
|
|
225
|
-
range: [range[1] - parsedClosing.
|
|
225
|
+
text: parsedClosing.after,
|
|
226
|
+
range: [range[1] - parsedClosing.after.length, range[1]],
|
|
226
227
|
loc: {
|
|
227
228
|
start: {
|
|
228
229
|
line: loc.end.line,
|
|
229
|
-
column: loc.end.column - parsedClosing.
|
|
230
|
+
column: loc.end.column - parsedClosing.after.length
|
|
230
231
|
},
|
|
231
232
|
end: loc.end
|
|
232
233
|
}
|
|
@@ -242,38 +243,23 @@ function parseATXHeading(sourceCode, node) {
|
|
|
242
243
|
end: spaceAfterClosing.loc.start
|
|
243
244
|
}
|
|
244
245
|
};
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
range: [closingSequence.range[0] - parsedClosing.rawBefore.length, closingSequence.range[0]],
|
|
248
|
-
loc: {
|
|
249
|
-
start: {
|
|
250
|
-
line: closingSequence.loc.start.line,
|
|
251
|
-
column: closingSequence.loc.start.column - parsedClosing.rawBefore.length
|
|
252
|
-
},
|
|
253
|
-
end: closingSequence.loc.start
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
const contentText = sourceCode.text.slice(spaceAfterOpening.range[1], spaceBeforeClosing.range[0]);
|
|
246
|
+
const contentRange = [openingSequence.range[1] + parsedOpening.after.length, closingSequence.range[0] - parsedClosing.before.length];
|
|
247
|
+
const contentText = sourceCode.text.slice(...contentRange);
|
|
257
248
|
return {
|
|
258
|
-
openingSequence
|
|
259
|
-
...openingSequence,
|
|
260
|
-
raws: { spaceAfter: spaceAfterOpening }
|
|
261
|
-
},
|
|
249
|
+
openingSequence,
|
|
262
250
|
content: {
|
|
263
251
|
text: contentText,
|
|
264
|
-
range:
|
|
252
|
+
range: contentRange,
|
|
265
253
|
loc: {
|
|
266
|
-
start:
|
|
267
|
-
end:
|
|
254
|
+
start: contentLocStart,
|
|
255
|
+
end: {
|
|
256
|
+
line: closingSequence.loc.start.line,
|
|
257
|
+
column: closingSequence.loc.start.column - parsedClosing.before.length
|
|
258
|
+
}
|
|
268
259
|
}
|
|
269
260
|
},
|
|
270
|
-
closingSequence
|
|
271
|
-
|
|
272
|
-
raws: {
|
|
273
|
-
spaceBefore: spaceBeforeClosing,
|
|
274
|
-
spaceAfter: spaceAfterClosing
|
|
275
|
-
}
|
|
276
|
-
}
|
|
261
|
+
closingSequence,
|
|
262
|
+
after: spaceAfterClosing.range[0] < spaceAfterClosing.range[1] ? spaceAfterClosing : null
|
|
277
263
|
};
|
|
278
264
|
}
|
|
279
265
|
/**
|
|
@@ -287,7 +273,7 @@ function parseATXHeadingOpeningSequenceFromText(text) {
|
|
|
287
273
|
if (afterOffset === openingSequenceAfterOffset || afterOffset >= text.length) return null;
|
|
288
274
|
return {
|
|
289
275
|
openingSequence: text.slice(0, openingSequenceAfterOffset),
|
|
290
|
-
|
|
276
|
+
after: text.slice(openingSequenceAfterOffset, afterOffset)
|
|
291
277
|
};
|
|
292
278
|
/**
|
|
293
279
|
* Skip whitespace characters at the start of the text.
|
|
@@ -310,9 +296,9 @@ function parseATXHeadingClosingSequenceFromText(text) {
|
|
|
310
296
|
const beforeOffset = skipEndWhitespace(closingSequenceBeforeOffset);
|
|
311
297
|
if (beforeOffset === closingSequenceBeforeOffset || beforeOffset < 0) return null;
|
|
312
298
|
return {
|
|
313
|
-
|
|
299
|
+
before: text.slice(beforeOffset + 1, closingSequenceBeforeOffset + 1),
|
|
314
300
|
closingSequence: text.slice(closingSequenceBeforeOffset + 1, trimmedEndOffset),
|
|
315
|
-
|
|
301
|
+
after: text.slice(trimmedEndOffset)
|
|
316
302
|
};
|
|
317
303
|
/**
|
|
318
304
|
* Skip whitespace characters at the end of the text.
|
|
@@ -577,16 +563,16 @@ var atx_heading_closing_sequence_default = createRule("atx-heading-closing-seque
|
|
|
577
563
|
context.report({
|
|
578
564
|
node,
|
|
579
565
|
loc: {
|
|
580
|
-
start: parsed.
|
|
566
|
+
start: parsed.content.loc.end,
|
|
581
567
|
end: parsed.closingSequence.loc.end
|
|
582
568
|
},
|
|
583
569
|
messageId: "forbidClosing",
|
|
584
570
|
*fix(fixer) {
|
|
585
|
-
const removeRange = [parsed.
|
|
571
|
+
const removeRange = [parsed.content.range[1], parsed.closingSequence.range[1]];
|
|
586
572
|
const newHeadingText = sourceCode.text.slice(sourceCode.getRange(node)[0], removeRange[0]);
|
|
587
573
|
const newHeadingParsed = parseATXHeadingClosingSequenceFromText(newHeadingText);
|
|
588
574
|
if (newHeadingParsed) {
|
|
589
|
-
const escapeIndex = removeRange[0] - newHeadingParsed.
|
|
575
|
+
const escapeIndex = removeRange[0] - newHeadingParsed.after.length - 1;
|
|
590
576
|
yield fixer.insertTextBeforeRange([escapeIndex, escapeIndex], "\\");
|
|
591
577
|
}
|
|
592
578
|
yield fixer.removeRange(removeRange);
|
|
@@ -614,12 +600,28 @@ function getBlockquoteLevelFromLine(sourceCode, lineNumber) {
|
|
|
614
600
|
const lineText = sourceCode.lines[lineNumber - 1];
|
|
615
601
|
let prefix = "";
|
|
616
602
|
let level = 0;
|
|
603
|
+
let width = 0;
|
|
604
|
+
let leadingMarkerOffset = 0;
|
|
617
605
|
const blockquoteMarkers = /* @__PURE__ */ new Map();
|
|
618
606
|
for (const c of lineText) {
|
|
619
607
|
if (c === ">") {
|
|
608
|
+
if (width - leadingMarkerOffset > 3) break;
|
|
609
|
+
leadingMarkerOffset = width + 1;
|
|
620
610
|
level++;
|
|
621
|
-
blockquoteMarkers.set(level, {
|
|
622
|
-
|
|
611
|
+
blockquoteMarkers.set(level, { loc: {
|
|
612
|
+
start: {
|
|
613
|
+
line: lineNumber,
|
|
614
|
+
column: prefix.length + 1
|
|
615
|
+
},
|
|
616
|
+
end: {
|
|
617
|
+
line: lineNumber,
|
|
618
|
+
column: prefix.length + 2
|
|
619
|
+
}
|
|
620
|
+
} });
|
|
621
|
+
} else if (!isSpaceOrTab(c)) break;
|
|
622
|
+
if (c === " ") width += 4 - width % 4;
|
|
623
|
+
else width++;
|
|
624
|
+
if (c !== ">" && prefix.at(-1) === ">") leadingMarkerOffset++;
|
|
623
625
|
prefix += c;
|
|
624
626
|
}
|
|
625
627
|
const result = {
|
|
@@ -632,6 +634,64 @@ function getBlockquoteLevelFromLine(sourceCode, lineNumber) {
|
|
|
632
634
|
return result;
|
|
633
635
|
}
|
|
634
636
|
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/utils/width.ts
|
|
639
|
+
/**
|
|
640
|
+
* Get the visual width of the string.
|
|
641
|
+
*/
|
|
642
|
+
function getWidth(str) {
|
|
643
|
+
let width = 0;
|
|
644
|
+
for (const c of str) if (c === " ") width += 4 - width % 4;
|
|
645
|
+
else width++;
|
|
646
|
+
return width;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Get a slice of the string by visual width.
|
|
650
|
+
*/
|
|
651
|
+
function sliceWidth(str, start, end) {
|
|
652
|
+
const buffer = [...str];
|
|
653
|
+
let width = 0;
|
|
654
|
+
let c;
|
|
655
|
+
while (c = buffer.shift()) {
|
|
656
|
+
if (start <= width) {
|
|
657
|
+
buffer.unshift(c);
|
|
658
|
+
break;
|
|
659
|
+
}
|
|
660
|
+
if (c === " ") width += 4 - width % 4;
|
|
661
|
+
else width++;
|
|
662
|
+
}
|
|
663
|
+
if (buffer.length === 0) return "";
|
|
664
|
+
let result = " ".repeat(width - start);
|
|
665
|
+
if (end == null) return `${result}${buffer.join("")}`;
|
|
666
|
+
while (c = buffer.shift()) {
|
|
667
|
+
let newWidth;
|
|
668
|
+
if (c === " ") newWidth = width + 4 - width % 4;
|
|
669
|
+
else newWidth = width + 1;
|
|
670
|
+
if (end < newWidth) {
|
|
671
|
+
buffer.unshift(c);
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
result += c;
|
|
675
|
+
width = newWidth;
|
|
676
|
+
}
|
|
677
|
+
if (buffer.length === 0) return result;
|
|
678
|
+
result += " ".repeat(end - width);
|
|
679
|
+
return result;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Get the character at the visual width.
|
|
683
|
+
*/
|
|
684
|
+
function atWidth(str, target) {
|
|
685
|
+
let width = 0;
|
|
686
|
+
for (const c of str) {
|
|
687
|
+
if (target === width) return c;
|
|
688
|
+
if (target < width) return " ";
|
|
689
|
+
if (c === " ") width += 4 - width % 4;
|
|
690
|
+
else width++;
|
|
691
|
+
}
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
|
|
635
695
|
//#endregion
|
|
636
696
|
//#region src/rules/blockquote-marker-alignment.ts
|
|
637
697
|
var blockquote_marker_alignment_default = createRule("blockquote-marker-alignment", {
|
|
@@ -669,38 +729,33 @@ var blockquote_marker_alignment_default = createRule("blockquote-marker-alignmen
|
|
|
669
729
|
const endLine = loc.end.line;
|
|
670
730
|
const base = getBlockquoteLevelFromLine(sourceCode, startLine).blockquoteMarkers.get(blockquoteLevel);
|
|
671
731
|
if (!base) return;
|
|
732
|
+
const baseBeforeMarker = sourceCode.lines[startLine - 1].slice(0, base.loc.start.column - 1);
|
|
733
|
+
const baseIndentWidth = getWidth(baseBeforeMarker);
|
|
672
734
|
for (let lineNumber = startLine + 1; lineNumber <= endLine; lineNumber++) {
|
|
673
735
|
const marker = getBlockquoteLevelFromLine(sourceCode, lineNumber).blockquoteMarkers.get(blockquoteLevel);
|
|
674
736
|
if (!marker) continue;
|
|
675
|
-
|
|
737
|
+
const indentWidth = getWidth(sourceCode.lines[lineNumber - 1].slice(0, marker.loc.start.column - 1));
|
|
738
|
+
if (baseIndentWidth === indentWidth) continue;
|
|
676
739
|
blockquoteStack.reported = true;
|
|
677
740
|
context.report({
|
|
678
741
|
node,
|
|
679
|
-
loc:
|
|
680
|
-
start: {
|
|
681
|
-
line: lineNumber,
|
|
682
|
-
column: marker.index + 1
|
|
683
|
-
},
|
|
684
|
-
end: {
|
|
685
|
-
line: lineNumber,
|
|
686
|
-
column: marker.index + 2
|
|
687
|
-
}
|
|
688
|
-
},
|
|
742
|
+
loc: marker.loc,
|
|
689
743
|
messageId: "inconsistentAlignment",
|
|
690
744
|
fix(fixer) {
|
|
691
745
|
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
692
|
-
if (
|
|
693
|
-
const addSpaces = " ".repeat(
|
|
694
|
-
return fixer.insertTextBeforeRange([line.range[0] + marker.
|
|
746
|
+
if (indentWidth < baseIndentWidth) {
|
|
747
|
+
const addSpaces = " ".repeat(baseIndentWidth - indentWidth);
|
|
748
|
+
return fixer.insertTextBeforeRange([line.range[0] + marker.loc.start.column - 1, line.range[0] + marker.loc.start.column - 1], addSpaces);
|
|
695
749
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
750
|
+
let newBeforeMarker = line.text.slice(0, marker.loc.start.column - 1);
|
|
751
|
+
while (getWidth(newBeforeMarker) > baseIndentWidth) {
|
|
752
|
+
const last = newBeforeMarker.at(-1);
|
|
753
|
+
if (last && isWhitespace(last)) newBeforeMarker = newBeforeMarker.slice(0, -1);
|
|
754
|
+
else return null;
|
|
699
755
|
}
|
|
700
|
-
if (
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
return fixer.removeRange([line.range[0] + removeStartIndex, line.range[0] + marker.index]);
|
|
756
|
+
if (getWidth(newBeforeMarker) < baseIndentWidth) newBeforeMarker += " ".repeat(baseIndentWidth - getWidth(newBeforeMarker));
|
|
757
|
+
if (!baseBeforeMarker.includes(">") || baseBeforeMarker === newBeforeMarker) return fixer.replaceTextRange([line.range[0], line.range[0] + marker.loc.start.column - 1], newBeforeMarker);
|
|
758
|
+
return null;
|
|
704
759
|
}
|
|
705
760
|
});
|
|
706
761
|
}
|
|
@@ -728,7 +783,7 @@ function getOtherMarker(unavailableMarker) {
|
|
|
728
783
|
/**
|
|
729
784
|
* Parse rule options.
|
|
730
785
|
*/
|
|
731
|
-
function parseOptions$
|
|
786
|
+
function parseOptions$3(options) {
|
|
732
787
|
const primary = options.primary || "-";
|
|
733
788
|
const secondary = options.secondary || getOtherMarker(primary);
|
|
734
789
|
if (primary === secondary) throw new Error(`\`primary\` and \`secondary\` cannot be the same (primary: "${primary}", secondary: "${secondary}").`);
|
|
@@ -796,7 +851,7 @@ var bullet_list_marker_style_default = createRule("bullet-list-marker-style", {
|
|
|
796
851
|
},
|
|
797
852
|
create(context) {
|
|
798
853
|
const sourceCode = context.sourceCode;
|
|
799
|
-
const options = parseOptions$
|
|
854
|
+
const options = parseOptions$3(context.options[0] || {});
|
|
800
855
|
let containerStack = {
|
|
801
856
|
node: sourceCode.ast,
|
|
802
857
|
level: 1,
|
|
@@ -4348,395 +4403,341 @@ var heading_casing_default = createRule("heading-casing", {
|
|
|
4348
4403
|
});
|
|
4349
4404
|
|
|
4350
4405
|
//#endregion
|
|
4351
|
-
//#region src/utils/
|
|
4406
|
+
//#region src/utils/character-cursor.ts
|
|
4407
|
+
var CharacterCursor = class {
|
|
4408
|
+
text;
|
|
4409
|
+
constructor(text) {
|
|
4410
|
+
this.text = text;
|
|
4411
|
+
}
|
|
4412
|
+
curr() {
|
|
4413
|
+
return this.text[this.index];
|
|
4414
|
+
}
|
|
4415
|
+
currIndex() {
|
|
4416
|
+
return this.index;
|
|
4417
|
+
}
|
|
4418
|
+
setCurrIndex(index) {
|
|
4419
|
+
this.index = index;
|
|
4420
|
+
}
|
|
4421
|
+
isWhitespace(index) {
|
|
4422
|
+
if (index >= this.text.length) return false;
|
|
4423
|
+
const ch = this.text[index];
|
|
4424
|
+
if (isWhitespace(ch)) return true;
|
|
4425
|
+
if (ch !== ">") return false;
|
|
4426
|
+
const prefix = [ch];
|
|
4427
|
+
for (let prev = index - 1; prev >= 0; prev--) {
|
|
4428
|
+
const prevCh$1 = this.text[prev];
|
|
4429
|
+
if (prevCh$1 === "\n") break;
|
|
4430
|
+
if (isSpaceOrTab(prevCh$1) || prevCh$1 === ">") {
|
|
4431
|
+
prefix.unshift(prevCh$1);
|
|
4432
|
+
continue;
|
|
4433
|
+
}
|
|
4434
|
+
return false;
|
|
4435
|
+
}
|
|
4436
|
+
let width = 0;
|
|
4437
|
+
let leadingMarkerOffset = 0;
|
|
4438
|
+
let prevCh;
|
|
4439
|
+
for (const currCh of prefix) {
|
|
4440
|
+
if (currCh === ">") {
|
|
4441
|
+
if (width - leadingMarkerOffset > 3) return false;
|
|
4442
|
+
leadingMarkerOffset = width + 1;
|
|
4443
|
+
}
|
|
4444
|
+
if (currCh === " ") width += 4 - width % 4;
|
|
4445
|
+
else width++;
|
|
4446
|
+
if (prevCh === ">" && isSpaceOrTab(currCh)) leadingMarkerOffset++;
|
|
4447
|
+
prevCh = currCh;
|
|
4448
|
+
}
|
|
4449
|
+
return true;
|
|
4450
|
+
}
|
|
4451
|
+
};
|
|
4452
|
+
var ForwardCharacterCursor = class extends CharacterCursor {
|
|
4453
|
+
index;
|
|
4454
|
+
constructor(text) {
|
|
4455
|
+
super(text);
|
|
4456
|
+
this.index = 0;
|
|
4457
|
+
}
|
|
4458
|
+
next() {
|
|
4459
|
+
this.index++;
|
|
4460
|
+
return this.text[this.index];
|
|
4461
|
+
}
|
|
4462
|
+
finished() {
|
|
4463
|
+
return this.index >= this.text.length;
|
|
4464
|
+
}
|
|
4465
|
+
skipSpaces() {
|
|
4466
|
+
while (this.index < this.text.length && this.isWhitespace(this.index)) this.index++;
|
|
4467
|
+
}
|
|
4468
|
+
/**
|
|
4469
|
+
* Skip until the end by the given condition
|
|
4470
|
+
*/
|
|
4471
|
+
skipUntilEnd(checkEnd) {
|
|
4472
|
+
while (this.index < this.text.length) {
|
|
4473
|
+
const c = this.text[this.index];
|
|
4474
|
+
if (checkEnd(c, this.index)) return true;
|
|
4475
|
+
this.index++;
|
|
4476
|
+
if (c !== "\\") continue;
|
|
4477
|
+
if (this.index < this.text.length && (this.text[this.index] === "\\" || checkEnd(this.text[this.index], this.index)) && !isWhitespace(this.text[this.index])) this.index++;
|
|
4478
|
+
}
|
|
4479
|
+
return false;
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4482
|
+
var BackwardCharacterCursor = class extends CharacterCursor {
|
|
4483
|
+
index;
|
|
4484
|
+
constructor(text) {
|
|
4485
|
+
super(text);
|
|
4486
|
+
this.index = text.length - 1;
|
|
4487
|
+
}
|
|
4488
|
+
prev() {
|
|
4489
|
+
this.index--;
|
|
4490
|
+
return this.text[this.index];
|
|
4491
|
+
}
|
|
4492
|
+
finished() {
|
|
4493
|
+
return this.index < 0;
|
|
4494
|
+
}
|
|
4495
|
+
skipSpaces() {
|
|
4496
|
+
while (this.index >= 0 && this.isWhitespace(this.index)) this.index--;
|
|
4497
|
+
}
|
|
4498
|
+
/**
|
|
4499
|
+
* Skip until the start by the given condition
|
|
4500
|
+
*/
|
|
4501
|
+
skipUntilStart(checkStart) {
|
|
4502
|
+
while (this.index >= 0) {
|
|
4503
|
+
const c = this.text[this.index];
|
|
4504
|
+
if (checkStart(c, this.index)) {
|
|
4505
|
+
if (this.index > 1 && !isWhitespace(c)) {
|
|
4506
|
+
let escapeText = "";
|
|
4507
|
+
while (this.text.endsWith(`${escapeText}\\`, this.index)) escapeText += "\\";
|
|
4508
|
+
if (escapeText.length % 2 === 1) {
|
|
4509
|
+
this.index -= escapeText.length + 1;
|
|
4510
|
+
continue;
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
return true;
|
|
4514
|
+
}
|
|
4515
|
+
this.index--;
|
|
4516
|
+
}
|
|
4517
|
+
return false;
|
|
4518
|
+
}
|
|
4519
|
+
};
|
|
4520
|
+
|
|
4521
|
+
//#endregion
|
|
4522
|
+
//#region src/utils/link-definition.ts
|
|
4352
4523
|
/**
|
|
4353
|
-
* Parse the
|
|
4524
|
+
* Parse the link definition.
|
|
4354
4525
|
*/
|
|
4355
|
-
function
|
|
4356
|
-
|
|
4357
|
-
const
|
|
4358
|
-
|
|
4359
|
-
const
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4526
|
+
function parseLinkDefinition(sourceCode, node) {
|
|
4527
|
+
const text = sourceCode.getText(node);
|
|
4528
|
+
const parsed = parseLinkDefinitionFromText(text);
|
|
4529
|
+
if (!parsed) return null;
|
|
4530
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4531
|
+
const labelRange = [nodeRange[0] + parsed.label.range[0], nodeRange[0] + parsed.label.range[1]];
|
|
4532
|
+
const destinationRange = [nodeRange[0] + parsed.destination.range[0], nodeRange[0] + parsed.destination.range[1]];
|
|
4533
|
+
return {
|
|
4534
|
+
label: {
|
|
4535
|
+
text: parsed.label.text,
|
|
4536
|
+
range: labelRange,
|
|
4537
|
+
loc: getSourceLocationFromRange(sourceCode, node, labelRange)
|
|
4538
|
+
},
|
|
4539
|
+
destination: {
|
|
4540
|
+
type: parsed.destination.type,
|
|
4541
|
+
text: parsed.destination.text,
|
|
4542
|
+
range: destinationRange,
|
|
4543
|
+
loc: getSourceLocationFromRange(sourceCode, node, destinationRange)
|
|
4544
|
+
},
|
|
4545
|
+
title: parsed.title ? {
|
|
4546
|
+
type: parsed.title.type,
|
|
4547
|
+
text: parsed.title.text,
|
|
4548
|
+
range: [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]],
|
|
4549
|
+
loc: getSourceLocationFromRange(sourceCode, node, [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]])
|
|
4550
|
+
} : null
|
|
4551
|
+
};
|
|
4552
|
+
}
|
|
4553
|
+
/**
|
|
4554
|
+
* Parse the link definition from the given text.
|
|
4555
|
+
*/
|
|
4556
|
+
function parseLinkDefinitionFromText(text) {
|
|
4557
|
+
if (!text.startsWith("[")) return null;
|
|
4558
|
+
const cursor = new ForwardCharacterCursor(text);
|
|
4559
|
+
const labelStartIndex = 0;
|
|
4560
|
+
cursor.next();
|
|
4561
|
+
if (!cursor.skipUntilEnd((c) => c === "]")) return null;
|
|
4562
|
+
cursor.next();
|
|
4563
|
+
const labelRange = [labelStartIndex, cursor.currIndex()];
|
|
4564
|
+
if (!text.slice(labelRange[0] + 1, labelRange[1] - 1).trim()) return null;
|
|
4565
|
+
if (cursor.curr() !== ":") return null;
|
|
4566
|
+
const label = {
|
|
4567
|
+
text: text.slice(...labelRange),
|
|
4568
|
+
range: labelRange
|
|
4569
|
+
};
|
|
4570
|
+
cursor.next();
|
|
4571
|
+
cursor.skipSpaces();
|
|
4572
|
+
let destination;
|
|
4573
|
+
const destinationStartIndex = cursor.currIndex();
|
|
4574
|
+
if (cursor.curr() === "<") {
|
|
4575
|
+
cursor.next();
|
|
4576
|
+
if (!cursor.skipUntilEnd((c) => c === ">")) return null;
|
|
4577
|
+
cursor.next();
|
|
4578
|
+
const destinationRange = [destinationStartIndex, cursor.currIndex()];
|
|
4579
|
+
destination = {
|
|
4580
|
+
type: "pointy-bracketed",
|
|
4581
|
+
text: text.slice(...destinationRange),
|
|
4582
|
+
range: destinationRange
|
|
4583
|
+
};
|
|
4584
|
+
} else {
|
|
4585
|
+
if (cursor.finished()) return null;
|
|
4586
|
+
cursor.skipUntilEnd((c, i) => cursor.isWhitespace(i) || isAsciiControlCharacter(c));
|
|
4587
|
+
const destinationRange = [destinationStartIndex, cursor.currIndex()];
|
|
4588
|
+
destination = {
|
|
4589
|
+
type: "bare",
|
|
4590
|
+
text: text.slice(...destinationRange),
|
|
4591
|
+
range: destinationRange
|
|
4592
|
+
};
|
|
4363
4593
|
}
|
|
4364
|
-
|
|
4365
|
-
if (
|
|
4594
|
+
cursor.skipSpaces();
|
|
4595
|
+
if (cursor.finished()) return {
|
|
4596
|
+
label,
|
|
4597
|
+
destination,
|
|
4598
|
+
title: null
|
|
4599
|
+
};
|
|
4600
|
+
let title;
|
|
4601
|
+
const titleStartIndex = cursor.currIndex();
|
|
4602
|
+
const startChar = cursor.curr();
|
|
4603
|
+
if (startChar === "'" || startChar === "\"" || startChar === "(") {
|
|
4604
|
+
cursor.next();
|
|
4605
|
+
const endChar = startChar === "(" ? ")" : startChar;
|
|
4606
|
+
if (!cursor.skipUntilEnd((c) => c === endChar)) return null;
|
|
4607
|
+
cursor.next();
|
|
4608
|
+
const titleRange = [titleStartIndex, cursor.currIndex()];
|
|
4609
|
+
title = {
|
|
4610
|
+
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
4611
|
+
text: text.slice(...titleRange),
|
|
4612
|
+
range: titleRange
|
|
4613
|
+
};
|
|
4614
|
+
} else return null;
|
|
4615
|
+
cursor.skipSpaces();
|
|
4616
|
+
if (!cursor.finished()) return null;
|
|
4366
4617
|
return {
|
|
4367
|
-
|
|
4368
|
-
|
|
4618
|
+
label,
|
|
4619
|
+
destination,
|
|
4620
|
+
title
|
|
4369
4621
|
};
|
|
4370
4622
|
}
|
|
4623
|
+
|
|
4624
|
+
//#endregion
|
|
4625
|
+
//#region src/utils/link.ts
|
|
4371
4626
|
/**
|
|
4372
|
-
* Parse the
|
|
4627
|
+
* Parse the inline link.
|
|
4373
4628
|
*/
|
|
4374
|
-
function
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
let
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
continue;
|
|
4383
|
-
}
|
|
4384
|
-
if (c === ">" && spaceBefore.length < 4) {
|
|
4385
|
-
prefix += spaceBefore + c;
|
|
4386
|
-
spaceBefore = "";
|
|
4387
|
-
continue;
|
|
4388
|
-
}
|
|
4389
|
-
suffix = line.text.slice(index);
|
|
4390
|
-
break;
|
|
4629
|
+
function parseInlineLink(sourceCode, node) {
|
|
4630
|
+
if (getLinkKind(sourceCode, node) !== "inline") return null;
|
|
4631
|
+
const nodeRange = sourceCode.getRange(node);
|
|
4632
|
+
let textRange;
|
|
4633
|
+
if (node.children.length === 0) textRange = [nodeRange[0], sourceCode.text.indexOf("]", nodeRange[0]) + 1];
|
|
4634
|
+
else {
|
|
4635
|
+
const lastChildRange = sourceCode.getRange(node.children[node.children.length - 1]);
|
|
4636
|
+
textRange = [nodeRange[0], sourceCode.text.indexOf("]", lastChildRange[1]) + 1];
|
|
4391
4637
|
}
|
|
4392
|
-
const
|
|
4393
|
-
|
|
4638
|
+
const parsed = parseInlineLinkDestAndTitleFromText(sourceCode.text.slice(textRange[1], nodeRange[1]));
|
|
4639
|
+
if (!parsed) return null;
|
|
4640
|
+
const openingParenRange = [textRange[1] + parsed.openingParen.range[0], textRange[1] + parsed.openingParen.range[1]];
|
|
4641
|
+
const destinationRange = [textRange[1] + parsed.destination.range[0], textRange[1] + parsed.destination.range[1]];
|
|
4642
|
+
const closingParenRange = [textRange[1] + parsed.closingParen.range[0], textRange[1] + parsed.closingParen.range[1]];
|
|
4394
4643
|
return {
|
|
4395
|
-
text:
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
start: {
|
|
4399
|
-
line: line.line,
|
|
4400
|
-
column: prefix.length + spaceBefore.length + 1
|
|
4401
|
-
},
|
|
4402
|
-
end: {
|
|
4403
|
-
line: line.line,
|
|
4404
|
-
column: prefix.length + spaceBefore.length + content.length + 1
|
|
4405
|
-
}
|
|
4644
|
+
text: {
|
|
4645
|
+
range: textRange,
|
|
4646
|
+
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4406
4647
|
},
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4648
|
+
openingParen: {
|
|
4649
|
+
range: openingParenRange,
|
|
4650
|
+
loc: getSourceLocationFromRange(sourceCode, node, openingParenRange)
|
|
4651
|
+
},
|
|
4652
|
+
destination: {
|
|
4653
|
+
type: parsed.destination.type,
|
|
4654
|
+
text: parsed.destination.text,
|
|
4655
|
+
range: destinationRange,
|
|
4656
|
+
loc: getSourceLocationFromRange(sourceCode, node, destinationRange)
|
|
4657
|
+
},
|
|
4658
|
+
title: parsed.title ? {
|
|
4659
|
+
type: parsed.title.type,
|
|
4660
|
+
text: parsed.title.text,
|
|
4661
|
+
range: [textRange[1] + parsed.title.range[0], textRange[1] + parsed.title.range[1]],
|
|
4662
|
+
loc: getSourceLocationFromRange(sourceCode, node, [textRange[1] + parsed.title.range[0], textRange[1] + parsed.title.range[1]])
|
|
4663
|
+
} : null,
|
|
4664
|
+
closingParen: {
|
|
4665
|
+
range: closingParenRange,
|
|
4666
|
+
loc: getSourceLocationFromRange(sourceCode, node, closingParenRange)
|
|
4411
4667
|
}
|
|
4412
4668
|
};
|
|
4413
4669
|
}
|
|
4414
4670
|
/**
|
|
4415
|
-
* Parse the
|
|
4416
|
-
*/
|
|
4417
|
-
function parseUnderline(line) {
|
|
4418
|
-
let marker = null;
|
|
4419
|
-
let underlineText = "";
|
|
4420
|
-
let prefix = "";
|
|
4421
|
-
let spaceBefore = "";
|
|
4422
|
-
let spaceAfter = "";
|
|
4423
|
-
for (let index = line.text.length - 1; index >= 0; index--) {
|
|
4424
|
-
const c = line.text[index];
|
|
4425
|
-
if (!marker) {
|
|
4426
|
-
if (c === "=" || c === "-") {
|
|
4427
|
-
underlineText = c + underlineText;
|
|
4428
|
-
marker = c;
|
|
4429
|
-
} else if (!c.trim()) spaceAfter = c + spaceAfter;
|
|
4430
|
-
else return null;
|
|
4431
|
-
continue;
|
|
4432
|
-
}
|
|
4433
|
-
if (c === marker) {
|
|
4434
|
-
underlineText = c + spaceBefore + underlineText;
|
|
4435
|
-
spaceBefore = "";
|
|
4436
|
-
} else if (!c.trim()) spaceBefore = c + spaceBefore;
|
|
4437
|
-
else {
|
|
4438
|
-
prefix = line.text.slice(0, index + 1);
|
|
4439
|
-
break;
|
|
4440
|
-
}
|
|
4441
|
-
}
|
|
4442
|
-
if (!marker) return null;
|
|
4443
|
-
const underlineLoc = {
|
|
4444
|
-
start: {
|
|
4445
|
-
line: line.line,
|
|
4446
|
-
column: prefix.length + spaceBefore.length + 1
|
|
4447
|
-
},
|
|
4448
|
-
end: {
|
|
4449
|
-
line: line.line,
|
|
4450
|
-
column: prefix.length + spaceBefore.length + underlineText.length + 1
|
|
4451
|
-
}
|
|
4452
|
-
};
|
|
4453
|
-
return {
|
|
4454
|
-
text: underlineText,
|
|
4455
|
-
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
4456
|
-
loc: underlineLoc,
|
|
4457
|
-
marker,
|
|
4458
|
-
raws: {
|
|
4459
|
-
prefix,
|
|
4460
|
-
spaceBefore,
|
|
4461
|
-
spaceAfter
|
|
4462
|
-
}
|
|
4463
|
-
};
|
|
4464
|
-
}
|
|
4465
|
-
|
|
4466
|
-
//#endregion
|
|
4467
|
-
//#region src/rules/level1-heading-style.ts
|
|
4468
|
-
var level1_heading_style_default = createRule("level1-heading-style", {
|
|
4469
|
-
meta: {
|
|
4470
|
-
type: "layout",
|
|
4471
|
-
docs: {
|
|
4472
|
-
description: "enforce consistent style for level 1 headings",
|
|
4473
|
-
categories: ["standard"],
|
|
4474
|
-
listCategory: "Stylistic"
|
|
4475
|
-
},
|
|
4476
|
-
fixable: "code",
|
|
4477
|
-
hasSuggestions: false,
|
|
4478
|
-
schema: [{
|
|
4479
|
-
type: "object",
|
|
4480
|
-
properties: {
|
|
4481
|
-
style: { enum: ["atx", "setext"] },
|
|
4482
|
-
allowMultilineSetext: { type: "boolean" }
|
|
4483
|
-
},
|
|
4484
|
-
additionalProperties: false
|
|
4485
|
-
}],
|
|
4486
|
-
messages: {
|
|
4487
|
-
expectedAtx: "Expected ATX style heading (# Heading).",
|
|
4488
|
-
expectedSetext: "Expected Setext style heading (Heading\\n======).",
|
|
4489
|
-
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
4490
|
-
}
|
|
4491
|
-
},
|
|
4492
|
-
create(context) {
|
|
4493
|
-
const sourceCode = context.sourceCode;
|
|
4494
|
-
const opt = context.options[0] || {};
|
|
4495
|
-
const style = opt.style ?? "atx";
|
|
4496
|
-
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
4497
|
-
return { heading(node) {
|
|
4498
|
-
if (node.depth !== 1) return;
|
|
4499
|
-
const headingKind = getHeadingKind(sourceCode, node);
|
|
4500
|
-
if (style === "atx") {
|
|
4501
|
-
if (headingKind !== "setext") return;
|
|
4502
|
-
const parsed = parseSetextHeading(sourceCode, node);
|
|
4503
|
-
if (!parsed) return;
|
|
4504
|
-
if (parsed.contentLines.length > 1) {
|
|
4505
|
-
if (allowMultilineSetext) return;
|
|
4506
|
-
context.report({
|
|
4507
|
-
node,
|
|
4508
|
-
messageId: "multilineSetextNotAllowed"
|
|
4509
|
-
});
|
|
4510
|
-
return;
|
|
4511
|
-
}
|
|
4512
|
-
context.report({
|
|
4513
|
-
node,
|
|
4514
|
-
messageId: "expectedAtx",
|
|
4515
|
-
*fix(fixer) {
|
|
4516
|
-
const heading = parsed.contentLines[0];
|
|
4517
|
-
yield fixer.insertTextBeforeRange(heading.range, "# ");
|
|
4518
|
-
const lines = getParsedLines(sourceCode);
|
|
4519
|
-
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
4520
|
-
}
|
|
4521
|
-
});
|
|
4522
|
-
} else if (style === "setext") {
|
|
4523
|
-
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
4524
|
-
context.report({
|
|
4525
|
-
node,
|
|
4526
|
-
messageId: "expectedSetext",
|
|
4527
|
-
*fix(fixer) {
|
|
4528
|
-
const parsed = parseATXHeading(sourceCode, node);
|
|
4529
|
-
if (!parsed) return;
|
|
4530
|
-
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.openingSequence.raws.spaceAfter.range[1]]);
|
|
4531
|
-
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4532
|
-
const lines = getParsedLines(sourceCode);
|
|
4533
|
-
const underline = "=".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4534
|
-
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
4535
|
-
yield fixer.insertTextAfter(node, appendingText);
|
|
4536
|
-
}
|
|
4537
|
-
});
|
|
4538
|
-
}
|
|
4539
|
-
} };
|
|
4540
|
-
}
|
|
4541
|
-
});
|
|
4542
|
-
|
|
4543
|
-
//#endregion
|
|
4544
|
-
//#region src/rules/level2-heading-style.ts
|
|
4545
|
-
var level2_heading_style_default = createRule("level2-heading-style", {
|
|
4546
|
-
meta: {
|
|
4547
|
-
type: "layout",
|
|
4548
|
-
docs: {
|
|
4549
|
-
description: "enforce consistent style for level 2 headings",
|
|
4550
|
-
categories: ["standard"],
|
|
4551
|
-
listCategory: "Stylistic"
|
|
4552
|
-
},
|
|
4553
|
-
fixable: "code",
|
|
4554
|
-
hasSuggestions: false,
|
|
4555
|
-
schema: [{
|
|
4556
|
-
type: "object",
|
|
4557
|
-
properties: {
|
|
4558
|
-
style: { enum: ["atx", "setext"] },
|
|
4559
|
-
allowMultilineSetext: { type: "boolean" }
|
|
4560
|
-
},
|
|
4561
|
-
additionalProperties: false
|
|
4562
|
-
}],
|
|
4563
|
-
messages: {
|
|
4564
|
-
expectedAtx: "Expected ATX style heading (## Heading).",
|
|
4565
|
-
expectedSetext: "Expected Setext style heading (Heading\\n------).",
|
|
4566
|
-
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
4567
|
-
}
|
|
4568
|
-
},
|
|
4569
|
-
create(context) {
|
|
4570
|
-
const sourceCode = context.sourceCode;
|
|
4571
|
-
const opt = context.options[0] || {};
|
|
4572
|
-
const style = opt.style ?? "atx";
|
|
4573
|
-
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
4574
|
-
return { heading(node) {
|
|
4575
|
-
if (node.depth !== 2) return;
|
|
4576
|
-
const headingKind = getHeadingKind(sourceCode, node);
|
|
4577
|
-
if (style === "atx") {
|
|
4578
|
-
if (headingKind !== "setext") return;
|
|
4579
|
-
const parsed = parseSetextHeading(sourceCode, node);
|
|
4580
|
-
if (!parsed) return;
|
|
4581
|
-
if (parsed.contentLines.length > 1) {
|
|
4582
|
-
if (allowMultilineSetext) return;
|
|
4583
|
-
context.report({
|
|
4584
|
-
node,
|
|
4585
|
-
messageId: "multilineSetextNotAllowed"
|
|
4586
|
-
});
|
|
4587
|
-
return;
|
|
4588
|
-
}
|
|
4589
|
-
context.report({
|
|
4590
|
-
node,
|
|
4591
|
-
messageId: "expectedAtx",
|
|
4592
|
-
*fix(fixer) {
|
|
4593
|
-
const heading = parsed.contentLines[0];
|
|
4594
|
-
yield fixer.insertTextBeforeRange(heading.range, "## ");
|
|
4595
|
-
const lines = getParsedLines(sourceCode);
|
|
4596
|
-
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
4597
|
-
}
|
|
4598
|
-
});
|
|
4599
|
-
} else if (style === "setext") {
|
|
4600
|
-
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
4601
|
-
context.report({
|
|
4602
|
-
node,
|
|
4603
|
-
messageId: "expectedSetext",
|
|
4604
|
-
*fix(fixer) {
|
|
4605
|
-
const parsed = parseATXHeading(sourceCode, node);
|
|
4606
|
-
if (!parsed) return;
|
|
4607
|
-
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.openingSequence.raws.spaceAfter.range[1]]);
|
|
4608
|
-
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4609
|
-
const lines = getParsedLines(sourceCode);
|
|
4610
|
-
const underline = "-".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4611
|
-
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
4612
|
-
yield fixer.insertTextAfter(node, appendingText);
|
|
4613
|
-
}
|
|
4614
|
-
});
|
|
4615
|
-
}
|
|
4616
|
-
} };
|
|
4617
|
-
}
|
|
4618
|
-
});
|
|
4619
|
-
|
|
4620
|
-
//#endregion
|
|
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.
|
|
4671
|
+
* Parse the inline link destination and link title from the given text.
|
|
4658
4672
|
*/
|
|
4659
4673
|
function parseInlineLinkDestAndTitleFromText(text) {
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
skipSpaces();
|
|
4674
|
+
if (!text.startsWith("(")) return null;
|
|
4675
|
+
const cursor = new ForwardCharacterCursor(text);
|
|
4676
|
+
cursor.next();
|
|
4677
|
+
cursor.skipSpaces();
|
|
4664
4678
|
let destination;
|
|
4665
|
-
const destinationStartIndex =
|
|
4666
|
-
if (
|
|
4667
|
-
|
|
4668
|
-
if (!skipUntilEnd((c) => c === ">")) return null;
|
|
4669
|
-
|
|
4670
|
-
const destinationRange = [destinationStartIndex,
|
|
4679
|
+
const destinationStartIndex = cursor.currIndex();
|
|
4680
|
+
if (cursor.curr() === "<") {
|
|
4681
|
+
cursor.next();
|
|
4682
|
+
if (!cursor.skipUntilEnd((c) => c === ">")) return null;
|
|
4683
|
+
cursor.next();
|
|
4684
|
+
const destinationRange = [destinationStartIndex, cursor.currIndex()];
|
|
4671
4685
|
destination = {
|
|
4672
4686
|
type: "pointy-bracketed",
|
|
4673
4687
|
text: text.slice(...destinationRange),
|
|
4674
4688
|
range: destinationRange
|
|
4675
4689
|
};
|
|
4676
4690
|
} else {
|
|
4677
|
-
if (
|
|
4678
|
-
skipUntilEnd((c) => isWhitespace(
|
|
4679
|
-
const destinationRange = [destinationStartIndex,
|
|
4691
|
+
if (cursor.finished()) return null;
|
|
4692
|
+
cursor.skipUntilEnd((c, i) => cursor.isWhitespace(i) || isAsciiControlCharacter(c) || c === ")");
|
|
4693
|
+
const destinationRange = [destinationStartIndex, cursor.currIndex()];
|
|
4680
4694
|
destination = {
|
|
4681
4695
|
type: "bare",
|
|
4682
4696
|
text: text.slice(...destinationRange),
|
|
4683
4697
|
range: destinationRange
|
|
4684
4698
|
};
|
|
4685
4699
|
}
|
|
4686
|
-
skipSpaces();
|
|
4687
|
-
if (
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4700
|
+
cursor.skipSpaces();
|
|
4701
|
+
if (cursor.curr() === ")") {
|
|
4702
|
+
const closingParenStartIndex$1 = cursor.currIndex();
|
|
4703
|
+
cursor.next();
|
|
4704
|
+
cursor.skipSpaces();
|
|
4705
|
+
if (!cursor.finished()) return null;
|
|
4691
4706
|
return {
|
|
4707
|
+
openingParen: { range: [0, 1] },
|
|
4692
4708
|
destination,
|
|
4693
|
-
title: null
|
|
4709
|
+
title: null,
|
|
4710
|
+
closingParen: { range: [closingParenStartIndex$1, closingParenStartIndex$1 + 1] }
|
|
4694
4711
|
};
|
|
4695
4712
|
}
|
|
4696
|
-
if (
|
|
4713
|
+
if (cursor.finished()) return null;
|
|
4697
4714
|
let title;
|
|
4698
|
-
const titleStartIndex =
|
|
4699
|
-
const startChar =
|
|
4715
|
+
const titleStartIndex = cursor.currIndex();
|
|
4716
|
+
const startChar = cursor.curr();
|
|
4700
4717
|
if (startChar === "'" || startChar === "\"" || startChar === "(") {
|
|
4701
|
-
|
|
4718
|
+
cursor.next();
|
|
4702
4719
|
const endChar = startChar === "(" ? ")" : startChar;
|
|
4703
|
-
if (!skipUntilEnd((c) => c === endChar)) return null;
|
|
4704
|
-
|
|
4705
|
-
const titleRange = [titleStartIndex,
|
|
4720
|
+
if (!cursor.skipUntilEnd((c) => c === endChar)) return null;
|
|
4721
|
+
cursor.next();
|
|
4722
|
+
const titleRange = [titleStartIndex, cursor.currIndex()];
|
|
4706
4723
|
title = {
|
|
4707
4724
|
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
4708
4725
|
text: text.slice(...titleRange),
|
|
4709
4726
|
range: titleRange
|
|
4710
4727
|
};
|
|
4711
4728
|
} else return null;
|
|
4712
|
-
skipSpaces();
|
|
4713
|
-
if (
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4729
|
+
cursor.skipSpaces();
|
|
4730
|
+
if (cursor.curr() !== ")") return null;
|
|
4731
|
+
const closingParenStartIndex = cursor.currIndex();
|
|
4732
|
+
cursor.next();
|
|
4733
|
+
cursor.skipSpaces();
|
|
4734
|
+
if (!cursor.finished()) return null;
|
|
4717
4735
|
return {
|
|
4736
|
+
openingParen: { range: [0, 1] },
|
|
4718
4737
|
destination,
|
|
4719
|
-
title
|
|
4738
|
+
title,
|
|
4739
|
+
closingParen: { range: [closingParenStartIndex, closingParenStartIndex + 1] }
|
|
4720
4740
|
};
|
|
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
|
}
|
|
4741
4742
|
|
|
4742
4743
|
//#endregion
|
|
@@ -4808,12 +4809,18 @@ function parseImage(sourceCode, node) {
|
|
|
4808
4809
|
if (!parsed) return null;
|
|
4809
4810
|
const nodeRange = sourceCode.getRange(node);
|
|
4810
4811
|
const textRange = [nodeRange[0] + parsed.text.range[0], nodeRange[0] + parsed.text.range[1]];
|
|
4812
|
+
const openingParenRange = [nodeRange[0] + parsed.openingParen.range[0], nodeRange[0] + parsed.openingParen.range[1]];
|
|
4811
4813
|
const destinationRange = [nodeRange[0] + parsed.destination.range[0], nodeRange[0] + parsed.destination.range[1]];
|
|
4814
|
+
const closingParenRange = [nodeRange[0] + parsed.closingParen.range[0], nodeRange[0] + parsed.closingParen.range[1]];
|
|
4812
4815
|
return {
|
|
4813
4816
|
text: {
|
|
4814
4817
|
range: textRange,
|
|
4815
4818
|
loc: getSourceLocationFromRange(sourceCode, node, textRange)
|
|
4816
4819
|
},
|
|
4820
|
+
openingParen: {
|
|
4821
|
+
range: openingParenRange,
|
|
4822
|
+
loc: getSourceLocationFromRange(sourceCode, node, openingParenRange)
|
|
4823
|
+
},
|
|
4817
4824
|
destination: {
|
|
4818
4825
|
type: parsed.destination.type,
|
|
4819
4826
|
text: parsed.destination.text,
|
|
@@ -4825,7 +4832,11 @@ function parseImage(sourceCode, node) {
|
|
|
4825
4832
|
text: parsed.title.text,
|
|
4826
4833
|
range: [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]],
|
|
4827
4834
|
loc: getSourceLocationFromRange(sourceCode, node, [nodeRange[0] + parsed.title.range[0], nodeRange[0] + parsed.title.range[1]])
|
|
4828
|
-
} : null
|
|
4835
|
+
} : null,
|
|
4836
|
+
closingParen: {
|
|
4837
|
+
range: closingParenRange,
|
|
4838
|
+
loc: getSourceLocationFromRange(sourceCode, node, closingParenRange)
|
|
4839
|
+
}
|
|
4829
4840
|
};
|
|
4830
4841
|
}
|
|
4831
4842
|
/**
|
|
@@ -4833,87 +4844,64 @@ function parseImage(sourceCode, node) {
|
|
|
4833
4844
|
*/
|
|
4834
4845
|
function parseImageFromText(text) {
|
|
4835
4846
|
if (!text.startsWith("![")) return null;
|
|
4836
|
-
|
|
4837
|
-
skipSpaces();
|
|
4838
|
-
if (
|
|
4839
|
-
|
|
4840
|
-
|
|
4847
|
+
const cursor = new BackwardCharacterCursor(text);
|
|
4848
|
+
cursor.skipSpaces();
|
|
4849
|
+
if (cursor.curr() !== ")") return null;
|
|
4850
|
+
const closingParenStartIndex = cursor.currIndex();
|
|
4851
|
+
cursor.prev();
|
|
4852
|
+
cursor.skipSpaces();
|
|
4841
4853
|
let title = null;
|
|
4842
|
-
const titleEndIndex =
|
|
4843
|
-
const endChar =
|
|
4854
|
+
const titleEndIndex = cursor.currIndex() + 1;
|
|
4855
|
+
const endChar = cursor.curr();
|
|
4844
4856
|
if (endChar === "'" || endChar === "\"" || endChar === ")") {
|
|
4845
|
-
|
|
4857
|
+
cursor.prev();
|
|
4846
4858
|
const startChar = endChar === ")" ? "(" : endChar;
|
|
4847
|
-
if (skipUntilStart((c) => c === startChar)) {
|
|
4848
|
-
const titleRange = [
|
|
4849
|
-
|
|
4859
|
+
if (cursor.skipUntilStart((c) => c === startChar)) {
|
|
4860
|
+
const titleRange = [cursor.currIndex(), titleEndIndex];
|
|
4861
|
+
cursor.prev();
|
|
4850
4862
|
title = {
|
|
4851
4863
|
type: startChar === "'" ? "single-quoted" : startChar === "\"" ? "double-quoted" : "parenthesized",
|
|
4852
4864
|
text: text.slice(...titleRange),
|
|
4853
4865
|
range: titleRange
|
|
4854
4866
|
};
|
|
4855
|
-
skipSpaces();
|
|
4867
|
+
cursor.skipSpaces();
|
|
4856
4868
|
}
|
|
4857
4869
|
}
|
|
4858
|
-
if (title == null)
|
|
4870
|
+
if (title == null) cursor.setCurrIndex(titleEndIndex - 1);
|
|
4859
4871
|
let destination;
|
|
4860
|
-
const destinationEndIndex =
|
|
4861
|
-
if (
|
|
4862
|
-
|
|
4863
|
-
if (!skipUntilStart((c) => c === "<")) return null;
|
|
4864
|
-
const destinationRange = [
|
|
4865
|
-
|
|
4872
|
+
const destinationEndIndex = cursor.currIndex() + 1;
|
|
4873
|
+
if (cursor.curr() === ">") {
|
|
4874
|
+
cursor.prev();
|
|
4875
|
+
if (!cursor.skipUntilStart((c) => c === "<")) return null;
|
|
4876
|
+
const destinationRange = [cursor.currIndex(), destinationEndIndex];
|
|
4877
|
+
cursor.prev();
|
|
4866
4878
|
destination = {
|
|
4867
4879
|
type: "pointy-bracketed",
|
|
4868
4880
|
text: text.slice(...destinationRange),
|
|
4869
4881
|
range: destinationRange
|
|
4870
4882
|
};
|
|
4871
4883
|
} else {
|
|
4872
|
-
if (
|
|
4873
|
-
skipUntilStart((c) => isWhitespace(
|
|
4874
|
-
const destinationRange = [
|
|
4884
|
+
if (cursor.finished()) return null;
|
|
4885
|
+
cursor.skipUntilStart((c, i) => cursor.isWhitespace(i) || isAsciiControlCharacter(c) || c === "(");
|
|
4886
|
+
const destinationRange = [cursor.currIndex() + 1, destinationEndIndex];
|
|
4875
4887
|
destination = {
|
|
4876
4888
|
type: "bare",
|
|
4877
4889
|
text: text.slice(...destinationRange),
|
|
4878
4890
|
range: destinationRange
|
|
4879
4891
|
};
|
|
4880
4892
|
}
|
|
4881
|
-
skipSpaces();
|
|
4882
|
-
if (
|
|
4883
|
-
|
|
4884
|
-
if (
|
|
4893
|
+
cursor.skipSpaces();
|
|
4894
|
+
if (cursor.curr() !== "(") return null;
|
|
4895
|
+
const openingParenStartIndex = cursor.currIndex();
|
|
4896
|
+
if (cursor.prev() !== "]") return null;
|
|
4897
|
+
const textRange = [1, cursor.currIndex() + 1];
|
|
4885
4898
|
return {
|
|
4886
|
-
|
|
4899
|
+
openingParen: { range: [openingParenStartIndex, openingParenStartIndex + 1] },
|
|
4900
|
+
text: { range: textRange },
|
|
4887
4901
|
destination,
|
|
4888
|
-
title
|
|
4902
|
+
title,
|
|
4903
|
+
closingParen: { range: [closingParenStartIndex, closingParenStartIndex + 1] }
|
|
4889
4904
|
};
|
|
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
4905
|
}
|
|
4918
4906
|
|
|
4919
4907
|
//#endregion
|
|
@@ -4973,21 +4961,20 @@ function parseImageReference(sourceCode, node) {
|
|
|
4973
4961
|
*/
|
|
4974
4962
|
function parseFullImageReferenceFromText(text) {
|
|
4975
4963
|
if (!text.startsWith("![")) return null;
|
|
4976
|
-
|
|
4977
|
-
skipSpaces();
|
|
4978
|
-
if (
|
|
4979
|
-
const labelEndIndex =
|
|
4980
|
-
|
|
4981
|
-
skipSpaces();
|
|
4982
|
-
if (!skipUntilStart((c) => c === "[")) return null;
|
|
4983
|
-
const labelRange = [
|
|
4984
|
-
index--;
|
|
4964
|
+
const cursor = new BackwardCharacterCursor(text);
|
|
4965
|
+
cursor.skipSpaces();
|
|
4966
|
+
if (cursor.curr() !== "]") return null;
|
|
4967
|
+
const labelEndIndex = cursor.currIndex() + 1;
|
|
4968
|
+
cursor.prev();
|
|
4969
|
+
cursor.skipSpaces();
|
|
4970
|
+
if (!cursor.skipUntilStart((c) => c === "[")) return null;
|
|
4971
|
+
const labelRange = [cursor.currIndex(), labelEndIndex];
|
|
4985
4972
|
const label = {
|
|
4986
4973
|
text: text.slice(...labelRange),
|
|
4987
4974
|
range: labelRange
|
|
4988
4975
|
};
|
|
4989
|
-
if (
|
|
4990
|
-
const textRange = [1,
|
|
4976
|
+
if (cursor.prev() !== "]") return null;
|
|
4977
|
+
const textRange = [1, cursor.currIndex() + 1];
|
|
4991
4978
|
return {
|
|
4992
4979
|
text: {
|
|
4993
4980
|
text: text.slice(...textRange),
|
|
@@ -4995,156 +4982,1208 @@ function parseFullImageReferenceFromText(text) {
|
|
|
4995
4982
|
},
|
|
4996
4983
|
label
|
|
4997
4984
|
};
|
|
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
4985
|
}
|
|
5026
4986
|
|
|
5027
4987
|
//#endregion
|
|
5028
|
-
//#region src/utils/
|
|
4988
|
+
//#region src/utils/list-item.ts
|
|
5029
4989
|
/**
|
|
5030
|
-
* Parse the
|
|
4990
|
+
* Parse the list item.
|
|
5031
4991
|
*/
|
|
5032
|
-
function
|
|
5033
|
-
const
|
|
5034
|
-
const parsed = parseLinkDefinitionFromText(text);
|
|
5035
|
-
if (!parsed) return null;
|
|
4992
|
+
function parseListItem(sourceCode, node) {
|
|
4993
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
5036
4994
|
const nodeRange = sourceCode.getRange(node);
|
|
5037
|
-
const
|
|
5038
|
-
const
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
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
|
|
4995
|
+
const markerRange = [nodeRange[0], nodeRange[0] + marker.raw.length];
|
|
4996
|
+
const parsedMarker = marker.kind === "." || marker.kind === ")" ? {
|
|
4997
|
+
kind: marker.kind,
|
|
4998
|
+
text: marker.raw,
|
|
4999
|
+
value: marker.sequence.value,
|
|
5000
|
+
range: markerRange,
|
|
5001
|
+
loc: getSourceLocationFromRange(sourceCode, node, markerRange)
|
|
5002
|
+
} : {
|
|
5003
|
+
kind: marker.kind,
|
|
5004
|
+
text: marker.raw,
|
|
5005
|
+
range: markerRange,
|
|
5006
|
+
loc: getSourceLocationFromRange(sourceCode, node, markerRange)
|
|
5057
5007
|
};
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
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
|
|
5008
|
+
if (node.checked == null) return {
|
|
5009
|
+
marker: parsedMarker,
|
|
5010
|
+
taskListItemMarker: null
|
|
5075
5011
|
};
|
|
5076
|
-
index
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
if (
|
|
5083
|
-
index
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
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
|
|
5012
|
+
for (let index = nodeRange[0] + marker.raw.length; index < nodeRange[1]; index++) {
|
|
5013
|
+
const c = sourceCode.text[index];
|
|
5014
|
+
if (isSpaceOrTab(c)) continue;
|
|
5015
|
+
if (c !== "[") break;
|
|
5016
|
+
const middle = sourceCode.text[index + 1];
|
|
5017
|
+
if (middle !== "x" && middle !== " ") break;
|
|
5018
|
+
if (sourceCode.text[index + 2] !== "]") break;
|
|
5019
|
+
const taskListItemMarkerRange = [index, index + 3];
|
|
5020
|
+
return {
|
|
5021
|
+
marker: parsedMarker,
|
|
5022
|
+
taskListItemMarker: {
|
|
5023
|
+
text: sourceCode.text.slice(...taskListItemMarkerRange),
|
|
5024
|
+
range: taskListItemMarkerRange,
|
|
5025
|
+
loc: getSourceLocationFromRange(sourceCode, node, taskListItemMarkerRange)
|
|
5026
|
+
}
|
|
5098
5027
|
};
|
|
5099
5028
|
}
|
|
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
5029
|
return {
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
title
|
|
5030
|
+
marker: parsedMarker,
|
|
5031
|
+
taskListItemMarker: null
|
|
5127
5032
|
};
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5033
|
+
}
|
|
5034
|
+
|
|
5035
|
+
//#endregion
|
|
5036
|
+
//#region src/rules/indent.ts
|
|
5037
|
+
/**
|
|
5038
|
+
* Parse options.
|
|
5039
|
+
*/
|
|
5040
|
+
function parseOptions$2(options) {
|
|
5041
|
+
const listItems = options?.listItems;
|
|
5042
|
+
return { listItems: {
|
|
5043
|
+
first: listItems?.first ?? 1,
|
|
5044
|
+
other: listItems?.other ?? "first",
|
|
5045
|
+
relativeTo: listItems?.relativeTo ?? "taskListMarkerEnd"
|
|
5046
|
+
} };
|
|
5047
|
+
}
|
|
5048
|
+
var indent_default = createRule("indent", {
|
|
5049
|
+
meta: {
|
|
5050
|
+
type: "layout",
|
|
5051
|
+
docs: {
|
|
5052
|
+
description: "enforce consistent indentation in Markdown files",
|
|
5053
|
+
categories: ["standard"],
|
|
5054
|
+
listCategory: "Stylistic"
|
|
5055
|
+
},
|
|
5056
|
+
fixable: "whitespace",
|
|
5057
|
+
hasSuggestions: false,
|
|
5058
|
+
schema: [{
|
|
5059
|
+
type: "object",
|
|
5060
|
+
properties: { listItems: {
|
|
5061
|
+
type: "object",
|
|
5062
|
+
properties: {
|
|
5063
|
+
first: { anyOf: [{ const: "ignore" }, {
|
|
5064
|
+
type: "number",
|
|
5065
|
+
minimum: 1
|
|
5066
|
+
}] },
|
|
5067
|
+
other: { anyOf: [{ enum: ["first", "minimum"] }, {
|
|
5068
|
+
type: "number",
|
|
5069
|
+
minimum: 1
|
|
5070
|
+
}] },
|
|
5071
|
+
relativeTo: { enum: [
|
|
5072
|
+
"markerStart",
|
|
5073
|
+
"markerEnd",
|
|
5074
|
+
"taskListMarkerStart",
|
|
5075
|
+
"taskListMarkerEnd"
|
|
5076
|
+
] }
|
|
5077
|
+
},
|
|
5078
|
+
additionalProperties: false
|
|
5079
|
+
} },
|
|
5080
|
+
additionalProperties: false
|
|
5081
|
+
}],
|
|
5082
|
+
messages: {
|
|
5083
|
+
wrongIndentation: "Expected indentation of {{expected}} but found {{actual}}.",
|
|
5084
|
+
wrongIndentationFromBlockquoteMarker: "Expected indentation of {{expected}} from the blockquote marker but found {{actual}}.",
|
|
5085
|
+
wrongIndentationFromListMarker: "Expected indentation of {{expected}} from the list marker but found {{actual}}.",
|
|
5086
|
+
wrongIndentationWithTab: "Expected indentation of {{expected}} but found {{actual}} (tab width is 4).",
|
|
5087
|
+
wrongIndentationFromBlockquoteMarkerWithTab: "Expected indentation of {{expected}} from the blockquote marker but found {{actual}} (tab width is 4).",
|
|
5088
|
+
wrongIndentationFromListMarkerWithTab: "Expected indentation of {{expected}} from the list marker but found {{actual}} (tab width is 4)."
|
|
5089
|
+
}
|
|
5090
|
+
},
|
|
5091
|
+
create(context) {
|
|
5092
|
+
const sourceCode = context.sourceCode;
|
|
5093
|
+
const options = parseOptions$2(context.options[0]);
|
|
5094
|
+
class AbsBlockStack {
|
|
5095
|
+
violations = [];
|
|
5096
|
+
getCurrentBlockquote() {
|
|
5097
|
+
let block = this;
|
|
5098
|
+
while (block) {
|
|
5099
|
+
if (block.type === "blockquote") return block;
|
|
5100
|
+
block = block.upper;
|
|
5101
|
+
}
|
|
5102
|
+
return null;
|
|
5103
|
+
}
|
|
5104
|
+
getCurrentListItemAtLine(lineNumber) {
|
|
5105
|
+
let block = this;
|
|
5106
|
+
while (block) {
|
|
5107
|
+
if (block.type === "blockquote") return null;
|
|
5108
|
+
if (block.type === "listItem") {
|
|
5109
|
+
if (sourceCode.getLoc(block.node).start.line === lineNumber) return block;
|
|
5110
|
+
}
|
|
5111
|
+
block = block.upper;
|
|
5112
|
+
}
|
|
5113
|
+
return null;
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
5116
|
+
class RootStack extends AbsBlockStack {
|
|
5117
|
+
type = "root";
|
|
5118
|
+
node;
|
|
5119
|
+
upper = null;
|
|
5120
|
+
constructor(node) {
|
|
5121
|
+
super();
|
|
5122
|
+
this.node = node;
|
|
5123
|
+
}
|
|
5124
|
+
getExpectedIndent() {
|
|
5125
|
+
return 0;
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
class BlockquoteStack extends AbsBlockStack {
|
|
5129
|
+
type = "blockquote";
|
|
5130
|
+
node;
|
|
5131
|
+
upper;
|
|
5132
|
+
_expectedIndent;
|
|
5133
|
+
_markerIndent;
|
|
5134
|
+
constructor(node) {
|
|
5135
|
+
super();
|
|
5136
|
+
this.node = node;
|
|
5137
|
+
this.upper = blockStack;
|
|
5138
|
+
}
|
|
5139
|
+
getExpectedIndent() {
|
|
5140
|
+
if (this._expectedIndent == null) this._expectedIndent = this.getMarkerIndent() + 1 + 1;
|
|
5141
|
+
return this._expectedIndent;
|
|
5142
|
+
}
|
|
5143
|
+
getMarkerIndent() {
|
|
5144
|
+
if (this._markerIndent == null) {
|
|
5145
|
+
const loc = sourceCode.getLoc(this.node);
|
|
5146
|
+
this._markerIndent = getWidth(sourceCode.lines[loc.start.line - 1].slice(0, loc.start.column - 1));
|
|
5147
|
+
}
|
|
5148
|
+
return this._markerIndent;
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
class ListItemStack extends AbsBlockStack {
|
|
5152
|
+
type = "listItem";
|
|
5153
|
+
node;
|
|
5154
|
+
upper;
|
|
5155
|
+
_expectedIndentForFirstLine;
|
|
5156
|
+
_expectedIndentForOtherLines;
|
|
5157
|
+
_parsed;
|
|
5158
|
+
nodeLoc;
|
|
5159
|
+
constructor(node) {
|
|
5160
|
+
super();
|
|
5161
|
+
this.node = node;
|
|
5162
|
+
this.upper = blockStack;
|
|
5163
|
+
this.nodeLoc = sourceCode.getLoc(this.node);
|
|
5164
|
+
}
|
|
5165
|
+
getParsedListItem() {
|
|
5166
|
+
return this._parsed ??= parseListItem(sourceCode, this.node);
|
|
5167
|
+
}
|
|
5168
|
+
getExpectedIndent({ lineNumber, block }) {
|
|
5169
|
+
const loc = this.nodeLoc;
|
|
5170
|
+
if (lineNumber === loc.start.line) return this.getExpectedIndentForFirstLine();
|
|
5171
|
+
const expected = this.getExpectedIndentAfterFirstLine();
|
|
5172
|
+
if (expected === "ignore") return "ignore";
|
|
5173
|
+
if (!block) return expected;
|
|
5174
|
+
const actualFirstLineIndent = this.getActualFirstLineIndent({ withoutTaskListMarker: true });
|
|
5175
|
+
if (actualFirstLineIndent != null) return Math.min(expected, actualFirstLineIndent + 3);
|
|
5176
|
+
return expected;
|
|
5177
|
+
}
|
|
5178
|
+
getExpectedIndentForFirstLine() {
|
|
5179
|
+
if (options.listItems.first === "ignore") return "ignore";
|
|
5180
|
+
if (this._expectedIndentForFirstLine != null) return this._expectedIndentForFirstLine;
|
|
5181
|
+
const loc = this.nodeLoc;
|
|
5182
|
+
const parsed = this.getParsedListItem();
|
|
5183
|
+
const lineText = sourceCode.lines[loc.start.line - 1];
|
|
5184
|
+
if (options.listItems.relativeTo === "markerStart") {
|
|
5185
|
+
const baseIndent = getWidth(lineText.slice(0, loc.start.column - 1));
|
|
5186
|
+
return this._expectedIndentForFirstLine = Math.max(baseIndent + options.listItems.first, baseIndent + parsed.marker.text.length + 1);
|
|
5187
|
+
}
|
|
5188
|
+
if (options.listItems.relativeTo === "taskListMarkerEnd" && parsed.taskListItemMarker) return this._expectedIndentForFirstLine = getWidth(lineText.slice(0, parsed.taskListItemMarker.loc.end.column - 1)) + options.listItems.first;
|
|
5189
|
+
return this._expectedIndentForFirstLine = getWidth(lineText.slice(0, parsed.marker.loc.end.column - 1)) + options.listItems.first;
|
|
5190
|
+
}
|
|
5191
|
+
getExpectedIndentAfterFirstLine() {
|
|
5192
|
+
if (this._expectedIndentForOtherLines != null) return this._expectedIndentForOtherLines;
|
|
5193
|
+
const loc = this.nodeLoc;
|
|
5194
|
+
if (options.listItems.other === "first") {
|
|
5195
|
+
const firstLineIndent = this.getExpectedIndentForFirstLine();
|
|
5196
|
+
if (firstLineIndent === "ignore") {
|
|
5197
|
+
const actualFirstLineIndent = this.getActualFirstLineIndent();
|
|
5198
|
+
if (actualFirstLineIndent != null) return this._expectedIndentForOtherLines = actualFirstLineIndent;
|
|
5199
|
+
for (const child of this.node.children) {
|
|
5200
|
+
const childLoc = sourceCode.getLoc(child);
|
|
5201
|
+
if (loc.start.line < childLoc.start.line) return this._expectedIndentForOtherLines = getWidth(sourceCode.lines[childLoc.start.line - 1].slice(0, childLoc.start.column - 1));
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
return this._expectedIndentForOtherLines = firstLineIndent;
|
|
5205
|
+
}
|
|
5206
|
+
if (options.listItems.other === "minimum") return this._expectedIndentForOtherLines = this.getMinimumLineIndent();
|
|
5207
|
+
const lineText = sourceCode.lines[loc.start.line - 1];
|
|
5208
|
+
if (options.listItems.relativeTo === "markerStart") {
|
|
5209
|
+
const baseIndent = getWidth(lineText.slice(0, loc.start.column - 1));
|
|
5210
|
+
const minimumLineIndent = this.getMinimumLineIndent();
|
|
5211
|
+
return this._expectedIndentForOtherLines = Math.max(baseIndent + options.listItems.other, minimumLineIndent);
|
|
5212
|
+
}
|
|
5213
|
+
const parsed = this.getParsedListItem();
|
|
5214
|
+
if (options.listItems.relativeTo === "taskListMarkerEnd" && parsed.taskListItemMarker) return this._expectedIndentForOtherLines = getWidth(lineText.slice(0, parsed.taskListItemMarker.loc.end.column - 1)) + options.listItems.other;
|
|
5215
|
+
return this._expectedIndentForOtherLines = getWidth(lineText.slice(0, parsed.marker.loc.end.column - 1)) + options.listItems.other;
|
|
5216
|
+
}
|
|
5217
|
+
getMinimumLineIndent() {
|
|
5218
|
+
const actualFirstLineIndent = this.getActualFirstLineIndent({ withoutTaskListMarker: true });
|
|
5219
|
+
if (actualFirstLineIndent != null) return this._expectedIndentForOtherLines = actualFirstLineIndent;
|
|
5220
|
+
const parsed = this.getParsedListItem();
|
|
5221
|
+
const lineText = sourceCode.lines[parsed.marker.loc.end.line - 1];
|
|
5222
|
+
return getWidth(lineText.slice(0, parsed.marker.loc.end.column - 1)) + 1;
|
|
5223
|
+
}
|
|
5224
|
+
getActualFirstLineIndent({ withoutTaskListMarker = false } = {}) {
|
|
5225
|
+
const parsed = this.getParsedListItem();
|
|
5226
|
+
const markerEndPos = withoutTaskListMarker ? parsed.marker.loc.end : parsed.taskListItemMarker?.loc.end ?? parsed.marker.loc.end;
|
|
5227
|
+
const lineText = sourceCode.lines[markerEndPos.line - 1];
|
|
5228
|
+
const afterMarkerText = lineText.slice(markerEndPos.column - 1);
|
|
5229
|
+
const trimmedAfterMarkerText = afterMarkerText.trimStart();
|
|
5230
|
+
if (trimmedAfterMarkerText) {
|
|
5231
|
+
const afterMarkerSpacesLength = afterMarkerText.length - trimmedAfterMarkerText.length;
|
|
5232
|
+
return getWidth(lineText.slice(0, markerEndPos.column - 1 + afterMarkerSpacesLength));
|
|
5233
|
+
}
|
|
5234
|
+
return null;
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
class FootnoteDefinitionStack extends AbsBlockStack {
|
|
5238
|
+
type = "footnoteDefinition";
|
|
5239
|
+
node;
|
|
5240
|
+
upper;
|
|
5241
|
+
_expectedIndent;
|
|
5242
|
+
constructor(node) {
|
|
5243
|
+
super();
|
|
5244
|
+
this.node = node;
|
|
5245
|
+
this.upper = blockStack;
|
|
5246
|
+
}
|
|
5247
|
+
getExpectedIndent() {
|
|
5248
|
+
if (this._expectedIndent == null) {
|
|
5249
|
+
const loc = sourceCode.getLoc(this.node);
|
|
5250
|
+
this._expectedIndent = getWidth(sourceCode.lines[loc.start.line - 1].slice(0, loc.start.column - 1)) + 4;
|
|
5251
|
+
}
|
|
5252
|
+
return this._expectedIndent;
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
class LinkStack extends AbsBlockStack {
|
|
5256
|
+
type = "link";
|
|
5257
|
+
node;
|
|
5258
|
+
upper;
|
|
5259
|
+
nodeLoc;
|
|
5260
|
+
constructor(node) {
|
|
5261
|
+
super();
|
|
5262
|
+
this.node = node;
|
|
5263
|
+
this.upper = blockStack;
|
|
5264
|
+
this.nodeLoc = sourceCode.getLoc(this.node);
|
|
5265
|
+
}
|
|
5266
|
+
getExpectedIndent(ctx) {
|
|
5267
|
+
const loc = this.nodeLoc;
|
|
5268
|
+
if (ctx.lineNumber === loc.start.line) return this.upper.getExpectedIndent(ctx);
|
|
5269
|
+
const base = this.upper.getExpectedIndent({
|
|
5270
|
+
lineNumber: loc.start.line,
|
|
5271
|
+
block: ctx.block
|
|
5272
|
+
});
|
|
5273
|
+
if (base === "ignore") return "ignore";
|
|
5274
|
+
return base + 2;
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
5277
|
+
let blockStack = new RootStack(sourceCode.ast);
|
|
5278
|
+
const reportedLocations = Object.create(null);
|
|
5279
|
+
/**
|
|
5280
|
+
* Reported locations (line and column) to avoid duplicate reports.
|
|
5281
|
+
*/
|
|
5282
|
+
function reportIncorrectIndent(violation) {
|
|
5283
|
+
const reportedColumns = reportedLocations[violation.loc.start.line] ??= /* @__PURE__ */ new Set();
|
|
5284
|
+
if (reportedColumns.has(violation.loc.start.column)) return;
|
|
5285
|
+
reportedColumns.add(violation.loc.start.column);
|
|
5286
|
+
blockStack.violations.push(violation);
|
|
5287
|
+
}
|
|
5288
|
+
/**
|
|
5289
|
+
* Flush violations to the context.
|
|
5290
|
+
*/
|
|
5291
|
+
function flushViolations({ violations }) {
|
|
5292
|
+
for (const violation of violations) context.report({
|
|
5293
|
+
loc: violation.loc,
|
|
5294
|
+
messageId: violation.messageId,
|
|
5295
|
+
data: {
|
|
5296
|
+
expected: String(violation.data.expected),
|
|
5297
|
+
actual: String(violation.data.actual)
|
|
5298
|
+
},
|
|
5299
|
+
fix(fixer) {
|
|
5300
|
+
const result = [];
|
|
5301
|
+
for (const { fix } of violations) result.push(...fix(fixer));
|
|
5302
|
+
return result;
|
|
5303
|
+
}
|
|
5304
|
+
});
|
|
5305
|
+
}
|
|
5306
|
+
return {
|
|
5307
|
+
thematicBreak: verifyThematicBreak,
|
|
5308
|
+
heading: verifyHeading,
|
|
5309
|
+
code: verifyCodeBlock,
|
|
5310
|
+
html: verifyHtml,
|
|
5311
|
+
definition: verifyLinkDefinition,
|
|
5312
|
+
table: verifyTable,
|
|
5313
|
+
list: verifyList,
|
|
5314
|
+
inlineCode: verifyInlineCode,
|
|
5315
|
+
emphasis: verifyEmphasisOrStrongOrDelete,
|
|
5316
|
+
strong: verifyEmphasisOrStrongOrDelete,
|
|
5317
|
+
delete: verifyEmphasisOrStrongOrDelete,
|
|
5318
|
+
image: verifyImage,
|
|
5319
|
+
imageReference: verifyImageReference,
|
|
5320
|
+
footnoteReference: verifyInline,
|
|
5321
|
+
break: verifyInline,
|
|
5322
|
+
text: verifyText,
|
|
5323
|
+
blockquote(node) {
|
|
5324
|
+
verifyBlockquote(node);
|
|
5325
|
+
blockStack = new BlockquoteStack(node);
|
|
5326
|
+
},
|
|
5327
|
+
listItem(node) {
|
|
5328
|
+
blockStack = new ListItemStack(node);
|
|
5329
|
+
},
|
|
5330
|
+
footnoteDefinition(node) {
|
|
5331
|
+
verifyFootnoteDefinition(node);
|
|
5332
|
+
blockStack = new FootnoteDefinitionStack(node);
|
|
5333
|
+
},
|
|
5334
|
+
link(node) {
|
|
5335
|
+
verifyLink(node);
|
|
5336
|
+
blockStack = new LinkStack(node);
|
|
5337
|
+
},
|
|
5338
|
+
linkReference(node) {
|
|
5339
|
+
verifyLinkReference(node);
|
|
5340
|
+
blockStack = new LinkStack(node);
|
|
5341
|
+
},
|
|
5342
|
+
"blockquote, listItem, footnoteDefinition, link, linkReference:exit"() {
|
|
5343
|
+
flushViolations(blockStack);
|
|
5344
|
+
blockStack = blockStack.upper;
|
|
5345
|
+
},
|
|
5346
|
+
"root:exit"() {
|
|
5347
|
+
flushViolations(blockStack);
|
|
5348
|
+
}
|
|
5349
|
+
};
|
|
5350
|
+
/**
|
|
5351
|
+
* Verify a thematic break node.
|
|
5352
|
+
*/
|
|
5353
|
+
function verifyThematicBreak(node) {
|
|
5354
|
+
const loc = sourceCode.getLoc(node);
|
|
5355
|
+
verifyLinesIndent(lineNumbersFromRange(loc.start.line, loc.end.line), (lineNumber) => blockStack.getExpectedIndent({
|
|
5356
|
+
lineNumber,
|
|
5357
|
+
block: true
|
|
5358
|
+
}));
|
|
5359
|
+
}
|
|
5360
|
+
/**
|
|
5361
|
+
* Verify a heading node.
|
|
5362
|
+
*/
|
|
5363
|
+
function verifyHeading(node) {
|
|
5364
|
+
const loc = sourceCode.getLoc(node);
|
|
5365
|
+
verifyLinesIndent(lineNumbersFromRange(loc.start.line, loc.end.line), (lineNumber) => blockStack.getExpectedIndent({
|
|
5366
|
+
lineNumber,
|
|
5367
|
+
block: true
|
|
5368
|
+
}));
|
|
5369
|
+
}
|
|
5370
|
+
/**
|
|
5371
|
+
* Verify a code block node.
|
|
5372
|
+
*/
|
|
5373
|
+
function verifyCodeBlock(node) {
|
|
5374
|
+
if (getCodeBlockKind(sourceCode, node) === "indented") return;
|
|
5375
|
+
const loc = sourceCode.getLoc(node);
|
|
5376
|
+
verifyLinesIndent([loc.start.line, loc.end.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5377
|
+
lineNumber,
|
|
5378
|
+
block: true
|
|
5379
|
+
}), additionalFixes);
|
|
5380
|
+
/**
|
|
5381
|
+
* Additional fixes for code block content lines.
|
|
5382
|
+
*/
|
|
5383
|
+
function* additionalFixes(fixer, info) {
|
|
5384
|
+
if (info.loc.start.line !== loc.start.line) return;
|
|
5385
|
+
for (let lineNumber = loc.start.line + 1; lineNumber < loc.end.line; lineNumber++) {
|
|
5386
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5387
|
+
if (!line) continue;
|
|
5388
|
+
if (info.expectedIndentWidth > info.actualIndentWidth) {
|
|
5389
|
+
const before = sliceWidth(line.text, 0, info.actualIndentWidth);
|
|
5390
|
+
const after = sliceWidth(line.text, info.actualIndentWidth);
|
|
5391
|
+
const diffWidth = info.expectedIndentWidth - info.actualIndentWidth;
|
|
5392
|
+
yield fixer.replaceTextRange([line.range[0], line.range[0] + line.text.length], before + " ".repeat(diffWidth) + after);
|
|
5393
|
+
} else {
|
|
5394
|
+
let before = sliceWidth(line.text, 0, info.expectedIndentWidth);
|
|
5395
|
+
let between = sliceWidth(line.text, info.expectedIndentWidth, info.actualIndentWidth);
|
|
5396
|
+
const after = sliceWidth(line.text, info.actualIndentWidth);
|
|
5397
|
+
while (between && !isSpaceOrTab(between)) {
|
|
5398
|
+
before += between[0];
|
|
5399
|
+
between = between.slice(1);
|
|
5400
|
+
}
|
|
5401
|
+
yield fixer.replaceTextRange([line.range[0], line.range[0] + line.text.length], before + after);
|
|
5402
|
+
}
|
|
5403
|
+
}
|
|
5404
|
+
}
|
|
5405
|
+
}
|
|
5406
|
+
/**
|
|
5407
|
+
* Verify an HTML node.
|
|
5408
|
+
*/
|
|
5409
|
+
function verifyHtml(node) {
|
|
5410
|
+
const loc = sourceCode.getLoc(node);
|
|
5411
|
+
if (!inlineToBeChecked(loc.start)) return;
|
|
5412
|
+
verifyLinesIndent([loc.start.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5413
|
+
lineNumber,
|
|
5414
|
+
block: true
|
|
5415
|
+
}));
|
|
5416
|
+
}
|
|
5417
|
+
/**
|
|
5418
|
+
* Verify a link definition node.
|
|
5419
|
+
*/
|
|
5420
|
+
function verifyLinkDefinition(node) {
|
|
5421
|
+
const parsed = parseLinkDefinition(sourceCode, node);
|
|
5422
|
+
if (!parsed) return;
|
|
5423
|
+
const loc = sourceCode.getLoc(node);
|
|
5424
|
+
verifyLinesIndent(lineNumbersFromRange(loc.start.line, loc.end.line), (lineNumber, column) => {
|
|
5425
|
+
const baseIndent = blockStack.getExpectedIndent({
|
|
5426
|
+
lineNumber,
|
|
5427
|
+
block: true
|
|
5428
|
+
});
|
|
5429
|
+
if (baseIndent === "ignore") return "ignore";
|
|
5430
|
+
if (lineNumber <= loc.start.line) return baseIndent;
|
|
5431
|
+
if (lineNumber < parsed.label.loc.end.line) return baseIndent + 2;
|
|
5432
|
+
if (lineNumber === parsed.label.loc.end.line) {
|
|
5433
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5434
|
+
if (!line) return baseIndent;
|
|
5435
|
+
const between = line.text.slice(column - 1, parsed.label.loc.end.column - 2);
|
|
5436
|
+
return !between || isWhitespace(between) ? baseIndent : baseIndent + 2;
|
|
5437
|
+
}
|
|
5438
|
+
if (lineNumber <= parsed.destination.loc.end.line) return baseIndent + 4;
|
|
5439
|
+
if (!parsed.title) return baseIndent;
|
|
5440
|
+
if (lineNumber <= parsed.title.loc.start.line) return baseIndent + 4;
|
|
5441
|
+
if (lineNumber < parsed.title.loc.end.line) return baseIndent + 6;
|
|
5442
|
+
if (lineNumber === parsed.title.loc.end.line) {
|
|
5443
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5444
|
+
if (!line) return baseIndent;
|
|
5445
|
+
const between = line.text.slice(column - 1, parsed.title.loc.end.column - 2);
|
|
5446
|
+
return !between || isWhitespace(between) ? baseIndent + 4 : baseIndent + 6;
|
|
5447
|
+
}
|
|
5448
|
+
return baseIndent;
|
|
5449
|
+
});
|
|
5450
|
+
}
|
|
5451
|
+
/**
|
|
5452
|
+
* Verify a blockquote node.
|
|
5453
|
+
*/
|
|
5454
|
+
function verifyBlockquote(node) {
|
|
5455
|
+
const loc = sourceCode.getLoc(node);
|
|
5456
|
+
verifyLinesIndent(lineNumbersFromRange(loc.start.line, loc.end.line), (lineNumber) => blockStack.getExpectedIndent({
|
|
5457
|
+
lineNumber,
|
|
5458
|
+
block: true
|
|
5459
|
+
}));
|
|
5460
|
+
}
|
|
5461
|
+
/**
|
|
5462
|
+
* Verify a table node.
|
|
5463
|
+
*/
|
|
5464
|
+
function verifyTable(node) {
|
|
5465
|
+
const loc = sourceCode.getLoc(node);
|
|
5466
|
+
verifyLinesIndent(lineNumbersFromRange(loc.start.line, loc.end.line), (lineNumber) => blockStack.getExpectedIndent({
|
|
5467
|
+
lineNumber,
|
|
5468
|
+
block: true
|
|
5469
|
+
}));
|
|
5470
|
+
}
|
|
5471
|
+
/**
|
|
5472
|
+
* Verify a list node.
|
|
5473
|
+
*/
|
|
5474
|
+
function verifyList(node) {
|
|
5475
|
+
const loc = sourceCode.getLoc(node);
|
|
5476
|
+
verifyLinesIndent([loc.start.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5477
|
+
lineNumber,
|
|
5478
|
+
block: true
|
|
5479
|
+
}), additionalFixes);
|
|
5480
|
+
/**
|
|
5481
|
+
* Additional fixes for list item lines.
|
|
5482
|
+
*/
|
|
5483
|
+
function* additionalFixes(fixer, info) {
|
|
5484
|
+
const [firstItem, ...otherItems] = node.children;
|
|
5485
|
+
yield* fixAfterFirstLine(firstItem, info.actualIndentWidth);
|
|
5486
|
+
for (const listItem of otherItems) {
|
|
5487
|
+
const listItemLoc = sourceCode.getLoc(listItem);
|
|
5488
|
+
const listItemIndentWidth = getWidth(sourceCode.lines[listItemLoc.start.line - 1].slice(0, listItemLoc.start.column - 1));
|
|
5489
|
+
if (listItemIndentWidth === info.expectedIndentWidth) continue;
|
|
5490
|
+
yield getFixForLine(listItemLoc.start.line, listItemIndentWidth);
|
|
5491
|
+
yield* fixAfterFirstLine(listItem, listItemIndentWidth);
|
|
5492
|
+
}
|
|
5493
|
+
/**
|
|
5494
|
+
* Get fixes for lines after the first line of the list item.
|
|
5495
|
+
*/
|
|
5496
|
+
function* fixAfterFirstLine(item, actualIndentWidth) {
|
|
5497
|
+
const itemLoc = sourceCode.getLoc(item);
|
|
5498
|
+
for (let lineNumber = itemLoc.start.line + 1; lineNumber <= itemLoc.end.line; lineNumber++) yield getFixForLine(lineNumber, actualIndentWidth);
|
|
5499
|
+
}
|
|
5500
|
+
/**
|
|
5501
|
+
* Get a fix for a line.
|
|
5502
|
+
*/
|
|
5503
|
+
function getFixForLine(lineNumber, actualIndentWidth) {
|
|
5504
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5505
|
+
if (info.expectedIndentWidth > actualIndentWidth) {
|
|
5506
|
+
const before$1 = sliceWidth(line.text, 0, actualIndentWidth);
|
|
5507
|
+
const diffWidth = info.expectedIndentWidth - actualIndentWidth;
|
|
5508
|
+
return fixer.insertTextAfterRange([line.range[0], line.range[0] + before$1.length], " ".repeat(diffWidth));
|
|
5509
|
+
}
|
|
5510
|
+
let before = sliceWidth(line.text, 0, info.expectedIndentWidth);
|
|
5511
|
+
let between = sliceWidth(line.text, info.expectedIndentWidth, actualIndentWidth);
|
|
5512
|
+
while (between && !isSpaceOrTab(between)) {
|
|
5513
|
+
before += between[0];
|
|
5514
|
+
between = between.slice(1);
|
|
5515
|
+
}
|
|
5516
|
+
return fixer.replaceTextRange([line.range[0], line.range[0] + before.length + between.length], before);
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
/**
|
|
5521
|
+
* Verify a footnote definition node.
|
|
5522
|
+
*/
|
|
5523
|
+
function verifyFootnoteDefinition(node) {
|
|
5524
|
+
const loc = sourceCode.getLoc(node);
|
|
5525
|
+
verifyLinesIndent([loc.start.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5526
|
+
lineNumber,
|
|
5527
|
+
block: true
|
|
5528
|
+
}));
|
|
5529
|
+
}
|
|
5530
|
+
/**
|
|
5531
|
+
* Verify an inline code node.
|
|
5532
|
+
*/
|
|
5533
|
+
function verifyInlineCode(node) {
|
|
5534
|
+
const loc = sourceCode.getLoc(node);
|
|
5535
|
+
if (!inlineToBeChecked(loc.start)) return;
|
|
5536
|
+
verifyLinesIndent([loc.start.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5537
|
+
lineNumber,
|
|
5538
|
+
block: false
|
|
5539
|
+
}));
|
|
5540
|
+
}
|
|
5541
|
+
/**
|
|
5542
|
+
* Verify an emphasis, strong, or delete node.
|
|
5543
|
+
*/
|
|
5544
|
+
function verifyEmphasisOrStrongOrDelete(node) {
|
|
5545
|
+
const loc = sourceCode.getLoc(node);
|
|
5546
|
+
if (!inlineToBeChecked(loc.start)) return;
|
|
5547
|
+
verifyLinesIndent([loc.start.line], (lineNumber) => blockStack.getExpectedIndent({
|
|
5548
|
+
lineNumber,
|
|
5549
|
+
block: false
|
|
5550
|
+
}));
|
|
5551
|
+
}
|
|
5552
|
+
/**
|
|
5553
|
+
* Verify a link node.
|
|
5554
|
+
*/
|
|
5555
|
+
function verifyLink(node) {
|
|
5556
|
+
const loc = sourceCode.getLoc(node);
|
|
5557
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5558
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5559
|
+
const kind = getLinkKind(sourceCode, node);
|
|
5560
|
+
if (kind === "autolink" || kind === "gfm-autolink") verifyLinesIndent(lines, (lineNumber) => blockStack.getExpectedIndent({
|
|
5561
|
+
lineNumber,
|
|
5562
|
+
block: false
|
|
5563
|
+
}));
|
|
5564
|
+
else if (kind === "inline") {
|
|
5565
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
5566
|
+
if (!parsed) return;
|
|
5567
|
+
const lastChild = node.children.at(-1);
|
|
5568
|
+
if (lastChild && parsed.text.loc.start.line < parsed.text.loc.end.line) {
|
|
5569
|
+
const lastChildLoc = sourceCode.getLoc(lastChild);
|
|
5570
|
+
const lastChildEndLine = lastChild.type === "text" && lastChild.value.endsWith("\n") ? lastChildLoc.end.line - 1 : lastChildLoc.end.line;
|
|
5571
|
+
lines = lines.filter((lineNumber) => lineNumber <= parsed.text.loc.start.line || lastChildEndLine < lineNumber);
|
|
5572
|
+
}
|
|
5573
|
+
verifyLinesIndent(lines, (lineNumber, column) => {
|
|
5574
|
+
const baseIndent = blockStack.getExpectedIndent({
|
|
5575
|
+
lineNumber,
|
|
5576
|
+
block: false
|
|
5577
|
+
});
|
|
5578
|
+
if (baseIndent === "ignore") return "ignore";
|
|
5579
|
+
if (lineNumber <= loc.start.line) return baseIndent;
|
|
5580
|
+
if (lineNumber < parsed.text.loc.end.line) return baseIndent + 2;
|
|
5581
|
+
if (lineNumber <= parsed.openingParen.loc.end.line) return baseIndent;
|
|
5582
|
+
if (lineNumber <= parsed.destination.loc.end.line) return baseIndent + 2;
|
|
5583
|
+
if (!parsed.title) return baseIndent;
|
|
5584
|
+
if (lineNumber <= parsed.title.loc.start.line) return baseIndent + 2;
|
|
5585
|
+
if (lineNumber < parsed.title.loc.end.line) return baseIndent + 4;
|
|
5586
|
+
if (lineNumber === parsed.title.loc.end.line) {
|
|
5587
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5588
|
+
if (!line) return baseIndent;
|
|
5589
|
+
const between = line.text.slice(column - 1, parsed.title.loc.end.column - 2);
|
|
5590
|
+
return !between || isWhitespace(between) ? baseIndent + 2 : baseIndent + 4;
|
|
5591
|
+
}
|
|
5592
|
+
return baseIndent;
|
|
5593
|
+
});
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5596
|
+
/**
|
|
5597
|
+
* Verify a link reference node.
|
|
5598
|
+
*/
|
|
5599
|
+
function verifyLinkReference(node) {
|
|
5600
|
+
const loc = sourceCode.getLoc(node);
|
|
5601
|
+
const parsed = parseLinkReference(sourceCode, node);
|
|
5602
|
+
if (!parsed) return;
|
|
5603
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5604
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5605
|
+
const lastChild = node.children.at(-1);
|
|
5606
|
+
if (lastChild && parsed.text.loc.start.line < parsed.text.loc.end.line) {
|
|
5607
|
+
const lastChildLoc = sourceCode.getLoc(lastChild);
|
|
5608
|
+
const lastChildEndLine = lastChild.type === "text" && lastChild.value.endsWith("\n") ? lastChildLoc.end.line - 1 : lastChildLoc.end.line;
|
|
5609
|
+
lines = lines.filter((lineNumber) => lineNumber <= parsed.text.loc.start.line || lastChildEndLine < lineNumber);
|
|
5610
|
+
}
|
|
5611
|
+
verifyLinesIndent(lines, (lineNumber, column) => {
|
|
5612
|
+
const baseIndent = blockStack.getExpectedIndent({
|
|
5613
|
+
lineNumber,
|
|
5614
|
+
block: false
|
|
5615
|
+
});
|
|
5616
|
+
if (baseIndent === "ignore") return "ignore";
|
|
5617
|
+
if (lineNumber <= loc.start.line) return baseIndent;
|
|
5618
|
+
if (lineNumber < parsed.text.loc.end.line) return baseIndent + 2;
|
|
5619
|
+
if (!parsed.label) return baseIndent;
|
|
5620
|
+
if (lineNumber <= parsed.label.loc.start.line) return baseIndent;
|
|
5621
|
+
if (lineNumber < parsed.label.loc.end.line) return baseIndent + 2;
|
|
5622
|
+
if (lineNumber === parsed.label.loc.end.line) {
|
|
5623
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5624
|
+
if (!line) return baseIndent;
|
|
5625
|
+
const between = line.text.slice(column - 1, parsed.label.loc.end.column - 2);
|
|
5626
|
+
return !between || isWhitespace(between) ? baseIndent : baseIndent + 2;
|
|
5627
|
+
}
|
|
5628
|
+
return baseIndent;
|
|
5629
|
+
});
|
|
5630
|
+
}
|
|
5631
|
+
/**
|
|
5632
|
+
* Verify an image node.
|
|
5633
|
+
*/
|
|
5634
|
+
function verifyImage(node) {
|
|
5635
|
+
const loc = sourceCode.getLoc(node);
|
|
5636
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5637
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5638
|
+
const parsed = parseImage(sourceCode, node);
|
|
5639
|
+
if (!parsed) return;
|
|
5640
|
+
verifyLinesIndent(lines, (lineNumber, column) => {
|
|
5641
|
+
const baseIndent = blockStack.getExpectedIndent({
|
|
5642
|
+
lineNumber,
|
|
5643
|
+
block: false
|
|
5644
|
+
});
|
|
5645
|
+
if (baseIndent === "ignore") return "ignore";
|
|
5646
|
+
if (lineNumber <= loc.start.line) return baseIndent;
|
|
5647
|
+
if (lineNumber < parsed.text.loc.end.line) return baseIndent + 2;
|
|
5648
|
+
if (lineNumber === parsed.text.loc.end.line) {
|
|
5649
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5650
|
+
if (!line) return baseIndent;
|
|
5651
|
+
const between = line.text.slice(column - 1, parsed.text.loc.end.column - 2);
|
|
5652
|
+
return !between || isWhitespace(between) ? baseIndent : baseIndent + 2;
|
|
5653
|
+
}
|
|
5654
|
+
if (lineNumber <= parsed.openingParen.loc.end.line) return baseIndent;
|
|
5655
|
+
if (lineNumber <= parsed.destination.loc.end.line) return baseIndent + 2;
|
|
5656
|
+
if (!parsed.title) return baseIndent;
|
|
5657
|
+
if (lineNumber <= parsed.title.loc.start.line) return baseIndent + 2;
|
|
5658
|
+
if (lineNumber < parsed.title.loc.end.line) return baseIndent + 4;
|
|
5659
|
+
if (lineNumber === parsed.title.loc.end.line) {
|
|
5660
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5661
|
+
if (!line) return baseIndent;
|
|
5662
|
+
const between = line.text.slice(column - 1, parsed.title.loc.end.column - 2);
|
|
5663
|
+
return !between || isWhitespace(between) ? baseIndent + 2 : baseIndent + 4;
|
|
5664
|
+
}
|
|
5665
|
+
return baseIndent;
|
|
5666
|
+
});
|
|
5667
|
+
}
|
|
5668
|
+
/**
|
|
5669
|
+
* Verify an image reference node.
|
|
5670
|
+
*/
|
|
5671
|
+
function verifyImageReference(node) {
|
|
5672
|
+
const loc = sourceCode.getLoc(node);
|
|
5673
|
+
const parsed = parseImageReference(sourceCode, node);
|
|
5674
|
+
if (!parsed) return;
|
|
5675
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5676
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5677
|
+
verifyLinesIndent(lines, (lineNumber, column) => {
|
|
5678
|
+
const baseIndent = blockStack.getExpectedIndent({
|
|
5679
|
+
lineNumber,
|
|
5680
|
+
block: false
|
|
5681
|
+
});
|
|
5682
|
+
if (baseIndent === "ignore") return "ignore";
|
|
5683
|
+
if (lineNumber <= loc.start.line) return baseIndent;
|
|
5684
|
+
if (lineNumber < parsed.text.loc.end.line) return baseIndent + 2;
|
|
5685
|
+
if (lineNumber === parsed.text.loc.end.line) {
|
|
5686
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5687
|
+
if (!line) return baseIndent;
|
|
5688
|
+
const between = line.text.slice(column - 1, parsed.text.loc.end.column - 2);
|
|
5689
|
+
return !between || isWhitespace(between) ? baseIndent : baseIndent + 2;
|
|
5690
|
+
}
|
|
5691
|
+
if (!parsed.label) return baseIndent;
|
|
5692
|
+
if (lineNumber <= parsed.label.loc.start.line) return baseIndent;
|
|
5693
|
+
if (lineNumber < parsed.label.loc.end.line) return baseIndent + 2;
|
|
5694
|
+
if (lineNumber === parsed.label.loc.end.line) {
|
|
5695
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5696
|
+
if (!line) return baseIndent;
|
|
5697
|
+
const between = line.text.slice(column - 1, parsed.label.loc.end.column - 2);
|
|
5698
|
+
return !between || isWhitespace(between) ? baseIndent : baseIndent + 2;
|
|
5699
|
+
}
|
|
5700
|
+
return baseIndent;
|
|
5701
|
+
});
|
|
5702
|
+
}
|
|
5703
|
+
/**
|
|
5704
|
+
* Verify a text node.
|
|
5705
|
+
*/
|
|
5706
|
+
function verifyText(node) {
|
|
5707
|
+
const loc = sourceCode.getLoc(node);
|
|
5708
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5709
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5710
|
+
if (node.value.endsWith("\n")) lines = lines.slice(0, -1);
|
|
5711
|
+
verifyLinesIndent(lines, (lineNumber) => blockStack.getExpectedIndent({
|
|
5712
|
+
lineNumber,
|
|
5713
|
+
block: false
|
|
5714
|
+
}));
|
|
5715
|
+
}
|
|
5716
|
+
/**
|
|
5717
|
+
* Verify an inline node.
|
|
5718
|
+
*/
|
|
5719
|
+
function verifyInline(node) {
|
|
5720
|
+
const loc = sourceCode.getLoc(node);
|
|
5721
|
+
let lines = lineNumbersFromRange(loc.start.line, loc.end.line);
|
|
5722
|
+
if (!inlineToBeChecked(loc.start)) lines = lines.slice(1);
|
|
5723
|
+
verifyLinesIndent(lines, (lineNumber) => blockStack.getExpectedIndent({
|
|
5724
|
+
lineNumber,
|
|
5725
|
+
block: false
|
|
5726
|
+
}));
|
|
5727
|
+
}
|
|
5728
|
+
/**
|
|
5729
|
+
* Check whether the inline node should be checked.
|
|
5730
|
+
*/
|
|
5731
|
+
function inlineToBeChecked(position) {
|
|
5732
|
+
const blockquote = blockStack.getCurrentBlockquote();
|
|
5733
|
+
const listItem = blockStack.getCurrentListItemAtLine(position.line);
|
|
5734
|
+
const lineText = sourceCode.lines[position.line - 1];
|
|
5735
|
+
if (listItem) {
|
|
5736
|
+
const parsed = listItem.getParsedListItem();
|
|
5737
|
+
const indentText = lineText.slice((parsed.taskListItemMarker?.loc ?? parsed.marker.loc).end.column - 1, position.column - 1);
|
|
5738
|
+
if (indentText && !isSpaceOrTab(indentText)) return false;
|
|
5739
|
+
} else if (blockquote) {
|
|
5740
|
+
if (atWidth(lineText, blockquote.getMarkerIndent()) !== ">") return false;
|
|
5741
|
+
const indentText = sliceWidth(lineText.slice(0, position.column - 1), blockquote.getMarkerIndent() + 1);
|
|
5742
|
+
if (indentText && !isSpaceOrTab(indentText)) return false;
|
|
5743
|
+
} else {
|
|
5744
|
+
const indentText = lineText.slice(0, position.column - 1);
|
|
5745
|
+
if (indentText && !isSpaceOrTab(indentText)) return false;
|
|
5746
|
+
}
|
|
5747
|
+
return true;
|
|
5748
|
+
}
|
|
5749
|
+
/**
|
|
5750
|
+
* Get line numbers from the range.
|
|
5751
|
+
*/
|
|
5752
|
+
function lineNumbersFromRange(lineNumberFrom, lineNumberTo) {
|
|
5753
|
+
const lines = [];
|
|
5754
|
+
for (let lineNumber = lineNumberFrom; lineNumber <= lineNumberTo; lineNumber++) lines.push(lineNumber);
|
|
5755
|
+
return lines;
|
|
5756
|
+
}
|
|
5757
|
+
/**
|
|
5758
|
+
* Verify the indentation of the lines.
|
|
5759
|
+
*/
|
|
5760
|
+
function verifyLinesIndent(lineNumbers, expectedIndentWidthProvider, additionalFixes) {
|
|
5761
|
+
const blockquote = blockStack.getCurrentBlockquote();
|
|
5762
|
+
if (!blockquote) {
|
|
5763
|
+
verifyLinesIndentFromRoot(lineNumbers, expectedIndentWidthProvider, additionalFixes);
|
|
5764
|
+
return;
|
|
5765
|
+
}
|
|
5766
|
+
verifyLinesIndentFromBlockquoteMarker(lineNumbers, blockquote, expectedIndentWidthProvider, additionalFixes);
|
|
5767
|
+
}
|
|
5768
|
+
/**
|
|
5769
|
+
* Verify the indentation of the lines from the root.
|
|
5770
|
+
*/
|
|
5771
|
+
function verifyLinesIndentFromRoot(lineNumbers, expectedIndentWidthProvider, additionalFixes) {
|
|
5772
|
+
const reports = [];
|
|
5773
|
+
for (const lineNumber of lineNumbers) {
|
|
5774
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5775
|
+
if (!line) return;
|
|
5776
|
+
const listItem = blockStack.getCurrentListItemAtLine(lineNumber);
|
|
5777
|
+
if (!listItem) {
|
|
5778
|
+
const indentText = /^\s*/u.exec(line.text)[0];
|
|
5779
|
+
const actualIndentWidth = getWidth(indentText);
|
|
5780
|
+
const expectedIndentWidth = expectedIndentWidthProvider(lineNumber, 1);
|
|
5781
|
+
if (expectedIndentWidth === "ignore") continue;
|
|
5782
|
+
if (actualIndentWidth === expectedIndentWidth) continue;
|
|
5783
|
+
reports.push({
|
|
5784
|
+
loc: {
|
|
5785
|
+
start: {
|
|
5786
|
+
line: line.line,
|
|
5787
|
+
column: 1
|
|
5788
|
+
},
|
|
5789
|
+
end: {
|
|
5790
|
+
line: line.line,
|
|
5791
|
+
column: indentText.length + 1
|
|
5792
|
+
}
|
|
5793
|
+
},
|
|
5794
|
+
messageId: indentText.includes(" ") ? "wrongIndentationWithTab" : "wrongIndentation",
|
|
5795
|
+
data: {
|
|
5796
|
+
expected: expectedIndentWidth,
|
|
5797
|
+
actual: actualIndentWidth
|
|
5798
|
+
},
|
|
5799
|
+
fix(fixer) {
|
|
5800
|
+
return fixer.replaceTextRange([line.range[0], line.range[0] + indentText.length], " ".repeat(expectedIndentWidth));
|
|
5801
|
+
},
|
|
5802
|
+
expectedIndentWidth,
|
|
5803
|
+
actualIndentWidth
|
|
5804
|
+
});
|
|
5805
|
+
continue;
|
|
5806
|
+
}
|
|
5807
|
+
const report = verifyLineIndentFromListItemMarker(line, listItem, expectedIndentWidthProvider);
|
|
5808
|
+
if (!report) continue;
|
|
5809
|
+
reports.push(report);
|
|
5810
|
+
}
|
|
5811
|
+
if (!reports.length) return;
|
|
5812
|
+
for (const report of reports) reportIncorrectIndent({
|
|
5813
|
+
loc: report.loc,
|
|
5814
|
+
messageId: report.messageId,
|
|
5815
|
+
data: report.data,
|
|
5816
|
+
*fix(fixer) {
|
|
5817
|
+
yield report.fix(fixer);
|
|
5818
|
+
if (additionalFixes) yield* additionalFixes(fixer, report) ?? [];
|
|
5819
|
+
}
|
|
5820
|
+
});
|
|
5821
|
+
}
|
|
5822
|
+
/**
|
|
5823
|
+
* Verify the indentation of the lines from the blockquote marker.
|
|
5824
|
+
*/
|
|
5825
|
+
function verifyLinesIndentFromBlockquoteMarker(lineNumbers, blockquote, expectedIndentWidthProvider, additionalFixes) {
|
|
5826
|
+
const blockquoteLoc = sourceCode.getLoc(blockquote.node);
|
|
5827
|
+
const reports = [];
|
|
5828
|
+
let cannotFix = false;
|
|
5829
|
+
for (const lineNumber of lineNumbers) {
|
|
5830
|
+
const line = getParsedLines(sourceCode).get(lineNumber);
|
|
5831
|
+
if (!line) return;
|
|
5832
|
+
if (atWidth(line.text, blockquote.getMarkerIndent()) !== ">") {
|
|
5833
|
+
cannotFix = true;
|
|
5834
|
+
continue;
|
|
5835
|
+
}
|
|
5836
|
+
const listItem = blockStack.getCurrentListItemAtLine(lineNumber);
|
|
5837
|
+
if (!listItem) {
|
|
5838
|
+
const before = line.text.slice(0, blockquoteLoc.start.column);
|
|
5839
|
+
const after = line.text.slice(blockquoteLoc.start.column);
|
|
5840
|
+
const indentText = /^\s*/u.exec(after)[0];
|
|
5841
|
+
const actualIndentWidth = getWidth(before + indentText);
|
|
5842
|
+
const expectedIndentWidth = expectedIndentWidthProvider(lineNumber, blockquoteLoc.start.column + 1);
|
|
5843
|
+
if (expectedIndentWidth === "ignore") continue;
|
|
5844
|
+
if (actualIndentWidth === expectedIndentWidth) continue;
|
|
5845
|
+
const linePrefixWidth = getWidth(before);
|
|
5846
|
+
reports.push({
|
|
5847
|
+
loc: {
|
|
5848
|
+
start: {
|
|
5849
|
+
line: line.line,
|
|
5850
|
+
column: blockquoteLoc.start.column + 1
|
|
5851
|
+
},
|
|
5852
|
+
end: {
|
|
5853
|
+
line: line.line,
|
|
5854
|
+
column: blockquoteLoc.start.column + 1 + indentText.length
|
|
5855
|
+
}
|
|
5856
|
+
},
|
|
5857
|
+
messageId: indentText.includes(" ") ? "wrongIndentationFromBlockquoteMarkerWithTab" : "wrongIndentationFromBlockquoteMarker",
|
|
5858
|
+
data: {
|
|
5859
|
+
expected: expectedIndentWidth - linePrefixWidth,
|
|
5860
|
+
actual: actualIndentWidth - linePrefixWidth
|
|
5861
|
+
},
|
|
5862
|
+
fix(fixer) {
|
|
5863
|
+
return fixer.replaceTextRange([line.range[0] + blockquoteLoc.start.column, line.range[0] + blockquoteLoc.start.column + indentText.length], " ".repeat(expectedIndentWidth - linePrefixWidth));
|
|
5864
|
+
},
|
|
5865
|
+
expectedIndentWidth,
|
|
5866
|
+
actualIndentWidth
|
|
5867
|
+
});
|
|
5868
|
+
continue;
|
|
5869
|
+
}
|
|
5870
|
+
const report = verifyLineIndentFromListItemMarker(line, listItem, expectedIndentWidthProvider);
|
|
5871
|
+
if (!report) continue;
|
|
5872
|
+
reports.push(report);
|
|
5873
|
+
}
|
|
5874
|
+
if (!reports.length) return;
|
|
5875
|
+
for (const report of reports) reportIncorrectIndent({
|
|
5876
|
+
loc: report.loc,
|
|
5877
|
+
messageId: report.messageId,
|
|
5878
|
+
data: report.data,
|
|
5879
|
+
*fix(fixer) {
|
|
5880
|
+
if (cannotFix) return;
|
|
5881
|
+
yield report.fix(fixer);
|
|
5882
|
+
if (additionalFixes) yield* additionalFixes(fixer, report) ?? [];
|
|
5883
|
+
}
|
|
5884
|
+
});
|
|
5885
|
+
}
|
|
5886
|
+
/**
|
|
5887
|
+
* Verify the indentation of the line from the list item marker.
|
|
5888
|
+
*/
|
|
5889
|
+
function verifyLineIndentFromListItemMarker(line, listItem, expectedIndentWidthProvider) {
|
|
5890
|
+
const parsed = listItem.getParsedListItem();
|
|
5891
|
+
const markerAfterColumn = (parsed.taskListItemMarker?.loc ?? parsed.marker.loc).end.column;
|
|
5892
|
+
const before = line.text.slice(0, markerAfterColumn - 1);
|
|
5893
|
+
const after = line.text.slice(markerAfterColumn - 1);
|
|
5894
|
+
const indentText = /^\s*/u.exec(after)[0];
|
|
5895
|
+
const actualIndentWidth = getWidth(before + indentText);
|
|
5896
|
+
const expectedIndentWidth = expectedIndentWidthProvider(line.line, markerAfterColumn);
|
|
5897
|
+
if (expectedIndentWidth === "ignore") return null;
|
|
5898
|
+
if (actualIndentWidth === expectedIndentWidth) return null;
|
|
5899
|
+
const linePrefixWidth = getWidth(before);
|
|
5900
|
+
const range = [line.range[0] + before.length, line.range[0] + before.length + indentText.length];
|
|
5901
|
+
return {
|
|
5902
|
+
loc: getSourceLocationFromRange(sourceCode, listItem.node, range),
|
|
5903
|
+
messageId: indentText.includes(" ") ? "wrongIndentationFromListMarkerWithTab" : "wrongIndentationFromListMarker",
|
|
5904
|
+
data: {
|
|
5905
|
+
expected: expectedIndentWidth - linePrefixWidth,
|
|
5906
|
+
actual: actualIndentWidth - linePrefixWidth
|
|
5907
|
+
},
|
|
5908
|
+
fix(fixer) {
|
|
5909
|
+
return fixer.replaceTextRange(range, " ".repeat(expectedIndentWidth - linePrefixWidth));
|
|
5910
|
+
},
|
|
5911
|
+
expectedIndentWidth,
|
|
5912
|
+
actualIndentWidth
|
|
5913
|
+
};
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
});
|
|
5917
|
+
|
|
5918
|
+
//#endregion
|
|
5919
|
+
//#region src/utils/setext-heading.ts
|
|
5920
|
+
/**
|
|
5921
|
+
* Parse the setext heading.
|
|
5922
|
+
*/
|
|
5923
|
+
function parseSetextHeading(sourceCode, node) {
|
|
5924
|
+
if (getHeadingKind(sourceCode, node) !== "setext") return null;
|
|
5925
|
+
const lines = getParsedLines(sourceCode);
|
|
5926
|
+
const contentLines = [];
|
|
5927
|
+
const nodeLoc = sourceCode.getLoc(node);
|
|
5928
|
+
for (let lineNumber = nodeLoc.start.line; lineNumber < nodeLoc.end.line; lineNumber++) {
|
|
5929
|
+
const content = parseContent(lines.get(lineNumber));
|
|
5930
|
+
contentLines.push(content);
|
|
5931
|
+
}
|
|
5932
|
+
const underline = parseUnderline(lines.get(nodeLoc.end.line));
|
|
5933
|
+
if (!underline) return null;
|
|
5934
|
+
return {
|
|
5935
|
+
contentLines,
|
|
5936
|
+
underline
|
|
5937
|
+
};
|
|
5938
|
+
}
|
|
5939
|
+
/**
|
|
5940
|
+
* Parse the content line of a setext heading.
|
|
5941
|
+
*/
|
|
5942
|
+
function parseContent(line) {
|
|
5943
|
+
let prefix = "";
|
|
5944
|
+
let spaceBefore = "";
|
|
5945
|
+
let suffix = "";
|
|
5946
|
+
for (let index = 0; index < line.text.length; index++) {
|
|
5947
|
+
const c = line.text[index];
|
|
5948
|
+
if (!c.trim()) {
|
|
5949
|
+
spaceBefore += c;
|
|
5950
|
+
continue;
|
|
5951
|
+
}
|
|
5952
|
+
if (c === ">" && spaceBefore.length < 4) {
|
|
5953
|
+
prefix += spaceBefore + c;
|
|
5954
|
+
spaceBefore = "";
|
|
5955
|
+
continue;
|
|
5956
|
+
}
|
|
5957
|
+
suffix = line.text.slice(index);
|
|
5958
|
+
break;
|
|
5959
|
+
}
|
|
5960
|
+
const content = suffix.trimEnd();
|
|
5961
|
+
const spaceAfter = suffix.slice(content.length);
|
|
5962
|
+
return {
|
|
5963
|
+
text: content,
|
|
5964
|
+
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
5965
|
+
loc: {
|
|
5966
|
+
start: {
|
|
5967
|
+
line: line.line,
|
|
5968
|
+
column: prefix.length + spaceBefore.length + 1
|
|
5969
|
+
},
|
|
5970
|
+
end: {
|
|
5971
|
+
line: line.line,
|
|
5972
|
+
column: prefix.length + spaceBefore.length + content.length + 1
|
|
5973
|
+
}
|
|
5974
|
+
},
|
|
5975
|
+
raws: {
|
|
5976
|
+
prefix,
|
|
5977
|
+
spaceBefore,
|
|
5978
|
+
spaceAfter
|
|
5979
|
+
}
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5982
|
+
/**
|
|
5983
|
+
* Parse the underline of a setext heading.
|
|
5984
|
+
*/
|
|
5985
|
+
function parseUnderline(line) {
|
|
5986
|
+
let marker = null;
|
|
5987
|
+
let underlineText = "";
|
|
5988
|
+
let prefix = "";
|
|
5989
|
+
let spaceBefore = "";
|
|
5990
|
+
let spaceAfter = "";
|
|
5991
|
+
for (let index = line.text.length - 1; index >= 0; index--) {
|
|
5992
|
+
const c = line.text[index];
|
|
5993
|
+
if (!marker) {
|
|
5994
|
+
if (c === "=" || c === "-") {
|
|
5995
|
+
underlineText = c + underlineText;
|
|
5996
|
+
marker = c;
|
|
5997
|
+
} else if (!c.trim()) spaceAfter = c + spaceAfter;
|
|
5998
|
+
else return null;
|
|
5999
|
+
continue;
|
|
6000
|
+
}
|
|
6001
|
+
if (c === marker) {
|
|
6002
|
+
underlineText = c + spaceBefore + underlineText;
|
|
6003
|
+
spaceBefore = "";
|
|
6004
|
+
} else if (!c.trim()) spaceBefore = c + spaceBefore;
|
|
6005
|
+
else {
|
|
6006
|
+
prefix = line.text.slice(0, index + 1);
|
|
6007
|
+
break;
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
6010
|
+
if (!marker) return null;
|
|
6011
|
+
const underlineLoc = {
|
|
6012
|
+
start: {
|
|
6013
|
+
line: line.line,
|
|
6014
|
+
column: prefix.length + spaceBefore.length + 1
|
|
6015
|
+
},
|
|
6016
|
+
end: {
|
|
6017
|
+
line: line.line,
|
|
6018
|
+
column: prefix.length + spaceBefore.length + underlineText.length + 1
|
|
6019
|
+
}
|
|
6020
|
+
};
|
|
6021
|
+
return {
|
|
6022
|
+
text: underlineText,
|
|
6023
|
+
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
6024
|
+
loc: underlineLoc,
|
|
6025
|
+
marker,
|
|
6026
|
+
raws: {
|
|
6027
|
+
prefix,
|
|
6028
|
+
spaceBefore,
|
|
6029
|
+
spaceAfter
|
|
6030
|
+
}
|
|
6031
|
+
};
|
|
6032
|
+
}
|
|
6033
|
+
|
|
6034
|
+
//#endregion
|
|
6035
|
+
//#region src/rules/level1-heading-style.ts
|
|
6036
|
+
var level1_heading_style_default = createRule("level1-heading-style", {
|
|
6037
|
+
meta: {
|
|
6038
|
+
type: "layout",
|
|
6039
|
+
docs: {
|
|
6040
|
+
description: "enforce consistent style for level 1 headings",
|
|
6041
|
+
categories: ["standard"],
|
|
6042
|
+
listCategory: "Stylistic"
|
|
6043
|
+
},
|
|
6044
|
+
fixable: "code",
|
|
6045
|
+
hasSuggestions: false,
|
|
6046
|
+
schema: [{
|
|
6047
|
+
type: "object",
|
|
6048
|
+
properties: {
|
|
6049
|
+
style: { enum: ["atx", "setext"] },
|
|
6050
|
+
allowMultilineSetext: { type: "boolean" }
|
|
6051
|
+
},
|
|
6052
|
+
additionalProperties: false
|
|
6053
|
+
}],
|
|
6054
|
+
messages: {
|
|
6055
|
+
expectedAtx: "Expected ATX style heading (# Heading).",
|
|
6056
|
+
expectedSetext: "Expected Setext style heading (Heading\\n======).",
|
|
6057
|
+
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
6058
|
+
}
|
|
6059
|
+
},
|
|
6060
|
+
create(context) {
|
|
6061
|
+
const sourceCode = context.sourceCode;
|
|
6062
|
+
const opt = context.options[0] || {};
|
|
6063
|
+
const style = opt.style ?? "atx";
|
|
6064
|
+
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
6065
|
+
return { heading(node) {
|
|
6066
|
+
if (node.depth !== 1) return;
|
|
6067
|
+
const headingKind = getHeadingKind(sourceCode, node);
|
|
6068
|
+
if (style === "atx") {
|
|
6069
|
+
if (headingKind !== "setext") return;
|
|
6070
|
+
const parsed = parseSetextHeading(sourceCode, node);
|
|
6071
|
+
if (!parsed) return;
|
|
6072
|
+
if (parsed.contentLines.length > 1) {
|
|
6073
|
+
if (allowMultilineSetext) return;
|
|
6074
|
+
context.report({
|
|
6075
|
+
node,
|
|
6076
|
+
messageId: "multilineSetextNotAllowed"
|
|
6077
|
+
});
|
|
6078
|
+
return;
|
|
6079
|
+
}
|
|
6080
|
+
context.report({
|
|
6081
|
+
node,
|
|
6082
|
+
messageId: "expectedAtx",
|
|
6083
|
+
*fix(fixer) {
|
|
6084
|
+
const heading = parsed.contentLines[0];
|
|
6085
|
+
yield fixer.insertTextBeforeRange(heading.range, "# ");
|
|
6086
|
+
const lines = getParsedLines(sourceCode);
|
|
6087
|
+
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
6088
|
+
}
|
|
6089
|
+
});
|
|
6090
|
+
} else if (style === "setext") {
|
|
6091
|
+
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
6092
|
+
context.report({
|
|
6093
|
+
node,
|
|
6094
|
+
messageId: "expectedSetext",
|
|
6095
|
+
*fix(fixer) {
|
|
6096
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
6097
|
+
if (!parsed) return;
|
|
6098
|
+
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.content.range[0]]);
|
|
6099
|
+
if (parsed.closingSequence) yield fixer.removeRange([parsed.content.range[1], parsed.after?.range[1] ?? parsed.closingSequence.range[1]]);
|
|
6100
|
+
const lines = getParsedLines(sourceCode);
|
|
6101
|
+
const underline = "=".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
6102
|
+
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
6103
|
+
yield fixer.insertTextAfter(node, appendingText);
|
|
6104
|
+
}
|
|
6105
|
+
});
|
|
6106
|
+
}
|
|
6107
|
+
} };
|
|
6108
|
+
}
|
|
6109
|
+
});
|
|
6110
|
+
|
|
6111
|
+
//#endregion
|
|
6112
|
+
//#region src/rules/level2-heading-style.ts
|
|
6113
|
+
var level2_heading_style_default = createRule("level2-heading-style", {
|
|
6114
|
+
meta: {
|
|
6115
|
+
type: "layout",
|
|
6116
|
+
docs: {
|
|
6117
|
+
description: "enforce consistent style for level 2 headings",
|
|
6118
|
+
categories: ["standard"],
|
|
6119
|
+
listCategory: "Stylistic"
|
|
6120
|
+
},
|
|
6121
|
+
fixable: "code",
|
|
6122
|
+
hasSuggestions: false,
|
|
6123
|
+
schema: [{
|
|
6124
|
+
type: "object",
|
|
6125
|
+
properties: {
|
|
6126
|
+
style: { enum: ["atx", "setext"] },
|
|
6127
|
+
allowMultilineSetext: { type: "boolean" }
|
|
6128
|
+
},
|
|
6129
|
+
additionalProperties: false
|
|
6130
|
+
}],
|
|
6131
|
+
messages: {
|
|
6132
|
+
expectedAtx: "Expected ATX style heading (## Heading).",
|
|
6133
|
+
expectedSetext: "Expected Setext style heading (Heading\\n------).",
|
|
6134
|
+
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
5144
6135
|
}
|
|
5145
|
-
|
|
6136
|
+
},
|
|
6137
|
+
create(context) {
|
|
6138
|
+
const sourceCode = context.sourceCode;
|
|
6139
|
+
const opt = context.options[0] || {};
|
|
6140
|
+
const style = opt.style ?? "atx";
|
|
6141
|
+
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
6142
|
+
return { heading(node) {
|
|
6143
|
+
if (node.depth !== 2) return;
|
|
6144
|
+
const headingKind = getHeadingKind(sourceCode, node);
|
|
6145
|
+
if (style === "atx") {
|
|
6146
|
+
if (headingKind !== "setext") return;
|
|
6147
|
+
const parsed = parseSetextHeading(sourceCode, node);
|
|
6148
|
+
if (!parsed) return;
|
|
6149
|
+
if (parsed.contentLines.length > 1) {
|
|
6150
|
+
if (allowMultilineSetext) return;
|
|
6151
|
+
context.report({
|
|
6152
|
+
node,
|
|
6153
|
+
messageId: "multilineSetextNotAllowed"
|
|
6154
|
+
});
|
|
6155
|
+
return;
|
|
6156
|
+
}
|
|
6157
|
+
context.report({
|
|
6158
|
+
node,
|
|
6159
|
+
messageId: "expectedAtx",
|
|
6160
|
+
*fix(fixer) {
|
|
6161
|
+
const heading = parsed.contentLines[0];
|
|
6162
|
+
yield fixer.insertTextBeforeRange(heading.range, "## ");
|
|
6163
|
+
const lines = getParsedLines(sourceCode);
|
|
6164
|
+
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
6165
|
+
}
|
|
6166
|
+
});
|
|
6167
|
+
} else if (style === "setext") {
|
|
6168
|
+
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
6169
|
+
context.report({
|
|
6170
|
+
node,
|
|
6171
|
+
messageId: "expectedSetext",
|
|
6172
|
+
*fix(fixer) {
|
|
6173
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
6174
|
+
if (!parsed) return;
|
|
6175
|
+
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.content.range[0]]);
|
|
6176
|
+
if (parsed.closingSequence) yield fixer.removeRange([parsed.content.range[1], parsed.after?.range[1] ?? parsed.closingSequence.range[1]]);
|
|
6177
|
+
const lines = getParsedLines(sourceCode);
|
|
6178
|
+
const underline = "-".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
6179
|
+
const appendingText = `\n${lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1)}${underline}`;
|
|
6180
|
+
yield fixer.insertTextAfter(node, appendingText);
|
|
6181
|
+
}
|
|
6182
|
+
});
|
|
6183
|
+
}
|
|
6184
|
+
} };
|
|
5146
6185
|
}
|
|
5147
|
-
}
|
|
6186
|
+
});
|
|
5148
6187
|
|
|
5149
6188
|
//#endregion
|
|
5150
6189
|
//#region src/rules/link-bracket-newline.ts
|
|
@@ -5179,11 +6218,11 @@ var link_bracket_newline_default = createRule("link-bracket-newline", {
|
|
|
5179
6218
|
},
|
|
5180
6219
|
create(context) {
|
|
5181
6220
|
const sourceCode = context.sourceCode;
|
|
5182
|
-
const optionProvider = parseOptions$
|
|
6221
|
+
const optionProvider = parseOptions$4(context.options[0]);
|
|
5183
6222
|
/**
|
|
5184
6223
|
* Parse the options.
|
|
5185
6224
|
*/
|
|
5186
|
-
function parseOptions$
|
|
6225
|
+
function parseOptions$4(option) {
|
|
5187
6226
|
const newline = option?.newline ?? "never";
|
|
5188
6227
|
const multiline = option?.multiline ?? false;
|
|
5189
6228
|
return (bracketsRange) => {
|
|
@@ -5624,6 +6663,265 @@ function hasLoneLastBackslash(text) {
|
|
|
5624
6663
|
return escapeText.length % 2 === 1;
|
|
5625
6664
|
}
|
|
5626
6665
|
|
|
6666
|
+
//#endregion
|
|
6667
|
+
//#region src/rules/link-paren-newline.ts
|
|
6668
|
+
var link_paren_newline_default = createRule("link-paren-newline", {
|
|
6669
|
+
meta: {
|
|
6670
|
+
type: "layout",
|
|
6671
|
+
docs: {
|
|
6672
|
+
description: "enforce linebreaks after opening and before closing link parentheses",
|
|
6673
|
+
categories: ["standard"],
|
|
6674
|
+
listCategory: "Stylistic"
|
|
6675
|
+
},
|
|
6676
|
+
fixable: "whitespace",
|
|
6677
|
+
hasSuggestions: false,
|
|
6678
|
+
schema: [{
|
|
6679
|
+
type: "object",
|
|
6680
|
+
properties: {
|
|
6681
|
+
newline: { enum: [
|
|
6682
|
+
"always",
|
|
6683
|
+
"never",
|
|
6684
|
+
"consistent"
|
|
6685
|
+
] },
|
|
6686
|
+
multiline: { type: "boolean" }
|
|
6687
|
+
},
|
|
6688
|
+
additionalProperties: false
|
|
6689
|
+
}],
|
|
6690
|
+
messages: {
|
|
6691
|
+
expectedNewlineAfterOpeningParen: "Expected a linebreak after this opening parenthesis.",
|
|
6692
|
+
unexpectedNewlineAfterOpeningParen: "Unexpected linebreak after this opening parenthesis.",
|
|
6693
|
+
expectedNewlineBeforeClosingParen: "Expected a linebreak before this closing parenthesis.",
|
|
6694
|
+
unexpectedNewlineBeforeClosingParen: "Unexpected linebreak before this closing parenthesis."
|
|
6695
|
+
}
|
|
6696
|
+
},
|
|
6697
|
+
create(context) {
|
|
6698
|
+
const sourceCode = context.sourceCode;
|
|
6699
|
+
const optionProvider = parseOptions$4(context.options[0]);
|
|
6700
|
+
/**
|
|
6701
|
+
* Parse the options.
|
|
6702
|
+
*/
|
|
6703
|
+
function parseOptions$4(option) {
|
|
6704
|
+
const newline = option?.newline ?? "never";
|
|
6705
|
+
const multiline = option?.multiline ?? false;
|
|
6706
|
+
return (openingParenIndex, closingParenIndex) => {
|
|
6707
|
+
if (multiline) {
|
|
6708
|
+
if (sourceCode.text.slice(openingParenIndex + 1, closingParenIndex).trim().includes("\n")) return "always";
|
|
6709
|
+
}
|
|
6710
|
+
return newline;
|
|
6711
|
+
};
|
|
6712
|
+
}
|
|
6713
|
+
/**
|
|
6714
|
+
* Verify the newline around the parentheses.
|
|
6715
|
+
*/
|
|
6716
|
+
function verifyNewlineAroundParens(node, openingParenIndex, closingParenIndex) {
|
|
6717
|
+
const newline = optionProvider(openingParenIndex, closingParenIndex);
|
|
6718
|
+
const spaceAfterOpeningParen = getSpaceAfterOpeningParen(openingParenIndex);
|
|
6719
|
+
verifyNewlineAfterOpeningParen(node, spaceAfterOpeningParen, openingParenIndex, newline);
|
|
6720
|
+
const newlineOptionBeforeClosingParen = newline === "consistent" ? getSpaceAfterOpeningParen(openingParenIndex).includes("\n") ? "always" : "never" : newline;
|
|
6721
|
+
verifyNewlineBeforeClosingParen(node, getSpaceBeforeClosingParen(closingParenIndex), openingParenIndex, closingParenIndex, newlineOptionBeforeClosingParen);
|
|
6722
|
+
}
|
|
6723
|
+
/**
|
|
6724
|
+
* Verify the newline after the opening parenthesis and before the closing parenthesis.
|
|
6725
|
+
*/
|
|
6726
|
+
function verifyNewlineAfterOpeningParen(node, spaceAfterOpeningParen, openingParenIndex, newline) {
|
|
6727
|
+
if (newline === "always") {
|
|
6728
|
+
if (spaceAfterOpeningParen.includes("\n")) return;
|
|
6729
|
+
const loc = getSourceLocationFromRange(sourceCode, node, [openingParenIndex, openingParenIndex + 1]);
|
|
6730
|
+
context.report({
|
|
6731
|
+
node,
|
|
6732
|
+
loc,
|
|
6733
|
+
messageId: "expectedNewlineAfterOpeningParen",
|
|
6734
|
+
fix: (fixer) => fixer.insertTextAfterRange([openingParenIndex, openingParenIndex + 1], `\n${" ".repeat(loc.start.column)}${spaceAfterOpeningParen}`)
|
|
6735
|
+
});
|
|
6736
|
+
} else if (newline === "never") {
|
|
6737
|
+
if (!spaceAfterOpeningParen.includes("\n")) return;
|
|
6738
|
+
context.report({
|
|
6739
|
+
node,
|
|
6740
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingParenIndex + 1, openingParenIndex + 1 + spaceAfterOpeningParen.length]),
|
|
6741
|
+
messageId: "unexpectedNewlineAfterOpeningParen",
|
|
6742
|
+
fix: (fixer) => fixer.replaceTextRange([openingParenIndex + 1, openingParenIndex + 1 + spaceAfterOpeningParen.length], " ")
|
|
6743
|
+
});
|
|
6744
|
+
}
|
|
6745
|
+
}
|
|
6746
|
+
/**
|
|
6747
|
+
* Verify the newline before the closing parenthesis.
|
|
6748
|
+
*/
|
|
6749
|
+
function verifyNewlineBeforeClosingParen(node, spaceBeforeClosingParen, openingParenIndex, closingParenIndex, newline) {
|
|
6750
|
+
if (openingParenIndex + 1 === closingParenIndex - spaceBeforeClosingParen.length) return;
|
|
6751
|
+
if (newline === "always") {
|
|
6752
|
+
if (spaceBeforeClosingParen.includes("\n")) return;
|
|
6753
|
+
context.report({
|
|
6754
|
+
node,
|
|
6755
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingParenIndex, closingParenIndex + 1]),
|
|
6756
|
+
messageId: "expectedNewlineBeforeClosingParen",
|
|
6757
|
+
fix: (fixer) => {
|
|
6758
|
+
const openingParenLoc = getSourceLocationFromRange(sourceCode, node, [openingParenIndex, openingParenIndex + 1]);
|
|
6759
|
+
return fixer.insertTextBeforeRange([closingParenIndex, closingParenIndex + 1], `\n${" ".repeat(openingParenLoc.start.column)}`);
|
|
6760
|
+
}
|
|
6761
|
+
});
|
|
6762
|
+
} else if (newline === "never") {
|
|
6763
|
+
if (!spaceBeforeClosingParen.includes("\n")) return;
|
|
6764
|
+
context.report({
|
|
6765
|
+
node,
|
|
6766
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingParenIndex - spaceBeforeClosingParen.length, closingParenIndex]),
|
|
6767
|
+
messageId: "unexpectedNewlineBeforeClosingParen",
|
|
6768
|
+
fix: (fixer) => fixer.replaceTextRange([closingParenIndex - spaceBeforeClosingParen.length, closingParenIndex], " ")
|
|
6769
|
+
});
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
return {
|
|
6773
|
+
link(node) {
|
|
6774
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
6775
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
6776
|
+
if (!parsed) return;
|
|
6777
|
+
verifyNewlineAroundParens(node, parsed.openingParen.range[0], parsed.closingParen.range[0]);
|
|
6778
|
+
},
|
|
6779
|
+
image(node) {
|
|
6780
|
+
const parsed = parseImage(sourceCode, node);
|
|
6781
|
+
if (!parsed) return;
|
|
6782
|
+
verifyNewlineAroundParens(node, parsed.openingParen.range[0], parsed.closingParen.range[0]);
|
|
6783
|
+
}
|
|
6784
|
+
};
|
|
6785
|
+
/**
|
|
6786
|
+
* Get the spaces after the opening parenthesis.
|
|
6787
|
+
*/
|
|
6788
|
+
function getSpaceAfterOpeningParen(openingParenIndex) {
|
|
6789
|
+
for (let i = openingParenIndex + 1; i < sourceCode.text.length; i++) {
|
|
6790
|
+
const char = sourceCode.text[i];
|
|
6791
|
+
if (isWhitespace(char)) continue;
|
|
6792
|
+
return sourceCode.text.slice(openingParenIndex + 1, i);
|
|
6793
|
+
}
|
|
6794
|
+
return sourceCode.text.slice(openingParenIndex + 1);
|
|
6795
|
+
}
|
|
6796
|
+
/**
|
|
6797
|
+
* Get the spaces before the closing parenthesis.
|
|
6798
|
+
*/
|
|
6799
|
+
function getSpaceBeforeClosingParen(closingParenIndex) {
|
|
6800
|
+
for (let i = closingParenIndex - 1; i >= 0; i--) {
|
|
6801
|
+
const char = sourceCode.text[i];
|
|
6802
|
+
if (isWhitespace(char)) continue;
|
|
6803
|
+
return sourceCode.text.slice(i + 1, closingParenIndex);
|
|
6804
|
+
}
|
|
6805
|
+
return sourceCode.text.slice(0, closingParenIndex);
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
});
|
|
6809
|
+
|
|
6810
|
+
//#endregion
|
|
6811
|
+
//#region src/rules/link-paren-spacing.ts
|
|
6812
|
+
var link_paren_spacing_default = createRule("link-paren-spacing", {
|
|
6813
|
+
meta: {
|
|
6814
|
+
type: "layout",
|
|
6815
|
+
docs: {
|
|
6816
|
+
description: "enforce consistent spacing inside link parentheses",
|
|
6817
|
+
categories: ["standard"],
|
|
6818
|
+
listCategory: "Stylistic"
|
|
6819
|
+
},
|
|
6820
|
+
fixable: "whitespace",
|
|
6821
|
+
hasSuggestions: false,
|
|
6822
|
+
schema: [{
|
|
6823
|
+
type: "object",
|
|
6824
|
+
properties: { space: { enum: ["always", "never"] } },
|
|
6825
|
+
additionalProperties: false
|
|
6826
|
+
}],
|
|
6827
|
+
messages: {
|
|
6828
|
+
unexpectedSpaceAfterOpeningParen: "Unexpected space after opening parenthesis.",
|
|
6829
|
+
expectedSpaceAfterOpeningParen: "Expected space after opening parenthesis.",
|
|
6830
|
+
unexpectedSpaceBeforeClosingParen: "Unexpected space before closing parenthesis.",
|
|
6831
|
+
expectedSpaceBeforeClosingParen: "Expected space before closing parenthesis."
|
|
6832
|
+
}
|
|
6833
|
+
},
|
|
6834
|
+
create(context) {
|
|
6835
|
+
const sourceCode = context.sourceCode;
|
|
6836
|
+
const spaceOption = context.options[0]?.space || "never";
|
|
6837
|
+
/**
|
|
6838
|
+
* Verify the space after the opening paren and before the closing paren.
|
|
6839
|
+
*/
|
|
6840
|
+
function verifySpaceAfterOpeningParen(node, openingParen) {
|
|
6841
|
+
const space = getSpaceAfterOpeningParen(openingParen);
|
|
6842
|
+
if (space.includes("\n")) return;
|
|
6843
|
+
if (spaceOption === "always") {
|
|
6844
|
+
if (space.length > 0) return;
|
|
6845
|
+
context.report({
|
|
6846
|
+
node,
|
|
6847
|
+
loc: openingParen.loc,
|
|
6848
|
+
messageId: "expectedSpaceAfterOpeningParen",
|
|
6849
|
+
fix: (fixer) => fixer.insertTextAfterRange(openingParen.range, " ")
|
|
6850
|
+
});
|
|
6851
|
+
} else if (spaceOption === "never") {
|
|
6852
|
+
if (space.length === 0) return;
|
|
6853
|
+
context.report({
|
|
6854
|
+
node,
|
|
6855
|
+
loc: getSourceLocationFromRange(sourceCode, node, [openingParen.range[1], openingParen.range[1] + space.length]),
|
|
6856
|
+
messageId: "unexpectedSpaceAfterOpeningParen",
|
|
6857
|
+
fix: (fixer) => fixer.removeRange([openingParen.range[1], openingParen.range[1] + space.length])
|
|
6858
|
+
});
|
|
6859
|
+
}
|
|
6860
|
+
}
|
|
6861
|
+
/**
|
|
6862
|
+
* Verify the space before the closing paren.
|
|
6863
|
+
*/
|
|
6864
|
+
function verifySpaceBeforeClosingParen(node, closingParen) {
|
|
6865
|
+
const space = getSpaceBeforeClosingParen(closingParen);
|
|
6866
|
+
if (space.includes("\n")) return;
|
|
6867
|
+
if (spaceOption === "always") {
|
|
6868
|
+
if (space.length > 0) return;
|
|
6869
|
+
context.report({
|
|
6870
|
+
node,
|
|
6871
|
+
loc: closingParen.loc,
|
|
6872
|
+
messageId: "expectedSpaceBeforeClosingParen",
|
|
6873
|
+
fix: (fixer) => fixer.insertTextBeforeRange(closingParen.range, " ")
|
|
6874
|
+
});
|
|
6875
|
+
} else if (spaceOption === "never") {
|
|
6876
|
+
if (space.length === 0) return;
|
|
6877
|
+
context.report({
|
|
6878
|
+
node,
|
|
6879
|
+
loc: getSourceLocationFromRange(sourceCode, node, [closingParen.range[0] - space.length, closingParen.range[0]]),
|
|
6880
|
+
messageId: "unexpectedSpaceBeforeClosingParen",
|
|
6881
|
+
fix: (fixer) => fixer.removeRange([closingParen.range[0] - space.length, closingParen.range[0]])
|
|
6882
|
+
});
|
|
6883
|
+
}
|
|
6884
|
+
}
|
|
6885
|
+
return {
|
|
6886
|
+
link(node) {
|
|
6887
|
+
if (getLinkKind(sourceCode, node) !== "inline") return;
|
|
6888
|
+
const parsed = parseInlineLink(sourceCode, node);
|
|
6889
|
+
if (!parsed) return;
|
|
6890
|
+
verifySpaceAfterOpeningParen(node, parsed.openingParen);
|
|
6891
|
+
verifySpaceBeforeClosingParen(node, parsed.closingParen);
|
|
6892
|
+
},
|
|
6893
|
+
image(node) {
|
|
6894
|
+
const parsed = parseImage(sourceCode, node);
|
|
6895
|
+
if (!parsed) return;
|
|
6896
|
+
verifySpaceAfterOpeningParen(node, parsed.openingParen);
|
|
6897
|
+
verifySpaceBeforeClosingParen(node, parsed.closingParen);
|
|
6898
|
+
}
|
|
6899
|
+
};
|
|
6900
|
+
/**
|
|
6901
|
+
* Get the spaces after the opening paren.
|
|
6902
|
+
*/
|
|
6903
|
+
function getSpaceAfterOpeningParen(openingParen) {
|
|
6904
|
+
for (let i = openingParen.range[1]; i < sourceCode.text.length; i++) {
|
|
6905
|
+
const char = sourceCode.text[i];
|
|
6906
|
+
if (isWhitespace(char)) continue;
|
|
6907
|
+
return sourceCode.text.slice(openingParen.range[1], i);
|
|
6908
|
+
}
|
|
6909
|
+
return sourceCode.text.slice(openingParen.range[1]);
|
|
6910
|
+
}
|
|
6911
|
+
/**
|
|
6912
|
+
* Get the spaces before the closing paren.
|
|
6913
|
+
*/
|
|
6914
|
+
function getSpaceBeforeClosingParen(closingParen) {
|
|
6915
|
+
for (let i = closingParen.range[0] - 1; i >= 0; i--) {
|
|
6916
|
+
const char = sourceCode.text[i];
|
|
6917
|
+
if (isWhitespace(char)) continue;
|
|
6918
|
+
return sourceCode.text.slice(i + 1, closingParen.range[0]);
|
|
6919
|
+
}
|
|
6920
|
+
return sourceCode.text.slice(0, closingParen.range[0]);
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
});
|
|
6924
|
+
|
|
5627
6925
|
//#endregion
|
|
5628
6926
|
//#region src/rules/link-title-style.ts
|
|
5629
6927
|
const STYLES = {
|
|
@@ -5768,10 +7066,22 @@ var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
|
5768
7066
|
const items = listNode.children;
|
|
5769
7067
|
if (items.length <= 1) return;
|
|
5770
7068
|
const referenceMarkerLocation = getMarkerLocation(items[0]);
|
|
7069
|
+
const expectedWidth = getWidth(sourceCode.lines[referenceMarkerLocation.line - 1].slice(0, referenceMarkerLocation[alignPositionName]));
|
|
5771
7070
|
for (const item of items.slice(1)) {
|
|
5772
7071
|
const markerLocation = getMarkerLocation(item);
|
|
5773
|
-
const
|
|
7072
|
+
const actualWidth = getWidth(sourceCode.lines[markerLocation.line - 1].slice(0, markerLocation[alignPositionName]));
|
|
7073
|
+
const diff = actualWidth - expectedWidth;
|
|
5774
7074
|
if (diff === 0) continue;
|
|
7075
|
+
const messageData = alignPositionName === "start" ? {
|
|
7076
|
+
expected: String(expectedWidth),
|
|
7077
|
+
actual: String(actualWidth)
|
|
7078
|
+
} : (() => {
|
|
7079
|
+
const start = getWidth(sourceCode.lines[markerLocation.line - 1].slice(0, markerLocation.start));
|
|
7080
|
+
return {
|
|
7081
|
+
expected: String(start - diff),
|
|
7082
|
+
actual: String(start)
|
|
7083
|
+
};
|
|
7084
|
+
})();
|
|
5775
7085
|
context.report({
|
|
5776
7086
|
node: item,
|
|
5777
7087
|
loc: {
|
|
@@ -5785,10 +7095,7 @@ var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
|
5785
7095
|
}
|
|
5786
7096
|
},
|
|
5787
7097
|
messageId: "incorrectAlignment",
|
|
5788
|
-
data:
|
|
5789
|
-
expected: String(markerLocation.start - diff),
|
|
5790
|
-
actual: String(markerLocation.start)
|
|
5791
|
-
},
|
|
7098
|
+
data: messageData,
|
|
5792
7099
|
fix(fixer) {
|
|
5793
7100
|
const lines = getParsedLines(sourceCode);
|
|
5794
7101
|
const line = lines.get(markerLocation.line);
|
|
@@ -5796,13 +7103,17 @@ var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
|
5796
7103
|
const addSpaces = " ".repeat(-diff);
|
|
5797
7104
|
return fixer.insertTextBeforeRange([line.range[0] + markerLocation.start, line.range[0] + markerLocation.start], addSpaces);
|
|
5798
7105
|
}
|
|
5799
|
-
const
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
const
|
|
5804
|
-
|
|
7106
|
+
const beforeItemMarker = line.text.slice(0, markerLocation.start);
|
|
7107
|
+
const newWidth = getWidth(beforeItemMarker) - diff;
|
|
7108
|
+
let newBeforeItemMarker = beforeItemMarker;
|
|
7109
|
+
while (getWidth(newBeforeItemMarker) > newWidth) {
|
|
7110
|
+
const last = newBeforeItemMarker.at(-1);
|
|
7111
|
+
if (last && isWhitespace(last)) newBeforeItemMarker = newBeforeItemMarker.slice(0, -1);
|
|
7112
|
+
else return null;
|
|
5805
7113
|
}
|
|
7114
|
+
if (getWidth(newBeforeItemMarker) < newWidth) newBeforeItemMarker += " ".repeat(newWidth - getWidth(newBeforeItemMarker));
|
|
7115
|
+
const referenceBeforeItemMarker = lines.get(referenceMarkerLocation.line).text.slice(0, referenceMarkerLocation.start);
|
|
7116
|
+
if (!referenceBeforeItemMarker.includes(">") || referenceBeforeItemMarker === newBeforeItemMarker) return fixer.replaceTextRange([line.range[0], line.range[0] + markerLocation.start], newBeforeItemMarker);
|
|
5806
7117
|
return null;
|
|
5807
7118
|
}
|
|
5808
7119
|
});
|
|
@@ -5936,6 +7247,7 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
5936
7247
|
},
|
|
5937
7248
|
create(context) {
|
|
5938
7249
|
const sourceCode = context.sourceCode;
|
|
7250
|
+
let codeText = sourceCode.text;
|
|
5939
7251
|
return {
|
|
5940
7252
|
definition: verifyLinkDefinition,
|
|
5941
7253
|
footnoteDefinition: verifyFootnoteDefinition,
|
|
@@ -5945,6 +7257,7 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
5945
7257
|
link: verifyLink,
|
|
5946
7258
|
linkReference: verifyLinkReference,
|
|
5947
7259
|
listItem: verifyListItem,
|
|
7260
|
+
blockquote: processBlockquote,
|
|
5948
7261
|
text: verifyText
|
|
5949
7262
|
};
|
|
5950
7263
|
/**
|
|
@@ -6018,7 +7331,13 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
6018
7331
|
* Verify a list item node
|
|
6019
7332
|
*/
|
|
6020
7333
|
function verifyListItem(node) {
|
|
6021
|
-
|
|
7334
|
+
const nodeRange = sourceCode.getRange(node);
|
|
7335
|
+
const parsed = parseListItem(sourceCode, node);
|
|
7336
|
+
if (parsed.taskListItemMarker) verifyTextInRange(node, [nodeRange[0], parsed.taskListItemMarker.range[0]]);
|
|
7337
|
+
let newCodeText = codeText.slice(0, parsed.marker.range[0]) + " ".repeat(parsed.marker.range[1] - parsed.marker.range[0]);
|
|
7338
|
+
if (parsed.taskListItemMarker) newCodeText += codeText.slice(parsed.marker.range[1], parsed.taskListItemMarker.range[0]) + " ".repeat(parsed.taskListItemMarker.range[1] - parsed.taskListItemMarker.range[0]) + codeText.slice(parsed.taskListItemMarker.range[1]);
|
|
7339
|
+
else newCodeText += codeText.slice(parsed.marker.range[1]);
|
|
7340
|
+
codeText = newCodeText;
|
|
6022
7341
|
}
|
|
6023
7342
|
/**
|
|
6024
7343
|
* Verify spaces in a node
|
|
@@ -6028,6 +7347,26 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
6028
7347
|
verifyTextInRange(node, nodeRange);
|
|
6029
7348
|
}
|
|
6030
7349
|
/**
|
|
7350
|
+
* Process a blockquote node
|
|
7351
|
+
*/
|
|
7352
|
+
function processBlockquote(node) {
|
|
7353
|
+
const nodeRange = sourceCode.getRange(node);
|
|
7354
|
+
let newCodeText = "";
|
|
7355
|
+
let inIndent = true;
|
|
7356
|
+
for (let index = nodeRange[0]; index < nodeRange[1]; index++) {
|
|
7357
|
+
const c = codeText[index];
|
|
7358
|
+
if (c === "\n") {
|
|
7359
|
+
inIndent = true;
|
|
7360
|
+
continue;
|
|
7361
|
+
}
|
|
7362
|
+
if (isWhitespace(c)) continue;
|
|
7363
|
+
if (c === ">" && inIndent) newCodeText += `${codeText.slice(newCodeText.length, index)} `;
|
|
7364
|
+
inIndent = false;
|
|
7365
|
+
}
|
|
7366
|
+
newCodeText += codeText.slice(newCodeText.length);
|
|
7367
|
+
codeText = newCodeText;
|
|
7368
|
+
}
|
|
7369
|
+
/**
|
|
6031
7370
|
* Verify spaces in a node excluding children
|
|
6032
7371
|
*/
|
|
6033
7372
|
function verifyTextOutsideChildren(node) {
|
|
@@ -6046,14 +7385,14 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
6046
7385
|
*/
|
|
6047
7386
|
function verifyTextInRange(node, textRange) {
|
|
6048
7387
|
const nodeRange = sourceCode.getRange(node);
|
|
6049
|
-
const text =
|
|
7388
|
+
const text = codeText.slice(...textRange);
|
|
6050
7389
|
const reSpaces = /\s{2,}|\n/gu;
|
|
6051
7390
|
let match;
|
|
6052
7391
|
while ((match = reSpaces.exec(text)) !== null) {
|
|
6053
7392
|
const spaces = match[0];
|
|
6054
7393
|
if (spaces.includes("\n")) {
|
|
6055
7394
|
let c = "";
|
|
6056
|
-
while ((c = text[reSpaces.lastIndex]) && (c
|
|
7395
|
+
while ((c = text[reSpaces.lastIndex]) && isWhitespace(c)) reSpaces.lastIndex++;
|
|
6057
7396
|
continue;
|
|
6058
7397
|
}
|
|
6059
7398
|
if (spaces.length < 2) continue;
|
|
@@ -6063,7 +7402,7 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
6063
7402
|
if (nodeRange[0] === range[0]) {
|
|
6064
7403
|
let isIndentation = true;
|
|
6065
7404
|
for (let index = nodeRange[0] - 1; index >= 0; index--) {
|
|
6066
|
-
const c =
|
|
7405
|
+
const c = codeText[index];
|
|
6067
7406
|
if (c === "\n") break;
|
|
6068
7407
|
if (isWhitespace(c)) continue;
|
|
6069
7408
|
isIndentation = false;
|
|
@@ -6073,8 +7412,8 @@ var no_multi_spaces_default = createRule("no-multi-spaces", {
|
|
|
6073
7412
|
}
|
|
6074
7413
|
if (nodeRange[1] === range[1]) {
|
|
6075
7414
|
let isTrailingSpaces = true;
|
|
6076
|
-
for (let index = nodeRange[1]; index <
|
|
6077
|
-
const c =
|
|
7415
|
+
for (let index = nodeRange[1]; index < codeText.length; index++) {
|
|
7416
|
+
const c = codeText[index];
|
|
6078
7417
|
if (c === "\n") break;
|
|
6079
7418
|
if (isWhitespace(c)) continue;
|
|
6080
7419
|
isTrailingSpaces = false;
|
|
@@ -8538,11 +9877,14 @@ const rules$1 = [
|
|
|
8538
9877
|
emphasis_delimiters_style_default,
|
|
8539
9878
|
hard_linebreak_style_default,
|
|
8540
9879
|
heading_casing_default,
|
|
9880
|
+
indent_default,
|
|
8541
9881
|
level1_heading_style_default,
|
|
8542
9882
|
level2_heading_style_default,
|
|
8543
9883
|
link_bracket_newline_default,
|
|
8544
9884
|
link_bracket_spacing_default,
|
|
8545
9885
|
link_destination_style_default,
|
|
9886
|
+
link_paren_newline_default,
|
|
9887
|
+
link_paren_spacing_default,
|
|
8546
9888
|
link_title_style_default,
|
|
8547
9889
|
list_marker_alignment_default,
|
|
8548
9890
|
no_laziness_blockquotes_default,
|
|
@@ -8570,8 +9912,7 @@ const rules$1 = [
|
|
|
8570
9912
|
|
|
8571
9913
|
//#endregion
|
|
8572
9914
|
//#region src/configs/recommended.ts
|
|
8573
|
-
var recommended_exports = {
|
|
8574
|
-
__export(recommended_exports, {
|
|
9915
|
+
var recommended_exports = __export({
|
|
8575
9916
|
files: () => files$1,
|
|
8576
9917
|
language: () => language$1,
|
|
8577
9918
|
languageOptions: () => languageOptions$1,
|
|
@@ -8601,8 +9942,7 @@ const rules$3 = {
|
|
|
8601
9942
|
|
|
8602
9943
|
//#endregion
|
|
8603
9944
|
//#region src/configs/standard.ts
|
|
8604
|
-
var standard_exports = {
|
|
8605
|
-
__export(standard_exports, {
|
|
9945
|
+
var standard_exports = __export({
|
|
8606
9946
|
files: () => files,
|
|
8607
9947
|
language: () => language,
|
|
8608
9948
|
languageOptions: () => languageOptions,
|
|
@@ -8629,11 +9969,14 @@ const rules$2 = {
|
|
|
8629
9969
|
"markdown-preferences/code-fence-style": "error",
|
|
8630
9970
|
"markdown-preferences/emphasis-delimiters-style": "error",
|
|
8631
9971
|
"markdown-preferences/hard-linebreak-style": "error",
|
|
9972
|
+
"markdown-preferences/indent": "error",
|
|
8632
9973
|
"markdown-preferences/level1-heading-style": "error",
|
|
8633
9974
|
"markdown-preferences/level2-heading-style": "error",
|
|
8634
9975
|
"markdown-preferences/link-bracket-newline": "error",
|
|
8635
9976
|
"markdown-preferences/link-bracket-spacing": "error",
|
|
8636
9977
|
"markdown-preferences/link-destination-style": "error",
|
|
9978
|
+
"markdown-preferences/link-paren-newline": "error",
|
|
9979
|
+
"markdown-preferences/link-paren-spacing": "error",
|
|
8637
9980
|
"markdown-preferences/link-title-style": "error",
|
|
8638
9981
|
"markdown-preferences/list-marker-alignment": "error",
|
|
8639
9982
|
"markdown-preferences/no-laziness-blockquotes": "error",
|
|
@@ -8657,13 +10000,12 @@ const rules$2 = {
|
|
|
8657
10000
|
|
|
8658
10001
|
//#endregion
|
|
8659
10002
|
//#region src/meta.ts
|
|
8660
|
-
var meta_exports = {
|
|
8661
|
-
__export(meta_exports, {
|
|
10003
|
+
var meta_exports = __export({
|
|
8662
10004
|
name: () => name,
|
|
8663
10005
|
version: () => version
|
|
8664
10006
|
});
|
|
8665
10007
|
const name = "eslint-plugin-markdown-preferences";
|
|
8666
|
-
const version = "0.
|
|
10008
|
+
const version = "0.24.0";
|
|
8667
10009
|
|
|
8668
10010
|
//#endregion
|
|
8669
10011
|
//#region src/index.ts
|