@miskamyasa/eslint-config 1.0.1 → 1.0.3

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
@@ -4,6 +4,8 @@ Opinionated ESLint config for React + TypeScript projects.
4
4
 
5
5
  ## What's included
6
6
 
7
+ ### JS/TS
8
+
7
9
  - ESLint recommended rules
8
10
  - TypeScript strict type checking (`typescript-eslint` recommended + strictTypeChecked + stylisticTypeChecked)
9
11
  - React rules (`@eslint-react/eslint-plugin` recommended-typescript + `react-hooks`)
@@ -11,6 +13,21 @@ Opinionated ESLint config for React + TypeScript projects.
11
13
  - Stylistic formatting (`@stylistic/eslint-plugin` with double quotes, no semicolons, 2-space indent, stroustrup brace style)
12
14
  - CommonJS overrides for `.js`/`.cjs` files
13
15
 
16
+ ### Data files (enabled by default)
17
+
18
+ - JSON/JSONC/JSON5 linting (`eslint-plugin-jsonc`)
19
+ - YAML linting (`eslint-plugin-yml`)
20
+ - TOML linting (`eslint-plugin-toml`)
21
+ - Markdown linting (`@eslint/markdown` with GFM support)
22
+
23
+ ### Formatters (opt-in)
24
+
25
+ - CSS/SCSS/Less formatting via Prettier
26
+ - HTML formatting via Prettier
27
+ - Markdown formatting via Prettier
28
+ - GraphQL formatting via Prettier
29
+ - XML/SVG formatting via Prettier (requires `@prettier/plugin-xml`)
30
+
14
31
  ## Requirements
15
32
 
16
33
  - Node.js >= 22
@@ -43,6 +60,44 @@ export default createConfig({
43
60
  |---|---|---|---|
44
61
  | `tsconfigRootDir` | `string` | `process.cwd()` | Root directory for TypeScript project service |
45
62
  | `ignores` | `string[]` | `[]` | Additional glob patterns to ignore |
63
+ | `jsonc` | `boolean` | `true` | Enable JSON/JSONC/JSON5 linting |
64
+ | `yaml` | `boolean` | `true` | Enable YAML linting |
65
+ | `toml` | `boolean` | `true` | Enable TOML linting |
66
+ | `markdown` | `boolean` | `true` | Enable Markdown linting |
67
+ | `formatters` | `boolean \| OptionsFormatters` | `false` | Enable Prettier formatting for CSS, HTML, etc. |
68
+
69
+ ### Formatters options
70
+
71
+ When `formatters` is set to `true`, CSS, HTML, Markdown, and GraphQL formatting are enabled. XML/SVG are disabled by default because they require `@prettier/plugin-xml` to be installed separately.
72
+
73
+ For fine-grained control, pass an `OptionsFormatters` object:
74
+
75
+ ```ts
76
+ export default createConfig({
77
+ tsconfigRootDir: import.meta.dirname,
78
+ formatters: {
79
+ css: true,
80
+ html: true,
81
+ markdown: true,
82
+ graphql: true,
83
+ xml: true, // requires: pnpm add -D @prettier/plugin-xml
84
+ svg: true, // requires: pnpm add -D @prettier/plugin-xml
85
+ prettierOptions: {
86
+ // override default Prettier options
87
+ },
88
+ },
89
+ })
90
+ ```
91
+
92
+ ### Disabling configs
93
+
94
+ ```ts
95
+ export default createConfig({
96
+ tsconfigRootDir: import.meta.dirname,
97
+ yaml: false,
98
+ toml: false,
99
+ })
100
+ ```
46
101
 
47
102
  ## Overrides
48
103
 
@@ -66,7 +121,18 @@ export default createConfig(
66
121
  Individual config functions are available for advanced composition:
67
122
 
68
123
  ```ts
69
- import {typescript, stylistic, imports, react, javascript} from "@miskamyasa/eslint-config"
124
+ import {
125
+ typescript,
126
+ stylistic,
127
+ imports,
128
+ react,
129
+ javascript,
130
+ jsonc,
131
+ yaml,
132
+ toml,
133
+ markdown,
134
+ formatters,
135
+ } from "@miskamyasa/eslint-config"
70
136
  ```
71
137
 
72
138
  ## Key style decisions
package/dist/index.d.ts CHANGED
@@ -1,22 +1,47 @@
1
1
  import { Linter } from 'eslint';
2
+ export { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript';
3
+
4
+ type ConfigItem = Linter.Config;
5
+ type OptionsFormatters = {
6
+ css?: boolean;
7
+ html?: boolean;
8
+ xml?: boolean;
9
+ svg?: boolean;
10
+ markdown?: boolean;
11
+ graphql?: boolean;
12
+ prettierOptions?: Record<string, unknown>;
13
+ };
14
+ type OptionsConfig = {
15
+ tsconfigRootDir?: string;
16
+ ignores?: string[];
17
+ yaml?: boolean;
18
+ toml?: boolean;
19
+ jsonc?: boolean;
20
+ markdown?: boolean;
21
+ formatters?: boolean | OptionsFormatters;
22
+ };
23
+
24
+ declare function formatters(options?: OptionsFormatters | true): Linter.Config[];
2
25
 
3
26
  declare function createImportsConfig(): Linter.Config[];
4
27
 
5
28
  declare function javascript(): Linter.Config[];
6
29
 
30
+ declare function jsonc(): Linter.Config[];
31
+
32
+ declare function markdown(): Linter.Config[];
33
+
7
34
  declare function react(): Linter.Config[];
8
35
 
9
36
  declare function stylistic(): Linter.Config[];
10
37
 
38
+ declare function toml(): Linter.Config[];
39
+
11
40
  declare function typescript(options: {
12
41
  tsconfigRootDir: string;
13
42
  }): Linter.Config[];
14
43
 
15
- type ConfigItem = Linter.Config;
16
- type OptionsConfig = {
17
- tsconfigRootDir?: string;
18
- ignores?: string[];
19
- };
44
+ declare function yaml(): Linter.Config[];
20
45
 
21
46
  /**
22
47
  * Construct an array of ESLint flat config items.
@@ -37,11 +62,26 @@ type OptionsConfig = {
37
62
  */
38
63
  declare function createConfig(options?: OptionsConfig, ...userConfigs: Linter.Config[]): Linter.Config[];
39
64
 
40
- declare const GLOB_JS = "**/*.js";
65
+ declare const GLOB_JS = "**/*.?([cm])js";
66
+ declare const GLOB_JSX = "**/*.jsx";
41
67
  declare const GLOB_CJS = "**/*.cjs";
42
- declare const GLOB_TS = "**/*.ts";
68
+ declare const GLOB_TS = "**/*.?([cm])ts";
43
69
  declare const GLOB_TSX = "**/*.tsx";
44
70
  declare const GLOB_SRC: string[];
71
+ declare const GLOB_YAML = "**/*.y?(a)ml";
72
+ declare const GLOB_TOML = "**/*.toml";
73
+ declare const GLOB_JSON = "**/*.json";
74
+ declare const GLOB_JSONC = "**/*.jsonc";
75
+ declare const GLOB_JSON5 = "**/*.json5";
76
+ declare const GLOB_MARKDOWN = "**/*.md";
77
+ declare const GLOB_CSS = "**/*.css";
78
+ declare const GLOB_POSTCSS = "**/*.{p,post}css";
79
+ declare const GLOB_SCSS = "**/*.scss";
80
+ declare const GLOB_LESS = "**/*.less";
81
+ declare const GLOB_HTML = "**/*.htm?(l)";
82
+ declare const GLOB_XML = "**/*.xml";
83
+ declare const GLOB_SVG = "**/*.svg";
84
+ declare const GLOB_GRAPHQL = "**/*.{g,graph}ql";
45
85
  declare const GLOB_EXCLUDE: string[];
46
86
 
47
- export { type ConfigItem, GLOB_CJS, GLOB_EXCLUDE, GLOB_JS, GLOB_SRC, GLOB_TS, GLOB_TSX, type OptionsConfig, createConfig, createConfig as default, createImportsConfig as imports, javascript, react, stylistic, typescript };
87
+ export { type ConfigItem, GLOB_CJS, GLOB_CSS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_MARKDOWN, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SVG, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_XML, GLOB_YAML, type OptionsConfig, type OptionsFormatters, createConfig, createConfig as default, formatters, createImportsConfig as imports, javascript, jsonc, markdown, react, stylistic, toml, typescript, yaml };
package/dist/index.js CHANGED
@@ -1,30 +1,215 @@
1
+ // src/configs/formatters.ts
2
+ import formatPlugin from "eslint-plugin-format";
3
+
4
+ // src/globs.ts
5
+ var GLOB_JS = "**/*.?([cm])js";
6
+ var GLOB_JSX = "**/*.jsx";
7
+ var GLOB_CJS = "**/*.cjs";
8
+ var GLOB_TS = "**/*.?([cm])ts";
9
+ var GLOB_TSX = "**/*.tsx";
10
+ var GLOB_SRC = [
11
+ GLOB_JS,
12
+ GLOB_JSX,
13
+ GLOB_TS,
14
+ GLOB_TSX
15
+ ];
16
+ var GLOB_YAML = "**/*.y?(a)ml";
17
+ var GLOB_TOML = "**/*.toml";
18
+ var GLOB_JSON = "**/*.json";
19
+ var GLOB_JSONC = "**/*.jsonc";
20
+ var GLOB_JSON5 = "**/*.json5";
21
+ var GLOB_MARKDOWN = "**/*.md";
22
+ var GLOB_CSS = "**/*.css";
23
+ var GLOB_POSTCSS = "**/*.{p,post}css";
24
+ var GLOB_SCSS = "**/*.scss";
25
+ var GLOB_LESS = "**/*.less";
26
+ var GLOB_HTML = "**/*.htm?(l)";
27
+ var GLOB_XML = "**/*.xml";
28
+ var GLOB_SVG = "**/*.svg";
29
+ var GLOB_GRAPHQL = "**/*.{g,graph}ql";
30
+ var GLOB_EXCLUDE = [
31
+ "**/node_modules",
32
+ "**/dist",
33
+ "**/package-lock.json",
34
+ "**/yarn.lock",
35
+ "**/pnpm-lock.yaml",
36
+ "**/bun.lockb"
37
+ ];
38
+
39
+ // src/configs/formatters.ts
40
+ var parserPlain = {
41
+ meta: {
42
+ name: "parser-plain"
43
+ },
44
+ parseForESLint: (code) => ({
45
+ ast: {
46
+ body: [],
47
+ comments: [],
48
+ loc: { end: code.length, start: 0 },
49
+ range: [0, code.length],
50
+ tokens: [],
51
+ type: "Program"
52
+ },
53
+ scopeManager: null,
54
+ services: { isPlain: true },
55
+ visitorKeys: {
56
+ Program: []
57
+ }
58
+ })
59
+ };
60
+ var defaultPrettierOptions = {
61
+ endOfLine: "auto",
62
+ printWidth: 120,
63
+ semi: false,
64
+ singleQuote: false,
65
+ tabWidth: 2,
66
+ trailingComma: "all",
67
+ useTabs: false
68
+ };
69
+ function formatters(options = {}) {
70
+ const resolvedOptions = options === true ? {
71
+ css: true,
72
+ graphql: true,
73
+ html: true,
74
+ markdown: true,
75
+ // XML/SVG require @prettier/plugin-xml to be installed separately
76
+ svg: false,
77
+ xml: false
78
+ } : options;
79
+ const prettierOptions = {
80
+ ...defaultPrettierOptions,
81
+ ...resolvedOptions.prettierOptions ?? {}
82
+ };
83
+ const configs2 = [
84
+ {
85
+ name: "miskamyasa/formatters/setup",
86
+ plugins: {
87
+ format: formatPlugin
88
+ }
89
+ }
90
+ ];
91
+ if (resolvedOptions.css) {
92
+ configs2.push(
93
+ {
94
+ name: "miskamyasa/formatters/css",
95
+ files: [GLOB_CSS, GLOB_POSTCSS],
96
+ languageOptions: { parser: parserPlain },
97
+ rules: {
98
+ "format/prettier": ["error", { ...prettierOptions, parser: "css" }]
99
+ }
100
+ },
101
+ {
102
+ name: "miskamyasa/formatters/scss",
103
+ files: [GLOB_SCSS],
104
+ languageOptions: { parser: parserPlain },
105
+ rules: {
106
+ "format/prettier": ["error", { ...prettierOptions, parser: "scss" }]
107
+ }
108
+ },
109
+ {
110
+ name: "miskamyasa/formatters/less",
111
+ files: [GLOB_LESS],
112
+ languageOptions: { parser: parserPlain },
113
+ rules: {
114
+ "format/prettier": ["error", { ...prettierOptions, parser: "less" }]
115
+ }
116
+ }
117
+ );
118
+ }
119
+ if (resolvedOptions.html) {
120
+ configs2.push({
121
+ name: "miskamyasa/formatters/html",
122
+ files: [GLOB_HTML],
123
+ languageOptions: { parser: parserPlain },
124
+ rules: {
125
+ "format/prettier": ["error", { ...prettierOptions, parser: "html" }]
126
+ }
127
+ });
128
+ }
129
+ if (resolvedOptions.xml) {
130
+ configs2.push({
131
+ name: "miskamyasa/formatters/xml",
132
+ files: [GLOB_XML],
133
+ languageOptions: { parser: parserPlain },
134
+ rules: {
135
+ "format/prettier": ["error", { ...prettierOptions, parser: "xml", plugins: ["@prettier/plugin-xml"] }]
136
+ }
137
+ });
138
+ }
139
+ if (resolvedOptions.svg) {
140
+ configs2.push({
141
+ name: "miskamyasa/formatters/svg",
142
+ files: [GLOB_SVG],
143
+ languageOptions: { parser: parserPlain },
144
+ rules: {
145
+ "format/prettier": ["error", { ...prettierOptions, parser: "xml", plugins: ["@prettier/plugin-xml"] }]
146
+ }
147
+ });
148
+ }
149
+ if (resolvedOptions.markdown) {
150
+ configs2.push({
151
+ name: "miskamyasa/formatters/markdown",
152
+ files: [GLOB_MARKDOWN],
153
+ languageOptions: { parser: parserPlain },
154
+ rules: {
155
+ "format/prettier": ["error", { ...prettierOptions, embeddedLanguageFormatting: "off", parser: "markdown" }]
156
+ }
157
+ });
158
+ }
159
+ if (resolvedOptions.graphql) {
160
+ configs2.push({
161
+ name: "miskamyasa/formatters/graphql",
162
+ files: [GLOB_GRAPHQL],
163
+ languageOptions: { parser: parserPlain },
164
+ rules: {
165
+ "format/prettier": ["error", { ...prettierOptions, parser: "graphql" }]
166
+ }
167
+ });
168
+ }
169
+ return configs2;
170
+ }
171
+
1
172
  // src/configs/imports.ts
2
173
  import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
3
- import { flatConfigs as imports } from "eslint-plugin-import-x";
174
+ import { flatConfigs as importConfigs } from "eslint-plugin-import-x";
4
175
  import unusedImports from "eslint-plugin-unused-imports";
5
176
  function createImportsConfig() {
6
177
  return [
178
+ // Plugin setup (global - registers import-x and unused-imports plugins)
179
+ {
180
+ name: "miskamyasa/imports/setup",
181
+ plugins: {
182
+ ...importConfigs.recommended.plugins,
183
+ "unused-imports": unusedImports
184
+ }
185
+ },
186
+ // Recommended rules - scoped to source files
7
187
  {
8
- ...imports.recommended,
9
- name: "miskamyasa/imports/recommended"
188
+ name: "miskamyasa/imports/recommended-rules",
189
+ files: GLOB_SRC,
190
+ rules: importConfigs.recommended.rules
10
191
  },
192
+ // React settings - scoped to source files
11
193
  {
12
- ...imports.react,
13
- name: "miskamyasa/imports/react"
194
+ name: "miskamyasa/imports/react",
195
+ files: GLOB_SRC,
196
+ settings: importConfigs.react.settings,
197
+ languageOptions: importConfigs.react.languageOptions
14
198
  },
199
+ // TypeScript resolver
15
200
  {
16
201
  name: "miskamyasa/imports/typescript",
202
+ files: GLOB_SRC,
17
203
  settings: {
18
204
  "import-x/resolver-next": [
19
205
  createTypeScriptImportResolver()
20
206
  ]
21
207
  }
22
208
  },
209
+ // Custom rules - scoped to source files
23
210
  {
24
211
  name: "miskamyasa/imports/rules",
25
- plugins: {
26
- "unused-imports": unusedImports
27
- },
212
+ files: GLOB_SRC,
28
213
  rules: {
29
214
  "import-x/namespace": "off",
30
215
  "import-x/newline-after-import": [
@@ -61,32 +246,12 @@ function createImportsConfig() {
61
246
  ];
62
247
  }
63
248
 
64
- // src/globs.ts
65
- var GLOB_JS = "**/*.js";
66
- var GLOB_CJS = "**/*.cjs";
67
- var GLOB_TS = "**/*.ts";
68
- var GLOB_TSX = "**/*.tsx";
69
- var GLOB_SRC = [
70
- GLOB_JS,
71
- GLOB_CJS,
72
- GLOB_TS,
73
- GLOB_TSX
74
- ];
75
- var GLOB_EXCLUDE = [
76
- "**/node_modules",
77
- "**/dist",
78
- "**/package-lock.json",
79
- "**/yarn.lock",
80
- "**/pnpm-lock.yaml",
81
- "**/bun.lockb"
82
- ];
83
-
84
249
  // src/configs/javascript.ts
85
250
  function javascript() {
86
251
  return [
87
252
  {
88
253
  name: "miskamyasa/javascript/overrides",
89
- files: [GLOB_JS, GLOB_CJS],
254
+ files: ["**/*.js", GLOB_CJS],
90
255
  languageOptions: {
91
256
  globals: {
92
257
  require: "readonly",
@@ -103,20 +268,113 @@ function javascript() {
103
268
  ];
104
269
  }
105
270
 
271
+ // src/configs/jsonc.ts
272
+ import jsoncPlugin from "eslint-plugin-jsonc";
273
+ import * as jsoncParser from "jsonc-eslint-parser";
274
+ var JSON_FILES = [GLOB_JSON, GLOB_JSONC, GLOB_JSON5];
275
+ function jsonc() {
276
+ const preset = jsoncPlugin.configs["flat/recommended-with-jsonc"];
277
+ return [
278
+ // Plugin setup (global - registers the jsonc plugin)
279
+ {
280
+ name: "miskamyasa/jsonc/setup",
281
+ plugins: preset[0].plugins
282
+ },
283
+ // Parser and basic overrides from preset (already scoped to JSON files)
284
+ {
285
+ ...preset[1],
286
+ name: "miskamyasa/jsonc/parser-overrides"
287
+ },
288
+ // Recommended rules - scoped to JSON files
289
+ {
290
+ name: "miskamyasa/jsonc/recommended-rules",
291
+ files: JSON_FILES,
292
+ rules: preset[2].rules
293
+ },
294
+ // Stylistic rules
295
+ {
296
+ name: "miskamyasa/jsonc/stylistic-rules",
297
+ files: JSON_FILES,
298
+ languageOptions: {
299
+ parser: jsoncParser
300
+ },
301
+ rules: {
302
+ "jsonc/indent": ["error", 2],
303
+ "jsonc/key-spacing": "error",
304
+ "jsonc/array-bracket-spacing": ["error", "never"],
305
+ "jsonc/sort-keys": "off"
306
+ }
307
+ },
308
+ // JSON-specific rules (strict JSON doesn't allow trailing commas)
309
+ {
310
+ name: "miskamyasa/jsonc/json-rules",
311
+ files: [GLOB_JSON],
312
+ languageOptions: {
313
+ parser: jsoncParser
314
+ },
315
+ rules: {
316
+ "jsonc/comma-dangle": ["error", "never"]
317
+ }
318
+ }
319
+ ];
320
+ }
321
+
322
+ // src/configs/markdown.ts
323
+ import markdownPlugin from "@eslint/markdown";
324
+ function markdown() {
325
+ return [
326
+ {
327
+ name: "miskamyasa/markdown/setup",
328
+ plugins: {
329
+ markdown: markdownPlugin
330
+ }
331
+ },
332
+ {
333
+ name: "miskamyasa/markdown/parser",
334
+ files: [GLOB_MARKDOWN],
335
+ language: "markdown/gfm"
336
+ },
337
+ {
338
+ name: "miskamyasa/markdown/rules",
339
+ files: [GLOB_MARKDOWN],
340
+ rules: {
341
+ "markdown/fenced-code-language": "warn",
342
+ "markdown/heading-increment": "error",
343
+ "markdown/no-duplicate-headings": "off",
344
+ "markdown/no-empty-links": "error",
345
+ "markdown/no-html": "off",
346
+ "markdown/no-invalid-label-refs": "off",
347
+ "markdown/no-missing-label-refs": "off"
348
+ }
349
+ }
350
+ ];
351
+ }
352
+
106
353
  // src/configs/react.ts
107
354
  import reactPlugin from "@eslint-react/eslint-plugin";
108
355
  import reactHooksPlugin from "eslint-plugin-react-hooks";
109
356
  function react() {
357
+ const preset = reactPlugin.configs["recommended-typescript"];
110
358
  return [
359
+ // Plugin setup (global - registers all react plugins)
111
360
  {
112
- ...reactPlugin.configs["recommended-typescript"],
113
- name: "miskamyasa/react/recommended-typescript"
114
- },
115
- {
116
- name: "miskamyasa/react/rules",
361
+ name: "miskamyasa/react/setup",
117
362
  plugins: {
363
+ ...preset.plugins,
118
364
  "react-hooks": reactHooksPlugin
119
365
  },
366
+ settings: preset.settings
367
+ },
368
+ // React rules - scoped to source files only
369
+ {
370
+ name: "miskamyasa/react/rules",
371
+ files: GLOB_SRC,
372
+ rules: preset.rules
373
+ },
374
+ // React hooks rules - scoped to source files only
375
+ {
376
+ name: "miskamyasa/react/hooks-rules",
377
+ files: GLOB_SRC,
120
378
  rules: {
121
379
  "react-hooks/rules-of-hooks": "error",
122
380
  "react-hooks/exhaustive-deps": "error"
@@ -128,17 +386,24 @@ function react() {
128
386
  // src/configs/stylistic.ts
129
387
  import stylisticPlugin from "@stylistic/eslint-plugin";
130
388
  function stylistic() {
131
- const stylistic2 = stylisticPlugin;
132
389
  return [
390
+ // Plugin setup (global - registers the @stylistic plugin)
391
+ {
392
+ name: "miskamyasa/stylistic/setup",
393
+ plugins: {
394
+ "@stylistic": stylisticPlugin
395
+ }
396
+ },
397
+ // Disable legacy ESLint formatting rules - scoped to source files
133
398
  {
134
- ...stylistic2.configs["disable-legacy"],
135
- name: "miskamyasa/stylistic/disable-legacy"
399
+ name: "miskamyasa/stylistic/disable-legacy",
400
+ files: GLOB_SRC,
401
+ rules: stylisticPlugin.configs["disable-legacy"].rules
136
402
  },
403
+ // Stylistic rules - scoped to source files
137
404
  {
138
405
  name: "miskamyasa/stylistic/rules",
139
- plugins: {
140
- "@stylistic": stylistic2
141
- },
406
+ files: GLOB_SRC,
142
407
  rules: {
143
408
  "@stylistic/block-spacing": ["error", "never"],
144
409
  "@stylistic/comma-dangle": ["error", "always-multiline"],
@@ -296,15 +561,89 @@ function stylistic() {
296
561
  ];
297
562
  }
298
563
 
564
+ // src/configs/toml.ts
565
+ import tomlPlugin from "eslint-plugin-toml";
566
+ import * as tomlParser from "toml-eslint-parser";
567
+ function toml() {
568
+ return [
569
+ {
570
+ name: "miskamyasa/toml/setup",
571
+ plugins: {
572
+ toml: tomlPlugin
573
+ }
574
+ },
575
+ {
576
+ name: "miskamyasa/toml/rules",
577
+ files: [GLOB_TOML],
578
+ languageOptions: {
579
+ parser: tomlParser
580
+ },
581
+ rules: {
582
+ "toml/comma-style": "error",
583
+ "toml/keys-order": "error",
584
+ "toml/no-space-dots": "error",
585
+ "toml/no-unreadable-number-separator": "error",
586
+ "toml/precision-of-fractional-seconds": "error",
587
+ "toml/precision-of-integer": "error",
588
+ "toml/tables-order": "error",
589
+ "toml/array-bracket-newline": "error",
590
+ "toml/array-bracket-spacing": "error",
591
+ "toml/array-element-newline": "error",
592
+ "toml/indent": ["error", 2],
593
+ "toml/inline-table-curly-spacing": "error",
594
+ "toml/key-spacing": "error",
595
+ "toml/padding-line-between-pairs": "error",
596
+ "toml/padding-line-between-tables": "error",
597
+ "toml/quoted-keys": "error",
598
+ "toml/spaced-comment": "error",
599
+ "toml/table-bracket-spacing": "error"
600
+ }
601
+ }
602
+ ];
603
+ }
604
+
299
605
  // src/configs/typescript.ts
300
- import { configs } from "typescript-eslint";
606
+ import { configs, parser } from "typescript-eslint";
301
607
  function typescript(options) {
608
+ const recommended = configs.recommended;
609
+ const strictTypeChecked = configs.strictTypeChecked;
610
+ const stylisticTypeChecked = configs.stylisticTypeChecked;
302
611
  return [
303
- ...configs.recommended,
304
- ...configs.strictTypeChecked,
305
- ...configs.stylisticTypeChecked,
612
+ // Plugin + parser setup (shared across all presets, only need it once)
613
+ {
614
+ name: "miskamyasa/typescript/setup",
615
+ plugins: recommended[0].plugins,
616
+ languageOptions: {
617
+ parser
618
+ }
619
+ },
620
+ // ESLint-recommended overrides for TS files (already scoped by preset)
621
+ {
622
+ ...recommended[1],
623
+ name: "miskamyasa/typescript/eslint-recommended"
624
+ },
625
+ // Recommended rules - scoped to source files
626
+ {
627
+ name: "miskamyasa/typescript/recommended-rules",
628
+ files: GLOB_SRC,
629
+ rules: recommended[2].rules
630
+ },
631
+ // Strict type-checked rules - scoped to source files
632
+ {
633
+ name: "miskamyasa/typescript/strict-type-checked-rules",
634
+ files: GLOB_SRC,
635
+ rules: strictTypeChecked[2].rules
636
+ },
637
+ // Stylistic type-checked rules - scoped to source files
638
+ {
639
+ name: "miskamyasa/typescript/stylistic-type-checked-rules",
640
+ files: GLOB_SRC,
641
+ rules: stylisticTypeChecked[2].rules
642
+ },
643
+ // Parser options with type information
306
644
  {
307
645
  name: "miskamyasa/typescript/language-options",
646
+ files: GLOB_SRC,
308
647
  languageOptions: {
309
648
  parserOptions: {
310
649
  projectService: true,
@@ -312,8 +651,10 @@ function typescript(options) {
312
651
  }
313
652
  }
314
653
  },
654
+ // Project-specific rule overrides
315
655
  {
316
656
  name: "miskamyasa/typescript/rules",
657
+ files: GLOB_SRC,
317
658
  rules: {
318
659
  "@typescript-eslint/consistent-type-definitions": ["error", "type"],
319
660
  "@typescript-eslint/no-unused-vars": "off",
@@ -336,12 +677,57 @@ function typescript(options) {
336
677
  ];
337
678
  }
338
679
 
680
+ // src/configs/yaml.ts
681
+ import yamlPlugin from "eslint-plugin-yml";
682
+ import * as yamlParser from "yaml-eslint-parser";
683
+ function yaml() {
684
+ return [
685
+ {
686
+ name: "miskamyasa/yaml/setup",
687
+ plugins: {
688
+ yaml: yamlPlugin
689
+ }
690
+ },
691
+ {
692
+ name: "miskamyasa/yaml/rules",
693
+ files: [GLOB_YAML],
694
+ languageOptions: {
695
+ parser: yamlParser
696
+ },
697
+ rules: {
698
+ "yaml/block-mapping": "error",
699
+ "yaml/block-sequence": "error",
700
+ "yaml/no-empty-key": "error",
701
+ "yaml/no-empty-sequence-entry": "error",
702
+ "yaml/no-irregular-whitespace": "error",
703
+ "yaml/plain-scalar": "error",
704
+ "yaml/block-mapping-question-indicator-newline": "error",
705
+ "yaml/block-sequence-hyphen-indicator-newline": "error",
706
+ "yaml/flow-mapping-curly-newline": "error",
707
+ "yaml/flow-mapping-curly-spacing": "error",
708
+ "yaml/flow-sequence-bracket-newline": "error",
709
+ "yaml/flow-sequence-bracket-spacing": "error",
710
+ "yaml/indent": ["error", 2],
711
+ "yaml/key-spacing": "error",
712
+ "yaml/no-tab-indent": "error",
713
+ "yaml/quotes": ["error", { "avoidEscape": true, "prefer": "double" }],
714
+ "yaml/spaced-comment": "error"
715
+ }
716
+ }
717
+ ];
718
+ }
719
+
339
720
  // src/factory.ts
340
721
  import eslint from "@eslint/js";
341
722
  function createConfig(options = {}, ...userConfigs) {
342
723
  const {
343
724
  tsconfigRootDir = process.cwd(),
344
- ignores = []
725
+ ignores = [],
726
+ jsonc: enableJsonc = true,
727
+ yaml: enableYaml = true,
728
+ toml: enableToml = true,
729
+ markdown: enableMarkdown = true,
730
+ formatters: enableFormatters = false
345
731
  } = options;
346
732
  return [
347
733
  // Global ignores
@@ -352,10 +738,12 @@ function createConfig(options = {}, ...userConfigs) {
352
738
  ...ignores
353
739
  ]
354
740
  },
355
- // ESLint recommended
741
+ // ESLint recommended rules (scoped to source files -
742
+ // core rules use JS-specific sourceCode APIs incompatible with other languages)
356
743
  {
357
- ...eslint.configs.recommended,
358
- name: "miskamyasa/eslint/recommended"
744
+ name: "miskamyasa/eslint/recommended",
745
+ files: GLOB_SRC,
746
+ rules: eslint.configs.recommended.rules
359
747
  },
360
748
  // TypeScript
361
749
  ...typescript({ tsconfigRootDir }),
@@ -365,24 +753,58 @@ function createConfig(options = {}, ...userConfigs) {
365
753
  ...react(),
366
754
  // Stylistic
367
755
  ...stylistic(),
756
+ // JSONC/JSON
757
+ ...enableJsonc ? jsonc() : [],
758
+ // YAML
759
+ ...enableYaml ? yaml() : [],
760
+ // TOML
761
+ ...enableToml ? toml() : [],
762
+ // Markdown
763
+ ...enableMarkdown ? markdown() : [],
764
+ // Formatters (Prettier via ESLint for CSS, HTML, XML, etc.)
765
+ ...enableFormatters ? formatters(enableFormatters) : [],
368
766
  // JavaScript/CJS overrides (must come after TypeScript rules)
369
767
  ...javascript(),
370
768
  // User configs (appended last for maximum override power)
371
769
  ...userConfigs
372
770
  ];
373
771
  }
772
+
773
+ // src/index.ts
774
+ import { createTypeScriptImportResolver as createTypeScriptImportResolver2 } from "eslint-import-resolver-typescript";
374
775
  export {
375
776
  GLOB_CJS,
777
+ GLOB_CSS,
376
778
  GLOB_EXCLUDE,
779
+ GLOB_GRAPHQL,
780
+ GLOB_HTML,
377
781
  GLOB_JS,
782
+ GLOB_JSON,
783
+ GLOB_JSON5,
784
+ GLOB_JSONC,
785
+ GLOB_JSX,
786
+ GLOB_LESS,
787
+ GLOB_MARKDOWN,
788
+ GLOB_POSTCSS,
789
+ GLOB_SCSS,
378
790
  GLOB_SRC,
791
+ GLOB_SVG,
792
+ GLOB_TOML,
379
793
  GLOB_TS,
380
794
  GLOB_TSX,
795
+ GLOB_XML,
796
+ GLOB_YAML,
381
797
  createConfig,
798
+ createTypeScriptImportResolver2 as createTypeScriptImportResolver,
382
799
  createConfig as default,
800
+ formatters,
383
801
  createImportsConfig as imports,
384
802
  javascript,
803
+ jsonc,
804
+ markdown,
385
805
  react,
386
806
  stylistic,
387
- typescript
807
+ toml,
808
+ typescript,
809
+ yaml
388
810
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@miskamyasa/eslint-config",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "description": "Opinionated ESLint config for React + TypeScript projects",
6
6
  "exports": {
7
7
  ".": {
@@ -24,26 +24,34 @@
24
24
  "author": "Denis <MiskaMyasa> Zaitsev",
25
25
  "license": "MIT",
26
26
  "engines": {
27
- "node": ">=22.0.0"
27
+ "node": ">=24.0.0"
28
28
  },
29
29
  "dependencies": {
30
30
  "@eslint-react/eslint-plugin": "2.13.0",
31
31
  "@eslint/js": "10.0.1",
32
+ "@eslint/markdown": "7.5.1",
32
33
  "@stylistic/eslint-plugin": "5.10.0",
33
34
  "eslint-import-resolver-typescript": "4.4.4",
35
+ "eslint-plugin-format": "2.0.1",
34
36
  "eslint-plugin-import-x": "4.16.2",
35
- "eslint-plugin-react-hooks": "7.0.1",
37
+ "eslint-plugin-jsonc": "3.1.2",
38
+ "eslint-plugin-react-hooks": "7.1.1",
39
+ "eslint-plugin-toml": "1.3.1",
36
40
  "eslint-plugin-unused-imports": "4.4.1",
37
- "typescript-eslint": "8.57.0"
41
+ "eslint-plugin-yml": "3.3.2",
42
+ "jsonc-eslint-parser": "3.1.0",
43
+ "toml-eslint-parser": "1.0.3",
44
+ "typescript-eslint": "8.59.4",
45
+ "yaml-eslint-parser": "2.0.0"
38
46
  },
39
47
  "peerDependencies": {
40
48
  "eslint": ">=9.0.0",
41
49
  "typescript": ">=5.0.0"
42
50
  },
43
51
  "devDependencies": {
44
- "@types/node": "25.5.0",
45
- "eslint": "10.0.3",
46
- "jiti": "2.6.1",
52
+ "@types/node": "24.12.4",
53
+ "eslint": "10.4.0",
54
+ "jiti": "2.7.0",
47
55
  "tsup": "8.5.1",
48
56
  "typescript": "5.9.3"
49
57
  },