eslint-plugin-markdown-preferences 0.6.0 → 0.7.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
@@ -2,13 +2,13 @@
2
2
 
3
3
  A specialized ESLint plugin that helps enforce consistent writing style and formatting conventions in Markdown files. Perfect for documentation projects, blog posts, and any Markdown content where consistency matters.
4
4
 
5
- [![NPM license](https://img.shields.io/npm/l/eslint-plugin-markdown-preferences.svg)](https://www.npmjs.com/package/eslint-plugin-markdown-preferences)
6
- [![NPM version](https://img.shields.io/npm/v/eslint-plugin-markdown-preferences.svg)](https://www.npmjs.com/package/eslint-plugin-markdown-preferences)
7
- [![NPM downloads](https://img.shields.io/badge/dynamic/json.svg?label=downloads&colorB=green&suffix=/day&query=$.downloads&uri=https://api.npmjs.org//downloads/point/last-day/eslint-plugin-markdown-preferences&maxAge=3600)](http://www.npmtrends.com/eslint-plugin-markdown-preferences)
8
- [![NPM downloads](https://img.shields.io/npm/dw/eslint-plugin-markdown-preferences.svg)](http://www.npmtrends.com/eslint-plugin-markdown-preferences)
9
- [![NPM downloads](https://img.shields.io/npm/dm/eslint-plugin-markdown-preferences.svg)](http://www.npmtrends.com/eslint-plugin-markdown-preferences)
10
- [![NPM downloads](https://img.shields.io/npm/dy/eslint-plugin-markdown-preferences.svg)](http://www.npmtrends.com/eslint-plugin-markdown-preferences)
11
- [![NPM downloads](https://img.shields.io/npm/dt/eslint-plugin-markdown-preferences.svg)](http://www.npmtrends.com/eslint-plugin-markdown-preferences)
5
+ [![NPM license](https://img.shields.io/npm/l/eslint-plugin-markdown-preferences.svg)][npm-package]
6
+ [![NPM version](https://img.shields.io/npm/v/eslint-plugin-markdown-preferences.svg)][npm-package]
7
+ [![NPM downloads](https://img.shields.io/badge/dynamic/json.svg?label=downloads&colorB=green&suffix=/day&query=$.downloads&uri=https://api.npmjs.org//downloads/point/last-day/eslint-plugin-markdown-preferences&maxAge=3600)][npmtrends]
8
+ [![NPM downloads](https://img.shields.io/npm/dw/eslint-plugin-markdown-preferences.svg)][npmtrends]
9
+ [![NPM downloads](https://img.shields.io/npm/dm/eslint-plugin-markdown-preferences.svg)][npmtrends]
10
+ [![NPM downloads](https://img.shields.io/npm/dy/eslint-plugin-markdown-preferences.svg)][npmtrends]
11
+ [![NPM downloads](https://img.shields.io/npm/dt/eslint-plugin-markdown-preferences.svg)][npmtrends]
12
12
  [![Build Status](https://github.com/ota-meshi/eslint-plugin-markdown-preferences/actions/workflows/NodeCI.yml/badge.svg?branch=main)](https://github.com/ota-meshi/eslint-plugin-markdown-preferences/actions/workflows/NodeCI.yml)
13
13
 
14
14
  ## 📛 Features
@@ -81,7 +81,7 @@ Is not supported.
81
81
 
82
82
  <!--RULES_SECTION_START-->
83
83
 
84
- The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench 🔧 below.
84
+ The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench 🔧 below.\
85
85
  The rules with the following star ⭐ are included in the configs.
86
86
 
87
87
  <!--RULES_TABLE_START-->
@@ -90,6 +90,7 @@ The rules with the following star ⭐ are included in the configs.
90
90
 
91
91
  | Rule ID | Description | Fixable | RECOMMENDED |
92
92
  |:--------|:------------|:-------:|:-----------:|
93
+ | [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 | 🔧 | |
93
94
  | [markdown-preferences/hard-linebreak-style](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html) | enforce consistent hard linebreak style. | 🔧 | ⭐ |
94
95
  | [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. | | ⭐ |
95
96
  | [markdown-preferences/no-trailing-spaces](https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/no-trailing-spaces.html) | disallow trailing whitespace at the end of lines in Markdown files. | 🔧 | |
@@ -109,9 +110,12 @@ Please use GitHub's Issues/PRs.
109
110
 
110
111
  ### Development Tools
111
112
 
112
- - `npm test` runs tests and measures coverage.
113
- - `npm run update` runs in order to update readme and recommended configuration.
113
+ - `npm test` runs tests and measures coverage.
114
+ - `npm run update` runs in order to update readme and recommended configuration.
114
115
 
115
116
  ## 🔒 License
116
117
 
117
118
  See the [LICENSE](LICENSE) file for license rights and limitations (MIT).
119
+
120
+ [npm-package]: https://www.npmjs.com/package/eslint-plugin-markdown-preferences
121
+ [npmtrends]: http://www.npmtrends.com/eslint-plugin-markdown-preferences
package/lib/index.d.ts CHANGED
@@ -10,6 +10,11 @@ declare module 'eslint' {
10
10
  }
11
11
  }
12
12
  interface RuleOptions {
13
+ /**
14
+ * require link definitions and footnote definitions to be placed at the end of the document
15
+ * @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/definitions-last.html
16
+ */
17
+ 'markdown-preferences/definitions-last'?: Linter.RuleEntry<[]>;
13
18
  /**
14
19
  * enforce consistent hard linebreak style.
15
20
  * @see https://ota-meshi.github.io/eslint-plugin-markdown-preferences/rules/hard-linebreak-style.html
@@ -90,7 +95,7 @@ declare namespace meta_d_exports {
90
95
  export { name, version };
91
96
  }
92
97
  declare const name: "eslint-plugin-markdown-preferences";
93
- declare const version: "0.6.0";
98
+ declare const version: "0.7.0";
94
99
  //#endregion
95
100
  //#region src/index.d.ts
96
101
  declare const configs: {
package/lib/index.js CHANGED
@@ -25,6 +25,46 @@ function createRule(ruleName, rule) {
25
25
  };
26
26
  }
27
27
 
28
+ //#endregion
29
+ //#region src/rules/definitions-last.ts
30
+ var definitions_last_default = createRule("definitions-last", {
31
+ meta: {
32
+ type: "layout",
33
+ docs: {
34
+ description: "require link definitions and footnote definitions to be placed at the end of the document",
35
+ categories: []
36
+ },
37
+ fixable: "code",
38
+ hasSuggestions: false,
39
+ schema: [],
40
+ messages: {}
41
+ },
42
+ create(context) {
43
+ const sourceCode = context.sourceCode;
44
+ const lastNonDefinition = sourceCode.ast.children.findLast((node) => node.type !== "definition" && node.type !== "footnoteDefinition" && !(node.type === "html" && (node.value.startsWith("<!--") || node.value.startsWith("<script") || node.value.startsWith("<style"))));
45
+ if (!lastNonDefinition) return {};
46
+ const lastNonDefinitionRange = sourceCode.getRange(lastNonDefinition);
47
+ return { "definition, footnoteDefinition"(node) {
48
+ const range = sourceCode.getRange(node);
49
+ if (lastNonDefinitionRange[1] <= range[0]) return;
50
+ context.report({
51
+ node,
52
+ message: "Definition or footnote definition should be placed at the end of the document.",
53
+ *fix(fixer) {
54
+ let rangeStart = range[0];
55
+ for (let index = range[0] - 1; index >= 0; index--) {
56
+ const c = sourceCode.text[index];
57
+ if (c.trim()) break;
58
+ rangeStart = index;
59
+ }
60
+ yield fixer.removeRange([rangeStart, range[1]]);
61
+ yield fixer.insertTextAfterRange(lastNonDefinitionRange, sourceCode.text.slice(rangeStart, range[1]));
62
+ }
63
+ });
64
+ } };
65
+ }
66
+ });
67
+
28
68
  //#endregion
29
69
  //#region src/rules/hard-linebreak-style.ts
30
70
  var hard_linebreak_style_default = createRule("hard-linebreak-style", {
@@ -433,6 +473,7 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
433
473
  const definitions = [];
434
474
  const links = [];
435
475
  const linkReferences = [];
476
+ const headings = [];
436
477
  /**
437
478
  * Verify links.
438
479
  */
@@ -456,15 +497,18 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
456
497
  const definition = nodes.definitions[0];
457
498
  let identifier;
458
499
  if (definition) identifier = definition.label ?? definition.identifier;
459
- else identifier = linkInfo.label.replaceAll(/\]/g, "-");
500
+ else identifier = linkInfo.label.replaceAll(/[[\]]/gu, "-");
460
501
  yield fixer.replaceText(link, `${sourceCode.text.slice(...linkInfo.labelRange)}${identifier === linkInfo.label ? "" : `[${identifier}]`}`);
461
502
  if (!definition) {
462
503
  const linkRange = sourceCode.getRange(link);
463
- const reLineBreaks = /\n#{1,6}\s/gu;
464
- reLineBreaks.lastIndex = linkRange[1];
465
- const nextSectionMatch = reLineBreaks.exec(sourceCode.text);
466
- const insertIndex = !nextSectionMatch ? sourceCode.text.trimEnd().length : nextSectionMatch.index;
467
- yield fixer.insertTextAfterRange([insertIndex, insertIndex], `${sourceCode.text[insertIndex - 1] === "\n" ? "" : "\n"}\n[${identifier}]: ${sourceCode.text.slice(linkInfo.urlAndTitleRange[0] + 1, linkInfo.urlAndTitleRange[1] - 1).trim()}${nextSectionMatch ? "\n" : ""}`);
504
+ const nextSectionHeading = headings.find((heading) => linkRange[1] < sourceCode.getRange(heading)[0]);
505
+ let insertIndex;
506
+ if (nextSectionHeading) {
507
+ const headingRange = sourceCode.getRange(nextSectionHeading);
508
+ const headingStartLoc = sourceCode.getLoc(nextSectionHeading).start;
509
+ insertIndex = headingRange[0] - headingStartLoc.column;
510
+ } else insertIndex = sourceCode.text.trimEnd().length;
511
+ yield fixer.insertTextAfterRange([insertIndex, insertIndex], `${sourceCode.text[insertIndex - 1] === "\n" ? "" : "\n"}\n[${identifier}]: ${sourceCode.text.slice(linkInfo.urlAndTitleRange[0] + 1, linkInfo.urlAndTitleRange[1] - 1).trim()}${nextSectionHeading ? "\n" : ""}`);
468
512
  }
469
513
  }
470
514
  });
@@ -503,6 +547,9 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
503
547
  definition(node) {
504
548
  definitions.push(node);
505
549
  },
550
+ heading(node) {
551
+ headings.push(node);
552
+ },
506
553
  "root:exit"() {
507
554
  verify();
508
555
  }
@@ -530,7 +577,7 @@ var prefer_link_reference_definitions_default = createRule("prefer-link-referenc
530
577
  return [range[0], index$1 + 1];
531
578
  }
532
579
  const lastRange = sourceCode.getRange(link.children[link.children.length - 1]);
533
- const index = sourceCode.text.indexOf("]", lastRange[0] + 1);
580
+ const index = sourceCode.text.indexOf("]", lastRange[1]);
534
581
  return [range[0], index + 1];
535
582
  }
536
583
  }
@@ -648,6 +695,7 @@ var prefer_linked_words_default = createRule("prefer-linked-words", {
648
695
  //#endregion
649
696
  //#region src/utils/rules.ts
650
697
  const rules$1 = [
698
+ definitions_last_default,
651
699
  hard_linebreak_style_default,
652
700
  no_text_backslash_linebreak_default,
653
701
  no_trailing_spaces_default,
@@ -667,7 +715,7 @@ __export(recommended_exports, {
667
715
  rules: () => rules$2
668
716
  });
669
717
  const name$1 = "markdown-preferences/recommended";
670
- const files = ["**/*.md"];
718
+ const files = ["*.md", "**/*.md"];
671
719
  const language = "markdown/commonmark";
672
720
  const plugins = {
673
721
  markdown,
@@ -688,7 +736,7 @@ __export(meta_exports, {
688
736
  version: () => version
689
737
  });
690
738
  const name = "eslint-plugin-markdown-preferences";
691
- const version = "0.6.0";
739
+ const version = "0.7.0";
692
740
 
693
741
  //#endregion
694
742
  //#region src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-markdown-preferences",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "ESLint plugin that enforces our markdown preferences",
5
5
  "type": "module",
6
6
  "exports": {
@@ -64,7 +64,7 @@
64
64
  "@changesets/get-release-plan": "^4.0.8",
65
65
  "@eslint/core": "^0.15.0",
66
66
  "@eslint/markdown": "^7.1.0",
67
- "@ota-meshi/eslint-plugin": "^0.17.6",
67
+ "@ota-meshi/eslint-plugin": "^0.18.0",
68
68
  "@shikijs/vitepress-twoslash": "^3.0.0",
69
69
  "@types/eslint": "^9.6.1",
70
70
  "@types/eslint-scope": "^8.0.0",
@@ -82,7 +82,7 @@
82
82
  "eslint-compat-utils": "^0.6.4",
83
83
  "eslint-config-prettier": "^10.1.1",
84
84
  "eslint-plugin-eslint-comments": "^3.2.0",
85
- "eslint-plugin-eslint-plugin": "^6.4.0",
85
+ "eslint-plugin-eslint-plugin": "^7.0.0",
86
86
  "eslint-plugin-jsdoc": "^52.0.0",
87
87
  "eslint-plugin-json-schema-validator": "^5.3.1",
88
88
  "eslint-plugin-jsonc": "^2.19.1",