eslint-markdown 0.8.0 → 0.9.1

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.
Files changed (34) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +1 -1
  3. package/build/rules/index.d.ts +1 -1
  4. package/build/rules/no-double-punctuation.d.ts +6 -2
  5. package/package.json +5 -3
  6. package/src/rules/allow-heading.js +1 -1
  7. package/src/rules/allow-image-url.js +1 -1
  8. package/src/rules/allow-link-url.js +1 -1
  9. package/src/rules/code-lang-shorthand.js +1 -1
  10. package/src/rules/consistent-code-style.js +1 -1
  11. package/src/rules/consistent-delete-style.js +1 -1
  12. package/src/rules/consistent-emphasis-style.js +1 -1
  13. package/src/rules/consistent-inline-code-style.js +1 -1
  14. package/src/rules/consistent-strong-style.js +1 -1
  15. package/src/rules/consistent-thematic-break-style.js +1 -1
  16. package/src/rules/en-capitalization.js +1 -1
  17. package/src/rules/heading-id.js +1 -1
  18. package/src/rules/no-bold-paragraph.js +1 -1
  19. package/src/rules/no-control-character.js +1 -1
  20. package/src/rules/no-curly-quote.js +1 -1
  21. package/src/rules/no-double-punctuation.js +59 -3
  22. package/src/rules/no-double-space.js +1 -1
  23. package/src/rules/no-emoji.js +1 -1
  24. package/src/rules/no-git-conflict-marker.js +1 -1
  25. package/src/rules/no-irregular-dash.js +1 -1
  26. package/src/rules/no-irregular-whitespace.js +1 -1
  27. package/src/rules/no-tab.js +1 -1
  28. package/src/rules/no-url-trailing-slash.js +1 -1
  29. package/src/rules/require-image-title.js +1 -1
  30. package/src/rules/require-link-title.js +1 -1
  31. package/build/core/rule-tester.d.ts +0 -13
  32. package/build/rules/footnote-order.d.ts +0 -1
  33. package/src/core/rule-tester.js +0 -127
  34. package/src/rules/footnote-order.js +0 -2
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2024-present 루밀LuMir(lumirlumir)
3
+ Copyright (c) 2024-present lumir(lumirlumir)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  > If you like this package, please give it a star on [GitHub](https://github.com/lumirlumir/npm-eslint-markdown)!⭐<br/>
14
14
  > Your support helps us improve and maintain the project.
15
15
 
16
- Lint your Markdown with ESLint.🛠️
16
+ Lint your Markdown with ESLint. Additional rules for use with `@eslint/markdown`.🛠️
17
17
 
18
18
  ## Documentation
19
19
 
@@ -11,7 +11,7 @@ declare const _default: {
11
11
  'consistent-unordered-list-style': import("../core/types.js").RuleModule<import("./consistent-unordered-list-style.js").RuleOptions, "style">;
12
12
  'no-control-character': import("../core/types.js").RuleModule<import("./no-control-character.js").RuleOptions, "noControlCharacter">;
13
13
  'no-curly-quote': import("../core/types.js").RuleModule<import("./no-curly-quote.js").RuleOptions, "noCurlyQuote">;
14
- 'no-double-punctuation': import("../core/types.js").RuleModule<import("./no-double-punctuation.js").RuleOptions, "noDoublePunctuation">;
14
+ 'no-double-punctuation': import("../core/types.js").RuleModule<import("./no-double-punctuation.js").RuleOptions, import("./no-double-punctuation.js").MessageIds>;
15
15
  'no-double-space': import("../core/types.js").RuleModule<import("./no-double-space.js").RuleOptions, import("./no-double-space.js").MessageIds>;
16
16
  'no-emoji': import("../core/types.js").RuleModule<import("./no-emoji.js").RuleOptions, "noEmoji">;
17
17
  'no-git-conflict-marker': import("../core/types.js").RuleModule<import("./no-git-conflict-marker.js").RuleOptions, "noGitConflictMarker">;
@@ -7,6 +7,8 @@ declare const _default: {
7
7
  recommended: boolean;
8
8
  stylistic: false;
9
9
  };
10
+ fixable: "code";
11
+ hasSuggestions: true;
10
12
  schema: {
11
13
  type: "object";
12
14
  properties: {
@@ -28,6 +30,8 @@ declare const _default: {
28
30
  }];
29
31
  messages: {
30
32
  noDoublePunctuation: string;
33
+ suggestReplaceWithLeft: string;
34
+ suggestReplaceWithRight: string;
31
35
  };
32
36
  language: string;
33
37
  dialects: string[];
@@ -37,7 +41,7 @@ declare const _default: {
37
41
  Code: import("@eslint/markdown").MarkdownSourceCode;
38
42
  RuleOptions: RuleOptions;
39
43
  Node: import("mdast").Node;
40
- MessageIds: "noDoublePunctuation";
44
+ MessageIds: MessageIds;
41
45
  }>): {
42
46
  text(node: import("mdast").Text): void;
43
47
  };
@@ -46,4 +50,4 @@ export default _default;
46
50
  export type RuleOptions = [{
47
51
  allow: string[];
48
52
  }];
49
- export type MessageIds = "noDoublePunctuation";
53
+ export type MessageIds = "noDoublePunctuation" | "suggestReplaceWithLeft" | "suggestReplaceWithRight";
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "eslint-markdown",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
- "description": "Lint your Markdown with ESLint.🛠️",
5
+ "sideEffects": false,
6
+ "description": "Lint your Markdown with ESLint. Additional rules for use with `@eslint/markdown`.🛠️",
6
7
  "exports": {
7
8
  ".": {
8
9
  "types": "./build/index.d.ts",
@@ -26,6 +27,7 @@
26
27
  "LICENSE.md",
27
28
  "README.md",
28
29
  "!src/**/*.test.{js,ts}",
30
+ "!{src,build}/tests/**",
29
31
  "!**/fixtures/**"
30
32
  ],
31
33
  "keywords": [
@@ -39,7 +41,7 @@
39
41
  "commonmark",
40
42
  "gfm"
41
43
  ],
42
- "author": "루밀LuMir <rpfos@naver.com> (https://github.com/lumirlumir)",
44
+ "author": "lumir <rpfos@naver.com> (https://github.com/lumirlumir)",
43
45
  "funding": "https://github.com/sponsors/lumirlumir",
44
46
  "license": "MIT",
45
47
  "homepage": "https://eslint-markdown.lumir.page",
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of allowed text for headings.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of allowed or disallowed URLs for images.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of allowed or disallowed URLs for links.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of shorthand for code block language identifiers.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent code style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  /*
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent delete style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent emphasis style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent inline code style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  * @see https://github.com/DavidAnson/markdownlint/blob/v0.40.0/lib/md038.mjs
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent strong style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce consistent thematic break style.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of capital letters at the beginning of sentences.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // @ts-nocheck -- TODO
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of heading IDs.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // @ts-nocheck -- TODO
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow using fully bolded paragraphs as headings.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // @ts-nocheck -- TODO
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow control character.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow curly quotes(`“`, `”`, `‘` or `’`) in text.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow double consecutive punctuation in text.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
  /**
17
17
  * @import { RuleModule } from '../core/types.js';
18
18
  * @typedef {[{ allow: string[] }]} RuleOptions
19
- * @typedef {'noDoublePunctuation'} MessageIds
19
+ * @typedef {'noDoublePunctuation' | 'suggestReplaceWithLeft' | 'suggestReplaceWithRight'} MessageIds
20
20
  */
21
21
 
22
22
  // --------------------------------------------------------------------------------
@@ -45,6 +45,10 @@ export default {
45
45
  stylistic: false,
46
46
  },
47
47
 
48
+ fixable: 'code',
49
+
50
+ hasSuggestions: true,
51
+
48
52
  schema: [
49
53
  {
50
54
  type: 'object',
@@ -72,6 +76,10 @@ export default {
72
76
 
73
77
  messages: {
74
78
  noDoublePunctuation: 'Double punctuation mark `{{ punctuation }}` is not allowed.',
79
+ suggestReplaceWithLeft:
80
+ 'Replace `{{ punctuation }}` with the left punctuation mark `{{ leftPunctuation }}`.',
81
+ suggestReplaceWithRight:
82
+ 'Replace `{{ punctuation }}` with the right punctuation mark `{{ rightPunctuation }}`.',
75
83
  },
76
84
 
77
85
  language: 'markdown',
@@ -96,7 +104,8 @@ export default {
96
104
 
97
105
  if (allow.includes(punctuation)) continue;
98
106
 
99
- context.report({
107
+ const [leftPunctuation, rightPunctuation] = punctuation;
108
+ const violation = /** @type {const} */ ({
100
109
  loc: {
101
110
  start: sourceCode.getLocFromIndex(startOffset),
102
111
  end: sourceCode.getLocFromIndex(endOffset),
@@ -108,6 +117,53 @@ export default {
108
117
 
109
118
  messageId: 'noDoublePunctuation',
110
119
  });
120
+
121
+ if (leftPunctuation === rightPunctuation) {
122
+ context.report({
123
+ ...violation,
124
+
125
+ fix(fixer) {
126
+ return fixer.replaceTextRange([startOffset, endOffset], leftPunctuation);
127
+ },
128
+ });
129
+ } else {
130
+ context.report({
131
+ ...violation,
132
+
133
+ suggest: [
134
+ {
135
+ messageId: 'suggestReplaceWithLeft',
136
+
137
+ data: {
138
+ punctuation,
139
+ leftPunctuation,
140
+ },
141
+
142
+ fix(fixer) {
143
+ return fixer.replaceTextRange(
144
+ [startOffset, endOffset],
145
+ leftPunctuation,
146
+ );
147
+ },
148
+ },
149
+ {
150
+ messageId: 'suggestReplaceWithRight',
151
+
152
+ data: {
153
+ punctuation,
154
+ rightPunctuation,
155
+ },
156
+
157
+ fix(fixer) {
158
+ return fixer.replaceTextRange(
159
+ [startOffset, endOffset],
160
+ rightPunctuation,
161
+ );
162
+ },
163
+ },
164
+ ],
165
+ });
166
+ }
111
167
  }
112
168
  },
113
169
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow double or multiple consecutive spaces in text, except for leading and trailing spaces.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow emojis in text.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow git conflict markers.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow irregular dash.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow irregular whitespace.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow tab characters.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to disallow URL trailing slash.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of title attribute for images.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule to enforce the use of title attribute for links.
3
- * @author 루밀LuMir(lumirlumir)
3
+ * @author lumir(lumirlumir)
4
4
  */
5
5
 
6
6
  // --------------------------------------------------------------------------------
@@ -1,13 +0,0 @@
1
- /**
2
- * Markdown rule tester.
3
- * @param {string} ruleName Rule name.
4
- * @param {RuleModule<RuleOptions, MessageIds>} rule Rule module.
5
- * @param {Tests} tests Tests.
6
- */
7
- export default function ruleTester(ruleName: string, rule: RuleModule<RuleOptions, MessageIds>, tests: Tests): void;
8
- export type RuleOptions = MarkdownRuleDefinitionTypeOptions["RuleOptions"];
9
- export type MessageIds = MarkdownRuleDefinitionTypeOptions["MessageIds"];
10
- export type Tests = Parameters<RuleTester["run"]>[2];
11
- import type { RuleModule } from './types.js';
12
- import type { MarkdownRuleDefinitionTypeOptions } from '@eslint/markdown';
13
- import { RuleTester } from 'eslint';
@@ -1 +0,0 @@
1
- export {};
@@ -1,127 +0,0 @@
1
- /**
2
- * @fileoverview Markdown rule tester.
3
- */
4
-
5
- // --------------------------------------------------------------------------------
6
- // Import
7
- // --------------------------------------------------------------------------------
8
-
9
- import { describe, it } from 'node:test';
10
- import { match, ok } from 'node:assert';
11
- import { RuleTester } from 'eslint';
12
- import markdown from '@eslint/markdown';
13
-
14
- // --------------------------------------------------------------------------------
15
- // Typedef
16
- // --------------------------------------------------------------------------------
17
-
18
- /**
19
- * @import { MarkdownRuleDefinitionTypeOptions } from '@eslint/markdown';
20
- * @import { RuleModule } from './types.js';
21
- * @typedef {MarkdownRuleDefinitionTypeOptions['RuleOptions']} RuleOptions
22
- * @typedef {MarkdownRuleDefinitionTypeOptions['MessageIds']} MessageIds
23
- * @typedef {Parameters<RuleTester['run']>[2]} Tests
24
- */
25
-
26
- // --------------------------------------------------------------------------------
27
- // Helper
28
- // --------------------------------------------------------------------------------
29
-
30
- /**
31
- * Rule tester for CommonMark.
32
- */
33
- const ruleTesterCommonmark = new RuleTester({
34
- plugins: {
35
- markdown,
36
- },
37
- language: 'markdown/commonmark',
38
- });
39
-
40
- /**
41
- * Rule tester for GFM.
42
- */
43
- const ruleTesterGfm = new RuleTester({
44
- plugins: {
45
- markdown,
46
- },
47
- language: 'markdown/gfm',
48
- });
49
-
50
- // --------------------------------------------------------------------------------
51
- // Export
52
- // --------------------------------------------------------------------------------
53
-
54
- /**
55
- * Markdown rule tester.
56
- * @param {string} ruleName Rule name.
57
- * @param {RuleModule<RuleOptions, MessageIds>} rule Rule module.
58
- * @param {Tests} tests Tests.
59
- */
60
- export default function ruleTester(ruleName, rule, tests) {
61
- const { meta } = rule;
62
-
63
- describe(ruleName, () => {
64
- describe('meta', () => {
65
- it('`meta` should exist', () => {
66
- ok(meta);
67
- });
68
-
69
- it('`meta.type` should exist', () => {
70
- ok(meta?.type);
71
- });
72
-
73
- it('`meta.docs` should exist', () => {
74
- ok(meta?.docs);
75
- });
76
-
77
- it('`meta.docs.description` should exist and follow the convention', () => {
78
- ok(meta?.docs?.description);
79
- match(meta?.docs?.description, /^(?:Enforce|Require|Disallow) .+[^. ]$/);
80
- });
81
-
82
- it('`meta.docs.url` should exist and end with the rule name', () => {
83
- ok(meta?.docs?.url);
84
- match(meta?.docs?.url, new RegExp(`${ruleName}$`));
85
- });
86
-
87
- it('`meta.messages` should exist', () => {
88
- ok(meta?.messages);
89
- });
90
-
91
- it('`meta.messages.messageId` should exist and value should follow the convention', () => {
92
- // @ts-expect-error -- Required for testing.
93
- Object.values(meta.messages).forEach(message => {
94
- ok(message);
95
- match(message, /^[^a-z].*\.$/);
96
- });
97
- });
98
-
99
- it("`meta.language` should exist and be `'markdown'`", () => {
100
- ok(meta?.language);
101
- match(meta?.language, /^markdown$/);
102
- });
103
-
104
- it("`meta.dialects` should exist and be `'commonmark'` or `'gfm'`", () => {
105
- ok(meta?.dialects);
106
- ok(meta?.dialects.length > 0);
107
- meta?.dialects.forEach(dialect => {
108
- match(dialect, /^(?:commonmark|gfm)$/);
109
- });
110
- });
111
- });
112
-
113
- describe('rule', () => {
114
- if (meta?.dialects?.includes('commonmark')) {
115
- it('commonmark', () => {
116
- ruleTesterCommonmark.run(ruleName, rule, tests);
117
- });
118
- }
119
-
120
- if (meta?.dialects?.includes('gfm')) {
121
- it('gfm', () => {
122
- ruleTesterGfm.run(ruleName, rule, tests);
123
- });
124
- }
125
- });
126
- });
127
- }
@@ -1,2 +0,0 @@
1
- // TODO
2
- // https://github.com/textlint-rule/textlint-rule-footnote-order