@whoj/eslint-config 7.5.0 → 7.5.2

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
@@ -249,6 +249,63 @@ lspconfig.eslint.setup({
249
249
 
250
250
  </details>
251
251
 
252
+ <details>
253
+ <summary>🟧 JetBrains IDEs support</summary>
254
+
255
+ <br>
256
+
257
+ JetBrains IDEs (WebStorm, IntelliJ IDEA, etc.) support ESLint auto fix on save natively. The recommended approach is to use the CLI setup wizard, which generates the required configuration automatically.
258
+
259
+ Run the setup wizard and select the JetBrains option when prompted:
260
+
261
+ ```bash
262
+ pnpm dlx @whoj/eslint-config@latest
263
+ ```
264
+
265
+ The wizard creates `.idea/jsLinters/eslint.xml` and a companion ESLint config file under `.idea/jsLinters/`. The companion config extends your project config and overrides editor-specific rules — downgrading `prefer-const`, `unused-imports/no-unused-imports`, and `test/no-only-tests` to warnings and disabling their auto-fix so they do not silently rewrite code while you type.
266
+
267
+ Alternatively, you can create the files manually. Add the following to `.idea/jsLinters/eslint.xml`:
268
+
269
+ ```xml
270
+ <?xml version="1.0" encoding="UTF-8" ?>
271
+ <project version="4">
272
+ <component name="EslintConfiguration">
273
+ <custom-configuration-file used="true" path="$PROJECT_DIR$/.idea/jsLinters/eslint.config.js" />
274
+ </component>
275
+ </project>
276
+ ```
277
+
278
+ Then create `.idea/jsLinters/eslint.config.js`, pointing to your project config:
279
+
280
+ ```js
281
+ import whoj from '../../eslint.config.js';
282
+
283
+ export default whoj.clone().overrides({
284
+ 'whoj/javascript/rules': {
285
+ rules: {
286
+ 'prefer-const': 'warn',
287
+ 'unused-imports/no-unused-imports': 'warn',
288
+ },
289
+ },
290
+ 'whoj/test/rules': {
291
+ rules: {
292
+ 'test/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }],
293
+ 'test/no-only-tests': 'warn',
294
+ },
295
+ },
296
+ }).disableRulesFix([
297
+ 'unused-imports/no-unused-imports',
298
+ 'test/no-only-tests',
299
+ 'prefer-const',
300
+ ], {
301
+ builtinRules: () => import(['eslint', 'use-at-your-own-risk'].join('/')).then(r => r.builtinRules),
302
+ });
303
+ ```
304
+
305
+ Then enable **ESLint** in **Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint**, select **Manual ESLint configuration**, and point the configuration file to `.idea/jsLinters/eslint.xml`. Enable **Run eslint --fix on save** to activate auto fix on save.
306
+
307
+ </details>
308
+
252
309
  ## Customization
253
310
 
254
311
  Since v1.0, we migrated to [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new). It provides much better organization and composition.
package/dist/cli.mjs CHANGED
@@ -217,7 +217,7 @@ const jetbrainsSettingsObj = {
217
217
 
218
218
  //#endregion
219
219
  //#region package.json
220
- var version = "7.5.0";
220
+ var version = "7.5.2";
221
221
 
222
222
  //#endregion
223
223
  //#region src/cli/constants-generated.ts
@@ -226,7 +226,7 @@ const versionsMap = {
226
226
  "@next/eslint-plugin-next": "^16.1.6",
227
227
  "@unocss/eslint-plugin": "^66.6.0",
228
228
  "astro-eslint-parser": "^1.2.2",
229
- "eslint": "^9.39.2",
229
+ "eslint": "^9.39.2||^10.0.0",
230
230
  "eslint-plugin-astro": "^1.5.0",
231
231
  "eslint-plugin-format": "^1.4.0",
232
232
  "eslint-plugin-react-hooks": "^7.0.1",
package/dist/index.d.mts CHANGED
@@ -930,6 +930,7 @@ interface RuleOptions {
930
930
  /**
931
931
  * disallow unused `eslint-disable` comments
932
932
  * @see https://eslint-community.github.io/eslint-plugin-eslint-comments/rules/no-unused-disable.html
933
+ * @deprecated
933
934
  */
934
935
  'eslint-comments/no-unused-disable'?: Linter.RuleEntry<[]>;
935
936
  /**
@@ -956,6 +957,10 @@ interface RuleOptions {
956
957
  * Use dprint to format code
957
958
  */
958
959
  'format/dprint'?: Linter.RuleEntry<FormatDprint>;
960
+ /**
961
+ * Use oxfmt to format code
962
+ */
963
+ 'format/oxfmt'?: Linter.RuleEntry<FormatOxfmt>;
959
964
  /**
960
965
  * Use Prettier to format code
961
966
  */
@@ -3215,6 +3220,11 @@ interface RuleOptions {
3215
3220
  * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/console.md
3216
3221
  */
3217
3222
  'node/prefer-global/console'?: Linter.RuleEntry<NodePreferGlobalConsole>;
3223
+ /**
3224
+ * enforce either `crypto` or `require("crypto").webcrypto`
3225
+ * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/crypto.md
3226
+ */
3227
+ 'node/prefer-global/crypto'?: Linter.RuleEntry<NodePreferGlobalCrypto>;
3218
3228
  /**
3219
3229
  * enforce either `process` or `require("process")`
3220
3230
  * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/process.md
@@ -3230,6 +3240,11 @@ interface RuleOptions {
3230
3240
  * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/text-encoder.md
3231
3241
  */
3232
3242
  'node/prefer-global/text-encoder'?: Linter.RuleEntry<NodePreferGlobalTextEncoder>;
3243
+ /**
3244
+ * enforce either global timer functions or `require("timers")`
3245
+ * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/timers.md
3246
+ */
3247
+ 'node/prefer-global/timers'?: Linter.RuleEntry<NodePreferGlobalTimers>;
3233
3248
  /**
3234
3249
  * enforce either `URL` or `require("url").URL`
3235
3250
  * @see https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/prefer-global/url.md
@@ -3563,7 +3578,7 @@ interface RuleOptions {
3563
3578
  */
3564
3579
  'quotes'?: Linter.RuleEntry<Quotes>;
3565
3580
  /**
3566
- * Enforce the consistent use of the radix argument when using `parseInt()`
3581
+ * Enforce the use of the radix argument when using `parseInt()`
3567
3582
  * @see https://eslint.org/docs/latest/rules/radix
3568
3583
  */
3569
3584
  'radix'?: Linter.RuleEntry<Radix>;
@@ -3800,6 +3815,11 @@ interface RuleOptions {
3800
3815
  * @see https://eslint-react.xyz/docs/rules/naming-convention-filename-extension
3801
3816
  */
3802
3817
  'react-naming-convention/filename-extension'?: Linter.RuleEntry<ReactNamingConventionFilenameExtension>;
3818
+ /**
3819
+ * Enforces identifier names assigned from 'useId' calls to be either 'id' or end with 'Id'.
3820
+ * @see https://eslint-react.xyz/docs/rules/naming-convention-id-name
3821
+ */
3822
+ 'react-naming-convention/id-name'?: Linter.RuleEntry<[]>;
3803
3823
  /**
3804
3824
  * Enforces identifier names assigned from 'useRef' calls to be either 'ref' or end with 'Ref'.
3805
3825
  * @see https://eslint-react.xyz/docs/rules/naming-convention-ref-name
@@ -3837,7 +3857,7 @@ interface RuleOptions {
3837
3857
  */
3838
3858
  'react-web-api/no-leaked-timeout'?: Linter.RuleEntry<[]>;
3839
3859
  /**
3840
- * Prevents unnecessary '$' symbols before JSX expressions.
3860
+ * Prevents unintentional '$' sign before expression.
3841
3861
  * @see https://eslint-react.xyz/docs/rules/jsx-dollar
3842
3862
  */
3843
3863
  'react/jsx-dollar'?: Linter.RuleEntry<[]>;
@@ -6114,11 +6134,21 @@ interface RuleOptions {
6114
6134
  * @see https://ota-meshi.github.io/eslint-plugin-toml/rules/indent.html
6115
6135
  */
6116
6136
  'toml/indent'?: Linter.RuleEntry<TomlIndent>;
6137
+ /**
6138
+ * enforce linebreaks after opening and before closing braces
6139
+ * @see https://ota-meshi.github.io/eslint-plugin-toml/rules/inline-table-curly-newline.html
6140
+ */
6141
+ 'toml/inline-table-curly-newline'?: Linter.RuleEntry<TomlInlineTableCurlyNewline>;
6117
6142
  /**
6118
6143
  * enforce consistent spacing inside braces
6119
6144
  * @see https://ota-meshi.github.io/eslint-plugin-toml/rules/inline-table-curly-spacing.html
6120
6145
  */
6121
6146
  'toml/inline-table-curly-spacing'?: Linter.RuleEntry<TomlInlineTableCurlySpacing>;
6147
+ /**
6148
+ * enforce placing inline table key-value pairs on separate lines
6149
+ * @see https://ota-meshi.github.io/eslint-plugin-toml/rules/inline-table-key-value-newline.html
6150
+ */
6151
+ 'toml/inline-table-key-value-newline'?: Linter.RuleEntry<TomlInlineTableKeyValueNewline>;
6122
6152
  /**
6123
6153
  * enforce consistent spacing between keys and values in key/value pairs
6124
6154
  * @see https://ota-meshi.github.io/eslint-plugin-toml/rules/key-spacing.html
@@ -8946,7 +8976,7 @@ interface RuleOptions {
8946
8976
  * enforce valid `v-for` directives
8947
8977
  * @see https://eslint.vuejs.org/rules/valid-v-for.html
8948
8978
  */
8949
- 'vue/valid-v-for'?: Linter.RuleEntry<[]>;
8979
+ 'vue/valid-v-for'?: Linter.RuleEntry<VueValidVFor>;
8950
8980
  /**
8951
8981
  * enforce valid `v-html` directives
8952
8982
  * @see https://eslint.vuejs.org/rules/valid-v-html.html
@@ -9782,6 +9812,10 @@ type FormatDprint = [] | [{
9782
9812
  plugins?: unknown[];
9783
9813
  [k: string]: unknown | undefined;
9784
9814
  }];
9815
+ // ----- format/oxfmt -----
9816
+ type FormatOxfmt = [] | [{
9817
+ [k: string]: unknown | undefined;
9818
+ }];
9785
9819
  // ----- format/prettier -----
9786
9820
  type FormatPrettier = [] | [{
9787
9821
  parser: string;
@@ -10436,6 +10470,7 @@ type JsdocTagLines = [] | [("always" | "any" | "never")] | [("always" | "any" |
10436
10470
  endLines?: (number | null);
10437
10471
  maxBlockLines?: (number | null);
10438
10472
  startLines?: (number | null);
10473
+ startLinesWithNoTags?: number;
10439
10474
  tags?: {
10440
10475
  [k: string]: {
10441
10476
  count?: number;
@@ -11511,6 +11546,7 @@ type MaxParams = [] | [(number | {
11511
11546
  maximum?: number;
11512
11547
  max?: number;
11513
11548
  countVoidThis?: boolean;
11549
+ countThis?: ("never" | "except-void" | "always");
11514
11550
  })];
11515
11551
  // ----- max-statements -----
11516
11552
  type MaxStatements = [] | [(number | {
@@ -12169,12 +12205,16 @@ type NodeNoUnsupportedFeaturesNodeBuiltins = [] | [{
12169
12205
  type NodePreferGlobalBuffer = [] | [("always" | "never")];
12170
12206
  // ----- node/prefer-global/console -----
12171
12207
  type NodePreferGlobalConsole = [] | [("always" | "never")];
12208
+ // ----- node/prefer-global/crypto -----
12209
+ type NodePreferGlobalCrypto = [] | [("always" | "never")];
12172
12210
  // ----- node/prefer-global/process -----
12173
12211
  type NodePreferGlobalProcess = [] | [("always" | "never")];
12174
12212
  // ----- node/prefer-global/text-decoder -----
12175
12213
  type NodePreferGlobalTextDecoder = [] | [("always" | "never")];
12176
12214
  // ----- node/prefer-global/text-encoder -----
12177
12215
  type NodePreferGlobalTextEncoder = [] | [("always" | "never")];
12216
+ // ----- node/prefer-global/timers -----
12217
+ type NodePreferGlobalTimers = [] | [("always" | "never")];
12178
12218
  // ----- node/prefer-global/url -----
12179
12219
  type NodePreferGlobalUrl = [] | [("always" | "never")];
12180
12220
  // ----- node/prefer-global/url-search-params -----
@@ -16382,13 +16422,17 @@ type StylePaddedBlocks = [] | [(("always" | "never" | "start" | "end") | {
16382
16422
  }];
16383
16423
  // ----- style/padding-line-between-statements -----
16384
16424
  type _StylePaddingLineBetweenStatementsPaddingType = ("any" | "never" | "always");
16385
- type _StylePaddingLineBetweenStatementsStatementOption = (_StylePaddingLineBetweenStatementsStatementType | [_StylePaddingLineBetweenStatementsStatementType, ...(_StylePaddingLineBetweenStatementsStatementType)[]]);
16425
+ type _StylePaddingLineBetweenStatementsStatementOption = (_StylePaddingLineBetweenStatementsStatementMatcher | [_StylePaddingLineBetweenStatementsStatementMatcher, ...(_StylePaddingLineBetweenStatementsStatementMatcher)[]]);
16426
+ type _StylePaddingLineBetweenStatementsStatementMatcher = (_StylePaddingLineBetweenStatementsStatementType | _StylePaddingLineBetweenStatements_SelectorOption);
16386
16427
  type _StylePaddingLineBetweenStatementsStatementType = ("*" | "exports" | "require" | "directive" | "iife" | "block" | "empty" | "function" | "ts-method" | "break" | "case" | "class" | "continue" | "debugger" | "default" | "do" | "for" | "if" | "import" | "switch" | "throw" | "try" | "while" | "with" | "cjs-export" | "cjs-import" | "enum" | "interface" | "function-overload" | "block-like" | "singleline-block-like" | "multiline-block-like" | "expression" | "singleline-expression" | "multiline-expression" | "return" | "singleline-return" | "multiline-return" | "export" | "singleline-export" | "multiline-export" | "var" | "singleline-var" | "multiline-var" | "let" | "singleline-let" | "multiline-let" | "const" | "singleline-const" | "multiline-const" | "using" | "singleline-using" | "multiline-using" | "type" | "singleline-type" | "multiline-type");
16387
16428
  type StylePaddingLineBetweenStatements = {
16388
16429
  blankLine: _StylePaddingLineBetweenStatementsPaddingType;
16389
16430
  prev: _StylePaddingLineBetweenStatementsStatementOption;
16390
16431
  next: _StylePaddingLineBetweenStatementsStatementOption;
16391
16432
  }[];
16433
+ interface _StylePaddingLineBetweenStatements_SelectorOption {
16434
+ selector: string;
16435
+ }
16392
16436
  // ----- style/quote-props -----
16393
16437
  type StyleQuoteProps = ([] | [("always" | "as-needed" | "consistent" | "consistent-as-needed")] | [] | [("always" | "as-needed" | "consistent" | "consistent-as-needed")] | [("always" | "as-needed" | "consistent" | "consistent-as-needed"), {
16394
16438
  keywords?: boolean;
@@ -16856,10 +16900,21 @@ type TomlIndent = [] | [("tab" | number)] | [("tab" | number), {
16856
16900
  subTables?: number;
16857
16901
  keyValuePairs?: number;
16858
16902
  }];
16903
+ // ----- toml/inline-table-curly-newline -----
16904
+ type TomlInlineTableCurlyNewline = [] | [(("always" | "never") | {
16905
+ multiline?: boolean;
16906
+ minProperties?: number;
16907
+ consistent?: boolean;
16908
+ })];
16859
16909
  // ----- toml/inline-table-curly-spacing -----
16860
16910
  type TomlInlineTableCurlySpacing = [] | [("always" | "never")] | [("always" | "never"), {
16861
16911
  arraysInObjects?: boolean;
16862
16912
  objectsInObjects?: boolean;
16913
+ emptyObjects?: ("ignore" | "always" | "never");
16914
+ }];
16915
+ // ----- toml/inline-table-key-value-newline -----
16916
+ type TomlInlineTableKeyValueNewline = [] | [{
16917
+ allowAllPropertiesOnSameLine?: boolean;
16863
16918
  }];
16864
16919
  // ----- toml/key-spacing -----
16865
16920
  type TomlKeySpacing = [] | [({
@@ -18304,6 +18359,7 @@ type VueAttributesOrder = [] | [{
18304
18359
  order?: (("DEFINITION" | "LIST_RENDERING" | "CONDITIONALS" | "RENDER_MODIFIERS" | "GLOBAL" | "UNIQUE" | "SLOT" | "TWO_WAY_BINDING" | "OTHER_DIRECTIVES" | "OTHER_ATTR" | "ATTR_STATIC" | "ATTR_DYNAMIC" | "ATTR_SHORTHAND_BOOL" | "EVENTS" | "CONTENT") | ("DEFINITION" | "LIST_RENDERING" | "CONDITIONALS" | "RENDER_MODIFIERS" | "GLOBAL" | "UNIQUE" | "SLOT" | "TWO_WAY_BINDING" | "OTHER_DIRECTIVES" | "OTHER_ATTR" | "ATTR_STATIC" | "ATTR_DYNAMIC" | "ATTR_SHORTHAND_BOOL" | "EVENTS" | "CONTENT")[])[];
18305
18360
  alphabetical?: boolean;
18306
18361
  sortLineLength?: boolean;
18362
+ ignoreVBindObject?: boolean;
18307
18363
  }];
18308
18364
  // ----- vue/block-lang -----
18309
18365
  type VueBlockLang = [] | [{
@@ -18395,7 +18451,7 @@ type VueDefineMacrosOrder = [] | [{
18395
18451
  type VueDefinePropsDeclaration = [] | [("type-based" | "runtime")];
18396
18452
  // ----- vue/define-props-destructuring -----
18397
18453
  type VueDefinePropsDestructuring = [] | [{
18398
- destructure?: ("always" | "never");
18454
+ destructure?: ("only-when-assigned" | "always" | "never");
18399
18455
  }];
18400
18456
  // ----- vue/dot-location -----
18401
18457
  type VueDotLocation = [] | [("object" | "property")];
@@ -19448,6 +19504,10 @@ type VueVSlotStyle = [] | [(("shorthand" | "longform") | {
19448
19504
  default?: ("shorthand" | "longform" | "v-slot");
19449
19505
  named?: ("shorthand" | "longform");
19450
19506
  })];
19507
+ // ----- vue/valid-v-for -----
19508
+ type VueValidVFor = [] | [{
19509
+ allowEmptyAlias?: boolean;
19510
+ }];
19451
19511
  // ----- vue/valid-v-on -----
19452
19512
  type VueValidVOn = [] | [{
19453
19513
  modifiers?: unknown[];
@@ -19527,6 +19587,7 @@ type YamlFlowMappingCurlyNewline = [] | [(("always" | "never") | {
19527
19587
  type YamlFlowMappingCurlySpacing = [] | [("always" | "never")] | [("always" | "never"), {
19528
19588
  arraysInObjects?: boolean;
19529
19589
  objectsInObjects?: boolean;
19590
+ emptyObjects?: ("ignore" | "always" | "never");
19530
19591
  }];
19531
19592
  // ----- yaml/flow-sequence-bracket-newline -----
19532
19593
  type YamlFlowSequenceBracketNewline = [] | [(("always" | "never" | "consistent") | {
package/dist/index.mjs CHANGED
@@ -2363,7 +2363,7 @@ async function typescript(options = {}) {
2363
2363
  }] : [],
2364
2364
  ...erasableOnly ? [{
2365
2365
  name: "whoj/typescript/erasable-syntax-only",
2366
- plugins: { "erasable-syntax-only": await interopDefault(import("./lib-DRA-mDV0.mjs")) },
2366
+ plugins: { "erasable-syntax-only": await interopDefault(import("./lib-B1Rme4qD.mjs")) },
2367
2367
  rules: {
2368
2368
  "erasable-syntax-only/enums": "error",
2369
2369
  "erasable-syntax-only/namespaces": "error",