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 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, linking, and style consistency automatically
17
- - **📖 Professional documentation** - Enforce consistent line breaks, clean up trailing spaces, and organize link definitions for enterprise-ready documentation
18
- - **🎯 Smart terminology management** - Automatically convert specified words into inline code or clickable links based on your configuration
19
- - **⚙️ Highly customizable configuration** - Fine-tune every aspect with granular rule options, word lists, ignore patterns, and flexible thresholds to match your exact requirements
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.14.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 parseLines(sourceCode) {
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(lines, parsed);
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(lines, heading.parsed);
261
+ const contentLength = getContentLength(heading.parsed);
264
262
  if (mostLongContentHeading == null || contentLength > mostLongContentHeading.contentLength) {
265
- const lineLength = getLineLength(lines, heading.parsed);
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(lines, heading.parsed);
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(lines, parsed);
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(lines, parsed) {
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(lines, parsed) {
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.line,
3718
+ line: first.line,
3523
3719
  column: 1
3524
3720
  },
3525
3721
  end: {
3526
- line: last.line.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) yield fixer.replaceTextRange([invalidLine.line.range[0], invalidLine.line.range[0] + invalidLine.prefix.length], base.prefix);
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
- return fixer.insertTextBeforeRange([first.line.range[0], first.line.range[0]], `${first.prefix.trimEnd()}\n`);
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 = getBlockquoteLineInfo(lines.get(startLine));
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 line = lines.get(lineNumber);
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 = [...parseLines(sourceCode)];
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 = parseLines(sourceCode);
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$1 = /* @__PURE__ */ new Map();
5011
+ const cache$2 = /* @__PURE__ */ new Map();
4812
5012
  const compiled = compileOptionWithoutCache(orderOption);
4813
5013
  return {
4814
5014
  match: (node) => {
4815
- const cached = cache$1.get(node);
5015
+ const cached = cache$2.get(node);
4816
5016
  if (cached != null) return cached;
4817
5017
  const result = compiled.match(node);
4818
- cache$1.set(node, result);
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.14.0";
5321
+ const version = "0.15.0";
5118
5322
 
5119
5323
  //#endregion
5120
5324
  //#region src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-markdown-preferences",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "ESLint plugin that enforces our markdown preferences",
5
5
  "type": "module",
6
6
  "exports": {