@kazupon/eslint-config 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,7 +63,7 @@ export default defineConfig(
63
63
  )
64
64
  ```
65
65
 
66
- > [!IMPORTANT]
66
+ > [!IMPORTANT] <!-- eslint-disable-line markdown/no-missing-label-refs -->
67
67
  > Support flat configuration only, **not supported Legacy style (`.eslintrc`)**
68
68
 
69
69
  ### Lint with npm scripts `package.json`
@@ -125,7 +125,7 @@ The following built-in preset configurations are supported:
125
125
  | `javascript` | [`@eslint/js`](https://www.npmjs.com/package/@eslint/js) | no (built-in) |
126
126
  | `comments` | [`@eslint-community/eslint-plugin-eslint-comments`](https://www.npmjs.com/package/@eslint-community/eslint-plugin-eslint-comments) | no (built-in) |
127
127
  | `typescript` | [`typescript-eslint`](https://www.npmjs.com/package/typescript-eslint) | yes |
128
- | `imports` | [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import), [`eslint-plugin-unused-imports`](https://www.npmjs.com/package/eslint-plugin-unused-imports) | yes |
128
+ | `imports` | [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import), [`eslint-plugin-unused-imports`](https://www.npmjs.com/package/eslint-plugin-unused-imports), [`eslint-plugin-module-interop`](https://www.npmjs.com/package/eslint-plugin-module-interop) | yes |
129
129
  | `jsdoc` | [`eslint-plugin-jsdoc`](https://www.npmjs.com/package/eslint-plugin-jsdoc) | yes |
130
130
  | `regexp` | [`eslint-plugin-regexp`](https://www.npmjs.com/package/eslint-plugin-regexp) | yes |
131
131
  | `promise` | [`eslint-plugin-promise`](https://www.npmjs.com/package/eslint-plugin-promise) | yes |
package/dist/index.d.ts CHANGED
@@ -362,6 +362,21 @@ interface ImportsRules {
362
362
  * @see https://github.com/import-js/eslint-plugin-import/blob/v2.31.0/docs/rules/unambiguous.md
363
363
  */
364
364
  'import/unambiguous'?: Linter.RuleEntry<[]>;
365
+ /**
366
+ * disallow importing CommonJS modules
367
+ * @see https://ota-meshi.github.io/eslint-plugin-module-interop/rules/no-import-cjs.html
368
+ */
369
+ 'module-interop/no-import-cjs'?: Linter.RuleEntry<[]>;
370
+ /**
371
+ * disallow `require(esm)`
372
+ * @see https://ota-meshi.github.io/eslint-plugin-module-interop/rules/no-require-esm.html
373
+ */
374
+ 'module-interop/no-require-esm'?: Linter.RuleEntry<[]>;
375
+ /**
376
+ * enforce json imports to have the `{type: "json"}` attribute.
377
+ * @see https://ota-meshi.github.io/eslint-plugin-module-interop/rules/prefer-json-modules.html
378
+ */
379
+ 'module-interop/prefer-json-modules'?: Linter.RuleEntry<[]>;
365
380
  /**
366
381
  * Disallow unused variables
367
382
  * @see https://github.com/sweepline/eslint-plugin-unused-imports/blob/master/docs/rules/no-unused-imports.md
@@ -13932,6 +13947,11 @@ interface ImportsOptions {
13932
13947
  * @default false
13933
13948
  */
13934
13949
  typescript?: boolean;
13950
+ /**
13951
+ * use `eslint-plugin-module-interop`
13952
+ * @default true
13953
+ */
13954
+ interop?: boolean;
13935
13955
  }
13936
13956
  /**
13937
13957
  * `eslint-plugin-import-x`, `eslint-plugin-unused-imports` and overrides configuration options
@@ -14037,6 +14057,10 @@ interface MarkdownOptions {
14037
14057
  * @default true
14038
14058
  */
14039
14059
  fencedCodeBlocks?: boolean;
14060
+ /**
14061
+ * enable block extensions
14062
+ */
14063
+ blockExtensions?: string[];
14040
14064
  }
14041
14065
  /**
14042
14066
  * `@eslint/markdown` and overrides configuration options
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ import { FlatConfigComposer } from "eslint-flat-config-utils";
2
2
  import { interopDefault } from "@kazupon/jts-utils/module";
3
3
  import { isObject } from "@kazupon/jts-utils/object";
4
4
  import globals from "globals";
5
+ import { mergeProcessors, processorPassThrough } from "eslint-merge-processors";
5
6
 
6
7
  //#region src/config.ts
7
8
  function defineConfig(...configs) {
@@ -25,6 +26,7 @@ const GLOB_SVELTE = "**/*.svelte";
25
26
  const GLOB_MARKDOWN = "**/*.md";
26
27
  const GLOB_CSS = "**/*.css";
27
28
  const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
29
+ const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
28
30
  const GLOB_TESTS = [
29
31
  `**/test/**/*.${GLOB_SRC_EXT}`,
30
32
  `**/tests/**/*.${GLOB_SRC_EXT}`,
@@ -66,6 +68,7 @@ async function comments(options = {}) {
66
68
  const comments$1 = await loadPlugin("@eslint-community/eslint-plugin-eslint-comments");
67
69
  return [{
68
70
  name: "@eslint-community/eslint-comments/recommended",
71
+ ignores: [GLOB_MARKDOWN],
69
72
  plugins: { "@eslint-community/eslint-comments": comments$1 },
70
73
  rules: { ...comments$1.configs.recommended.rules }
71
74
  }, {
@@ -82,6 +85,7 @@ async function css(options = {}) {
82
85
  const customSyntax = !!options.customSyntax;
83
86
  const css$1 = await loadPlugin("@eslint/css");
84
87
  const core = {
88
+ name: "@eslint/css/recommended",
85
89
  files: [GLOB_CSS],
86
90
  language: "css/css",
87
91
  ...css$1.configs["recommended"]
@@ -110,20 +114,29 @@ const IMPORTS_FILES = [
110
114
  GLOB_TSX
111
115
  ];
112
116
  async function imports(options = {}) {
113
- const { rules: overrideRules = {} } = options;
114
- const unused = await loadPlugin(
115
- // eslint-disable-line @typescript-eslint/no-unsafe-assignment
116
- "eslint-plugin-unused-imports"
117
- );
117
+ const { rules: overrideRules = {}, interop = true } = options;
118
+ const unused = await loadPlugin("eslint-plugin-unused-imports");
118
119
  const imports$1 = await loadPlugin("eslint-plugin-import");
119
120
  const configs = [imports$1.flatConfigs.recommended];
120
121
  if (options.typescript) try {
121
122
  await loadPlugin("eslint-import-resolver-typescript");
122
123
  imports$1.flatConfigs.typescript.settings["import/resolver"]["typescript"] = true;
123
- configs.push(imports$1.flatConfigs.typescript);
124
+ configs.push({
125
+ name: "import/typescript",
126
+ ...imports$1.flatConfigs.typescript
127
+ });
124
128
  } catch (error) {
125
129
  throw new Error(`Not found eslint-import-resolver-typescript: ${error.message}`);
126
130
  }
131
+ if (interop) try {
132
+ const modInterop = await loadPlugin("eslint-plugin-module-interop");
133
+ configs.push({
134
+ name: "module-interop",
135
+ ...modInterop.configs.recommended
136
+ });
137
+ } catch (error) {
138
+ throw new Error(`Not found eslint-plugin-module-interop: ${error.message}`);
139
+ }
127
140
  configs.push({
128
141
  name: "unused-imports",
129
142
  plugins: { "unused-imports": unused },
@@ -159,10 +172,11 @@ async function javascript(options = {}) {
159
172
  const { rules: overrideRules = {} } = options;
160
173
  const js = await loadPlugin("@eslint/js");
161
174
  return [{
162
- name: "eslint/defaults/rules",
175
+ name: "@kazupon/javascript/markdown-block",
176
+ files: ["**/*.md/*.{js,cjs,mjs}"],
163
177
  ...js.configs.recommended
164
178
  }, {
165
- name: "@kazupon/javascript/@eslint/js",
179
+ name: "@kazupon/javascript/overrides",
166
180
  languageOptions: {
167
181
  ecmaVersion: 2022,
168
182
  globals: {
@@ -197,7 +211,10 @@ async function jsdoc(options = {}) {
197
211
  if (error) preset = `${preset}-error`;
198
212
  return preset;
199
213
  }
200
- return [jsdoc$1.configs[`flat/${resolvePreset()}`], {
214
+ return [{
215
+ ignores: [GLOB_MARKDOWN],
216
+ ...jsdoc$1.configs[`flat/${resolvePreset()}`]
217
+ }, {
201
218
  name: "@kazupon/jsdoc",
202
219
  rules: { ...overrideRules }
203
220
  }];
@@ -216,16 +233,20 @@ async function jsonc(options = {}) {
216
233
  const jsonc$1 = await loadPlugin("eslint-plugin-jsonc");
217
234
  const configs = [];
218
235
  for (const kind of kinds) if (kind) configs.push(...jsonc$1.configs[`flat/recommended-with-${kind}`].map((config, index) => {
219
- return config.name ? config : {
220
- name: `jsonc/flat/recommended-with-${kind}/${index}`,
221
- ...config
236
+ const mapped = {
237
+ ...config,
238
+ ignores: [GLOB_MARKDOWN]
222
239
  };
240
+ if (!config.name) mapped.name = `jsonc/flat/recommended-with-${kind}/${index}`;
241
+ return mapped;
223
242
  }));
224
243
  if (usePrettier) configs.push(...jsonc$1.configs["flat/prettier"].map((config, index) => {
225
- return config.name ? config : {
226
- name: `jsonc/flat/prettier/${index}`,
227
- ...config
244
+ const mapped = {
245
+ ...config,
246
+ ignores: [GLOB_MARKDOWN]
228
247
  };
248
+ if (!config.name) mapped.name = `jsonc/flat/prettier/${index}`;
249
+ return mapped;
229
250
  }));
230
251
  const overriddenConfig = {
231
252
  name: "@kazupon/jsonc",
@@ -322,19 +343,36 @@ function jsoncSort() {
322
343
  //#endregion
323
344
  //#region src/configs/markdown.ts
324
345
  async function markdown(options = {}) {
325
- const { rules: overrideRules = {} } = options;
346
+ const { rules: overrideRules = {}, files = [GLOB_MARKDOWN], blockExtensions = [] } = options;
326
347
  const language = options.language || "gfm";
327
- const fencedCodeBlocks = typeof options.fencedCodeBlocks === "boolean" ? options.fencedCodeBlocks : true;
328
348
  const markdown$1 = await loadPlugin("@eslint/markdown");
329
- const recommended = markdown$1.configs["recommended"][0];
349
+ const recommended = { ...markdown$1.configs["recommended"][0] };
350
+ const codeblocks = markdown$1.configs.processor[2];
330
351
  recommended.language = `markdown/${language}`;
331
352
  return [
332
353
  recommended,
333
- ...fencedCodeBlocks ? markdown$1.configs["processor"] : [],
354
+ {
355
+ name: "markdown/makedown-in-markdown",
356
+ files,
357
+ ignores: [`${GLOB_MARKDOWN}/**`],
358
+ processor: mergeProcessors([markdown$1.processors.markdown, processorPassThrough])
359
+ },
360
+ {
361
+ name: "makrdown/ignore-lint-blocks-in-typescript",
362
+ files: ["**/*.md/**"],
363
+ languageOptions: { parserOptions: {} }
364
+ },
334
365
  {
335
366
  name: "@kazupon/markdown",
336
- files: [GLOB_MARKDOWN],
337
- rules: { ...overrideRules }
367
+ files: [`${GLOB_MARKDOWN}/${GLOB_SRC}`, ...blockExtensions.map((ext) => `${GLOB_MARKDOWN}/**/*.${ext}`)],
368
+ languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
369
+ rules: {
370
+ ...codeblocks.rules,
371
+ "import/no-unresolved": "off",
372
+ "unused-imports/no-unused-vars": "off",
373
+ "@typescript-eslint/no-unused-vars": "off",
374
+ ...overrideRules
375
+ }
338
376
  }
339
377
  ];
340
378
  }
@@ -345,7 +383,10 @@ const md = markdown;
345
383
  async function prettier(options = {}) {
346
384
  const { rules: overrideRules = {} } = options;
347
385
  const prettier$1 = await loadPlugin("eslint-config-prettier");
348
- return [prettier$1, {
386
+ return [{
387
+ name: "config-prettier",
388
+ ...prettier$1
389
+ }, {
349
390
  name: "@kazupon/prettier",
350
391
  rules: { ...overrideRules }
351
392
  }];
@@ -405,6 +446,7 @@ async function regexp(options = {}) {
405
446
  const regexp$1 = await loadPlugin("eslint-plugin-regexp");
406
447
  return [{
407
448
  name: "regexp/flat/recommended",
449
+ ignores: [GLOB_MARKDOWN],
408
450
  ...regexp$1.configs["flat/recommended"]
409
451
  }, {
410
452
  name: "@kazupon/eslint-regexp",
@@ -434,7 +476,10 @@ async function svelte(options = {}) {
434
476
  ...parserOptions
435
477
  }
436
478
  };
437
- return [...svelte$1.configs["flat/recommended"], customConfig];
479
+ return [...svelte$1.configs["flat/recommended"].map((config) => ({
480
+ ...config,
481
+ ignores: [GLOB_MARKDOWN]
482
+ })), customConfig];
438
483
  }
439
484
 
440
485
  //#endregion
@@ -444,10 +489,12 @@ async function toml(options = {}) {
444
489
  const toml$1 = await loadPlugin("eslint-plugin-toml");
445
490
  const configs = [];
446
491
  configs.push(...toml$1.configs["flat/standard"].map((config, index) => {
447
- return config.name ? config : {
448
- name: `toml/flat/standard/${index}`,
449
- ...config
492
+ const mapped = {
493
+ ...config,
494
+ ignores: [GLOB_MARKDOWN]
450
495
  };
496
+ if (!config.name) mapped.name = `toml/flat/standard/${index}`;
497
+ return mapped;
451
498
  }));
452
499
  const overriddenConfig = {
453
500
  name: "@kazupon/toml",
@@ -466,11 +513,16 @@ async function typescript(options = {}) {
466
513
  const baseFiles = [
467
514
  GLOB_TS,
468
515
  GLOB_TSX,
469
- ...extraFileExtensions.map((ext) => `**/*${ext}`)
516
+ ...extraFileExtensions.map((ext) => `**/*.${ext}`)
470
517
  ];
471
518
  const files = [...options.files ?? [], ...baseFiles];
519
+ const extendedPreset = ts.configs.recommendedTypeChecked.map((config) => {
520
+ const mapped = { ...config };
521
+ if (config.files) mapped.files = [...config.files, `${GLOB_MARKDOWN}/**/${GLOB_TS}`];
522
+ return mapped;
523
+ });
472
524
  return [
473
- ...ts.configs.recommendedTypeChecked,
525
+ ...extendedPreset,
474
526
  {
475
527
  files: [
476
528
  GLOB_JS,
@@ -479,17 +531,23 @@ async function typescript(options = {}) {
479
531
  GLOB_JSON5,
480
532
  GLOB_JSONC,
481
533
  GLOB_YAML,
482
- GLOB_TOML
534
+ GLOB_TOML,
535
+ GLOB_MARKDOWN,
536
+ `${GLOB_MARKDOWN}/**`
483
537
  ],
484
538
  ...ts.configs.disableTypeChecked
485
539
  },
540
+ {
541
+ name: "@kazupon/typescipt/typescript-eslint/overrides-for-disable-type-checked",
542
+ rules: { ...ts.configs.disableTypeChecked.rules }
543
+ },
486
544
  {
487
545
  name: "@kazupon/typescipt/typescript-eslint",
488
546
  files,
489
547
  languageOptions: {
490
548
  parser: ts.parser,
491
549
  parserOptions: {
492
- extraFileExtensions: extraFileExtensions.map((ext) => `${ext}`),
550
+ extraFileExtensions: extraFileExtensions.map((ext) => `.${ext}`),
493
551
  sourceType: "module",
494
552
  ...parserOptions
495
553
  }
@@ -560,7 +618,10 @@ async function vue(options = {}) {
560
618
  const vue$1 = await loadPlugin("eslint-plugin-vue");
561
619
  const vueParser = vue$1.configs["flat/base"][1]["languageOptions"]?.parser;
562
620
  const configs = [];
563
- configs.push(...vue$1.configs["flat/recommended"]);
621
+ configs.push(...vue$1.configs["flat/recommended"].map((config) => ({
622
+ ...config,
623
+ ignores: [GLOB_MARKDOWN]
624
+ })));
564
625
  if (options.composable) {
565
626
  const composable = await loadPlugin("eslint-plugin-vue-composable");
566
627
  const composableBase = { ...composable.configs["flat/recommended"][0] };
@@ -572,10 +633,12 @@ async function vue(options = {}) {
572
633
  const scopedCssMapped = scopedCss.configs["flat/recommended"].map(
573
634
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
574
635
  (config, index) => {
575
- return config.name ? config : {
576
- name: `vue/scoped-css/recommended/${index}`,
577
- ...config
636
+ const mapped = {
637
+ ...config,
638
+ ignores: [GLOB_MARKDOWN]
578
639
  };
640
+ if (!config.name) mapped.name = `vue/scoped-css/recommended/${index}`;
641
+ return mapped;
579
642
  }
580
643
  );
581
644
  configs.push(scopedCssMapped[0], scopedCssMapped[2]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kazupon/eslint-config",
3
3
  "description": "ESLint config for @kazupon",
4
- "version": "0.24.0",
4
+ "version": "0.25.0",
5
5
  "author": {
6
6
  "email": "kawakazu80@gmail.com",
7
7
  "name": "kazuya kawaguchi"
@@ -53,6 +53,7 @@
53
53
  "@eslint/js": "^9.22.0",
54
54
  "@kazupon/jts-utils": "^0.6.0",
55
55
  "eslint-flat-config-utils": "^2.0.1",
56
+ "eslint-merge-processors": "^2.0.0",
56
57
  "globals": "^16.0.0"
57
58
  },
58
59
  "peerDependencies": {
@@ -65,6 +66,7 @@
65
66
  "eslint-plugin-import": ">=2.31.0",
66
67
  "eslint-plugin-jsdoc": ">=48.5.0",
67
68
  "eslint-plugin-jsonc": ">=2.16.0",
69
+ "eslint-plugin-module-interop": ">=0.3.0",
68
70
  "eslint-plugin-promise": ">=6.4.0",
69
71
  "eslint-plugin-react": ">=7.35.0",
70
72
  "eslint-plugin-react-hooks": ">=5.2.0",
@@ -107,6 +109,9 @@
107
109
  "eslint-plugin-jsonc": {
108
110
  "optional": true
109
111
  },
112
+ "eslint-plugin-module-interop": {
113
+ "optional": true
114
+ },
110
115
  "eslint-plugin-promise": {
111
116
  "optional": true
112
117
  },
@@ -170,6 +175,7 @@
170
175
  "eslint-plugin-import": "^2.31.0",
171
176
  "eslint-plugin-jsdoc": "^50.6.8",
172
177
  "eslint-plugin-jsonc": "^2.19.1",
178
+ "eslint-plugin-module-interop": "^0.3.0",
173
179
  "eslint-plugin-promise": "^7.2.1",
174
180
  "eslint-plugin-react": "^7.37.4",
175
181
  "eslint-plugin-react-hooks": "^5.2.0",