eslint-markdown 0.18.1 → 0.19.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.
package/README.md CHANGED
@@ -1,21 +1,53 @@
1
- # eslint-markdown
1
+ <!-- eslint-disable markdown/no-html -->
2
2
 
3
- [![ci](https://img.shields.io/github/actions/workflow/status/eslint-markdown/eslint-markdown/ci.yml?label=ci&color=6358d4&labelColor=333333&logo=github)](https://github.com/eslint-markdown/eslint-markdown/actions/workflows/ci.yml)
4
- [![test](https://img.shields.io/github/actions/workflow/status/eslint-markdown/eslint-markdown/test.yml?label=test&color=6358d4&labelColor=333333&logo=github)](https://github.com/eslint-markdown/eslint-markdown/actions/workflows/test.yml)
5
- [![codecov](https://img.shields.io/codecov/c/gh/eslint-markdown/eslint-markdown?token=LJMUst9eR3&label=Codecov&color=6358d4&labelColor=333333&logo=codecov)](https://codecov.io/gh/eslint-markdown/eslint-markdown)
6
- ![Node Current](https://img.shields.io/node/v/eslint-markdown?color=6358d4&labelColor=333333&logo=node.js)
3
+ <p align="center">
4
+ <img alt="ESLint Markdown Logo" src="https://eslint-markdown.lumir.page/logo.svg" width="150">
5
+ </p>
7
6
 
8
- [![npm package eslint-markdown latest version](https://img.shields.io/npm/v/eslint-markdown?label=eslint-markdown@latest&color=6358d4&labelColor=333333&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
9
- [![npm package eslint-markdown next version](https://img.shields.io/npm/v/eslint-markdown/next?label=eslint-markdown@next&color=6358d4&labelColor=333333&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
10
- [![npm package eslint-markdown downloads per month](https://img.shields.io/npm/dm/eslint-markdown?label=downloads&color=6358d4&labelColor=333333&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
7
+ <h1 align="center">ESLint Markdown</h1>
8
+
9
+ <p align="center">
10
+ <a href="https://eslint-markdown.lumir.page">Documentation</a> |
11
+ <a href="https://eslint-markdown.lumir.page/docs/rules/">Rules</a> |
12
+ <a href="https://eslint-markdown.lumir.page/docs/get-started/configurations">Configurations</a> |
13
+ <a href="https://eslint-markdown.lumir.page/docs/get-started/migration">Migration</a> |
14
+ <a href="https://eslint-markdown.lumir.page/docs/packages">Packages</a> |
15
+ <a href="https://github.com/eslint-markdown/eslint-markdown">Repository</a> |
16
+ <a href="https://github.com/eslint-markdown/eslint-markdown/discussions">Discussions</a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ Community-Maintained ESLint Tools, Rules, and Configurations for High-Quality and Performant Markdown Linting.
21
+ </p>
22
+
23
+ <p align="center">
24
+ <a href="https://github.com/eslint-markdown/eslint-markdown/actions/workflows/ci.yml"><img alt="ci" src="https://img.shields.io/github/actions/workflow/status/eslint-markdown/eslint-markdown/ci.yml?label=ci&color=341bab&labelColor=1a1a1a&logo=github"></a>
25
+ <a href="https://github.com/eslint-markdown/eslint-markdown/actions/workflows/test.yml"><img alt="test" src="https://img.shields.io/github/actions/workflow/status/eslint-markdown/eslint-markdown/test.yml?label=test&color=341bab&labelColor=1a1a1a&logo=github"></a>
26
+ <a href="https://codecov.io/gh/eslint-markdown/eslint-markdown"><img alt="codecov" src="https://img.shields.io/codecov/c/gh/eslint-markdown/eslint-markdown?token=LJMUst9eR3&label=Codecov&color=341bab&labelColor=1a1a1a&logo=codecov"></a>
27
+ <img alt="Node Current" src="https://img.shields.io/node/v/eslint-markdown?color=341bab&labelColor=1a1a1a&logo=node.js">
28
+ </p>
29
+
30
+ <!-- eslint-enable markdown/no-html -->
11
31
 
12
32
  > [!IMPORTANT]
13
33
  >
14
34
  > If you like this package, please give it a star on [GitHub](https://github.com/eslint-markdown/eslint-markdown)!⭐<br/>
15
35
  > Your support helps us improve and maintain the project.
16
36
 
37
+ ## `eslint-markdown`
38
+
39
+ [![npm package eslint-markdown latest version](https://img.shields.io/npm/v/eslint-markdown?label=eslint-markdown@latest&color=341bab&labelColor=1a1a1a&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
40
+ [![npm package eslint-markdown next version](https://img.shields.io/npm/v/eslint-markdown/next?label=eslint-markdown@next&color=341bab&labelColor=1a1a1a&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
41
+ [![npm package eslint-markdown downloads per month](https://img.shields.io/npm/dm/eslint-markdown?label=downloads&color=341bab&labelColor=1a1a1a&logo=npm)](https://www.npmjs.com/package/eslint-markdown)
42
+
17
43
  Lint your Markdown with ESLint. Additional rules for use with `@eslint/markdown`.🛠️
18
44
 
45
+ > [!IMPORTANT]
46
+ >
47
+ > **Compatibility**: This [`eslint-markdown`](https://github.com/eslint-markdown/eslint-markdown#readme) plugin does not include any rules that overlap with ESLint's built-in Markdown rules provided by [`@eslint/markdown`](https://github.com/eslint/markdown#readme).
48
+ >
49
+ > So, we **highly recommend** using the `eslint-markdown` plugin alongside ESLint's built-in Markdown support, `@eslint/markdown`.
50
+
19
51
  ## Documentation
20
52
 
21
53
  For full documentation, see the [official documentation of the `eslint-markdown`](https://eslint-markdown.lumir.page).
@@ -23,30 +55,14 @@ For full documentation, see the [official documentation of the `eslint-markdown`
23
55
  - [Installation](https://eslint-markdown.lumir.page/docs/get-started/installation)
24
56
  - [Configurations](https://eslint-markdown.lumir.page/docs/get-started/configurations)
25
57
  - [Migration Guide](https://eslint-markdown.lumir.page/docs/get-started/migration)
58
+ - [Migrating from `markdownlint`](https://eslint-markdown.lumir.page/docs/get-started/migration#migrating-from-markdownlint)
59
+ - [Migrating from `remark-lint`](https://eslint-markdown.lumir.page/docs/get-started/migration#migrating-from-remark-lint)
60
+ - [Migrating from `textlint`](https://eslint-markdown.lumir.page/docs/get-started/migration#migrating-from-textlint)
26
61
  - [Rules](https://eslint-markdown.lumir.page/docs/rules)
27
-
28
- ## Compatibility
29
-
30
- This [`eslint-markdown`](https://github.com/eslint-markdown/eslint-markdown#readme) plugin does not include any rules that overlap with ESLint's built-in Markdown rules provided by [`@eslint/markdown`](https://github.com/eslint/markdown#readme).
31
-
32
- So, we **highly recommend** using the `eslint-markdown` plugin alongside ESLint's built-in Markdown support, `@eslint/markdown`.
33
-
34
- ## Code of Conduct
35
-
36
- See [Code of Conduct](https://github.com/eslint-markdown/eslint-markdown/blob/main/CODE_OF_CONDUCT.md).
37
-
38
- ## Change Log
39
-
40
- See [Change Log](https://github.com/eslint-markdown/eslint-markdown/blob/main/CHANGELOG.md).
41
-
42
- ## Versioning
43
-
44
- See [Versioning](https://eslint-markdown.lumir.page/docs/get-started/versioning).
45
-
46
- ## Security
47
-
48
- See [Security](https://github.com/eslint-markdown/eslint-markdown/blob/main/SECURITY.md).
62
+ - [Packages](https://eslint-markdown.lumir.page/docs/packages)
63
+ - [`eslint-markdown`](https://eslint-markdown.lumir.page/docs/packages/eslint-markdown)
64
+ - [`eslint-lumir`](https://eslint-markdown.lumir.page/docs/packages/eslint-lumir)
49
65
 
50
66
  ## License
51
67
 
52
- [MIT](https://github.com/eslint-markdown/eslint-markdown/blob/main/LICENSE.md)
68
+ [MIT](https://github.com/eslint-markdown/eslint-markdown/blob/main/packages/eslint-markdown/LICENSE.md)
@@ -25,6 +25,7 @@ export default function all(plugin: ESLint.Plugin): {
25
25
  readonly 'md/consistent-emphasis-style': "error";
26
26
  readonly 'md/consistent-heading-style': "error";
27
27
  readonly 'md/consistent-inline-code-style': "error";
28
+ readonly 'md/consistent-ordered-list-style': "error";
28
29
  readonly 'md/consistent-strong-style': "error";
29
30
  readonly 'md/consistent-thematic-break-style': "error";
30
31
  readonly 'md/consistent-unordered-list-style': "error";
@@ -33,6 +33,7 @@ export default function all(plugin) {
33
33
  'md/consistent-emphasis-style': 'error',
34
34
  'md/consistent-heading-style': 'error',
35
35
  'md/consistent-inline-code-style': 'error',
36
+ 'md/consistent-ordered-list-style': 'error',
36
37
  'md/consistent-strong-style': 'error',
37
38
  'md/consistent-thematic-break-style': 'error',
38
39
  'md/consistent-unordered-list-style': 'error',
@@ -21,6 +21,7 @@ export default function stylistic(plugin: ESLint.Plugin): {
21
21
  readonly 'md/consistent-emphasis-style': "error";
22
22
  readonly 'md/consistent-heading-style': "error";
23
23
  readonly 'md/consistent-inline-code-style': "error";
24
+ readonly 'md/consistent-ordered-list-style': "error";
24
25
  readonly 'md/consistent-strong-style': "error";
25
26
  readonly 'md/consistent-thematic-break-style': "error";
26
27
  readonly 'md/consistent-unordered-list-style': "error";
@@ -29,6 +29,7 @@ export default function stylistic(plugin) {
29
29
  'md/consistent-emphasis-style': 'error',
30
30
  'md/consistent-heading-style': 'error',
31
31
  'md/consistent-inline-code-style': 'error',
32
+ 'md/consistent-ordered-list-style': 'error',
32
33
  'md/consistent-strong-style': 'error',
33
34
  'md/consistent-thematic-break-style': 'error',
34
35
  'md/consistent-unordered-list-style': 'error',
@@ -30,6 +30,11 @@ export declare const punctuation: readonly [".", ",", ";", ":", "!", "。", ",
30
30
  * @see https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-punctuation#parameters
31
31
  */
32
32
  export declare const punctuationWithQuestionMark: readonly [".", ",", ";", ":", "!", "?", "。", ",", ";", ":", "!", "?"];
33
+ /**
34
+ * Matches a single ASCII punctuation character as defined by CommonMark.
35
+ * @see https://spec.commonmark.org/0.31.2/#ascii-punctuation-character
36
+ */
37
+ export declare const asciiPunctuationRegex: RegExp;
33
38
  /**
34
39
  * Regular expression for identifying an odd-length run of backslashes at the end of a string.
35
40
  */
@@ -49,6 +49,11 @@ export const punctuationWithQuestionMark = [
49
49
  // --------------------------------------------------------------------------------
50
50
  // --------------------------------------------------------------------------------
51
51
  // #region regex
52
+ /**
53
+ * Matches a single ASCII punctuation character as defined by CommonMark.
54
+ * @see https://spec.commonmark.org/0.31.2/#ascii-punctuation-character
55
+ */
56
+ export const asciiPunctuationRegex = /^[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]$/;
52
57
  /**
53
58
  * Regular expression for identifying an odd-length run of backslashes at the end of a string.
54
59
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview HTML AST utilities.
3
3
  */
4
- import type { DefaultTreeAdapterTypes } from 'parse5';
4
+ import { type DefaultTreeAdapterTypes } from 'parse5';
5
5
  /**
6
6
  * Mimics the behavior of `getElementsByTagName` in the DOM API.
7
7
  * @param html The HTML string to parse.
@@ -103,28 +103,30 @@ export default {
103
103
  const currentCodeStyle = getCodeStyle(currentCodeFenceChar);
104
104
  const nodeStartLineIndex = start.line - 1;
105
105
  const nodeEndLineIndex = end.line - 1;
106
+ const nodeStartLineText = lines[nodeStartLineIndex];
107
+ const nodeEndLineText = lines[nodeEndLineIndex];
108
+ const leadingCodeFenceLoc = {
109
+ start,
110
+ end: {
111
+ line: start.line,
112
+ column: (() => {
113
+ if (currentCodeStyle === 'indent') {
114
+ return nodeStartLineText.length + 1;
115
+ }
116
+ let { column } = start;
117
+ while (nodeStartLineText[column - 1] === currentCodeFenceChar) {
118
+ column++;
119
+ }
120
+ return column;
121
+ })(),
122
+ },
123
+ };
106
124
  if (codeStyle === null) {
107
125
  codeStyle = currentCodeStyle;
108
126
  }
109
127
  if (codeStyle !== currentCodeStyle) {
110
128
  context.report({
111
- loc: {
112
- start,
113
- end: {
114
- line: start.line,
115
- column: (() => {
116
- const nodeStartLineText = lines[nodeStartLineIndex];
117
- if (currentCodeStyle === 'indent') {
118
- return nodeStartLineText.length + 1;
119
- }
120
- let { column } = start;
121
- while (nodeStartLineText[column - 1] === currentCodeFenceChar) {
122
- column++;
123
- }
124
- return column;
125
- })(),
126
- },
127
- },
129
+ loc: leadingCodeFenceLoc,
128
130
  messageId: 'style',
129
131
  data: {
130
132
  style: codeStyle,
@@ -150,7 +152,7 @@ export default {
150
152
  continue;
151
153
  }
152
154
  context.report({
153
- node,
155
+ loc: leadingCodeFenceLoc,
154
156
  messageId: 'blankLineAbove',
155
157
  data: {
156
158
  blankLineAbove,
@@ -179,7 +181,18 @@ export default {
179
181
  continue;
180
182
  }
181
183
  context.report({
182
- node,
184
+ // Report the last line of the code block, as highlighting only the trailing
185
+ // code fence characters involves many edge cases that cannot be handled reliably.
186
+ loc: {
187
+ start: {
188
+ line: end.line,
189
+ column: 1,
190
+ },
191
+ end: {
192
+ line: end.line,
193
+ column: nodeEndLineText.length + 1,
194
+ },
195
+ },
183
196
  messageId: 'blankLineBelow',
184
197
  data: {
185
198
  blankLineBelow,
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @fileoverview Rule to enforce consistent ordered list style.
3
+ * @author Ga eun Lee(tooth-is-silver)
4
+ */
5
+ import type { ListItem } from 'mdast';
6
+ type OrderedListStyle = (typeof ORDERED_LIST_STYLE)[number];
7
+ /**
8
+ * Options for the `consistent-ordered-list-style` rule.
9
+ */
10
+ type RuleOptions = [
11
+ {
12
+ /**
13
+ * When `style` is set to `'one-or-ordered'`, the rule allows either the `'one'` or `'ordered'` style based on the first two list item prefixes.
14
+ *
15
+ * When `style` is set to `'one'`, the rule requires every prefix to be `1`.
16
+ *
17
+ * When `style` is set to `'ordered'`, the rule requires prefixes to increase sequentially, starting from `1` or from `0` when the list has two or more items.
18
+ *
19
+ * When `style` is set to `'zero'`, the rule requires every prefix to be `0`.
20
+ * @default 'one-or-ordered'
21
+ */
22
+ style: 'one-or-ordered' | OrderedListStyle;
23
+ }
24
+ ];
25
+ declare const ORDERED_LIST_STYLE: readonly ["one", "ordered", "zero"];
26
+ declare const _default: {
27
+ readonly meta: {
28
+ readonly type: "layout";
29
+ readonly docs: {
30
+ readonly description: "Enforce consistent ordered list style";
31
+ readonly url: string;
32
+ readonly recommended: false;
33
+ readonly stylistic: true;
34
+ };
35
+ readonly schema: [{
36
+ readonly type: "object";
37
+ readonly properties: {
38
+ readonly style: {
39
+ readonly enum: ["one-or-ordered", "one", "ordered", "zero"];
40
+ };
41
+ };
42
+ readonly additionalProperties: false;
43
+ }];
44
+ readonly defaultOptions: [{
45
+ readonly style: "one-or-ordered";
46
+ }];
47
+ readonly messages: {
48
+ readonly style: "Ordered list style should be `{{ style }}`.";
49
+ };
50
+ readonly language: "markdown";
51
+ readonly dialects: ["commonmark", "gfm"];
52
+ };
53
+ readonly create: (context: import("../core/types.js").RuleContext<{
54
+ RuleOptions: RuleOptions;
55
+ MessageIds: "style";
56
+ }>) => {
57
+ 'list[ordered=true]'(): void;
58
+ 'list[ordered=true] > listItem'(node: ListItem): void;
59
+ 'list[ordered=true]:exit'(): void;
60
+ };
61
+ };
62
+ export default _default;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @fileoverview Rule to enforce consistent ordered list style.
3
+ * @author Ga eun Lee(tooth-is-silver)
4
+ */
5
+ import { URL_RULE_DOCS } from '../core/constants.js';
6
+ // --------------------------------------------------------------------------------
7
+ // Helper
8
+ // --------------------------------------------------------------------------------
9
+ const ORDERED_LIST_STYLE = ['one', 'ordered', 'zero'];
10
+ /**
11
+ * Ordered list start numbers must be nine digits or less.
12
+ * @see https://spec.commonmark.org/0.31.2/#example-265
13
+ */
14
+ const orderedListPrefixRegex = /^\d{1,9}/u;
15
+ // --------------------------------------------------------------------------------
16
+ // Rule Definition
17
+ // --------------------------------------------------------------------------------
18
+ export default {
19
+ meta: {
20
+ type: 'layout',
21
+ docs: {
22
+ description: 'Enforce consistent ordered list style',
23
+ url: URL_RULE_DOCS('consistent-ordered-list-style'),
24
+ recommended: false,
25
+ stylistic: true,
26
+ },
27
+ schema: [
28
+ {
29
+ type: 'object',
30
+ properties: {
31
+ style: {
32
+ enum: ['one-or-ordered', ...ORDERED_LIST_STYLE],
33
+ },
34
+ },
35
+ additionalProperties: false,
36
+ },
37
+ ],
38
+ defaultOptions: [
39
+ {
40
+ style: 'one-or-ordered',
41
+ },
42
+ ],
43
+ messages: {
44
+ style: 'Ordered list style should be `{{ style }}`.',
45
+ },
46
+ language: 'markdown',
47
+ dialects: ['commonmark', 'gfm'],
48
+ },
49
+ create(context) {
50
+ const { sourceCode } = context;
51
+ const [{ style }] = context.options;
52
+ const orderedListPrefixesStack = [];
53
+ return {
54
+ 'list[ordered=true]'() {
55
+ orderedListPrefixesStack.push([]);
56
+ },
57
+ 'list[ordered=true] > listItem'(node) {
58
+ const [nodeStartOffset] = sourceCode.getRange(node);
59
+ // `match` is never `null` because this visitor only runs for
60
+ // ordered list items, whose source text starts with a numeric marker.
61
+ const match = orderedListPrefixRegex.exec(sourceCode.getText(node));
62
+ const orderedListPrefix = match[0];
63
+ orderedListPrefixesStack[orderedListPrefixesStack.length - 1].push({
64
+ startOffset: nodeStartOffset,
65
+ endOffset: nodeStartOffset + orderedListPrefix.length,
66
+ number: Number(orderedListPrefix),
67
+ });
68
+ },
69
+ 'list[ordered=true]:exit'() {
70
+ // Can never be `undefined` because `list[ordered=true]` always pushes to the stack before exiting.
71
+ const orderedListPrefixes = orderedListPrefixesStack.pop();
72
+ const [firstOrderedListPrefix, secondOrderedListPrefix] = orderedListPrefixes;
73
+ const hasMultipleItems = orderedListPrefixes.length > 1;
74
+ let orderedListStyle = style;
75
+ if (orderedListStyle === 'one-or-ordered') {
76
+ orderedListStyle =
77
+ hasMultipleItems &&
78
+ (firstOrderedListPrefix.number === 0 || secondOrderedListPrefix.number !== 1)
79
+ ? 'ordered'
80
+ : 'one';
81
+ }
82
+ let expectedOrderedListPrefixNumber = orderedListStyle === 'zero' ||
83
+ (orderedListStyle === 'ordered' &&
84
+ hasMultipleItems &&
85
+ firstOrderedListPrefix.number === 0)
86
+ ? 0
87
+ : 1;
88
+ for (const { startOffset, endOffset, number } of orderedListPrefixes) {
89
+ if (number !== expectedOrderedListPrefixNumber) {
90
+ context.report({
91
+ loc: {
92
+ start: sourceCode.getLocFromIndex(startOffset),
93
+ end: sourceCode.getLocFromIndex(endOffset),
94
+ },
95
+ messageId: 'style',
96
+ data: {
97
+ style: orderedListStyle,
98
+ },
99
+ });
100
+ }
101
+ if (orderedListStyle === 'ordered') {
102
+ expectedOrderedListPrefixNumber++;
103
+ }
104
+ }
105
+ },
106
+ };
107
+ },
108
+ };
@@ -11,7 +11,7 @@ const lowercaseRegex = /^[a-z]/u;
11
11
  * Traverses the Markdown AST using a DFS pre-order approach to find the first text node.
12
12
  * @param node The node to start searching from.
13
13
  * @returns The first text node, if present.
14
- */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: This rule is not fully migrated to TypeScript yet.
14
+ */ // eslint-disable-next-line typescript/no-explicit-any -- TODO: This rule is not fully migrated to TypeScript yet.
15
15
  function findFirstLeafTextNode(node) {
16
16
  // Base case: if this is a text node, return it
17
17
  if (node.type === 'text')
@@ -632,6 +632,44 @@ declare const _default: {
632
632
  inlineCode(node: import("mdast").InlineCode): void;
633
633
  };
634
634
  };
635
+ 'consistent-ordered-list-style': {
636
+ readonly meta: {
637
+ readonly type: "layout";
638
+ readonly docs: {
639
+ readonly description: "Enforce consistent ordered list style";
640
+ readonly url: string;
641
+ readonly recommended: false;
642
+ readonly stylistic: true;
643
+ };
644
+ readonly schema: [{
645
+ readonly type: "object";
646
+ readonly properties: {
647
+ readonly style: {
648
+ readonly enum: ["one-or-ordered", "one", "ordered", "zero"];
649
+ };
650
+ };
651
+ readonly additionalProperties: false;
652
+ }];
653
+ readonly defaultOptions: [{
654
+ readonly style: "one-or-ordered";
655
+ }];
656
+ readonly messages: {
657
+ readonly style: "Ordered list style should be `{{ style }}`.";
658
+ };
659
+ readonly language: "markdown";
660
+ readonly dialects: ["commonmark", "gfm"];
661
+ };
662
+ readonly create: (context: import("../core/types.js").RuleContext<{
663
+ RuleOptions: [{
664
+ style: "one-or-ordered" | ("one" | "ordered" | "zero");
665
+ }];
666
+ MessageIds: "style";
667
+ }>) => {
668
+ 'list[ordered=true]'(): void;
669
+ 'list[ordered=true] > listItem'(node: import("mdast").ListItem): void;
670
+ 'list[ordered=true]:exit'(): void;
671
+ };
672
+ };
635
673
  'consistent-strong-style': {
636
674
  readonly meta: {
637
675
  readonly type: "layout";
@@ -838,6 +876,12 @@ declare const _default: {
838
876
  readonly skipInlineCode: {
839
877
  readonly type: "boolean";
840
878
  };
879
+ readonly skipMath: {
880
+ readonly type: "boolean";
881
+ };
882
+ readonly skipInlineMath: {
883
+ readonly type: "boolean";
884
+ };
841
885
  };
842
886
  readonly additionalProperties: false;
843
887
  }];
@@ -845,6 +889,8 @@ declare const _default: {
845
889
  readonly allow: [];
846
890
  readonly skipCode: true;
847
891
  readonly skipInlineCode: true;
892
+ readonly skipMath: false;
893
+ readonly skipInlineMath: false;
848
894
  }];
849
895
  readonly messages: {
850
896
  readonly noControlCharacter: "Control character `{{ controlCharacter }}` is not allowed.";
@@ -858,11 +904,15 @@ declare const _default: {
858
904
  allow: string[];
859
905
  skipCode: boolean | string[];
860
906
  skipInlineCode: boolean;
907
+ skipMath: boolean;
908
+ skipInlineMath: boolean;
861
909
  }];
862
910
  MessageIds: "noControlCharacter" | "suggestRemove";
863
911
  }>) => {
864
912
  code(node: import("mdast").Code): void;
865
913
  inlineCode(node: import("mdast").InlineCode): void;
914
+ math(node: import("mdast-util-math").Math): void;
915
+ inlineMath(node: import("mdast-util-math").InlineMath): void;
866
916
  'root:exit'(): void;
867
917
  };
868
918
  };
@@ -9,6 +9,7 @@ import consistentDeleteStyle from './consistent-delete-style.js';
9
9
  import consistentEmphasisStyle from './consistent-emphasis-style.js';
10
10
  import consistentHeadingStyle from './consistent-heading-style.js';
11
11
  import consistentInlineCodeStyle from './consistent-inline-code-style.js';
12
+ import consistentOrderedListStyle from './consistent-ordered-list-style.js';
12
13
  import consistentStrongStyle from './consistent-strong-style.js';
13
14
  import consistentThematicBreakStyle from './consistent-thematic-break-style.js';
14
15
  import consistentUnorderedListStyle from './consistent-unordered-list-style.js';
@@ -40,6 +41,7 @@ export default {
40
41
  'consistent-emphasis-style': consistentEmphasisStyle,
41
42
  'consistent-heading-style': consistentHeadingStyle,
42
43
  'consistent-inline-code-style': consistentInlineCodeStyle,
44
+ 'consistent-ordered-list-style': consistentOrderedListStyle,
43
45
  'consistent-strong-style': consistentStrongStyle,
44
46
  'consistent-thematic-break-style': consistentThematicBreakStyle,
45
47
  'consistent-unordered-list-style': consistentUnorderedListStyle,
@@ -24,6 +24,16 @@ type RuleOptions = [
24
24
  * @default true
25
25
  */
26
26
  skipInlineCode: boolean;
27
+ /**
28
+ * `true` allows control characters in all math blocks.
29
+ * @default false
30
+ */
31
+ skipMath: boolean;
32
+ /**
33
+ * `true` allows control characters in all inline math.
34
+ * @default false
35
+ */
36
+ skipInlineMath: boolean;
27
37
  }
28
38
  ];
29
39
  type MessageIds = 'noControlCharacter' | 'suggestRemove';
@@ -61,6 +71,12 @@ declare const _default: {
61
71
  readonly skipInlineCode: {
62
72
  readonly type: "boolean";
63
73
  };
74
+ readonly skipMath: {
75
+ readonly type: "boolean";
76
+ };
77
+ readonly skipInlineMath: {
78
+ readonly type: "boolean";
79
+ };
64
80
  };
65
81
  readonly additionalProperties: false;
66
82
  }];
@@ -68,6 +84,8 @@ declare const _default: {
68
84
  readonly allow: [];
69
85
  readonly skipCode: true;
70
86
  readonly skipInlineCode: true;
87
+ readonly skipMath: false;
88
+ readonly skipInlineMath: false;
71
89
  }];
72
90
  readonly messages: {
73
91
  readonly noControlCharacter: "Control character `{{ controlCharacter }}` is not allowed.";
@@ -82,6 +100,8 @@ declare const _default: {
82
100
  }>) => {
83
101
  code(node: import("mdast").Code): void;
84
102
  inlineCode(node: import("mdast").InlineCode): void;
103
+ math(node: import("mdast-util-math").Math): void;
104
+ inlineMath(node: import("mdast-util-math").InlineMath): void;
85
105
  'root:exit'(): void;
86
106
  };
87
107
  };
@@ -53,6 +53,12 @@ export default {
53
53
  skipInlineCode: {
54
54
  type: 'boolean',
55
55
  },
56
+ skipMath: {
57
+ type: 'boolean',
58
+ },
59
+ skipInlineMath: {
60
+ type: 'boolean',
61
+ },
56
62
  },
57
63
  additionalProperties: false,
58
64
  },
@@ -62,6 +68,8 @@ export default {
62
68
  allow: [],
63
69
  skipCode: true,
64
70
  skipInlineCode: true,
71
+ skipMath: false,
72
+ skipInlineMath: false,
65
73
  },
66
74
  ],
67
75
  messages: {
@@ -73,7 +81,7 @@ export default {
73
81
  },
74
82
  create(context) {
75
83
  const { sourceCode } = context;
76
- const [{ allow, skipCode, skipInlineCode }] = context.options;
84
+ const [{ allow, skipCode, skipInlineCode, skipMath, skipInlineMath }] = context.options;
77
85
  const skipRanges = new SkipRanges();
78
86
  return {
79
87
  code(node) {
@@ -84,6 +92,14 @@ export default {
84
92
  if (skipInlineCode)
85
93
  skipRanges.push(sourceCode.getRange(node)); // Store range information of `InlineCode`.
86
94
  },
95
+ math(node) {
96
+ if (skipMath)
97
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Math`.
98
+ },
99
+ inlineMath(node) {
100
+ if (skipInlineMath)
101
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `InlineMath`.
102
+ },
87
103
  'root:exit'() {
88
104
  const matches = sourceCode.text.matchAll(controlCharacterRegex);
89
105
  for (const match of matches) {
@@ -6,7 +6,7 @@
6
6
  // Import
7
7
  // --------------------------------------------------------------------------------
8
8
  import { escapeStringRegexp } from '../core/utils/index.js';
9
- import { URL_RULE_DOCS, punctuation as defaultPunctuation, escapedTrailingBackslashRegex, gemojiRegex, htmlEntityRegex, } from '../core/constants.js';
9
+ import { URL_RULE_DOCS, punctuation as defaultPunctuation, asciiPunctuationRegex, escapedTrailingBackslashRegex, gemojiRegex, htmlEntityRegex, } from '../core/constants.js';
10
10
  // --------------------------------------------------------------------------------
11
11
  // Helper
12
12
  // --------------------------------------------------------------------------------
@@ -174,6 +174,8 @@ export default {
174
174
  Number(
175
175
  // When `leadingSpaces` is `''` (empty string), check for an escaped trailing backslash.
176
176
  !leadingSpaces &&
177
+ // The preceding backslash is an escape only when the punctuation is escapable.
178
+ asciiPunctuationRegex.test(trailingPunctuation[0]) &&
177
179
  escapedTrailingBackslashRegex.test(lastChildText.slice(0, -trailingPunctuation.length))),
178
180
  endOffset,
179
181
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-markdown",
3
- "version": "0.18.1",
3
+ "version": "0.19.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Lint your Markdown with ESLint. Additional rules for use with `@eslint/markdown`.🛠️",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "scripts": {
59
59
  "prepublishOnly": "npm run build",
60
- "build": "tsc -b tsconfig.build.json && node ../../scripts/build-config.js && tsc -b tsconfig.build.json && node ../../scripts/cp.js ../../LICENSE.md LICENSE.md ../../README.md README.md",
60
+ "build": "tsc -b tsconfig.build.json && node ../../scripts/build-config.js && tsc -b tsconfig.build.json",
61
61
  "test": "npm run test:types && npm run test:unit",
62
62
  "test:types": "tsc -b ./tsconfig.test-d.json",
63
63
  "test:unit": "vitest run"
@@ -79,7 +79,7 @@
79
79
  "@eslint/markdown": "^8.0.3",
80
80
  "@types/mdast": "^4.0.4",
81
81
  "@types/unist": "^3.0.3",
82
- "eslint": "^9.39.5",
82
+ "eslint": "^10.13.0",
83
83
  "vitest": "^4.1.9"
84
84
  }
85
85
  }
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- export {};
2
- // TODO
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- export {};
2
- // TODO
3
- // - string: string
4
- // - string: RegExp
5
- // - string: string[]
6
- // - string: RegExp[]
7
- // - string: { src: string | RegExp | string[] | RegExp[] }
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- export {};
2
- // TODO