eslint-markdown 0.2.0 → 0.4.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.
@@ -21,6 +21,7 @@ export default function all(plugin: ESLint.Plugin): {
21
21
  readonly 'md/consistent-emphasis-style': "error";
22
22
  readonly 'md/consistent-strong-style': "error";
23
23
  readonly 'md/consistent-thematic-break-style': "error";
24
+ readonly 'md/consistent-unordered-list-style': "error";
24
25
  readonly 'md/no-control-character': "error";
25
26
  readonly 'md/no-curly-quote': "error";
26
27
  readonly 'md/no-double-space': "error";
@@ -18,6 +18,7 @@ export default function stylistic(plugin: ESLint.Plugin): {
18
18
  readonly 'md/consistent-emphasis-style': "error";
19
19
  readonly 'md/consistent-strong-style': "error";
20
20
  readonly 'md/consistent-thematic-break-style': "error";
21
+ readonly 'md/consistent-unordered-list-style': "error";
21
22
  readonly 'md/no-tab': "error";
22
23
  };
23
24
  };
@@ -2,6 +2,11 @@
2
2
  * @fileoverview Define common types.
3
3
  */
4
4
  import type { MarkdownRuleDefinition, MarkdownRuleDefinitionTypeOptions } from '@eslint/markdown';
5
+ /**
6
+ * Represents a rule module with specific rule options and message IDs.
7
+ * @template RuleOptions The rule options.
8
+ * @template MessageIds The message IDs.
9
+ */
5
10
  export type RuleModule<RuleOptions extends MarkdownRuleDefinitionTypeOptions['RuleOptions'], MessageIds extends MarkdownRuleDefinitionTypeOptions['MessageIds']> = MarkdownRuleDefinition<{
6
11
  RuleOptions: RuleOptions;
7
12
  MessageIds: MessageIds;
@@ -0,0 +1,47 @@
1
+ declare const _default: {
2
+ meta: {
3
+ type: "layout";
4
+ docs: {
5
+ description: string;
6
+ url: string;
7
+ recommended: boolean;
8
+ stylistic: true;
9
+ };
10
+ fixable: "code";
11
+ schema: {
12
+ type: "object";
13
+ properties: {
14
+ style: {
15
+ enum: string[];
16
+ };
17
+ };
18
+ additionalProperties: false;
19
+ }[];
20
+ defaultOptions: [{
21
+ style: "consistent";
22
+ }];
23
+ messages: {
24
+ style: string;
25
+ };
26
+ language: string;
27
+ dialects: string[];
28
+ };
29
+ create(context: import("@eslint/core").RuleContext<{
30
+ LangOptions: import("@eslint/markdown").MarkdownLanguageOptions;
31
+ Code: import("@eslint/markdown").MarkdownSourceCode;
32
+ RuleOptions: RuleOptions;
33
+ Node: import("mdast").Node;
34
+ MessageIds: "style";
35
+ }>): {
36
+ list(): void;
37
+ 'list[ordered=false] > listItem'(node: ListItem): void;
38
+ 'list:exit'(): void;
39
+ };
40
+ };
41
+ export default _default;
42
+ export type UnorderedListMarker = "*" | "+" | "-";
43
+ export type RuleOptions = [{
44
+ style: "consistent" | "sublist" | UnorderedListMarker;
45
+ }];
46
+ export type MessageIds = "style";
47
+ import type { ListItem } from 'mdast';
@@ -6,6 +6,7 @@ declare const _default: {
6
6
  'consistent-emphasis-style': import("../core/types.js").RuleModule<import("./consistent-emphasis-style.js").RuleOptions, "style">;
7
7
  'consistent-strong-style': import("../core/types.js").RuleModule<import("./consistent-strong-style.js").RuleOptions, "style">;
8
8
  'consistent-thematic-break-style': import("../core/types.js").RuleModule<import("./consistent-thematic-break-style.js").RuleOptions, "style">;
9
+ 'consistent-unordered-list-style': import("../core/types.js").RuleModule<import("./consistent-unordered-list-style.js").RuleOptions, "style">;
9
10
  'no-control-character': import("../core/types.js").RuleModule<import("./no-control-character.js").RuleOptions, "noControlCharacter">;
10
11
  'no-curly-quote': import("../core/types.js").RuleModule<import("./no-curly-quote.js").RuleOptions, "noCurlyQuote">;
11
12
  'no-double-space': import("../core/types.js").RuleModule<import("./no-double-space.js").RuleOptions, import("./no-double-space.js").MessageIds>;
@@ -18,7 +18,17 @@ declare const _default: {
18
18
  uniqueItems: true;
19
19
  };
20
20
  skipCode: {
21
- type: "boolean";
21
+ oneOf: ({
22
+ type: "boolean";
23
+ items?: never;
24
+ uniqueItems?: never;
25
+ } | {
26
+ type: "array";
27
+ items: {
28
+ type: "string";
29
+ };
30
+ uniqueItems: true;
31
+ })[];
22
32
  };
23
33
  skipInlineCode: {
24
34
  type: "boolean";
@@ -52,7 +62,7 @@ declare const _default: {
52
62
  export default _default;
53
63
  export type RuleOptions = [{
54
64
  allow: string[];
55
- skipCode: boolean;
65
+ skipCode: boolean | string[];
56
66
  skipInlineCode: boolean;
57
67
  }];
58
68
  export type MessageIds = "noControlCharacter";
@@ -11,7 +11,17 @@ declare const _default: {
11
11
  type: "object";
12
12
  properties: {
13
13
  skipCode: {
14
- type: "boolean";
14
+ oneOf: ({
15
+ type: "boolean";
16
+ items?: never;
17
+ uniqueItems?: never;
18
+ } | {
19
+ type: "array";
20
+ items: {
21
+ type: "string";
22
+ };
23
+ uniqueItems: true;
24
+ })[];
15
25
  };
16
26
  };
17
27
  additionalProperties: false;
@@ -38,6 +48,6 @@ declare const _default: {
38
48
  };
39
49
  export default _default;
40
50
  export type RuleOptions = [{
41
- skipCode: boolean;
51
+ skipCode: boolean | string[];
42
52
  }];
43
53
  export type MessageIds = "noGitConflictMarker";
@@ -18,7 +18,17 @@ declare const _default: {
18
18
  uniqueItems: true;
19
19
  };
20
20
  skipCode: {
21
- type: "boolean";
21
+ oneOf: ({
22
+ type: "boolean";
23
+ items?: never;
24
+ uniqueItems?: never;
25
+ } | {
26
+ type: "array";
27
+ items: {
28
+ type: "string";
29
+ };
30
+ uniqueItems: true;
31
+ })[];
22
32
  };
23
33
  skipInlineCode: {
24
34
  type: "boolean";
@@ -52,7 +62,7 @@ declare const _default: {
52
62
  export default _default;
53
63
  export type RuleOptions = [{
54
64
  allow: string[];
55
- skipCode: boolean;
65
+ skipCode: boolean | string[];
56
66
  skipInlineCode: boolean;
57
67
  }];
58
68
  export type MessageIds = "noIrregularDash";
@@ -18,7 +18,17 @@ declare const _default: {
18
18
  uniqueItems: true;
19
19
  };
20
20
  skipCode: {
21
- type: "boolean";
21
+ oneOf: ({
22
+ type: "boolean";
23
+ items?: never;
24
+ uniqueItems?: never;
25
+ } | {
26
+ type: "array";
27
+ items: {
28
+ type: "string";
29
+ };
30
+ uniqueItems: true;
31
+ })[];
22
32
  };
23
33
  skipInlineCode: {
24
34
  type: "boolean";
@@ -52,7 +62,7 @@ declare const _default: {
52
62
  export default _default;
53
63
  export type RuleOptions = [{
54
64
  allow: string[];
55
- skipCode: boolean;
65
+ skipCode: boolean | string[];
56
66
  skipInlineCode: boolean;
57
67
  }];
58
68
  export type MessageIds = "noIrregularWhitespace";
@@ -12,7 +12,17 @@ declare const _default: {
12
12
  type: "object";
13
13
  properties: {
14
14
  skipCode: {
15
- type: "boolean";
15
+ oneOf: ({
16
+ type: "boolean";
17
+ items?: never;
18
+ uniqueItems?: never;
19
+ } | {
20
+ type: "array";
21
+ items: {
22
+ type: "string";
23
+ };
24
+ uniqueItems: true;
25
+ })[];
16
26
  };
17
27
  skipInlineCode: {
18
28
  type: "boolean";
@@ -49,7 +59,7 @@ declare const _default: {
49
59
  };
50
60
  export default _default;
51
61
  export type RuleOptions = [{
52
- skipCode: boolean;
62
+ skipCode: boolean | string[];
53
63
  skipInlineCode: boolean;
54
64
  tabWidth: number;
55
65
  }];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-markdown",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Lint your Markdown with ESLint.🛠️",
6
6
  "exports": {
@@ -64,7 +64,7 @@
64
64
  "test:unit": "node --test"
65
65
  },
66
66
  "peerDependencies": {
67
- "eslint": "^9.31.0 || ^10.0.0-beta.0"
67
+ "eslint": "^9.31.0 || ^10.0.0-rc.0"
68
68
  },
69
69
  "peerDependenciesMeta": {
70
70
  "eslint": {
@@ -45,6 +45,7 @@ export default function all(plugin) {
45
45
  'md/consistent-emphasis-style': 'error',
46
46
  'md/consistent-strong-style': 'error',
47
47
  'md/consistent-thematic-break-style': 'error',
48
+ 'md/consistent-unordered-list-style': 'error',
48
49
  'md/no-control-character': 'error',
49
50
  'md/no-curly-quote': 'error',
50
51
  'md/no-double-space': 'error',
@@ -42,6 +42,7 @@ export default function stylistic(plugin) {
42
42
  'md/consistent-emphasis-style': 'error',
43
43
  'md/consistent-strong-style': 'error',
44
44
  'md/consistent-thematic-break-style': 'error',
45
+ 'md/consistent-unordered-list-style': 'error',
45
46
  'md/no-tab': 'error',
46
47
  },
47
48
  });
package/src/core/types.ts CHANGED
@@ -15,6 +15,11 @@ import type {
15
15
  // Typedef
16
16
  // --------------------------------------------------------------------------------
17
17
 
18
+ /**
19
+ * Represents a rule module with specific rule options and message IDs.
20
+ * @template RuleOptions The rule options.
21
+ * @template MessageIds The message IDs.
22
+ */
18
23
  export type RuleModule<
19
24
  RuleOptions extends MarkdownRuleDefinitionTypeOptions['RuleOptions'],
20
25
  MessageIds extends MarkdownRuleDefinitionTypeOptions['MessageIds'],
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @fileoverview Rule to enforce consistent unordered list style.
3
+ * @author hyoban
4
+ */
5
+
6
+ // --------------------------------------------------------------------------------
7
+ // Import
8
+ // --------------------------------------------------------------------------------
9
+
10
+ import { URL_RULE_DOCS } from '../core/constants.js';
11
+
12
+ // --------------------------------------------------------------------------------
13
+ // Typedef
14
+ // --------------------------------------------------------------------------------
15
+
16
+ /**
17
+ * @import { ListItem } from 'mdast';
18
+ * @import { RuleModule } from '../core/types.js';
19
+ * @typedef {'*' | '+' | '-'} UnorderedListMarker
20
+ * @typedef {[{ style: 'consistent' | 'sublist' | UnorderedListMarker }]} RuleOptions
21
+ * @typedef {'style'} MessageIds
22
+ */
23
+
24
+ // --------------------------------------------------------------------------------
25
+ // Helper
26
+ // --------------------------------------------------------------------------------
27
+
28
+ /**
29
+ * Get the next unordered list marker in sequence.
30
+ * Inspired by [`markdownlint`](https://github.com/DavidAnson/markdownlint/blob/v0.40.0/lib/md004.mjs#L9).
31
+ * @param {UnorderedListMarker} currentUnorderedListMarker The current unordered list marker.
32
+ * @returns {UnorderedListMarker} The next unordered list marker.
33
+ */
34
+ function getNextUnorderedListMarker(currentUnorderedListMarker) {
35
+ if (currentUnorderedListMarker === '-') {
36
+ return '+';
37
+ } else if (currentUnorderedListMarker === '+') {
38
+ return '*';
39
+ } else {
40
+ return '-';
41
+ }
42
+ }
43
+
44
+ // --------------------------------------------------------------------------------
45
+ // Rule Definition
46
+ // --------------------------------------------------------------------------------
47
+
48
+ /** @type {RuleModule<RuleOptions, MessageIds>} */
49
+ export default {
50
+ meta: {
51
+ type: 'layout',
52
+
53
+ docs: {
54
+ description: 'Enforce consistent unordered list style',
55
+ url: URL_RULE_DOCS('consistent-unordered-list-style'),
56
+ recommended: false,
57
+ stylistic: true,
58
+ },
59
+
60
+ fixable: 'code',
61
+
62
+ schema: [
63
+ {
64
+ type: 'object',
65
+ properties: {
66
+ style: {
67
+ enum: ['consistent', 'sublist', '*', '+', '-'],
68
+ },
69
+ },
70
+ additionalProperties: false,
71
+ },
72
+ ],
73
+
74
+ defaultOptions: [
75
+ {
76
+ style: 'consistent',
77
+ },
78
+ ],
79
+
80
+ messages: {
81
+ style: 'Unordered list style should be `{{ style }}`.',
82
+ },
83
+
84
+ language: 'markdown',
85
+
86
+ dialects: ['commonmark', 'gfm'],
87
+ },
88
+
89
+ create(context) {
90
+ const { sourceCode } = context;
91
+ const [{ style }] = context.options;
92
+
93
+ /** @type {Array<UnorderedListMarker | null | undefined>} */
94
+ const unorderedListStyle = [
95
+ style === 'consistent' || style === 'sublist' ? null : style,
96
+ ];
97
+ let listDepth = -1;
98
+
99
+ return {
100
+ list() {
101
+ // When entering a `list` node, increase the depth.
102
+ // Counts both ordered and unordered lists, which matches `markdownlint`'s behavior.
103
+ listDepth++;
104
+ },
105
+
106
+ 'list[ordered=false] > listItem'(/** @type {ListItem} */ node) {
107
+ const [nodeStartOffset] = sourceCode.getRange(node);
108
+ const currentUnorderedListStyle = /** @type {UnorderedListMarker} */ (
109
+ sourceCode.text[nodeStartOffset]
110
+ );
111
+ const currentListDepth = style === 'sublist' ? listDepth : 0;
112
+
113
+ // `unorderedListStyle[currentListDepth]` can be `null` or `undefined`.
114
+ if (!unorderedListStyle[currentListDepth]) {
115
+ unorderedListStyle[currentListDepth] =
116
+ // If the previous depth used the same style, use the next style in sequence.
117
+ unorderedListStyle[currentListDepth - 1] === currentUnorderedListStyle
118
+ ? getNextUnorderedListMarker(currentUnorderedListStyle)
119
+ : currentUnorderedListStyle;
120
+ }
121
+
122
+ if (unorderedListStyle[currentListDepth] !== currentUnorderedListStyle) {
123
+ const stringifiedUnorderedListStyle = String(
124
+ unorderedListStyle[currentListDepth],
125
+ );
126
+
127
+ context.report({
128
+ loc: {
129
+ start: sourceCode.getLocFromIndex(nodeStartOffset),
130
+ end: sourceCode.getLocFromIndex(nodeStartOffset + 1),
131
+ },
132
+
133
+ messageId: 'style',
134
+
135
+ data: {
136
+ style: stringifiedUnorderedListStyle,
137
+ },
138
+
139
+ fix(fixer) {
140
+ return fixer.replaceTextRange(
141
+ [nodeStartOffset, nodeStartOffset + 1],
142
+ stringifiedUnorderedListStyle,
143
+ );
144
+ },
145
+ });
146
+ }
147
+ },
148
+
149
+ 'list:exit'() {
150
+ // When exiting a `list` node, decrease the depth.
151
+ // Counts both ordered and unordered lists, which matches `markdownlint`'s behavior.
152
+ listDepth--;
153
+ },
154
+ };
155
+ },
156
+ };
@@ -10,6 +10,7 @@ import consistentDeleteStyle from './consistent-delete-style.js';
10
10
  import consistentEmphasisStyle from './consistent-emphasis-style.js';
11
11
  import consistentStrongStyle from './consistent-strong-style.js';
12
12
  import consistentThematicBreakStyle from './consistent-thematic-break-style.js';
13
+ import consistentUnorderedListStyle from './consistent-unordered-list-style.js';
13
14
  // import enCapitalization from './en-capitalization.js';
14
15
  // import headingId from './heading-id.js';
15
16
  // import noBoldParagraph from './no-bold-paragraph.js';
@@ -34,6 +35,7 @@ export default {
34
35
  'consistent-emphasis-style': consistentEmphasisStyle,
35
36
  'consistent-strong-style': consistentStrongStyle,
36
37
  'consistent-thematic-break-style': consistentThematicBreakStyle,
38
+ 'consistent-unordered-list-style': consistentUnorderedListStyle,
37
39
  // 'en-capitalization': enCapitalization,
38
40
  // 'heading-id': headingId,
39
41
  // 'no-bold-paragraph': noBoldParagraph,
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
 
17
17
  /**
18
18
  * @import { RuleModule } from '../core/types.js';
19
- * @typedef {[{ allow: string[], skipCode: boolean, skipInlineCode: boolean }]} RuleOptions
19
+ * @typedef {[{ allow: string[], skipCode: boolean | string[], skipInlineCode: boolean }]} RuleOptions
20
20
  * @typedef {'noControlCharacter'} MessageIds
21
21
  */
22
22
 
@@ -55,7 +55,18 @@ export default {
55
55
  uniqueItems: true,
56
56
  },
57
57
  skipCode: {
58
- type: 'boolean',
58
+ oneOf: [
59
+ {
60
+ type: 'boolean',
61
+ },
62
+ {
63
+ type: 'array',
64
+ items: {
65
+ type: 'string',
66
+ },
67
+ uniqueItems: true,
68
+ },
69
+ ],
59
70
  },
60
71
  skipInlineCode: {
61
72
  type: 'boolean',
@@ -90,11 +101,14 @@ export default {
90
101
 
91
102
  return {
92
103
  code(node) {
93
- if (skipCode) skipRanges.push(sourceCode.getRange(node)); // Store position information of `Code`.
104
+ if (
105
+ Array.isArray(skipCode) ? node.lang && skipCode.includes(node.lang) : skipCode
106
+ )
107
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
94
108
  },
95
109
 
96
110
  inlineCode(node) {
97
- if (skipInlineCode) skipRanges.push(sourceCode.getRange(node)); // Store position information of `InlineCode`.
111
+ if (skipInlineCode) skipRanges.push(sourceCode.getRange(node)); // Store range information of `InlineCode`.
98
112
  },
99
113
 
100
114
  'root:exit'() {
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
 
17
17
  /**
18
18
  * @import { RuleModule } from '../core/types.js';
19
- * @typedef {[{ skipCode: boolean }]} RuleOptions
19
+ * @typedef {[{ skipCode: boolean | string[] }]} RuleOptions
20
20
  * @typedef {'noGitConflictMarker'} MessageIds
21
21
  */
22
22
 
@@ -47,7 +47,18 @@ export default {
47
47
  type: 'object',
48
48
  properties: {
49
49
  skipCode: {
50
- type: 'boolean',
50
+ oneOf: [
51
+ {
52
+ type: 'boolean',
53
+ },
54
+ {
55
+ type: 'array',
56
+ items: {
57
+ type: 'string',
58
+ },
59
+ uniqueItems: true,
60
+ },
61
+ ],
51
62
  },
52
63
  },
53
64
  additionalProperties: false,
@@ -78,7 +89,10 @@ export default {
78
89
 
79
90
  return {
80
91
  code(node) {
81
- if (skipCode) skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
92
+ if (
93
+ Array.isArray(skipCode) ? node.lang && skipCode.includes(node.lang) : skipCode
94
+ )
95
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
82
96
  },
83
97
 
84
98
  'root:exit'() {
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
 
17
17
  /**
18
18
  * @import { RuleModule } from '../core/types.js';
19
- * @typedef {[{ allow: string[], skipCode: boolean, skipInlineCode: boolean }]} RuleOptions
19
+ * @typedef {[{ allow: string[], skipCode: boolean | string[], skipInlineCode: boolean }]} RuleOptions
20
20
  * @typedef {'noIrregularDash'} MessageIds
21
21
  */
22
22
 
@@ -55,7 +55,18 @@ export default {
55
55
  uniqueItems: true,
56
56
  },
57
57
  skipCode: {
58
- type: 'boolean',
58
+ oneOf: [
59
+ {
60
+ type: 'boolean',
61
+ },
62
+ {
63
+ type: 'array',
64
+ items: {
65
+ type: 'string',
66
+ },
67
+ uniqueItems: true,
68
+ },
69
+ ],
59
70
  },
60
71
  skipInlineCode: {
61
72
  type: 'boolean',
@@ -90,11 +101,14 @@ export default {
90
101
 
91
102
  return {
92
103
  code(node) {
93
- if (skipCode) skipRanges.push(sourceCode.getRange(node)); // Store position information of `Code`.
104
+ if (
105
+ Array.isArray(skipCode) ? node.lang && skipCode.includes(node.lang) : skipCode
106
+ )
107
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
94
108
  },
95
109
 
96
110
  inlineCode(node) {
97
- if (skipInlineCode) skipRanges.push(sourceCode.getRange(node)); // Store position information of `InlineCode`.
111
+ if (skipInlineCode) skipRanges.push(sourceCode.getRange(node)); // Store range information of `InlineCode`.
98
112
  },
99
113
 
100
114
  'root:exit'() {
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
 
17
17
  /**
18
18
  * @import { RuleModule } from '../core/types.js';
19
- * @typedef {[{ allow: string[], skipCode: boolean, skipInlineCode: boolean }]} RuleOptions
19
+ * @typedef {[{ allow: string[], skipCode: boolean | string[], skipInlineCode: boolean }]} RuleOptions
20
20
  * @typedef {'noIrregularWhitespace'} MessageIds
21
21
  */
22
22
 
@@ -55,7 +55,18 @@ export default {
55
55
  uniqueItems: true,
56
56
  },
57
57
  skipCode: {
58
- type: 'boolean',
58
+ oneOf: [
59
+ {
60
+ type: 'boolean',
61
+ },
62
+ {
63
+ type: 'array',
64
+ items: {
65
+ type: 'string',
66
+ },
67
+ uniqueItems: true,
68
+ },
69
+ ],
59
70
  },
60
71
  skipInlineCode: {
61
72
  type: 'boolean',
@@ -91,7 +102,10 @@ export default {
91
102
 
92
103
  return {
93
104
  code(node) {
94
- if (skipCode) skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
105
+ if (
106
+ Array.isArray(skipCode) ? node.lang && skipCode.includes(node.lang) : skipCode
107
+ )
108
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
95
109
  },
96
110
 
97
111
  inlineCode(node) {
@@ -16,7 +16,7 @@ import { URL_RULE_DOCS } from '../core/constants.js';
16
16
 
17
17
  /**
18
18
  * @import { RuleModule } from '../core/types.js';
19
- * @typedef {[{ skipCode: boolean, skipInlineCode: boolean, tabWidth: number }]} RuleOptions
19
+ * @typedef {[{ skipCode: boolean | string[], skipInlineCode: boolean, tabWidth: number }]} RuleOptions
20
20
  * @typedef {'noTab'} MessageIds
21
21
  */
22
22
 
@@ -49,7 +49,18 @@ export default {
49
49
  type: 'object',
50
50
  properties: {
51
51
  skipCode: {
52
- type: 'boolean',
52
+ oneOf: [
53
+ {
54
+ type: 'boolean',
55
+ },
56
+ {
57
+ type: 'array',
58
+ items: {
59
+ type: 'string',
60
+ },
61
+ uniqueItems: true,
62
+ },
63
+ ],
53
64
  },
54
65
  skipInlineCode: {
55
66
  type: 'boolean',
@@ -88,7 +99,10 @@ export default {
88
99
 
89
100
  return {
90
101
  code(node) {
91
- if (skipCode) skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
102
+ if (
103
+ Array.isArray(skipCode) ? node.lang && skipCode.includes(node.lang) : skipCode
104
+ )
105
+ skipRanges.push(sourceCode.getRange(node)); // Store range information of `Code`.
92
106
  },
93
107
 
94
108
  inlineCode(node) {