eslint-plugin-markdown-preferences 0.17.0 → 0.19.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 +8 -2
- package/lib/index.d.ts +83 -7
- package/lib/index.js +1083 -240
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -73,13 +73,19 @@ function getListItemMarker(sourceCode, node) {
|
|
|
73
73
|
if (matchDot) return {
|
|
74
74
|
kind: ".",
|
|
75
75
|
raw: matchDot[0],
|
|
76
|
-
sequence:
|
|
76
|
+
sequence: {
|
|
77
|
+
value: Number(matchDot[1]),
|
|
78
|
+
raw: matchDot[1]
|
|
79
|
+
}
|
|
77
80
|
};
|
|
78
81
|
const matchParen = /^(\d+)\)/.exec(text);
|
|
79
82
|
return {
|
|
80
83
|
kind: ")",
|
|
81
84
|
raw: matchParen[0],
|
|
82
|
-
sequence:
|
|
85
|
+
sequence: {
|
|
86
|
+
value: Number(matchParen[1]),
|
|
87
|
+
raw: matchParen[1]
|
|
88
|
+
}
|
|
83
89
|
};
|
|
84
90
|
}
|
|
85
91
|
/**
|
|
@@ -124,58 +130,162 @@ function getSourceLocationFromRange(sourceCode, node, range) {
|
|
|
124
130
|
};
|
|
125
131
|
}
|
|
126
132
|
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/utils/unicode.ts
|
|
135
|
+
/**
|
|
136
|
+
* Check if the string is whitespace
|
|
137
|
+
*/
|
|
138
|
+
function isWhitespace(string) {
|
|
139
|
+
return /^[\p{Zs}\t\n\f\r]+$/u.test(string);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if the string is a space or tab
|
|
143
|
+
*/
|
|
144
|
+
function isSpaceOrTab(string) {
|
|
145
|
+
return /^[\t ]+$/u.test(string);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if the character is a punctuation character
|
|
149
|
+
*/
|
|
150
|
+
function isPunctuation(char) {
|
|
151
|
+
return /^[\p{P}\p{S}]+$/u.test(char);
|
|
152
|
+
}
|
|
153
|
+
|
|
127
154
|
//#endregion
|
|
128
155
|
//#region src/utils/atx-heading.ts
|
|
129
156
|
/**
|
|
130
|
-
* Parse the
|
|
157
|
+
* Parse the ATX heading.
|
|
131
158
|
*/
|
|
132
|
-
function
|
|
159
|
+
function parseATXHeading(sourceCode, node) {
|
|
133
160
|
if (getHeadingKind(sourceCode, node) !== "atx") return null;
|
|
134
161
|
const loc = sourceCode.getLoc(node);
|
|
135
162
|
const range = sourceCode.getRange(node);
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
const text = sourceCode.text.slice(...range);
|
|
164
|
+
const parsedOpening = parseATXHeadingOpeningSequenceFromText(text);
|
|
165
|
+
if (parsedOpening === null) return null;
|
|
166
|
+
const openingSequence = {
|
|
167
|
+
text: parsedOpening.openingSequence,
|
|
168
|
+
range: [range[0], range[0] + parsedOpening.openingSequence.length],
|
|
169
|
+
loc: {
|
|
170
|
+
start: loc.start,
|
|
171
|
+
end: {
|
|
172
|
+
line: loc.start.line,
|
|
173
|
+
column: loc.start.column + parsedOpening.openingSequence.length
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const spaceAfterOpening = {
|
|
178
|
+
text: parsedOpening.rawAfter,
|
|
179
|
+
range: [openingSequence.range[1], openingSequence.range[1] + parsedOpening.rawAfter.length],
|
|
180
|
+
loc: {
|
|
181
|
+
start: openingSequence.loc.end,
|
|
182
|
+
end: {
|
|
183
|
+
line: openingSequence.loc.end.line,
|
|
184
|
+
column: openingSequence.loc.end.column + parsedOpening.rawAfter.length
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const parsedClosing = parseATXHeadingClosingSequenceFromText(text);
|
|
189
|
+
if (parsedClosing == null) {
|
|
190
|
+
const textAfterOpening = sourceCode.text.slice(spaceAfterOpening.range[1], range[1]);
|
|
191
|
+
const contentText$1 = textAfterOpening.trimEnd();
|
|
192
|
+
return {
|
|
193
|
+
openingSequence: {
|
|
194
|
+
...openingSequence,
|
|
195
|
+
raws: { spaceAfter: spaceAfterOpening }
|
|
196
|
+
},
|
|
197
|
+
content: {
|
|
198
|
+
text: contentText$1,
|
|
199
|
+
range: [spaceAfterOpening.range[1], spaceAfterOpening.range[1] + contentText$1.length],
|
|
200
|
+
loc: {
|
|
201
|
+
start: spaceAfterOpening.loc.end,
|
|
202
|
+
end: {
|
|
203
|
+
line: loc.end.line,
|
|
204
|
+
column: loc.end.column - (textAfterOpening.length - contentText$1.length)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
closingSequence: null
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const spaceAfterClosing = {
|
|
212
|
+
text: parsedClosing.rawAfter,
|
|
213
|
+
range: [range[1] - parsedClosing.rawAfter.length, range[1]],
|
|
141
214
|
loc: {
|
|
142
215
|
start: {
|
|
143
216
|
line: loc.end.line,
|
|
144
|
-
column: loc.end.column -
|
|
217
|
+
column: loc.end.column - parsedClosing.rawAfter.length
|
|
145
218
|
},
|
|
146
|
-
end:
|
|
147
|
-
line: loc.end.line,
|
|
148
|
-
column: loc.end.column
|
|
149
|
-
}
|
|
219
|
+
end: loc.end
|
|
150
220
|
}
|
|
151
221
|
};
|
|
152
222
|
const closingSequence = {
|
|
153
|
-
text:
|
|
154
|
-
range: [
|
|
223
|
+
text: parsedClosing.closingSequence,
|
|
224
|
+
range: [spaceAfterClosing.range[0] - parsedClosing.closingSequence.length, spaceAfterClosing.range[0]],
|
|
155
225
|
loc: {
|
|
156
226
|
start: {
|
|
157
|
-
line:
|
|
158
|
-
column:
|
|
227
|
+
line: spaceAfterClosing.loc.start.line,
|
|
228
|
+
column: spaceAfterClosing.loc.start.column - parsedClosing.closingSequence.length
|
|
159
229
|
},
|
|
160
|
-
end:
|
|
230
|
+
end: spaceAfterClosing.loc.start
|
|
161
231
|
}
|
|
162
232
|
};
|
|
163
|
-
const
|
|
164
|
-
text:
|
|
165
|
-
range: [closingSequence.range[0] -
|
|
233
|
+
const spaceBeforeClosing = {
|
|
234
|
+
text: parsedClosing.rawBefore,
|
|
235
|
+
range: [closingSequence.range[0] - parsedClosing.rawBefore.length, closingSequence.range[0]],
|
|
166
236
|
loc: {
|
|
167
237
|
start: {
|
|
168
238
|
line: closingSequence.loc.start.line,
|
|
169
|
-
column: closingSequence.loc.start.column -
|
|
239
|
+
column: closingSequence.loc.start.column - parsedClosing.rawBefore.length
|
|
170
240
|
},
|
|
171
241
|
end: closingSequence.loc.start
|
|
172
242
|
}
|
|
173
243
|
};
|
|
244
|
+
const contentText = sourceCode.text.slice(spaceAfterOpening.range[1], spaceBeforeClosing.range[0]);
|
|
245
|
+
return {
|
|
246
|
+
openingSequence: {
|
|
247
|
+
...openingSequence,
|
|
248
|
+
raws: { spaceAfter: spaceAfterOpening }
|
|
249
|
+
},
|
|
250
|
+
content: {
|
|
251
|
+
text: contentText,
|
|
252
|
+
range: [spaceAfterOpening.range[1], spaceBeforeClosing.range[0]],
|
|
253
|
+
loc: {
|
|
254
|
+
start: spaceAfterOpening.loc.end,
|
|
255
|
+
end: spaceBeforeClosing.loc.start
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
closingSequence: {
|
|
259
|
+
...closingSequence,
|
|
260
|
+
raws: {
|
|
261
|
+
spaceBefore: spaceBeforeClosing,
|
|
262
|
+
spaceAfter: spaceAfterClosing
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Parse the opening sequence from a text string.
|
|
269
|
+
*/
|
|
270
|
+
function parseATXHeadingOpeningSequenceFromText(text) {
|
|
271
|
+
if (!text.startsWith("#")) return null;
|
|
272
|
+
let openingSequenceAfterOffset = 1;
|
|
273
|
+
while (openingSequenceAfterOffset < text.length && text[openingSequenceAfterOffset] === "#") openingSequenceAfterOffset++;
|
|
274
|
+
const afterOffset = skipWhitespace(openingSequenceAfterOffset);
|
|
275
|
+
if (afterOffset === openingSequenceAfterOffset || afterOffset >= text.length) return null;
|
|
174
276
|
return {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
rawAfter
|
|
277
|
+
openingSequence: text.slice(0, openingSequenceAfterOffset),
|
|
278
|
+
rawAfter: text.slice(openingSequenceAfterOffset, afterOffset)
|
|
178
279
|
};
|
|
280
|
+
/**
|
|
281
|
+
* Skip whitespace characters at the start of the text.
|
|
282
|
+
*/
|
|
283
|
+
function skipWhitespace(index) {
|
|
284
|
+
let result = index;
|
|
285
|
+
let c;
|
|
286
|
+
while (result < text.length && (c = text[result]) && isSpaceOrTab(c)) result++;
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
179
289
|
}
|
|
180
290
|
/**
|
|
181
291
|
* Parse the closing sequence from a text string.
|
|
@@ -198,7 +308,7 @@ function parseATXHeadingClosingSequenceFromText(text) {
|
|
|
198
308
|
function skipEndWhitespace(index) {
|
|
199
309
|
let result = index;
|
|
200
310
|
let c;
|
|
201
|
-
while (result >= 0 && (c = text[result]) && (c
|
|
311
|
+
while (result >= 0 && (c = text[result]) && isSpaceOrTab(c)) result--;
|
|
202
312
|
return result;
|
|
203
313
|
}
|
|
204
314
|
}
|
|
@@ -271,8 +381,8 @@ function getTextWidth(text) {
|
|
|
271
381
|
}
|
|
272
382
|
|
|
273
383
|
//#endregion
|
|
274
|
-
//#region src/rules/atx-
|
|
275
|
-
var
|
|
384
|
+
//#region src/rules/atx-heading-closing-sequence-length.ts
|
|
385
|
+
var atx_heading_closing_sequence_length_default = createRule("atx-heading-closing-sequence-length", {
|
|
276
386
|
meta: {
|
|
277
387
|
type: "layout",
|
|
278
388
|
docs: {
|
|
@@ -307,14 +417,11 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
307
417
|
/**
|
|
308
418
|
* Verify the closing sequence length of an ATX heading.
|
|
309
419
|
*/
|
|
310
|
-
function verifyATXHeadingClosingSequenceLength(
|
|
311
|
-
const parsed = parseATXHeadingClosingSequence(sourceCode, node);
|
|
312
|
-
if (!parsed || parsed.closingSequence == null) return;
|
|
420
|
+
function verifyATXHeadingClosingSequenceLength(parsed, reportNode, expectedLength) {
|
|
313
421
|
const actualLength = parsed.closingSequence.text.length;
|
|
314
|
-
const expectedLength = getExpected(node, parsed);
|
|
315
422
|
if (expectedLength === actualLength) return;
|
|
316
423
|
context.report({
|
|
317
|
-
node,
|
|
424
|
+
node: reportNode,
|
|
318
425
|
loc: parsed.closingSequence.loc,
|
|
319
426
|
messageId: "wrongClosingLength",
|
|
320
427
|
data: {
|
|
@@ -326,40 +433,41 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
326
433
|
}
|
|
327
434
|
});
|
|
328
435
|
}
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
436
|
+
if (option.mode === "match-opening") return { heading(node) {
|
|
437
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
438
|
+
if (!parsed || parsed.closingSequence == null) return;
|
|
439
|
+
verifyATXHeadingClosingSequenceLength(parsed, node, node.depth);
|
|
440
|
+
} };
|
|
441
|
+
if (option.mode === "length") {
|
|
335
442
|
const expected = option.length || 2;
|
|
336
|
-
const getExpected = () => expected;
|
|
337
443
|
return { heading(node) {
|
|
338
|
-
|
|
444
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
445
|
+
if (!parsed || parsed.closingSequence == null) return;
|
|
446
|
+
verifyATXHeadingClosingSequenceLength(parsed, node, expected);
|
|
339
447
|
} };
|
|
340
|
-
}
|
|
448
|
+
}
|
|
449
|
+
if (option.mode === "fixed-line-length") {
|
|
341
450
|
const totalLength = option.length || 80;
|
|
342
|
-
const getExpected = (_node, parsed) => {
|
|
343
|
-
return totalLength - getContentLength(parsed);
|
|
344
|
-
};
|
|
345
451
|
return { heading(node) {
|
|
346
|
-
|
|
452
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
453
|
+
if (!parsed || parsed.closingSequence == null) return;
|
|
454
|
+
verifyATXHeadingClosingSequenceLength(parsed, node, totalLength - getContentLength(parsed));
|
|
347
455
|
} };
|
|
348
|
-
}
|
|
349
|
-
|
|
456
|
+
}
|
|
457
|
+
if (option.mode === "consistent") {
|
|
458
|
+
let expectedLength = null;
|
|
350
459
|
return { heading(node) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
getExpected = () => expected;
|
|
356
|
-
} else verifyATXHeadingClosingSequenceLength(node, getExpected);
|
|
460
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
461
|
+
if (!parsed || parsed.closingSequence == null) return;
|
|
462
|
+
if (expectedLength == null) expectedLength = parsed.closingSequence.text.length;
|
|
463
|
+
else verifyATXHeadingClosingSequenceLength(parsed, node, expectedLength);
|
|
357
464
|
} };
|
|
358
|
-
}
|
|
465
|
+
}
|
|
466
|
+
if (option.mode === "consistent-line-length") {
|
|
359
467
|
const headings = [];
|
|
360
468
|
return {
|
|
361
469
|
heading(node) {
|
|
362
|
-
const parsed =
|
|
470
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
363
471
|
if (!parsed || !parsed.closingSequence) return;
|
|
364
472
|
headings.push({
|
|
365
473
|
node,
|
|
@@ -385,13 +493,11 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
385
493
|
const lineLength = getLineLength(heading.parsed);
|
|
386
494
|
if (mostLongContentHeading.contentLength < lineLength && lineLength < minLineLength) minLineLength = Math.min(minLineLength, lineLength);
|
|
387
495
|
}
|
|
388
|
-
const
|
|
389
|
-
return minLineLength - getContentLength(parsed);
|
|
390
|
-
};
|
|
391
|
-
for (const { node } of headings) verifyATXHeadingClosingSequenceLength(node, getExpected);
|
|
496
|
+
for (const heading of headings) verifyATXHeadingClosingSequenceLength(heading.parsed, heading.node, minLineLength - getContentLength(heading.parsed));
|
|
392
497
|
}
|
|
393
498
|
};
|
|
394
|
-
}
|
|
499
|
+
}
|
|
500
|
+
return {};
|
|
395
501
|
/**
|
|
396
502
|
* Get the content length of the heading.
|
|
397
503
|
*/
|
|
@@ -414,8 +520,8 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
414
520
|
});
|
|
415
521
|
|
|
416
522
|
//#endregion
|
|
417
|
-
//#region src/rules/atx-
|
|
418
|
-
var
|
|
523
|
+
//#region src/rules/atx-heading-closing-sequence.ts
|
|
524
|
+
var atx_heading_closing_sequence_default = createRule("atx-heading-closing-sequence", {
|
|
419
525
|
meta: {
|
|
420
526
|
type: "layout",
|
|
421
527
|
docs: {
|
|
@@ -443,7 +549,7 @@ var atx_headings_closing_sequence_default = createRule("atx-headings-closing-seq
|
|
|
443
549
|
if (opt.closingSequence === "always" || opt.closingSequence === "never") closingSequence = opt.closingSequence;
|
|
444
550
|
}
|
|
445
551
|
return { heading(node) {
|
|
446
|
-
const parsed =
|
|
552
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
447
553
|
if (!parsed) return;
|
|
448
554
|
if (closingSequence === "always") {
|
|
449
555
|
if (parsed.closingSequence) return;
|
|
@@ -460,12 +566,12 @@ var atx_headings_closing_sequence_default = createRule("atx-headings-closing-seq
|
|
|
460
566
|
context.report({
|
|
461
567
|
node,
|
|
462
568
|
loc: {
|
|
463
|
-
start: parsed.
|
|
569
|
+
start: parsed.closingSequence.raws.spaceBefore.loc.start,
|
|
464
570
|
end: parsed.closingSequence.loc.end
|
|
465
571
|
},
|
|
466
572
|
messageId: "forbidClosing",
|
|
467
573
|
*fix(fixer) {
|
|
468
|
-
const removeRange = [parsed.
|
|
574
|
+
const removeRange = [parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.range[1]];
|
|
469
575
|
const newHeadingText = sourceCode.text.slice(sourceCode.getRange(node)[0], removeRange[0]);
|
|
470
576
|
const newHeadingParsed = parseATXHeadingClosingSequenceFromText(newHeadingText);
|
|
471
577
|
if (newHeadingParsed) {
|
|
@@ -597,6 +703,176 @@ var blockquote_marker_alignment_default = createRule("blockquote-marker-alignmen
|
|
|
597
703
|
}
|
|
598
704
|
});
|
|
599
705
|
|
|
706
|
+
//#endregion
|
|
707
|
+
//#region src/rules/bullet-list-marker-style.ts
|
|
708
|
+
const MARKERS$1 = [
|
|
709
|
+
"-",
|
|
710
|
+
"*",
|
|
711
|
+
"+"
|
|
712
|
+
];
|
|
713
|
+
/**
|
|
714
|
+
* Get the other marker.
|
|
715
|
+
*/
|
|
716
|
+
function getOtherMarker(unavailableMarker) {
|
|
717
|
+
return MARKERS$1.find((mark) => unavailableMarker !== mark);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Parse rule options.
|
|
721
|
+
*/
|
|
722
|
+
function parseOptions$1(options) {
|
|
723
|
+
const primary = options.primary || "-";
|
|
724
|
+
const secondary = options.secondary || getOtherMarker(primary);
|
|
725
|
+
if (primary === secondary) throw new Error(`\`primary\` and \`secondary\` cannot be the same (primary: "${primary}", secondary: "${secondary}").`);
|
|
726
|
+
const overrides = (options.overrides ?? []).map((override, index) => {
|
|
727
|
+
const primaryForOverride = override.primary || "-";
|
|
728
|
+
const secondaryForOverride = override.secondary || getOtherMarker(primaryForOverride);
|
|
729
|
+
if (primaryForOverride === secondaryForOverride) throw new Error(`overrides[${index}]: \`primary\` and \`secondary\` cannot be the same (primary: "${primaryForOverride}", secondary: "${secondaryForOverride}").`);
|
|
730
|
+
return {
|
|
731
|
+
level: override.level,
|
|
732
|
+
parentMarker: override.parentMarker ?? "any",
|
|
733
|
+
primary: primaryForOverride,
|
|
734
|
+
secondary: secondaryForOverride
|
|
735
|
+
};
|
|
736
|
+
}).reverse();
|
|
737
|
+
return { get(level, parentMarker) {
|
|
738
|
+
for (const o of overrides) if ((o.level == null || o.level === level) && (o.parentMarker === "any" || o.parentMarker === parentMarker)) return {
|
|
739
|
+
primary: o.primary,
|
|
740
|
+
secondary: o.secondary
|
|
741
|
+
};
|
|
742
|
+
return {
|
|
743
|
+
primary,
|
|
744
|
+
secondary
|
|
745
|
+
};
|
|
746
|
+
} };
|
|
747
|
+
}
|
|
748
|
+
var bullet_list_marker_style_default = createRule("bullet-list-marker-style", {
|
|
749
|
+
meta: {
|
|
750
|
+
type: "layout",
|
|
751
|
+
docs: {
|
|
752
|
+
description: "enforce consistent bullet list (unordered list) marker style",
|
|
753
|
+
categories: [],
|
|
754
|
+
listCategory: "Stylistic"
|
|
755
|
+
},
|
|
756
|
+
fixable: "code",
|
|
757
|
+
hasSuggestions: false,
|
|
758
|
+
schema: [{
|
|
759
|
+
type: "object",
|
|
760
|
+
properties: {
|
|
761
|
+
primary: { enum: MARKERS$1 },
|
|
762
|
+
secondary: { enum: [...MARKERS$1, "any"] },
|
|
763
|
+
overrides: {
|
|
764
|
+
type: "array",
|
|
765
|
+
items: {
|
|
766
|
+
type: "object",
|
|
767
|
+
properties: {
|
|
768
|
+
level: {
|
|
769
|
+
type: "integer",
|
|
770
|
+
minimum: 1
|
|
771
|
+
},
|
|
772
|
+
parentMarker: { enum: [
|
|
773
|
+
...MARKERS$1,
|
|
774
|
+
"any",
|
|
775
|
+
"ordered"
|
|
776
|
+
] },
|
|
777
|
+
primary: { enum: MARKERS$1 },
|
|
778
|
+
secondary: { enum: [...MARKERS$1, "any"] }
|
|
779
|
+
},
|
|
780
|
+
additionalProperties: false
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
},
|
|
784
|
+
additionalProperties: false
|
|
785
|
+
}],
|
|
786
|
+
messages: { unexpected: "Bullet list marker should be '{{marker}}'." }
|
|
787
|
+
},
|
|
788
|
+
create(context) {
|
|
789
|
+
const sourceCode = context.sourceCode;
|
|
790
|
+
const options = parseOptions$1(context.options[0] || {});
|
|
791
|
+
let containerStack = {
|
|
792
|
+
node: sourceCode.ast,
|
|
793
|
+
level: 1,
|
|
794
|
+
upper: null
|
|
795
|
+
};
|
|
796
|
+
/**
|
|
797
|
+
* Check bullet list marker style
|
|
798
|
+
*/
|
|
799
|
+
function checkBulletList(node) {
|
|
800
|
+
let parentMarker;
|
|
801
|
+
if (containerStack.node.type === "listItem") {
|
|
802
|
+
const parentMarkerKind = getListItemMarker(sourceCode, containerStack.node).kind;
|
|
803
|
+
parentMarker = parentMarkerKind === "." || parentMarkerKind === ")" ? "ordered" : parentMarkerKind;
|
|
804
|
+
} else parentMarker = "top";
|
|
805
|
+
const { primary, secondary } = options.get(containerStack.level, parentMarker);
|
|
806
|
+
const nodeIndex = containerStack.node.children.indexOf(node);
|
|
807
|
+
if (nodeIndex === -1) return;
|
|
808
|
+
const prevNode = nodeIndex > 0 ? containerStack.node.children[nodeIndex - 1] : null;
|
|
809
|
+
const prevBulletList = prevNode && (prevNode.type === "list" ? prevNode : null);
|
|
810
|
+
const prevBulletListMarker = prevBulletList && getListItemMarker(sourceCode, prevBulletList);
|
|
811
|
+
const expectedMarker = prevBulletListMarker?.kind !== primary ? primary : secondary;
|
|
812
|
+
if (expectedMarker === "any") return;
|
|
813
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
814
|
+
if (marker.kind === expectedMarker) return;
|
|
815
|
+
const loc = sourceCode.getLoc(node);
|
|
816
|
+
context.report({
|
|
817
|
+
node,
|
|
818
|
+
loc: {
|
|
819
|
+
start: loc.start,
|
|
820
|
+
end: {
|
|
821
|
+
line: loc.start.line,
|
|
822
|
+
column: loc.start.column + marker.raw.length
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
messageId: "unexpected",
|
|
826
|
+
data: { marker: expectedMarker },
|
|
827
|
+
*fix(fixer) {
|
|
828
|
+
if (prevNode?.type === "list" && prevBulletListMarker && (prevBulletListMarker.kind === "-" || prevBulletListMarker.kind === "*" || prevBulletListMarker.kind === "+")) yield fixMarker(prevNode.children[0], prevBulletListMarker.kind);
|
|
829
|
+
yield* fixMarkers(node, expectedMarker);
|
|
830
|
+
let prevMarker = expectedMarker;
|
|
831
|
+
for (let index = nodeIndex + 1; index < containerStack.node.children.length; index++) {
|
|
832
|
+
const nextNode = containerStack.node.children[index];
|
|
833
|
+
if (nextNode.type !== "list") break;
|
|
834
|
+
const nextMarker = getListItemMarker(sourceCode, nextNode);
|
|
835
|
+
if (nextMarker.kind !== prevMarker) break;
|
|
836
|
+
let expectedNextMarker = prevMarker === primary ? secondary : primary;
|
|
837
|
+
if (expectedNextMarker === "any") expectedNextMarker = getOtherMarker(prevMarker);
|
|
838
|
+
yield* fixMarkers(nextNode, expectedNextMarker);
|
|
839
|
+
prevMarker = expectedNextMarker;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Fix bullet list markers
|
|
843
|
+
*/
|
|
844
|
+
function* fixMarkers(list, replacementMarker) {
|
|
845
|
+
for (const item of list.children) yield fixMarker(item, replacementMarker);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Fix bullet list item marker
|
|
849
|
+
*/
|
|
850
|
+
function fixMarker(item, replacementMarker) {
|
|
851
|
+
const range = sourceCode.getRange(item);
|
|
852
|
+
return fixer.replaceTextRange([range[0], range[0] + 1], replacementMarker);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
return {
|
|
858
|
+
list(node) {
|
|
859
|
+
if (node.ordered) return;
|
|
860
|
+
checkBulletList(node);
|
|
861
|
+
},
|
|
862
|
+
"root, blockquote, listItem, footnoteDefinition"(node) {
|
|
863
|
+
containerStack = {
|
|
864
|
+
node,
|
|
865
|
+
level: node.type === "listItem" ? containerStack.level + 1 : 1,
|
|
866
|
+
upper: containerStack
|
|
867
|
+
};
|
|
868
|
+
},
|
|
869
|
+
"root, blockquote, listItem, footnoteDefinition:exit"() {
|
|
870
|
+
containerStack = containerStack.upper;
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
|
|
600
876
|
//#endregion
|
|
601
877
|
//#region src/rules/canonical-code-block-language.ts
|
|
602
878
|
const DEFAULT_LANGUAGES = {
|
|
@@ -2788,6 +3064,199 @@ var emoji_notation_default = createRule("emoji-notation", {
|
|
|
2788
3064
|
}
|
|
2789
3065
|
});
|
|
2790
3066
|
|
|
3067
|
+
//#endregion
|
|
3068
|
+
//#region src/rules/emphasis-delimiters-style.ts
|
|
3069
|
+
/**
|
|
3070
|
+
* Check if the emphasis/strong node is intraword (inside a word)
|
|
3071
|
+
* CommonMark: Intraword emphasis with _ is not allowed
|
|
3072
|
+
*/
|
|
3073
|
+
function isIntrawordForUnderline(text, range) {
|
|
3074
|
+
const before = text[range[0] - 1];
|
|
3075
|
+
if (!isWhitespace(before) && !isPunctuation(before)) return true;
|
|
3076
|
+
const after = text[range[1]];
|
|
3077
|
+
if (!isWhitespace(after) && !isPunctuation(after)) return true;
|
|
3078
|
+
return false;
|
|
3079
|
+
}
|
|
3080
|
+
var emphasis_delimiters_style_default = createRule("emphasis-delimiters-style", {
|
|
3081
|
+
meta: {
|
|
3082
|
+
type: "layout",
|
|
3083
|
+
docs: {
|
|
3084
|
+
description: "enforce a consistent delimiter style for emphasis and strong emphasis",
|
|
3085
|
+
categories: [],
|
|
3086
|
+
listCategory: "Stylistic"
|
|
3087
|
+
},
|
|
3088
|
+
fixable: "code",
|
|
3089
|
+
hasSuggestions: false,
|
|
3090
|
+
schema: [{
|
|
3091
|
+
type: "object",
|
|
3092
|
+
properties: {
|
|
3093
|
+
emphasis: { enum: ["*", "_"] },
|
|
3094
|
+
strong: { enum: ["**", "__"] },
|
|
3095
|
+
strongEmphasis: { anyOf: [
|
|
3096
|
+
{ enum: ["***", "___"] },
|
|
3097
|
+
{
|
|
3098
|
+
type: "object",
|
|
3099
|
+
properties: {
|
|
3100
|
+
outer: { const: "*" },
|
|
3101
|
+
inner: { const: "__" }
|
|
3102
|
+
},
|
|
3103
|
+
required: ["outer", "inner"],
|
|
3104
|
+
additionalProperties: false
|
|
3105
|
+
},
|
|
3106
|
+
{
|
|
3107
|
+
type: "object",
|
|
3108
|
+
properties: {
|
|
3109
|
+
outer: { const: "**" },
|
|
3110
|
+
inner: { const: "_" }
|
|
3111
|
+
},
|
|
3112
|
+
required: ["outer", "inner"],
|
|
3113
|
+
additionalProperties: false
|
|
3114
|
+
},
|
|
3115
|
+
{
|
|
3116
|
+
type: "object",
|
|
3117
|
+
properties: {
|
|
3118
|
+
outer: { const: "_" },
|
|
3119
|
+
inner: { const: "**" }
|
|
3120
|
+
},
|
|
3121
|
+
required: ["outer", "inner"],
|
|
3122
|
+
additionalProperties: false
|
|
3123
|
+
},
|
|
3124
|
+
{
|
|
3125
|
+
type: "object",
|
|
3126
|
+
properties: {
|
|
3127
|
+
outer: { const: "__" },
|
|
3128
|
+
inner: { const: "*" }
|
|
3129
|
+
},
|
|
3130
|
+
required: ["outer", "inner"],
|
|
3131
|
+
additionalProperties: false
|
|
3132
|
+
}
|
|
3133
|
+
] }
|
|
3134
|
+
},
|
|
3135
|
+
additionalProperties: false
|
|
3136
|
+
}],
|
|
3137
|
+
messages: {
|
|
3138
|
+
wrongEmphasis: "Emphasis delimiter should be '{{expectedOpening}}' (was '{{actualOpening}}').",
|
|
3139
|
+
wrongStrong: "Strong emphasis delimiter should be '{{expectedOpening}}' (was '{{actualOpening}}').",
|
|
3140
|
+
wrongStrongEmphasis: "Delimiter for strong+emphasis should be '{{expectedOpening}}' (was '{{actualOpening}}').",
|
|
3141
|
+
wrongStrongEmphasisDelimiterPair: "Delimiters for strong+emphasis should be '{{expectedOpening}}' ... '{{expectedClosing}}' (was '{{actualOpening}}' ... '{{actualClosing}}')."
|
|
3142
|
+
}
|
|
3143
|
+
},
|
|
3144
|
+
create(context) {
|
|
3145
|
+
const sourceCode = context.sourceCode;
|
|
3146
|
+
const option = context.options[0] ?? {};
|
|
3147
|
+
const emphasisDelimiter = option.emphasis ?? "_";
|
|
3148
|
+
const emphasis = {
|
|
3149
|
+
opening: emphasisDelimiter,
|
|
3150
|
+
closing: emphasisDelimiter
|
|
3151
|
+
};
|
|
3152
|
+
const strongDelimiter = option.strong ?? "**";
|
|
3153
|
+
const strong = {
|
|
3154
|
+
opening: strongDelimiter,
|
|
3155
|
+
closing: strongDelimiter
|
|
3156
|
+
};
|
|
3157
|
+
const strongEmphasis = parseStrongEmphasis(emphasisDelimiter, strongDelimiter, option.strongEmphasis);
|
|
3158
|
+
const processed = /* @__PURE__ */ new Set();
|
|
3159
|
+
/**
|
|
3160
|
+
* Verify the delimiter of the node
|
|
3161
|
+
*/
|
|
3162
|
+
function verifyDelimiter(node, expected, messageId) {
|
|
3163
|
+
const range = sourceCode.getRange(node);
|
|
3164
|
+
if (sourceCode.text.startsWith(expected.opening, range[0]) && sourceCode.text.endsWith(expected.closing, range[1])) return;
|
|
3165
|
+
if (sourceCode.text[range[0] - 1] === expected.opening[0] || sourceCode.text[range[1]] === expected.closing.at(-1) || sourceCode.text[range[0] + expected.opening.length] === expected.opening.at(-1) || sourceCode.text[range[1] - expected.closing.length - 1] === expected.closing[0]) return;
|
|
3166
|
+
if ((expected.opening.startsWith("_") || expected.closing.at(-1) === "_") && isIntrawordForUnderline(sourceCode.text, range)) return;
|
|
3167
|
+
const actual = {
|
|
3168
|
+
opening: sourceCode.text.slice(range[0], range[0] + expected.opening.length),
|
|
3169
|
+
closing: sourceCode.text.slice(range[1] - expected.closing.length, range[1])
|
|
3170
|
+
};
|
|
3171
|
+
context.report({
|
|
3172
|
+
node,
|
|
3173
|
+
messageId: expected.opening === expected.closing && actual.opening === actual.closing ? messageId : "wrongStrongEmphasisDelimiterPair",
|
|
3174
|
+
data: {
|
|
3175
|
+
expectedOpening: expected.opening,
|
|
3176
|
+
actualOpening: actual.opening,
|
|
3177
|
+
expectedClosing: expected.closing,
|
|
3178
|
+
actualClosing: actual.closing
|
|
3179
|
+
},
|
|
3180
|
+
fix(fixer) {
|
|
3181
|
+
return [fixer.replaceTextRange([range[0], range[0] + expected.opening.length], expected.opening), fixer.replaceTextRange([range[1] - expected.closing.length, range[1]], expected.closing)];
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
}
|
|
3185
|
+
/**
|
|
3186
|
+
* Verify the emphasis node has the correct delimiter
|
|
3187
|
+
*/
|
|
3188
|
+
function verifyEmphasis(node) {
|
|
3189
|
+
verifyDelimiter(node, emphasis, "wrongEmphasis");
|
|
3190
|
+
}
|
|
3191
|
+
/**
|
|
3192
|
+
* Verify the emphasis node has the correct delimiter
|
|
3193
|
+
*/
|
|
3194
|
+
function verifyStrong(node) {
|
|
3195
|
+
verifyDelimiter(node, strong, "wrongStrong");
|
|
3196
|
+
}
|
|
3197
|
+
/**
|
|
3198
|
+
* Verify the strong emphasis node has the correct delimiter
|
|
3199
|
+
*/
|
|
3200
|
+
function verifyStrongEmphasis(node) {
|
|
3201
|
+
verifyDelimiter(node, strongEmphasis, "wrongStrongEmphasis");
|
|
3202
|
+
}
|
|
3203
|
+
return {
|
|
3204
|
+
emphasis(node) {
|
|
3205
|
+
if (processed.has(node)) return;
|
|
3206
|
+
processed.add(node);
|
|
3207
|
+
if (node.children.length === 1 && node.children[0].type === "strong") {
|
|
3208
|
+
processed.add(node.children[0]);
|
|
3209
|
+
verifyStrongEmphasis(node);
|
|
3210
|
+
return;
|
|
3211
|
+
}
|
|
3212
|
+
verifyEmphasis(node);
|
|
3213
|
+
},
|
|
3214
|
+
strong(node) {
|
|
3215
|
+
if (processed.has(node)) return;
|
|
3216
|
+
processed.add(node);
|
|
3217
|
+
if (node.children.length === 1 && node.children[0].type === "emphasis") {
|
|
3218
|
+
processed.add(node.children[0]);
|
|
3219
|
+
verifyStrongEmphasis(node);
|
|
3220
|
+
return;
|
|
3221
|
+
}
|
|
3222
|
+
verifyStrong(node);
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
});
|
|
3227
|
+
/**
|
|
3228
|
+
* Parse strongEmphasis option to normalized object form
|
|
3229
|
+
*/
|
|
3230
|
+
function parseStrongEmphasis(emphasis, strong, strongEmphasisOpt) {
|
|
3231
|
+
if (strongEmphasisOpt != null) {
|
|
3232
|
+
if (typeof strongEmphasisOpt === "string") return {
|
|
3233
|
+
opening: strongEmphasisOpt,
|
|
3234
|
+
closing: strongEmphasisOpt
|
|
3235
|
+
};
|
|
3236
|
+
return {
|
|
3237
|
+
opening: strongEmphasisOpt.outer + strongEmphasisOpt.inner,
|
|
3238
|
+
closing: strongEmphasisOpt.inner + strongEmphasisOpt.outer
|
|
3239
|
+
};
|
|
3240
|
+
}
|
|
3241
|
+
if (emphasis === "*") {
|
|
3242
|
+
if (strong === "**") return {
|
|
3243
|
+
opening: "***",
|
|
3244
|
+
closing: "***"
|
|
3245
|
+
};
|
|
3246
|
+
return {
|
|
3247
|
+
opening: "*__",
|
|
3248
|
+
closing: "__*"
|
|
3249
|
+
};
|
|
3250
|
+
} else if (strong === "**") return {
|
|
3251
|
+
opening: "**_",
|
|
3252
|
+
closing: "_**"
|
|
3253
|
+
};
|
|
3254
|
+
return {
|
|
3255
|
+
opening: "___",
|
|
3256
|
+
closing: "___"
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
|
|
2791
3260
|
//#endregion
|
|
2792
3261
|
//#region src/rules/hard-linebreak-style.ts
|
|
2793
3262
|
var hard_linebreak_style_default = createRule("hard-linebreak-style", {
|
|
@@ -3598,57 +4067,331 @@ var heading_casing_default = createRule("heading-casing", {
|
|
|
3598
4067
|
});
|
|
3599
4068
|
|
|
3600
4069
|
//#endregion
|
|
3601
|
-
//#region src/
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
}
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
4070
|
+
//#region src/utils/setext-heading.ts
|
|
4071
|
+
/**
|
|
4072
|
+
* Parse the setext heading.
|
|
4073
|
+
*/
|
|
4074
|
+
function parseSetextHeading(sourceCode, node) {
|
|
4075
|
+
if (getHeadingKind(sourceCode, node) !== "setext") return null;
|
|
4076
|
+
const lines = getParsedLines(sourceCode);
|
|
4077
|
+
const contentLines = [];
|
|
4078
|
+
const nodeLoc = sourceCode.getLoc(node);
|
|
4079
|
+
for (let lineNumber = nodeLoc.start.line; lineNumber < nodeLoc.end.line; lineNumber++) {
|
|
4080
|
+
const content = parseContent(lines.get(lineNumber));
|
|
4081
|
+
contentLines.push(content);
|
|
4082
|
+
}
|
|
4083
|
+
const underline = parseUnderline(lines.get(nodeLoc.end.line));
|
|
4084
|
+
if (!underline) return null;
|
|
4085
|
+
return {
|
|
4086
|
+
contentLines,
|
|
4087
|
+
underline
|
|
4088
|
+
};
|
|
4089
|
+
}
|
|
4090
|
+
/**
|
|
4091
|
+
* Parse the content line of a setext heading.
|
|
4092
|
+
*/
|
|
4093
|
+
function parseContent(line) {
|
|
4094
|
+
let prefix = "";
|
|
4095
|
+
let spaceBefore = "";
|
|
4096
|
+
let suffix = "";
|
|
4097
|
+
for (let index = 0; index < line.text.length; index++) {
|
|
4098
|
+
const c = line.text[index];
|
|
4099
|
+
if (!c.trim()) {
|
|
4100
|
+
spaceBefore += c;
|
|
4101
|
+
continue;
|
|
4102
|
+
}
|
|
4103
|
+
if (c === ">" && spaceBefore.length < 4) {
|
|
4104
|
+
prefix += spaceBefore + c;
|
|
4105
|
+
spaceBefore = "";
|
|
4106
|
+
continue;
|
|
4107
|
+
}
|
|
4108
|
+
suffix = line.text.slice(index);
|
|
4109
|
+
break;
|
|
4110
|
+
}
|
|
4111
|
+
const content = suffix.trimEnd();
|
|
4112
|
+
const spaceAfter = suffix.slice(content.length);
|
|
4113
|
+
return {
|
|
4114
|
+
text: content,
|
|
4115
|
+
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
4116
|
+
loc: {
|
|
4117
|
+
start: {
|
|
4118
|
+
line: line.line,
|
|
4119
|
+
column: prefix.length + spaceBefore.length + 1
|
|
4120
|
+
},
|
|
4121
|
+
end: {
|
|
4122
|
+
line: line.line,
|
|
4123
|
+
column: prefix.length + spaceBefore.length + content.length + 1
|
|
4124
|
+
}
|
|
4125
|
+
},
|
|
4126
|
+
raws: {
|
|
4127
|
+
prefix,
|
|
4128
|
+
spaceBefore,
|
|
4129
|
+
spaceAfter
|
|
4130
|
+
}
|
|
4131
|
+
};
|
|
4132
|
+
}
|
|
4133
|
+
/**
|
|
4134
|
+
* Parse the underline of a setext heading.
|
|
4135
|
+
*/
|
|
4136
|
+
function parseUnderline(line) {
|
|
4137
|
+
let marker = null;
|
|
4138
|
+
let underlineText = "";
|
|
4139
|
+
let prefix = "";
|
|
4140
|
+
let spaceBefore = "";
|
|
4141
|
+
let spaceAfter = "";
|
|
4142
|
+
for (let index = line.text.length - 1; index >= 0; index--) {
|
|
4143
|
+
const c = line.text[index];
|
|
4144
|
+
if (!marker) {
|
|
4145
|
+
if (c === "=" || c === "-") {
|
|
4146
|
+
underlineText = c + underlineText;
|
|
4147
|
+
marker = c;
|
|
4148
|
+
} else if (!c.trim()) spaceAfter = c + spaceAfter;
|
|
4149
|
+
else return null;
|
|
4150
|
+
continue;
|
|
4151
|
+
}
|
|
4152
|
+
if (c === marker) {
|
|
4153
|
+
underlineText = c + spaceBefore + underlineText;
|
|
4154
|
+
spaceBefore = "";
|
|
4155
|
+
} else if (!c.trim()) spaceBefore = c + spaceBefore;
|
|
4156
|
+
else {
|
|
4157
|
+
prefix = line.text.slice(0, index + 1);
|
|
4158
|
+
break;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
if (!marker) return null;
|
|
4162
|
+
const underlineLoc = {
|
|
4163
|
+
start: {
|
|
4164
|
+
line: line.line,
|
|
4165
|
+
column: prefix.length + spaceBefore.length + 1
|
|
4166
|
+
},
|
|
4167
|
+
end: {
|
|
4168
|
+
line: line.line,
|
|
4169
|
+
column: prefix.length + spaceBefore.length + underlineText.length + 1
|
|
4170
|
+
}
|
|
4171
|
+
};
|
|
4172
|
+
return {
|
|
4173
|
+
text: underlineText,
|
|
4174
|
+
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
4175
|
+
loc: underlineLoc,
|
|
4176
|
+
marker,
|
|
4177
|
+
raws: {
|
|
4178
|
+
prefix,
|
|
4179
|
+
spaceBefore,
|
|
4180
|
+
spaceAfter
|
|
4181
|
+
}
|
|
4182
|
+
};
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
//#endregion
|
|
4186
|
+
//#region src/rules/level1-heading-style.ts
|
|
4187
|
+
var level1_heading_style_default = createRule("level1-heading-style", {
|
|
4188
|
+
meta: {
|
|
4189
|
+
type: "layout",
|
|
4190
|
+
docs: {
|
|
4191
|
+
description: "enforce consistent style for level 1 headings",
|
|
4192
|
+
categories: [],
|
|
4193
|
+
listCategory: "Stylistic"
|
|
4194
|
+
},
|
|
4195
|
+
fixable: "code",
|
|
4196
|
+
hasSuggestions: false,
|
|
4197
|
+
schema: [{
|
|
4198
|
+
type: "object",
|
|
4199
|
+
properties: {
|
|
4200
|
+
style: { enum: ["atx", "setext"] },
|
|
4201
|
+
allowMultilineSetext: { type: "boolean" }
|
|
4202
|
+
},
|
|
4203
|
+
additionalProperties: false
|
|
4204
|
+
}],
|
|
4205
|
+
messages: {
|
|
4206
|
+
expectedAtx: "Expected ATX style heading (# Heading).",
|
|
4207
|
+
expectedSetext: "Expected Setext style heading (Heading\\n======).",
|
|
4208
|
+
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
4209
|
+
}
|
|
4210
|
+
},
|
|
4211
|
+
create(context) {
|
|
4212
|
+
const sourceCode = context.sourceCode;
|
|
4213
|
+
const opt = context.options[0] || {};
|
|
4214
|
+
const style = opt.style ?? "atx";
|
|
4215
|
+
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
4216
|
+
return { heading(node) {
|
|
4217
|
+
if (node.depth !== 1) return;
|
|
4218
|
+
const headingKind = getHeadingKind(sourceCode, node);
|
|
4219
|
+
if (style === "atx") {
|
|
4220
|
+
if (headingKind !== "setext") return;
|
|
4221
|
+
const parsed = parseSetextHeading(sourceCode, node);
|
|
4222
|
+
if (!parsed) return;
|
|
4223
|
+
const isMultiline = parsed.contentLines.length > 1;
|
|
4224
|
+
if (isMultiline) {
|
|
4225
|
+
if (allowMultilineSetext) return;
|
|
4226
|
+
context.report({
|
|
4227
|
+
node,
|
|
4228
|
+
messageId: "multilineSetextNotAllowed"
|
|
4229
|
+
});
|
|
4230
|
+
return;
|
|
4231
|
+
}
|
|
4232
|
+
context.report({
|
|
4233
|
+
node,
|
|
4234
|
+
messageId: "expectedAtx",
|
|
4235
|
+
*fix(fixer) {
|
|
4236
|
+
const heading = parsed.contentLines[0];
|
|
4237
|
+
yield fixer.insertTextBeforeRange(heading.range, "# ");
|
|
4238
|
+
const lines = getParsedLines(sourceCode);
|
|
4239
|
+
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
4240
|
+
}
|
|
4241
|
+
});
|
|
4242
|
+
} else if (style === "setext") {
|
|
4243
|
+
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
4244
|
+
context.report({
|
|
4245
|
+
node,
|
|
4246
|
+
messageId: "expectedSetext",
|
|
4247
|
+
*fix(fixer) {
|
|
4248
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
4249
|
+
if (!parsed) return;
|
|
4250
|
+
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.openingSequence.raws.spaceAfter.range[1]]);
|
|
4251
|
+
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4252
|
+
const lines = getParsedLines(sourceCode);
|
|
4253
|
+
const underline = "=".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4254
|
+
const prefix = lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1);
|
|
4255
|
+
const appendingText = `\n${prefix}${underline}`;
|
|
4256
|
+
yield fixer.insertTextAfter(node, appendingText);
|
|
4257
|
+
}
|
|
4258
|
+
});
|
|
4259
|
+
}
|
|
4260
|
+
} };
|
|
4261
|
+
}
|
|
4262
|
+
});
|
|
4263
|
+
|
|
4264
|
+
//#endregion
|
|
4265
|
+
//#region src/rules/level2-heading-style.ts
|
|
4266
|
+
var level2_heading_style_default = createRule("level2-heading-style", {
|
|
4267
|
+
meta: {
|
|
4268
|
+
type: "layout",
|
|
4269
|
+
docs: {
|
|
4270
|
+
description: "enforce consistent style for level 2 headings",
|
|
4271
|
+
categories: [],
|
|
4272
|
+
listCategory: "Stylistic"
|
|
4273
|
+
},
|
|
4274
|
+
fixable: "code",
|
|
4275
|
+
hasSuggestions: false,
|
|
4276
|
+
schema: [{
|
|
4277
|
+
type: "object",
|
|
4278
|
+
properties: {
|
|
4279
|
+
style: { enum: ["atx", "setext"] },
|
|
4280
|
+
allowMultilineSetext: { type: "boolean" }
|
|
4281
|
+
},
|
|
4282
|
+
additionalProperties: false
|
|
4283
|
+
}],
|
|
4284
|
+
messages: {
|
|
4285
|
+
expectedAtx: "Expected ATX style heading (## Heading).",
|
|
4286
|
+
expectedSetext: "Expected Setext style heading (Heading\\n------).",
|
|
4287
|
+
multilineSetextNotAllowed: "Multiline Setext headings are not allowed."
|
|
4288
|
+
}
|
|
4289
|
+
},
|
|
4290
|
+
create(context) {
|
|
4291
|
+
const sourceCode = context.sourceCode;
|
|
4292
|
+
const opt = context.options[0] || {};
|
|
4293
|
+
const style = opt.style ?? "atx";
|
|
4294
|
+
const allowMultilineSetext = opt.allowMultilineSetext;
|
|
4295
|
+
return { heading(node) {
|
|
4296
|
+
if (node.depth !== 2) return;
|
|
4297
|
+
const headingKind = getHeadingKind(sourceCode, node);
|
|
4298
|
+
if (style === "atx") {
|
|
4299
|
+
if (headingKind !== "setext") return;
|
|
4300
|
+
const parsed = parseSetextHeading(sourceCode, node);
|
|
4301
|
+
if (!parsed) return;
|
|
4302
|
+
const isMultiline = parsed.contentLines.length > 1;
|
|
4303
|
+
if (isMultiline) {
|
|
4304
|
+
if (allowMultilineSetext) return;
|
|
4305
|
+
context.report({
|
|
4306
|
+
node,
|
|
4307
|
+
messageId: "multilineSetextNotAllowed"
|
|
4308
|
+
});
|
|
4309
|
+
return;
|
|
4310
|
+
}
|
|
4311
|
+
context.report({
|
|
4312
|
+
node,
|
|
4313
|
+
messageId: "expectedAtx",
|
|
4314
|
+
*fix(fixer) {
|
|
4315
|
+
const heading = parsed.contentLines[0];
|
|
4316
|
+
yield fixer.insertTextBeforeRange(heading.range, "## ");
|
|
4317
|
+
const lines = getParsedLines(sourceCode);
|
|
4318
|
+
yield fixer.removeRange(lines.get(parsed.underline.loc.start.line).range);
|
|
4319
|
+
}
|
|
4320
|
+
});
|
|
4321
|
+
} else if (style === "setext") {
|
|
4322
|
+
if (headingKind !== "atx" || node.children.length === 0) return;
|
|
4323
|
+
context.report({
|
|
4324
|
+
node,
|
|
4325
|
+
messageId: "expectedSetext",
|
|
4326
|
+
*fix(fixer) {
|
|
4327
|
+
const parsed = parseATXHeading(sourceCode, node);
|
|
4328
|
+
if (!parsed) return;
|
|
4329
|
+
yield fixer.removeRange([parsed.openingSequence.range[0], parsed.openingSequence.raws.spaceAfter.range[1]]);
|
|
4330
|
+
if (parsed.closingSequence) yield fixer.removeRange([parsed.closingSequence.raws.spaceBefore.range[0], parsed.closingSequence.raws.spaceAfter.range[1]]);
|
|
4331
|
+
const lines = getParsedLines(sourceCode);
|
|
4332
|
+
const underline = "-".repeat(Math.max(getTextWidth(parsed.content.text), 3));
|
|
4333
|
+
const prefix = lines.get(parsed.openingSequence.loc.start.line).text.slice(0, parsed.openingSequence.loc.start.column - 1);
|
|
4334
|
+
const appendingText = `\n${prefix}${underline}`;
|
|
4335
|
+
yield fixer.insertTextAfter(node, appendingText);
|
|
4336
|
+
}
|
|
4337
|
+
});
|
|
4338
|
+
}
|
|
4339
|
+
} };
|
|
4340
|
+
}
|
|
4341
|
+
});
|
|
4342
|
+
|
|
4343
|
+
//#endregion
|
|
4344
|
+
//#region src/rules/list-marker-alignment.ts
|
|
4345
|
+
const ALIGN_TO_POSITION_NAME = {
|
|
4346
|
+
left: "start",
|
|
4347
|
+
right: "end"
|
|
4348
|
+
};
|
|
4349
|
+
var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
4350
|
+
meta: {
|
|
4351
|
+
type: "layout",
|
|
4352
|
+
docs: {
|
|
4353
|
+
description: "enforce consistent alignment of list markers",
|
|
4354
|
+
categories: ["recommended"],
|
|
4355
|
+
listCategory: "Stylistic"
|
|
4356
|
+
},
|
|
4357
|
+
fixable: "whitespace",
|
|
4358
|
+
hasSuggestions: false,
|
|
4359
|
+
schema: [{
|
|
4360
|
+
type: "object",
|
|
4361
|
+
properties: { align: { enum: ["left", "right"] } },
|
|
4362
|
+
additionalProperties: false
|
|
4363
|
+
}],
|
|
4364
|
+
messages: { incorrectAlignment: "List marker alignment is inconsistent. Expected {{expected}} characters of indentation, but got {{actual}}." }
|
|
4365
|
+
},
|
|
4366
|
+
create(context) {
|
|
4367
|
+
const sourceCode = context.sourceCode;
|
|
4368
|
+
const alignPositionName = ALIGN_TO_POSITION_NAME[context.options[0]?.align ?? "left"];
|
|
4369
|
+
/**
|
|
4370
|
+
* Get the marker location of a list item
|
|
4371
|
+
*/
|
|
4372
|
+
function getMarkerLocation(node) {
|
|
4373
|
+
const start = sourceCode.getLoc(node).start;
|
|
4374
|
+
const startColumnIndex = start.column - 1;
|
|
4375
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
4376
|
+
return {
|
|
4377
|
+
line: start.line,
|
|
4378
|
+
start: startColumnIndex,
|
|
4379
|
+
end: startColumnIndex + marker.raw.length
|
|
4380
|
+
};
|
|
4381
|
+
}
|
|
4382
|
+
/**
|
|
4383
|
+
* Check if list items have consistent alignment
|
|
4384
|
+
*/
|
|
4385
|
+
function checkListAlignment(listNode) {
|
|
4386
|
+
const items = listNode.children;
|
|
4387
|
+
if (items.length <= 1) return;
|
|
4388
|
+
const referenceMarkerLocation = getMarkerLocation(items[0]);
|
|
4389
|
+
for (const item of items.slice(1)) {
|
|
4390
|
+
const markerLocation = getMarkerLocation(item);
|
|
4391
|
+
const diff = markerLocation[alignPositionName] - referenceMarkerLocation[alignPositionName];
|
|
4392
|
+
if (diff === 0) continue;
|
|
4393
|
+
context.report({
|
|
4394
|
+
node: item,
|
|
3652
4395
|
loc: {
|
|
3653
4396
|
start: {
|
|
3654
4397
|
line: markerLocation.line,
|
|
@@ -4150,7 +4893,7 @@ var ordered_list_marker_sequence_default = createRule("ordered-list-marker-seque
|
|
|
4150
4893
|
messageId: "inconsistentStart",
|
|
4151
4894
|
data: {
|
|
4152
4895
|
expected: new Intl.ListFormat("en-US", { type: "disjunction" }).format(expected.map((n) => `'${n}'`)),
|
|
4153
|
-
actual:
|
|
4896
|
+
actual: marker.sequence.raw
|
|
4154
4897
|
},
|
|
4155
4898
|
fix: scope.last == null ? (fixer) => {
|
|
4156
4899
|
const expectedMarker = `1${marker.kind}`;
|
|
@@ -4171,7 +4914,7 @@ var ordered_list_marker_sequence_default = createRule("ordered-list-marker-seque
|
|
|
4171
4914
|
const marker = getListItemMarker(sourceCode, item);
|
|
4172
4915
|
if (marker.kind !== "." && marker.kind !== ")") continue;
|
|
4173
4916
|
const expectedSequence = node.start + i;
|
|
4174
|
-
if (marker.sequence !== expectedSequence) {
|
|
4917
|
+
if (marker.sequence.value !== expectedSequence) {
|
|
4175
4918
|
const expectedMarker = `${expectedSequence}${marker.kind}`;
|
|
4176
4919
|
context.report({
|
|
4177
4920
|
node: item,
|
|
@@ -4306,6 +5049,174 @@ var ordered_list_marker_start_default = createRule("ordered-list-marker-start",
|
|
|
4306
5049
|
}
|
|
4307
5050
|
});
|
|
4308
5051
|
|
|
5052
|
+
//#endregion
|
|
5053
|
+
//#region src/rules/ordered-list-marker-style.ts
|
|
5054
|
+
const MARKER_KINDS = [".", ")"];
|
|
5055
|
+
const MARKERS = MARKER_KINDS.map((kind) => `n${kind}`);
|
|
5056
|
+
/**
|
|
5057
|
+
* Get the other marker kind.
|
|
5058
|
+
*/
|
|
5059
|
+
function getOtherMarkerKind(unavailableMarker) {
|
|
5060
|
+
return MARKER_KINDS.find((mark) => unavailableMarker !== mark);
|
|
5061
|
+
}
|
|
5062
|
+
function markerToKind(marker) {
|
|
5063
|
+
if (marker === "n.") return ".";
|
|
5064
|
+
if (marker === "n)") return ")";
|
|
5065
|
+
return marker;
|
|
5066
|
+
}
|
|
5067
|
+
/**
|
|
5068
|
+
* Parse rule options.
|
|
5069
|
+
*/
|
|
5070
|
+
function parseOptions(options) {
|
|
5071
|
+
const prefer = markerToKind(options.prefer) || ".";
|
|
5072
|
+
const overrides = (options.overrides ?? []).map((override) => {
|
|
5073
|
+
const preferForOverride = markerToKind(override.prefer) || ".";
|
|
5074
|
+
return {
|
|
5075
|
+
level: override.level,
|
|
5076
|
+
parentMarker: markerToKind(override.parentMarker) ?? "any",
|
|
5077
|
+
prefer: preferForOverride
|
|
5078
|
+
};
|
|
5079
|
+
}).reverse();
|
|
5080
|
+
return { get(level, parentMarker) {
|
|
5081
|
+
for (const o of overrides) if ((o.level == null || o.level === level) && (o.parentMarker === "any" || o.parentMarker === parentMarker)) return { prefer: o.prefer };
|
|
5082
|
+
return { prefer };
|
|
5083
|
+
} };
|
|
5084
|
+
}
|
|
5085
|
+
/**
|
|
5086
|
+
* Check if a item marker is an ordered list marker.
|
|
5087
|
+
*/
|
|
5088
|
+
function isOrderedListItemMarker(itemMarker) {
|
|
5089
|
+
return itemMarker.kind === "." || itemMarker.kind === ")";
|
|
5090
|
+
}
|
|
5091
|
+
var ordered_list_marker_style_default = createRule("ordered-list-marker-style", {
|
|
5092
|
+
meta: {
|
|
5093
|
+
type: "layout",
|
|
5094
|
+
docs: {
|
|
5095
|
+
description: "enforce consistent ordered list marker style",
|
|
5096
|
+
categories: [],
|
|
5097
|
+
listCategory: "Stylistic"
|
|
5098
|
+
},
|
|
5099
|
+
fixable: "code",
|
|
5100
|
+
hasSuggestions: false,
|
|
5101
|
+
schema: [{
|
|
5102
|
+
type: "object",
|
|
5103
|
+
properties: {
|
|
5104
|
+
prefer: { enum: MARKERS },
|
|
5105
|
+
overrides: {
|
|
5106
|
+
type: "array",
|
|
5107
|
+
items: {
|
|
5108
|
+
type: "object",
|
|
5109
|
+
properties: {
|
|
5110
|
+
level: {
|
|
5111
|
+
type: "integer",
|
|
5112
|
+
minimum: 1
|
|
5113
|
+
},
|
|
5114
|
+
parentMarker: { enum: [
|
|
5115
|
+
...MARKERS,
|
|
5116
|
+
"any",
|
|
5117
|
+
"bullet"
|
|
5118
|
+
] },
|
|
5119
|
+
prefer: { enum: MARKERS }
|
|
5120
|
+
},
|
|
5121
|
+
additionalProperties: false
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
},
|
|
5125
|
+
additionalProperties: false
|
|
5126
|
+
}],
|
|
5127
|
+
messages: { unexpected: "Ordered list marker should be '{{sequence}}{{markerKind}}'." }
|
|
5128
|
+
},
|
|
5129
|
+
create(context) {
|
|
5130
|
+
const sourceCode = context.sourceCode;
|
|
5131
|
+
const options = parseOptions(context.options[0] || {});
|
|
5132
|
+
let containerStack = {
|
|
5133
|
+
node: sourceCode.ast,
|
|
5134
|
+
level: 1,
|
|
5135
|
+
upper: null
|
|
5136
|
+
};
|
|
5137
|
+
/**
|
|
5138
|
+
* Check ordered list marker style
|
|
5139
|
+
*/
|
|
5140
|
+
function checkOrderedList(node) {
|
|
5141
|
+
let parentMarker;
|
|
5142
|
+
if (containerStack.node.type === "listItem") {
|
|
5143
|
+
const parentMarkerKind = getListItemMarker(sourceCode, containerStack.node).kind;
|
|
5144
|
+
parentMarker = parentMarkerKind === "-" || parentMarkerKind === "*" || parentMarkerKind === "+" ? "bullet" : parentMarkerKind;
|
|
5145
|
+
} else parentMarker = "top";
|
|
5146
|
+
const { prefer } = options.get(containerStack.level, parentMarker);
|
|
5147
|
+
const nodeIndex = containerStack.node.children.indexOf(node);
|
|
5148
|
+
if (nodeIndex === -1) return;
|
|
5149
|
+
const prevNode = nodeIndex > 0 ? containerStack.node.children[nodeIndex - 1] : null;
|
|
5150
|
+
const prevBulletList = prevNode && (prevNode.type === "list" ? prevNode : null);
|
|
5151
|
+
const prevBulletListMarker = prevBulletList && getListItemMarker(sourceCode, prevBulletList);
|
|
5152
|
+
const expectedMarker = prevBulletListMarker?.kind !== prefer ? prefer : getOtherMarkerKind(prefer);
|
|
5153
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
5154
|
+
if (marker.kind === expectedMarker || !isOrderedListItemMarker(marker)) return;
|
|
5155
|
+
const loc = sourceCode.getLoc(node);
|
|
5156
|
+
context.report({
|
|
5157
|
+
node,
|
|
5158
|
+
loc: {
|
|
5159
|
+
start: loc.start,
|
|
5160
|
+
end: {
|
|
5161
|
+
line: loc.start.line,
|
|
5162
|
+
column: loc.start.column + marker.raw.length
|
|
5163
|
+
}
|
|
5164
|
+
},
|
|
5165
|
+
messageId: "unexpected",
|
|
5166
|
+
data: {
|
|
5167
|
+
sequence: marker.sequence.raw,
|
|
5168
|
+
markerKind: expectedMarker
|
|
5169
|
+
},
|
|
5170
|
+
*fix(fixer) {
|
|
5171
|
+
if (prevNode?.type === "list" && prevBulletListMarker && isOrderedListItemMarker(prevBulletListMarker)) yield* fixMarker(prevNode.children[0], prevBulletListMarker.kind);
|
|
5172
|
+
yield* fixMarkers(node, expectedMarker);
|
|
5173
|
+
let prevMarker = expectedMarker;
|
|
5174
|
+
for (let index = nodeIndex + 1; index < containerStack.node.children.length; index++) {
|
|
5175
|
+
const nextNode = containerStack.node.children[index];
|
|
5176
|
+
if (nextNode.type !== "list") break;
|
|
5177
|
+
const nextMarker = getListItemMarker(sourceCode, nextNode);
|
|
5178
|
+
if (nextMarker.kind !== prevMarker) break;
|
|
5179
|
+
const expectedNextMarker = prevMarker === prefer ? getOtherMarkerKind(prefer) : prefer;
|
|
5180
|
+
yield* fixMarkers(nextNode, expectedNextMarker);
|
|
5181
|
+
prevMarker = expectedNextMarker;
|
|
5182
|
+
}
|
|
5183
|
+
/**
|
|
5184
|
+
* Fix ordered list markers
|
|
5185
|
+
*/
|
|
5186
|
+
function* fixMarkers(list, replacementMarker) {
|
|
5187
|
+
for (const item of list.children) yield* fixMarker(item, replacementMarker);
|
|
5188
|
+
}
|
|
5189
|
+
/**
|
|
5190
|
+
* Fix ordered list item marker
|
|
5191
|
+
*/
|
|
5192
|
+
function* fixMarker(item, replacementMarker) {
|
|
5193
|
+
const range = sourceCode.getRange(item);
|
|
5194
|
+
const itemMarker = getListItemMarker(sourceCode, item);
|
|
5195
|
+
if (!isOrderedListItemMarker(itemMarker)) return;
|
|
5196
|
+
yield fixer.replaceTextRange([range[0] + itemMarker.raw.length - 1, range[0] + itemMarker.raw.length], replacementMarker);
|
|
5197
|
+
}
|
|
5198
|
+
}
|
|
5199
|
+
});
|
|
5200
|
+
}
|
|
5201
|
+
return {
|
|
5202
|
+
list(node) {
|
|
5203
|
+
if (!node.ordered) return;
|
|
5204
|
+
checkOrderedList(node);
|
|
5205
|
+
},
|
|
5206
|
+
"root, blockquote, listItem, footnoteDefinition"(node) {
|
|
5207
|
+
containerStack = {
|
|
5208
|
+
node,
|
|
5209
|
+
level: node.type === "listItem" ? containerStack.level + 1 : 1,
|
|
5210
|
+
upper: containerStack
|
|
5211
|
+
};
|
|
5212
|
+
},
|
|
5213
|
+
"root, blockquote, listItem, footnoteDefinition:exit"() {
|
|
5214
|
+
containerStack = containerStack.upper;
|
|
5215
|
+
}
|
|
5216
|
+
};
|
|
5217
|
+
}
|
|
5218
|
+
});
|
|
5219
|
+
|
|
4309
5220
|
//#endregion
|
|
4310
5221
|
//#region src/rules/padding-line-between-blocks.ts
|
|
4311
5222
|
/**
|
|
@@ -5123,122 +6034,6 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
|
|
|
5123
6034
|
}
|
|
5124
6035
|
});
|
|
5125
6036
|
|
|
5126
|
-
//#endregion
|
|
5127
|
-
//#region src/utils/setext-heading.ts
|
|
5128
|
-
/**
|
|
5129
|
-
* Parse the setext heading.
|
|
5130
|
-
*/
|
|
5131
|
-
function parseSetextHeading(sourceCode, node) {
|
|
5132
|
-
if (getHeadingKind(sourceCode, node) !== "setext") return null;
|
|
5133
|
-
const lines = getParsedLines(sourceCode);
|
|
5134
|
-
const contentLines = [];
|
|
5135
|
-
const nodeLoc = sourceCode.getLoc(node);
|
|
5136
|
-
for (let lineNumber = nodeLoc.start.line; lineNumber < nodeLoc.end.line; lineNumber++) {
|
|
5137
|
-
const content = parseContent(lines.get(lineNumber));
|
|
5138
|
-
contentLines.push(content);
|
|
5139
|
-
}
|
|
5140
|
-
const underline = parseUnderline(lines.get(nodeLoc.end.line));
|
|
5141
|
-
if (!underline) return null;
|
|
5142
|
-
return {
|
|
5143
|
-
contentLines,
|
|
5144
|
-
underline
|
|
5145
|
-
};
|
|
5146
|
-
}
|
|
5147
|
-
/**
|
|
5148
|
-
* Parse the content line of a setext heading.
|
|
5149
|
-
*/
|
|
5150
|
-
function parseContent(line) {
|
|
5151
|
-
let prefix = "";
|
|
5152
|
-
let spaceBefore = "";
|
|
5153
|
-
let suffix = "";
|
|
5154
|
-
for (let index = 0; index < line.text.length; index++) {
|
|
5155
|
-
const c = line.text[index];
|
|
5156
|
-
if (!c.trim()) {
|
|
5157
|
-
spaceBefore += c;
|
|
5158
|
-
continue;
|
|
5159
|
-
}
|
|
5160
|
-
if (c === ">" && spaceBefore.length < 4) {
|
|
5161
|
-
prefix += spaceBefore + c;
|
|
5162
|
-
spaceBefore = "";
|
|
5163
|
-
continue;
|
|
5164
|
-
}
|
|
5165
|
-
suffix = line.text.slice(index);
|
|
5166
|
-
break;
|
|
5167
|
-
}
|
|
5168
|
-
const content = suffix.trimEnd();
|
|
5169
|
-
const spaceAfter = suffix.slice(content.length);
|
|
5170
|
-
return {
|
|
5171
|
-
text: content,
|
|
5172
|
-
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
5173
|
-
loc: {
|
|
5174
|
-
start: {
|
|
5175
|
-
line: line.line,
|
|
5176
|
-
column: prefix.length + spaceBefore.length + 1
|
|
5177
|
-
},
|
|
5178
|
-
end: {
|
|
5179
|
-
line: line.line,
|
|
5180
|
-
column: prefix.length + spaceBefore.length + content.length + 1
|
|
5181
|
-
}
|
|
5182
|
-
},
|
|
5183
|
-
raws: {
|
|
5184
|
-
prefix,
|
|
5185
|
-
spaceBefore,
|
|
5186
|
-
spaceAfter
|
|
5187
|
-
}
|
|
5188
|
-
};
|
|
5189
|
-
}
|
|
5190
|
-
/**
|
|
5191
|
-
* Parse the underline of a setext heading.
|
|
5192
|
-
*/
|
|
5193
|
-
function parseUnderline(line) {
|
|
5194
|
-
let marker = null;
|
|
5195
|
-
let underlineText = "";
|
|
5196
|
-
let prefix = "";
|
|
5197
|
-
let spaceBefore = "";
|
|
5198
|
-
let spaceAfter = "";
|
|
5199
|
-
for (let index = line.text.length - 1; index >= 0; index--) {
|
|
5200
|
-
const c = line.text[index];
|
|
5201
|
-
if (!marker) {
|
|
5202
|
-
if (c === "=" || c === "-") {
|
|
5203
|
-
underlineText = c + underlineText;
|
|
5204
|
-
marker = c;
|
|
5205
|
-
} else if (!c.trim()) spaceAfter = c + spaceAfter;
|
|
5206
|
-
else return null;
|
|
5207
|
-
continue;
|
|
5208
|
-
}
|
|
5209
|
-
if (c === marker) {
|
|
5210
|
-
underlineText = c + spaceBefore + underlineText;
|
|
5211
|
-
spaceBefore = "";
|
|
5212
|
-
} else if (!c.trim()) spaceBefore = c + spaceBefore;
|
|
5213
|
-
else {
|
|
5214
|
-
prefix = line.text.slice(0, index + 1);
|
|
5215
|
-
break;
|
|
5216
|
-
}
|
|
5217
|
-
}
|
|
5218
|
-
if (!marker) return null;
|
|
5219
|
-
const underlineLoc = {
|
|
5220
|
-
start: {
|
|
5221
|
-
line: line.line,
|
|
5222
|
-
column: prefix.length + spaceBefore.length + 1
|
|
5223
|
-
},
|
|
5224
|
-
end: {
|
|
5225
|
-
line: line.line,
|
|
5226
|
-
column: prefix.length + spaceBefore.length + underlineText.length + 1
|
|
5227
|
-
}
|
|
5228
|
-
};
|
|
5229
|
-
return {
|
|
5230
|
-
text: underlineText,
|
|
5231
|
-
range: [line.range[0] + prefix.length + spaceBefore.length, line.range[1] - line.linebreak.length - spaceAfter.length],
|
|
5232
|
-
loc: underlineLoc,
|
|
5233
|
-
marker,
|
|
5234
|
-
raws: {
|
|
5235
|
-
prefix,
|
|
5236
|
-
spaceBefore,
|
|
5237
|
-
spaceAfter
|
|
5238
|
-
}
|
|
5239
|
-
};
|
|
5240
|
-
}
|
|
5241
|
-
|
|
5242
6037
|
//#endregion
|
|
5243
6038
|
//#region src/rules/setext-heading-underline-length.ts
|
|
5244
6039
|
var setext_heading_underline_length_default = createRule("setext-heading-underline-length", {
|
|
@@ -5602,7 +6397,7 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
5602
6397
|
const last = group.at(-1);
|
|
5603
6398
|
if (last && (node.type !== "definition" && node.type !== "footnoteDefinition" || sourceCode.getParent(node) !== sourceCode.getParent(last))) {
|
|
5604
6399
|
const range = sourceCode.getRange(node);
|
|
5605
|
-
const lastDefinitionRange = sourceCode.getRange(
|
|
6400
|
+
const lastDefinitionRange = sourceCode.getRange(last);
|
|
5606
6401
|
if (lastDefinitionRange[1] <= range[0]) {
|
|
5607
6402
|
verify(group);
|
|
5608
6403
|
group.length = 0;
|
|
@@ -5760,6 +6555,48 @@ function normalizedURL(url) {
|
|
|
5760
6555
|
return urlObj.href.endsWith("/") ? urlObj.href : `${urlObj.href}/`;
|
|
5761
6556
|
}
|
|
5762
6557
|
|
|
6558
|
+
//#endregion
|
|
6559
|
+
//#region src/rules/strikethrough-delimiters-style.ts
|
|
6560
|
+
var strikethrough_delimiters_style_default = createRule("strikethrough-delimiters-style", {
|
|
6561
|
+
meta: {
|
|
6562
|
+
type: "layout",
|
|
6563
|
+
docs: {
|
|
6564
|
+
description: "enforce a consistent delimiter style for strikethrough",
|
|
6565
|
+
categories: [],
|
|
6566
|
+
listCategory: "Stylistic"
|
|
6567
|
+
},
|
|
6568
|
+
fixable: "code",
|
|
6569
|
+
hasSuggestions: false,
|
|
6570
|
+
schema: [{
|
|
6571
|
+
type: "object",
|
|
6572
|
+
properties: { delimiter: { enum: ["~", "~~"] } },
|
|
6573
|
+
additionalProperties: false
|
|
6574
|
+
}],
|
|
6575
|
+
messages: { wrongDelimiter: "Strikethrough delimiter should be '{{expected}}' (was '{{actual}}')." }
|
|
6576
|
+
},
|
|
6577
|
+
create(context) {
|
|
6578
|
+
const sourceCode = context.sourceCode;
|
|
6579
|
+
const option = context.options[0] ?? {};
|
|
6580
|
+
const delimiter = option.delimiter ?? "~~";
|
|
6581
|
+
return { delete(node) {
|
|
6582
|
+
const range = sourceCode.getRange(node);
|
|
6583
|
+
const actualDelimiter = ["~~", "~"].find((d) => sourceCode.text.startsWith(d, range[0]) && sourceCode.text.endsWith(d, range[1]));
|
|
6584
|
+
if (!actualDelimiter || actualDelimiter === delimiter) return;
|
|
6585
|
+
context.report({
|
|
6586
|
+
node,
|
|
6587
|
+
messageId: "wrongDelimiter",
|
|
6588
|
+
data: {
|
|
6589
|
+
expected: delimiter,
|
|
6590
|
+
actual: actualDelimiter
|
|
6591
|
+
},
|
|
6592
|
+
fix(fixer) {
|
|
6593
|
+
return [fixer.replaceTextRange([range[0], range[0] + actualDelimiter.length], delimiter), fixer.replaceTextRange([range[1] - actualDelimiter.length, range[1]], delimiter)];
|
|
6594
|
+
}
|
|
6595
|
+
});
|
|
6596
|
+
} };
|
|
6597
|
+
}
|
|
6598
|
+
});
|
|
6599
|
+
|
|
5763
6600
|
//#endregion
|
|
5764
6601
|
//#region src/rules/table-header-casing.ts
|
|
5765
6602
|
var table_header_casing_default = createRule("table-header-casing", {
|
|
@@ -6108,14 +6945,18 @@ var thematic_break_sequence_pattern_default = createRule("thematic-break-sequenc
|
|
|
6108
6945
|
//#endregion
|
|
6109
6946
|
//#region src/utils/rules.ts
|
|
6110
6947
|
const rules$1 = [
|
|
6111
|
-
|
|
6112
|
-
|
|
6948
|
+
atx_heading_closing_sequence_length_default,
|
|
6949
|
+
atx_heading_closing_sequence_default,
|
|
6113
6950
|
blockquote_marker_alignment_default,
|
|
6951
|
+
bullet_list_marker_style_default,
|
|
6114
6952
|
canonical_code_block_language_default,
|
|
6115
6953
|
definitions_last_default,
|
|
6116
6954
|
emoji_notation_default,
|
|
6955
|
+
emphasis_delimiters_style_default,
|
|
6117
6956
|
hard_linebreak_style_default,
|
|
6118
6957
|
heading_casing_default,
|
|
6958
|
+
level1_heading_style_default,
|
|
6959
|
+
level2_heading_style_default,
|
|
6119
6960
|
list_marker_alignment_default,
|
|
6120
6961
|
no_laziness_blockquotes_default,
|
|
6121
6962
|
no_multiple_empty_lines_default,
|
|
@@ -6123,6 +6964,7 @@ const rules$1 = [
|
|
|
6123
6964
|
no_trailing_spaces_default,
|
|
6124
6965
|
ordered_list_marker_sequence_default,
|
|
6125
6966
|
ordered_list_marker_start_default,
|
|
6967
|
+
ordered_list_marker_style_default,
|
|
6126
6968
|
padding_line_between_blocks_default,
|
|
6127
6969
|
prefer_autolinks_default,
|
|
6128
6970
|
prefer_fenced_code_blocks_default,
|
|
@@ -6131,6 +6973,7 @@ const rules$1 = [
|
|
|
6131
6973
|
prefer_linked_words_default,
|
|
6132
6974
|
setext_heading_underline_length_default,
|
|
6133
6975
|
sort_definitions_default,
|
|
6976
|
+
strikethrough_delimiters_style_default,
|
|
6134
6977
|
table_header_casing_default,
|
|
6135
6978
|
thematic_break_character_style_default,
|
|
6136
6979
|
thematic_break_length_default,
|
|
@@ -6177,7 +7020,7 @@ __export(meta_exports, {
|
|
|
6177
7020
|
version: () => version
|
|
6178
7021
|
});
|
|
6179
7022
|
const name = "eslint-plugin-markdown-preferences";
|
|
6180
|
-
const version = "0.
|
|
7023
|
+
const version = "0.19.0";
|
|
6181
7024
|
|
|
6182
7025
|
//#endregion
|
|
6183
7026
|
//#region src/index.ts
|