eslint-plugin-markdown-preferences 0.14.0 → 0.15.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 +6 -4
- package/lib/index.d.ts +14 -1
- package/lib/index.js +245 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,10 +13,10 @@ A specialized ESLint plugin that helps enforce consistent writing style and form
|
|
|
13
13
|
|
|
14
14
|
## 📛 Features
|
|
15
15
|
|
|
16
|
-
- **⚡ Effortless automation** - Transform your Markdown with auto-fixing that handles formatting,
|
|
17
|
-
- **📖 Professional documentation** - Enforce consistent
|
|
18
|
-
-
|
|
19
|
-
- **⚙️
|
|
16
|
+
- **⚡ Effortless automation** - Transform your Markdown with auto-fixing that handles formatting, casing, and style consistency automatically
|
|
17
|
+
- **📖 Professional documentation** - Enforce consistent headings, table headers, and organize link definitions for enterprise-ready documentation
|
|
18
|
+
- **🎨 Clean formatting** - Remove trailing spaces, control line breaks, standardize code blocks, and ensure consistent list numbering for polished output
|
|
19
|
+
- **⚙️ Flexible customization** - Configure casing styles (Title Case, Sentence case), code block languages, emoji notation, and more with extensive options
|
|
20
20
|
|
|
21
21
|
**Try it live:** Check out the [Online Demo](https://eslint-online-playground.netlify.app/#eslint-plugin-markdown-preferences) to see the plugin in action!
|
|
22
22
|
|
|
@@ -110,8 +110,10 @@ The rules with the following star ⭐ are included in the configs.
|
|
|
110
110
|
|:--------|:------------|:-------:|:-----------:|
|
|
111
111
|
| [markdown-preferences/atx-headings-closing-sequence-length](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/atx-headings-closing-sequence-length.html) | enforce consistent length for the closing sequence (trailing #s) in ATX headings. | 🔧 | |
|
|
112
112
|
| [markdown-preferences/atx-headings-closing-sequence](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/atx-headings-closing-sequence.html) | enforce consistent use of closing sequence in ATX headings. | 🔧 | |
|
|
113
|
+
| [markdown-preferences/blockquote-marker-alignment](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/blockquote-marker-alignment.html) | enforce consistent alignment of blockquote markers | 🔧 | ⭐ |
|
|
113
114
|
| [markdown-preferences/definitions-last](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/definitions-last.html) | require link definitions and footnote definitions to be placed at the end of the document | 🔧 | |
|
|
114
115
|
| [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style. | 🔧 | ⭐ |
|
|
116
|
+
| [markdown-preferences/list-marker-alignment](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/list-marker-alignment.html) | enforce consistent alignment of list markers | 🔧 | ⭐ |
|
|
115
117
|
| [markdown-preferences/no-laziness-blockquotes](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-laziness-blockquotes.html) | disallow laziness in blockquotes | | ⭐ |
|
|
116
118
|
| [markdown-preferences/no-multiple-empty-lines](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-multiple-empty-lines.html) | disallow multiple empty lines in Markdown files. | 🔧 | |
|
|
117
119
|
| [markdown-preferences/no-text-backslash-linebreak](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-text-backslash-linebreak.html) | disallow text backslash at the end of a line. | | ⭐ |
|
package/lib/index.d.ts
CHANGED
|
@@ -20,6 +20,11 @@ interface RuleOptions {
|
|
|
20
20
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/atx-headings-closing-sequence-length.html
|
|
21
21
|
*/
|
|
22
22
|
'markdown-preferences/atx-headings-closing-sequence-length'?: Linter.RuleEntry<MarkdownPreferencesAtxHeadingsClosingSequenceLength>;
|
|
23
|
+
/**
|
|
24
|
+
* enforce consistent alignment of blockquote markers
|
|
25
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/blockquote-marker-alignment.html
|
|
26
|
+
*/
|
|
27
|
+
'markdown-preferences/blockquote-marker-alignment'?: Linter.RuleEntry<[]>;
|
|
23
28
|
/**
|
|
24
29
|
* enforce canonical language names in code blocks
|
|
25
30
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/canonical-code-block-language.html
|
|
@@ -45,6 +50,11 @@ interface RuleOptions {
|
|
|
45
50
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/heading-casing.html
|
|
46
51
|
*/
|
|
47
52
|
'markdown-preferences/heading-casing'?: Linter.RuleEntry<MarkdownPreferencesHeadingCasing>;
|
|
53
|
+
/**
|
|
54
|
+
* enforce consistent alignment of list markers
|
|
55
|
+
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/list-marker-alignment.html
|
|
56
|
+
*/
|
|
57
|
+
'markdown-preferences/list-marker-alignment'?: Linter.RuleEntry<MarkdownPreferencesListMarkerAlignment>;
|
|
48
58
|
/**
|
|
49
59
|
* disallow laziness in blockquotes
|
|
50
60
|
* @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-laziness-blockquotes.html
|
|
@@ -137,6 +147,9 @@ type MarkdownPreferencesHeadingCasing = [] | [{
|
|
|
137
147
|
ignorePatterns?: string[];
|
|
138
148
|
minorWords?: string[];
|
|
139
149
|
}];
|
|
150
|
+
type MarkdownPreferencesListMarkerAlignment = [] | [{
|
|
151
|
+
align?: ("left" | "right");
|
|
152
|
+
}];
|
|
140
153
|
type MarkdownPreferencesNoMultipleEmptyLines = [] | [{
|
|
141
154
|
max?: number;
|
|
142
155
|
maxEOF?: number;
|
|
@@ -207,7 +220,7 @@ declare namespace meta_d_exports {
|
|
|
207
220
|
export { name, version };
|
|
208
221
|
}
|
|
209
222
|
declare const name: "eslint-plugin-markdown-preferences";
|
|
210
|
-
declare const version: "0.
|
|
223
|
+
declare const version: "0.15.0";
|
|
211
224
|
//#endregion
|
|
212
225
|
//#region src/index.d.ts
|
|
213
226
|
declare const configs: {
|
package/lib/index.js
CHANGED
|
@@ -108,7 +108,7 @@ function parseATXHeadingClosingSequenceFromText(text) {
|
|
|
108
108
|
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/utils/lines.ts
|
|
111
|
-
const cache = /* @__PURE__ */ new WeakMap();
|
|
111
|
+
const cache$1 = /* @__PURE__ */ new WeakMap();
|
|
112
112
|
var ParsedLines = class {
|
|
113
113
|
lines;
|
|
114
114
|
constructor(codeText) {
|
|
@@ -150,11 +150,11 @@ var ParsedLines = class {
|
|
|
150
150
|
* @param sourceCode source code to parse
|
|
151
151
|
* @returns parsed lines
|
|
152
152
|
*/
|
|
153
|
-
function
|
|
154
|
-
const cached = cache.get(sourceCode);
|
|
153
|
+
function getParsedLines(sourceCode) {
|
|
154
|
+
const cached = cache$1.get(sourceCode);
|
|
155
155
|
if (cached) return cached;
|
|
156
156
|
const parsedLines = new ParsedLines(sourceCode.text);
|
|
157
|
-
cache.set(sourceCode, parsedLines);
|
|
157
|
+
cache$1.set(sourceCode, parsedLines);
|
|
158
158
|
return parsedLines;
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -228,9 +228,8 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
228
228
|
} };
|
|
229
229
|
})() : option.mode === "fixed-line-length" ? (() => {
|
|
230
230
|
const totalLength = option.length || 80;
|
|
231
|
-
const lines = parseLines(sourceCode);
|
|
232
231
|
const getExpected = (_node, parsed) => {
|
|
233
|
-
return totalLength - getContentLength(
|
|
232
|
+
return totalLength - getContentLength(parsed);
|
|
234
233
|
};
|
|
235
234
|
return { heading(node) {
|
|
236
235
|
verifyATXHeadingClosingSequenceLength(node, getExpected);
|
|
@@ -246,7 +245,6 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
246
245
|
} else verifyATXHeadingClosingSequenceLength(node, getExpected);
|
|
247
246
|
} };
|
|
248
247
|
})() : option.mode === "consistent-line-length" ? (() => {
|
|
249
|
-
const lines = parseLines(sourceCode);
|
|
250
248
|
const headings = [];
|
|
251
249
|
return {
|
|
252
250
|
heading(node) {
|
|
@@ -260,9 +258,9 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
260
258
|
"root:exit"() {
|
|
261
259
|
let mostLongContentHeading = null;
|
|
262
260
|
for (const heading of headings) {
|
|
263
|
-
const contentLength = getContentLength(
|
|
261
|
+
const contentLength = getContentLength(heading.parsed);
|
|
264
262
|
if (mostLongContentHeading == null || contentLength > mostLongContentHeading.contentLength) {
|
|
265
|
-
const lineLength = getLineLength(
|
|
263
|
+
const lineLength = getLineLength(heading.parsed);
|
|
266
264
|
mostLongContentHeading = {
|
|
267
265
|
...heading,
|
|
268
266
|
contentLength,
|
|
@@ -273,11 +271,11 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
273
271
|
if (!mostLongContentHeading) return;
|
|
274
272
|
let minLineLength = mostLongContentHeading.lineLength;
|
|
275
273
|
for (const heading of headings) {
|
|
276
|
-
const lineLength = getLineLength(
|
|
274
|
+
const lineLength = getLineLength(heading.parsed);
|
|
277
275
|
if (mostLongContentHeading.contentLength < lineLength && lineLength < minLineLength) minLineLength = Math.min(minLineLength, lineLength);
|
|
278
276
|
}
|
|
279
277
|
const getExpected = (_node, parsed) => {
|
|
280
|
-
return minLineLength - getContentLength(
|
|
278
|
+
return minLineLength - getContentLength(parsed);
|
|
281
279
|
};
|
|
282
280
|
for (const { node } of headings) verifyATXHeadingClosingSequenceLength(node, getExpected);
|
|
283
281
|
}
|
|
@@ -286,7 +284,8 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
286
284
|
/**
|
|
287
285
|
* Get the content length of the heading.
|
|
288
286
|
*/
|
|
289
|
-
function getContentLength(
|
|
287
|
+
function getContentLength(parsed) {
|
|
288
|
+
const lines = getParsedLines(sourceCode);
|
|
290
289
|
const line = lines.get(parsed.closingSequence.loc.start.line);
|
|
291
290
|
const beforeClosing = sourceCode.text.slice(line.range[0], parsed.closingSequence.range[0]);
|
|
292
291
|
return getTextWidth(beforeClosing);
|
|
@@ -294,7 +293,8 @@ var atx_headings_closing_sequence_length_default = createRule("atx-headings-clos
|
|
|
294
293
|
/**
|
|
295
294
|
* Get the line length of the heading.
|
|
296
295
|
*/
|
|
297
|
-
function getLineLength(
|
|
296
|
+
function getLineLength(parsed) {
|
|
297
|
+
const lines = getParsedLines(sourceCode);
|
|
298
298
|
const line = lines.get(parsed.closingSequence.loc.start.line);
|
|
299
299
|
const lineText = sourceCode.text.slice(line.range[0], parsed.closingSequence.range[1]);
|
|
300
300
|
return getTextWidth(lineText);
|
|
@@ -380,6 +380,123 @@ var atx_headings_closing_sequence_default = createRule("atx-headings-closing-seq
|
|
|
380
380
|
}
|
|
381
381
|
});
|
|
382
382
|
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/utils/blockquotes.ts
|
|
385
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
386
|
+
/**
|
|
387
|
+
* Helper function to get blockquote level information.
|
|
388
|
+
*/
|
|
389
|
+
function getBlockquoteLevelFromLine(sourceCode, lineNumber) {
|
|
390
|
+
let map = cache.get(sourceCode);
|
|
391
|
+
if (!map) {
|
|
392
|
+
map = /* @__PURE__ */ new Map();
|
|
393
|
+
cache.set(sourceCode, map);
|
|
394
|
+
}
|
|
395
|
+
const cached = map.get(lineNumber);
|
|
396
|
+
if (cached) return cached;
|
|
397
|
+
const lineText = sourceCode.lines[lineNumber - 1];
|
|
398
|
+
let prefix = "";
|
|
399
|
+
let level = 0;
|
|
400
|
+
const blockquoteMarkers = /* @__PURE__ */ new Map();
|
|
401
|
+
for (const c of lineText) {
|
|
402
|
+
if (c === ">") {
|
|
403
|
+
level++;
|
|
404
|
+
blockquoteMarkers.set(level, { index: prefix.length });
|
|
405
|
+
} else if (c.trim()) break;
|
|
406
|
+
prefix += c;
|
|
407
|
+
}
|
|
408
|
+
const result = {
|
|
409
|
+
line: lineNumber,
|
|
410
|
+
prefix,
|
|
411
|
+
level,
|
|
412
|
+
blockquoteMarkers
|
|
413
|
+
};
|
|
414
|
+
map.set(lineNumber, result);
|
|
415
|
+
return result;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
//#endregion
|
|
419
|
+
//#region src/rules/blockquote-marker-alignment.ts
|
|
420
|
+
var blockquote_marker_alignment_default = createRule("blockquote-marker-alignment", {
|
|
421
|
+
meta: {
|
|
422
|
+
type: "layout",
|
|
423
|
+
docs: {
|
|
424
|
+
description: "enforce consistent alignment of blockquote markers",
|
|
425
|
+
categories: ["recommended"],
|
|
426
|
+
listCategory: "Stylistic"
|
|
427
|
+
},
|
|
428
|
+
fixable: "whitespace",
|
|
429
|
+
hasSuggestions: false,
|
|
430
|
+
schema: [],
|
|
431
|
+
messages: { inconsistentAlignment: "Blockquote markers should be consistently aligned at the same nesting level." }
|
|
432
|
+
},
|
|
433
|
+
create(context) {
|
|
434
|
+
const sourceCode = context.sourceCode;
|
|
435
|
+
let blockquoteStack = {
|
|
436
|
+
node: sourceCode.ast,
|
|
437
|
+
level: 0,
|
|
438
|
+
upper: null
|
|
439
|
+
};
|
|
440
|
+
return {
|
|
441
|
+
blockquote(node) {
|
|
442
|
+
blockquoteStack = {
|
|
443
|
+
node,
|
|
444
|
+
level: blockquoteStack.level + 1,
|
|
445
|
+
upper: blockquoteStack,
|
|
446
|
+
reported: blockquoteStack.reported
|
|
447
|
+
};
|
|
448
|
+
if (blockquoteStack.reported) return;
|
|
449
|
+
const blockquoteLevel = blockquoteStack.level;
|
|
450
|
+
const loc = sourceCode.getLoc(node);
|
|
451
|
+
const startLine = loc.start.line;
|
|
452
|
+
const endLine = loc.end.line;
|
|
453
|
+
const base = getBlockquoteLevelFromLine(sourceCode, startLine).blockquoteMarkers.get(blockquoteLevel);
|
|
454
|
+
if (!base) return;
|
|
455
|
+
for (let lineNumber = startLine + 1; lineNumber <= endLine; lineNumber++) {
|
|
456
|
+
const marker = getBlockquoteLevelFromLine(sourceCode, lineNumber).blockquoteMarkers.get(blockquoteLevel);
|
|
457
|
+
if (!marker) continue;
|
|
458
|
+
if (base.index === marker.index) continue;
|
|
459
|
+
blockquoteStack.reported = true;
|
|
460
|
+
context.report({
|
|
461
|
+
node,
|
|
462
|
+
loc: {
|
|
463
|
+
start: {
|
|
464
|
+
line: lineNumber,
|
|
465
|
+
column: marker.index + 1
|
|
466
|
+
},
|
|
467
|
+
end: {
|
|
468
|
+
line: lineNumber,
|
|
469
|
+
column: marker.index + 2
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
messageId: "inconsistentAlignment",
|
|
473
|
+
fix(fixer) {
|
|
474
|
+
const lines = getParsedLines(sourceCode);
|
|
475
|
+
const line = lines.get(lineNumber);
|
|
476
|
+
if (marker.index < base.index) {
|
|
477
|
+
const addSpaces = " ".repeat(base.index - marker.index);
|
|
478
|
+
return fixer.insertTextBeforeRange([line.range[0] + marker.index, line.range[0] + marker.index], addSpaces);
|
|
479
|
+
}
|
|
480
|
+
if (blockquoteLevel === 1) {
|
|
481
|
+
const expectedSpaces = " ".repeat(base.index);
|
|
482
|
+
return fixer.replaceTextRange([line.range[0], line.range[0] + marker.index], expectedSpaces);
|
|
483
|
+
}
|
|
484
|
+
const itemBefore = line.text.slice(0, line.range[0] + marker.index);
|
|
485
|
+
if (itemBefore.includes(" ")) return null;
|
|
486
|
+
let removeStartIndex = marker.index;
|
|
487
|
+
for (; removeStartIndex > base.index; removeStartIndex--) if (line.text[removeStartIndex - 1] !== " ") break;
|
|
488
|
+
return fixer.removeRange([line.range[0] + removeStartIndex, line.range[0] + marker.index]);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
"blockquote:exit"() {
|
|
494
|
+
blockquoteStack = blockquoteStack.upper;
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
|
|
383
500
|
//#endregion
|
|
384
501
|
//#region src/utils/ast.ts
|
|
385
502
|
/**
|
|
@@ -3458,20 +3575,99 @@ var heading_casing_default = createRule("heading-casing", {
|
|
|
3458
3575
|
}
|
|
3459
3576
|
});
|
|
3460
3577
|
|
|
3578
|
+
//#endregion
|
|
3579
|
+
//#region src/rules/list-marker-alignment.ts
|
|
3580
|
+
const ALIGN_TO_POSITION_NAME = {
|
|
3581
|
+
left: "start",
|
|
3582
|
+
right: "end"
|
|
3583
|
+
};
|
|
3584
|
+
var list_marker_alignment_default = createRule("list-marker-alignment", {
|
|
3585
|
+
meta: {
|
|
3586
|
+
type: "layout",
|
|
3587
|
+
docs: {
|
|
3588
|
+
description: "enforce consistent alignment of list markers",
|
|
3589
|
+
categories: ["recommended"],
|
|
3590
|
+
listCategory: "Stylistic"
|
|
3591
|
+
},
|
|
3592
|
+
fixable: "whitespace",
|
|
3593
|
+
hasSuggestions: false,
|
|
3594
|
+
schema: [{
|
|
3595
|
+
type: "object",
|
|
3596
|
+
properties: { align: { enum: ["left", "right"] } },
|
|
3597
|
+
additionalProperties: false
|
|
3598
|
+
}],
|
|
3599
|
+
messages: { incorrectAlignment: "List marker alignment is inconsistent. Expected {{expected}} characters of indentation, but got {{actual}}." }
|
|
3600
|
+
},
|
|
3601
|
+
create(context) {
|
|
3602
|
+
const sourceCode = context.sourceCode;
|
|
3603
|
+
const alignPositionName = ALIGN_TO_POSITION_NAME[context.options[0]?.align ?? "left"];
|
|
3604
|
+
/**
|
|
3605
|
+
* Get the marker location of a list item
|
|
3606
|
+
*/
|
|
3607
|
+
function getMarkerLocation(node) {
|
|
3608
|
+
const start = sourceCode.getLoc(node).start;
|
|
3609
|
+
const startColumnIndex = start.column - 1;
|
|
3610
|
+
const marker = getListItemMarker(sourceCode, node);
|
|
3611
|
+
return {
|
|
3612
|
+
line: start.line,
|
|
3613
|
+
start: startColumnIndex,
|
|
3614
|
+
end: startColumnIndex + marker.raw.length
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3617
|
+
/**
|
|
3618
|
+
* Check if list items have consistent alignment
|
|
3619
|
+
*/
|
|
3620
|
+
function checkListAlignment(listNode) {
|
|
3621
|
+
const items = listNode.children;
|
|
3622
|
+
if (items.length <= 1) return;
|
|
3623
|
+
const referenceMarkerLocation = getMarkerLocation(items[0]);
|
|
3624
|
+
for (const item of items.slice(1)) {
|
|
3625
|
+
const markerLocation = getMarkerLocation(item);
|
|
3626
|
+
const diff = markerLocation[alignPositionName] - referenceMarkerLocation[alignPositionName];
|
|
3627
|
+
if (diff === 0) continue;
|
|
3628
|
+
context.report({
|
|
3629
|
+
node: item,
|
|
3630
|
+
loc: {
|
|
3631
|
+
start: {
|
|
3632
|
+
line: markerLocation.line,
|
|
3633
|
+
column: markerLocation.start + 1
|
|
3634
|
+
},
|
|
3635
|
+
end: {
|
|
3636
|
+
line: markerLocation.line,
|
|
3637
|
+
column: markerLocation.end + 1
|
|
3638
|
+
}
|
|
3639
|
+
},
|
|
3640
|
+
messageId: "incorrectAlignment",
|
|
3641
|
+
data: {
|
|
3642
|
+
expected: String(markerLocation.start - diff),
|
|
3643
|
+
actual: String(markerLocation.start)
|
|
3644
|
+
},
|
|
3645
|
+
fix(fixer) {
|
|
3646
|
+
const lines = getParsedLines(sourceCode);
|
|
3647
|
+
const line = lines.get(markerLocation.line);
|
|
3648
|
+
if (diff < 0) {
|
|
3649
|
+
const addSpaces = " ".repeat(-diff);
|
|
3650
|
+
return fixer.insertTextBeforeRange([line.range[0] + markerLocation.start, line.range[0] + markerLocation.start], addSpaces);
|
|
3651
|
+
}
|
|
3652
|
+
const itemBefore = line.text.slice(0, markerLocation.start - diff);
|
|
3653
|
+
if (itemBefore.includes(" ")) return null;
|
|
3654
|
+
const referenceMarkerBefore = lines.get(referenceMarkerLocation.line).text.slice(0, referenceMarkerLocation.start);
|
|
3655
|
+
if (referenceMarkerBefore === itemBefore) {
|
|
3656
|
+
const removeEndIndex = line.range[0] + markerLocation.start;
|
|
3657
|
+
const removeStartIndex = removeEndIndex - diff;
|
|
3658
|
+
return fixer.removeRange([removeStartIndex, removeEndIndex]);
|
|
3659
|
+
}
|
|
3660
|
+
return null;
|
|
3661
|
+
}
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
return { list: checkListAlignment };
|
|
3666
|
+
}
|
|
3667
|
+
});
|
|
3668
|
+
|
|
3461
3669
|
//#endregion
|
|
3462
3670
|
//#region src/rules/no-laziness-blockquotes.ts
|
|
3463
|
-
/**
|
|
3464
|
-
* Helper function to get blockquote line information.
|
|
3465
|
-
*/
|
|
3466
|
-
function getBlockquoteLineInfo(line) {
|
|
3467
|
-
const regex = /^\s*(?:>\s*)*/u;
|
|
3468
|
-
const match = regex.exec(line.text);
|
|
3469
|
-
return {
|
|
3470
|
-
line,
|
|
3471
|
-
prefix: match[0],
|
|
3472
|
-
level: (match[0].match(/>/gu) || []).length
|
|
3473
|
-
};
|
|
3474
|
-
}
|
|
3475
3671
|
var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
3476
3672
|
meta: {
|
|
3477
3673
|
type: "problem",
|
|
@@ -3492,7 +3688,6 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
3492
3688
|
create(context) {
|
|
3493
3689
|
const sourceCode = context.sourceCode;
|
|
3494
3690
|
const checkedLines = /* @__PURE__ */ new Set();
|
|
3495
|
-
const lines = parseLines(sourceCode);
|
|
3496
3691
|
/**
|
|
3497
3692
|
* Report invalid blockquote lines.
|
|
3498
3693
|
*/
|
|
@@ -3516,15 +3711,16 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
3516
3711
|
for (const group of invalidGroups) {
|
|
3517
3712
|
const first = group.lines[0];
|
|
3518
3713
|
const last = group.lines.at(-1);
|
|
3714
|
+
const lines = getParsedLines(sourceCode);
|
|
3519
3715
|
context.report({
|
|
3520
3716
|
loc: {
|
|
3521
3717
|
start: {
|
|
3522
|
-
line: first.line
|
|
3718
|
+
line: first.line,
|
|
3523
3719
|
column: 1
|
|
3524
3720
|
},
|
|
3525
3721
|
end: {
|
|
3526
|
-
line: last.line
|
|
3527
|
-
column: last.line.text.length + 1
|
|
3722
|
+
line: last.line,
|
|
3723
|
+
column: lines.get(last.line).text.length + 1
|
|
3528
3724
|
}
|
|
3529
3725
|
},
|
|
3530
3726
|
messageId: "lazyBlockquoteLine",
|
|
@@ -3536,12 +3732,16 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
3536
3732
|
messageId: "addMarker",
|
|
3537
3733
|
data: { missingMarkers: `${base.level - group.level}` },
|
|
3538
3734
|
*fix(fixer) {
|
|
3539
|
-
for (const invalidLine of group.lines)
|
|
3735
|
+
for (const invalidLine of group.lines) {
|
|
3736
|
+
const parsedLine = lines.get(invalidLine.line);
|
|
3737
|
+
yield fixer.replaceTextRange([parsedLine.range[0], parsedLine.range[0] + invalidLine.prefix.length], base.prefix);
|
|
3738
|
+
}
|
|
3540
3739
|
}
|
|
3541
3740
|
}, {
|
|
3542
3741
|
messageId: "addLineBreak",
|
|
3543
3742
|
fix: (fixer) => {
|
|
3544
|
-
|
|
3743
|
+
const parsedLine = lines.get(first.line);
|
|
3744
|
+
return fixer.insertTextBeforeRange([parsedLine.range[0], parsedLine.range[0]], `${first.prefix.trimEnd()}\n`);
|
|
3545
3745
|
}
|
|
3546
3746
|
}]
|
|
3547
3747
|
});
|
|
@@ -3551,7 +3751,7 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
3551
3751
|
const loc = sourceCode.getLoc(node);
|
|
3552
3752
|
const startLine = loc.start.line;
|
|
3553
3753
|
const endLine = loc.end.line;
|
|
3554
|
-
const base =
|
|
3754
|
+
const base = getBlockquoteLevelFromLine(sourceCode, startLine);
|
|
3555
3755
|
const invalidLines = [];
|
|
3556
3756
|
for (let lineNumber = startLine + 1; lineNumber <= endLine; lineNumber++) {
|
|
3557
3757
|
if (checkedLines.has(lineNumber)) {
|
|
@@ -3560,8 +3760,7 @@ var no_laziness_blockquotes_default = createRule("no-laziness-blockquotes", {
|
|
|
3560
3760
|
continue;
|
|
3561
3761
|
}
|
|
3562
3762
|
checkedLines.add(lineNumber);
|
|
3563
|
-
const
|
|
3564
|
-
const current = getBlockquoteLineInfo(line);
|
|
3763
|
+
const current = getBlockquoteLevelFromLine(sourceCode, lineNumber);
|
|
3565
3764
|
if (base.level <= current.level) {
|
|
3566
3765
|
reportInvalidLines(invalidLines, base);
|
|
3567
3766
|
invalidLines.length = 0;
|
|
@@ -3638,7 +3837,7 @@ var no_multiple_empty_lines_default = createRule("no-multiple-empty-lines", {
|
|
|
3638
3837
|
toml: addIgnoreLoc,
|
|
3639
3838
|
json: addIgnoreLoc,
|
|
3640
3839
|
"root:exit"() {
|
|
3641
|
-
const lines = [...
|
|
3840
|
+
const lines = [...getParsedLines(sourceCode)];
|
|
3642
3841
|
const bofEmptyLines = [];
|
|
3643
3842
|
while (lines.length) {
|
|
3644
3843
|
if (lines[0].text.trim()) break;
|
|
@@ -3852,7 +4051,7 @@ var no_trailing_spaces_default = createRule("no-trailing-spaces", {
|
|
|
3852
4051
|
"root:exit"() {
|
|
3853
4052
|
const re = /[^\S\n\r]+$/u;
|
|
3854
4053
|
const skipMatch = /^[^\S\n\r]*$/u;
|
|
3855
|
-
const lines =
|
|
4054
|
+
const lines = getParsedLines(sourceCode);
|
|
3856
4055
|
const commentLineNumbers = getCommentLineNumbers();
|
|
3857
4056
|
for (const lineInfo of lines) {
|
|
3858
4057
|
const matches = re.exec(lineInfo.text);
|
|
@@ -4140,7 +4339,6 @@ var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks",
|
|
|
4140
4339
|
},
|
|
4141
4340
|
create(context) {
|
|
4142
4341
|
const sourceCode = context.sourceCode;
|
|
4143
|
-
const lines = parseLines(sourceCode);
|
|
4144
4342
|
return { code(node) {
|
|
4145
4343
|
const kind = getCodeBlockKind(sourceCode, node);
|
|
4146
4344
|
if (kind === "backtick-fenced" || kind === "tilde-fenced") return;
|
|
@@ -4150,6 +4348,7 @@ var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks",
|
|
|
4150
4348
|
messageId: "useFencedCodeBlock",
|
|
4151
4349
|
fix(fixer) {
|
|
4152
4350
|
if (!isFixableIndentedCodeBlock(node)) return null;
|
|
4351
|
+
const lines = getParsedLines(sourceCode);
|
|
4153
4352
|
const startColumnOffset = loc.start.column - 1;
|
|
4154
4353
|
const removeRanges = [];
|
|
4155
4354
|
let prefixText = null;
|
|
@@ -4185,6 +4384,7 @@ var prefer_fenced_code_blocks_default = createRule("prefer-fenced-code-blocks",
|
|
|
4185
4384
|
*/
|
|
4186
4385
|
function isFixableIndentedCodeBlock(node) {
|
|
4187
4386
|
if (!node.value.startsWith(" ")) return true;
|
|
4387
|
+
const lines = getParsedLines(sourceCode);
|
|
4188
4388
|
const loc = sourceCode.getLoc(node);
|
|
4189
4389
|
const firstLine = lines.get(loc.start.line);
|
|
4190
4390
|
const codeBlockFirstLine = normalizePrefix(node.value.split(/\r?\n/u)[0]);
|
|
@@ -4808,14 +5008,14 @@ var sort_definitions_default = createRule("sort-definitions", {
|
|
|
4808
5008
|
}
|
|
4809
5009
|
/** Compile order option */
|
|
4810
5010
|
function compileOption(orderOption) {
|
|
4811
|
-
const cache$
|
|
5011
|
+
const cache$2 = /* @__PURE__ */ new Map();
|
|
4812
5012
|
const compiled = compileOptionWithoutCache(orderOption);
|
|
4813
5013
|
return {
|
|
4814
5014
|
match: (node) => {
|
|
4815
|
-
const cached = cache$
|
|
5015
|
+
const cached = cache$2.get(node);
|
|
4816
5016
|
if (cached != null) return cached;
|
|
4817
5017
|
const result = compiled.match(node);
|
|
4818
|
-
cache$
|
|
5018
|
+
cache$2.set(node, result);
|
|
4819
5019
|
return result;
|
|
4820
5020
|
},
|
|
4821
5021
|
sort: compiled.sort
|
|
@@ -5057,11 +5257,13 @@ var table_header_casing_default = createRule("table-header-casing", {
|
|
|
5057
5257
|
const rules$1 = [
|
|
5058
5258
|
atx_headings_closing_sequence_length_default,
|
|
5059
5259
|
atx_headings_closing_sequence_default,
|
|
5260
|
+
blockquote_marker_alignment_default,
|
|
5060
5261
|
canonical_code_block_language_default,
|
|
5061
5262
|
definitions_last_default,
|
|
5062
5263
|
emoji_notation_default,
|
|
5063
5264
|
hard_linebreak_style_default,
|
|
5064
5265
|
heading_casing_default,
|
|
5266
|
+
list_marker_alignment_default,
|
|
5065
5267
|
no_laziness_blockquotes_default,
|
|
5066
5268
|
no_multiple_empty_lines_default,
|
|
5067
5269
|
no_text_backslash_linebreak_default,
|
|
@@ -5099,7 +5301,9 @@ const plugins = {
|
|
|
5099
5301
|
}
|
|
5100
5302
|
};
|
|
5101
5303
|
const rules$2 = {
|
|
5304
|
+
"markdown-preferences/blockquote-marker-alignment": "error",
|
|
5102
5305
|
"markdown-preferences/hard-linebreak-style": "error",
|
|
5306
|
+
"markdown-preferences/list-marker-alignment": "error",
|
|
5103
5307
|
"markdown-preferences/no-laziness-blockquotes": "error",
|
|
5104
5308
|
"markdown-preferences/no-text-backslash-linebreak": "error",
|
|
5105
5309
|
"markdown-preferences/prefer-autolinks": "error",
|
|
@@ -5114,7 +5318,7 @@ __export(meta_exports, {
|
|
|
5114
5318
|
version: () => version
|
|
5115
5319
|
});
|
|
5116
5320
|
const name = "eslint-plugin-markdown-preferences";
|
|
5117
|
-
const version = "0.
|
|
5321
|
+
const version = "0.15.0";
|
|
5118
5322
|
|
|
5119
5323
|
//#endregion
|
|
5120
5324
|
//#region src/index.ts
|