ultracite 7.8.4 → 7.9.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.
Files changed (33) hide show
  1. package/README.md +2 -3
  2. package/config/biome/core/biome.jsonc +65 -4
  3. package/config/biome/next/biome.jsonc +3 -1
  4. package/config/biome/react/biome.jsonc +1 -0
  5. package/config/biome/vue/biome.jsonc +22 -2
  6. package/config/eslint/astro/rules/astro.mjs +4 -1
  7. package/config/eslint/core/eslint.config.mjs +22 -2
  8. package/config/eslint/core/rules/eslint-typescript.mjs +0 -2
  9. package/config/eslint/core/rules/eslint.mjs +15 -1
  10. package/config/eslint/core/rules/github.mjs +7 -0
  11. package/config/eslint/core/rules/import.mjs +10 -1
  12. package/config/eslint/core/rules/jsdoc.mjs +31 -0
  13. package/config/eslint/core/rules/n.mjs +5 -0
  14. package/config/eslint/core/rules/promise.mjs +6 -1
  15. package/config/eslint/core/rules/sonarjs.mjs +24 -0
  16. package/config/eslint/core/rules/typescript.mjs +12 -1
  17. package/config/eslint/core/rules/unicorn.mjs +21 -5
  18. package/config/eslint/next/eslint.config.mjs +4 -0
  19. package/config/eslint/next/rules/react-doctor.mjs +27 -0
  20. package/config/eslint/react/eslint.config.mjs +20 -1
  21. package/config/eslint/react/rules/react-doctor.mjs +153 -0
  22. package/config/eslint/react/rules/react.mjs +7 -6
  23. package/config/eslint/svelte/rules/svelte.mjs +9 -2
  24. package/config/eslint/tanstack/eslint.config.mjs +4 -0
  25. package/config/eslint/tanstack/rules/react-doctor.mjs +25 -0
  26. package/config/eslint/vue/eslint.config.mjs +9 -0
  27. package/config/oxlint/core/index.mjs +251 -3
  28. package/config/oxlint/next/index.mjs +53 -1
  29. package/config/oxlint/react/index.mjs +245 -2
  30. package/config/oxlint/tanstack/index.mjs +26 -1
  31. package/config/oxlint/vue/index.mjs +3 -0
  32. package/dist/index.js +64 -100
  33. package/package.json +25 -21
@@ -16,13 +16,21 @@ export default defineConfig({
16
16
  "**/__tests__/**/*.{ts,tsx,js,jsx}",
17
17
  ],
18
18
  rules: {
19
- // Disabled: mock callbacks often need empty functions
20
19
  "no-empty-function": "off",
21
- // Disabled: mock factories use Promise.resolve/reject (conflicts with require-await)
20
+ // Repeated string literals (test titles, expected values) are normal
21
+ // and idiomatic in test files.
22
+ "sonarjs/no-duplicate-string": "off",
22
23
  "promise/prefer-await-to-then": "off",
23
24
  },
24
25
  },
25
26
  ],
27
+ // eslint-plugin-github and eslint-plugin-sonarjs run through oxlint's JS
28
+ // plugin support to close the gap with the ESLint preset. Rules that require
29
+ // type information are not supported by the JS plugin bridge and are excluded.
30
+ jsPlugins: [
31
+ { name: "github", specifier: "eslint-plugin-github" },
32
+ { name: "sonarjs", specifier: "eslint-plugin-sonarjs" },
33
+ ],
26
34
  plugins: [
27
35
  "eslint",
28
36
  "typescript",
@@ -58,6 +66,7 @@ export default defineConfig({
58
66
  allowArrowFunctions: true,
59
67
  },
60
68
  ],
69
+ "getter-return": "error",
61
70
  "grouped-accessor-pairs": "error",
62
71
  "guard-for-in": "error",
63
72
  "id-length": "off",
@@ -150,7 +159,6 @@ export default defineConfig({
150
159
  "no-regex-spaces": "error",
151
160
  "no-restricted-globals": "error",
152
161
  "no-restricted-imports": "error",
153
- // Disabled: requires project-specific configuration to be useful
154
162
  "no-restricted-properties": "off",
155
163
  "no-return-assign": "error",
156
164
  "no-script-url": "error",
@@ -171,6 +179,7 @@ export default defineConfig({
171
179
  "no-unexpected-multiline": "error",
172
180
  "no-unmodified-loop-condition": "error",
173
181
  "no-unneeded-ternary": "error",
182
+ "no-unreachable": "error",
174
183
  "no-unsafe-finally": "error",
175
184
  "no-unsafe-negation": "error",
176
185
  "no-unsafe-optional-chaining": "error",
@@ -224,6 +233,36 @@ export default defineConfig({
224
233
  "vars-on-top": "error",
225
234
  yoda: "error",
226
235
 
236
+ // ── github ─────────────────────────────────────────────────────────
237
+ "github/a11y-aria-label-is-well-formatted": "error",
238
+ "github/a11y-no-title-attribute": "error",
239
+ "github/a11y-no-visually-hidden-interactive-element": "error",
240
+ "github/a11y-role-supports-aria-props": "error",
241
+ "github/a11y-svg-has-accessible-name": "error",
242
+ "github/array-foreach": "error",
243
+ "github/async-currenttarget": "error",
244
+ "github/async-preventdefault": "error",
245
+ "github/authenticity-token": "error",
246
+ "github/filenames-match-regex": "error",
247
+ "github/get-attribute": "error",
248
+ "github/js-class-name": "error",
249
+ "github/no-blur": "error",
250
+ "github/no-d-none": "error",
251
+ // Conflicts with unicorn/prefer-dom-node-dataset, which is the benchmark.
252
+ "github/no-dataset": "off",
253
+ "github/no-dynamic-script-tag": "error",
254
+ // The JS plugin bridge misreads module-scoped declarations (e.g. Astro
255
+ // frontmatter) as implicit globals, producing false positives.
256
+ "github/no-implicit-buggy-globals": "off",
257
+ "github/no-inner-html": "error",
258
+ "github/no-innerText": "error",
259
+ "github/no-then": "error",
260
+ "github/no-useless-passive": "error",
261
+ "github/prefer-observers": "error",
262
+ "github/require-passive-events": "error",
263
+ // Mirrors the ESLint preset.
264
+ "github/unescaped-html-literal": "off",
265
+
227
266
  // ── import ─────────────────────────────────────────────────────────
228
267
  "import/consistent-type-specifier-style": ["error", "prefer-top-level"],
229
268
  "import/default": "error",
@@ -286,9 +325,11 @@ export default defineConfig({
286
325
  "node/global-require": "error",
287
326
  "node/handle-callback-err": "error",
288
327
  "node/no-exports-assign": "error",
328
+ "node/no-mixed-requires": "error",
289
329
  "node/no-new-require": "error",
290
330
  "node/no-path-concat": "error",
291
331
  "node/no-process-env": "off",
332
+ "node/no-sync": "off",
292
333
 
293
334
  // ── oxc ────────────────────────────────────────────────────────────
294
335
  "oxc/approx-constant": "error",
@@ -299,6 +340,7 @@ export default defineConfig({
299
340
  "oxc/bad-min-max-func": "error",
300
341
  "oxc/bad-object-literal-comparison": "error",
301
342
  "oxc/bad-replace-all-arg": "error",
343
+ "oxc/branches-sharing-code": "error",
302
344
  "oxc/const-comparisons": "error",
303
345
  "oxc/double-comparisons": "error",
304
346
  "oxc/erasing-op": "error",
@@ -334,6 +376,207 @@ export default defineConfig({
334
376
  "promise/spec-only": "error",
335
377
  "promise/valid-params": "error",
336
378
 
379
+ // ── sonarjs ────────────────────────────────────────────────────────
380
+ // These sonarjs rules exist in eslint-plugin-sonarjs but oxlint's JS
381
+ // plugin bridge does not register them, so listing them fails config
382
+ // parsing. They are intentionally omitted here (still enabled in the
383
+ // ESLint preset): async-test-assertions, hooks-before-test-cases,
384
+ // no-duplicate-test-title, no-empty-test-title, no-floating-point-equality,
385
+ // no-forced-browser-interaction, no-trivial-assertions,
386
+ // prefer-specific-assertions, super-linear-regex.
387
+ "sonarjs/arguments-usage": "error",
388
+ "sonarjs/array-constructor": "error",
389
+ // Fights the formatter (arrowParentheses: always).
390
+ "sonarjs/arrow-function-convention": "off",
391
+ "sonarjs/aws-apigateway-public-api": "error",
392
+ "sonarjs/aws-ec2-rds-dms-public": "error",
393
+ "sonarjs/aws-ec2-unencrypted-ebs-volume": "error",
394
+ "sonarjs/aws-efs-unencrypted": "error",
395
+ "sonarjs/aws-iam-all-privileges": "error",
396
+ "sonarjs/aws-iam-all-resources-accessible": "error",
397
+ "sonarjs/aws-iam-privilege-escalation": "error",
398
+ "sonarjs/aws-iam-public-access": "error",
399
+ "sonarjs/aws-opensearchservice-domain": "error",
400
+ "sonarjs/aws-rds-unencrypted-databases": "error",
401
+ "sonarjs/aws-restricted-ip-admin-access": "error",
402
+ "sonarjs/aws-s3-bucket-granted-access": "error",
403
+ "sonarjs/aws-s3-bucket-insecure-http": "error",
404
+ "sonarjs/aws-s3-bucket-public-access": "error",
405
+ "sonarjs/aws-s3-bucket-versioning": "error",
406
+ "sonarjs/aws-sagemaker-unencrypted-notebook": "error",
407
+ "sonarjs/aws-sns-unencrypted-topics": "error",
408
+ "sonarjs/aws-sqs-unencrypted-queue": "error",
409
+ "sonarjs/block-scoped-var": "error",
410
+ "sonarjs/bool-param-default": "error",
411
+ "sonarjs/call-argument-line": "error",
412
+ "sonarjs/chai-determinate-assertion": "error",
413
+ "sonarjs/class-name": "error",
414
+ "sonarjs/code-eval": "error",
415
+ // Matches Biome's noExcessiveCognitiveComplexity limit.
416
+ "sonarjs/cognitive-complexity": ["error", 20],
417
+ "sonarjs/comma-or-logical-or-case": "error",
418
+ "sonarjs/comment-regex": "error",
419
+ "sonarjs/constructor-for-side-effects": "error",
420
+ "sonarjs/content-length": "error",
421
+ "sonarjs/content-security-policy": "error",
422
+ "sonarjs/cookie-no-httponly": "error",
423
+ "sonarjs/cors": "error",
424
+ "sonarjs/csrf": "error",
425
+ // Duplicate of the core complexity rule.
426
+ "sonarjs/cyclomatic-complexity": "off",
427
+ "sonarjs/declarations-in-global-scope": "error",
428
+ "sonarjs/destructuring-assignment-syntax": "error",
429
+ "sonarjs/disabled-timeout": "error",
430
+ "sonarjs/dynamically-constructed-templates": "error",
431
+ // Mirrors the ESLint preset.
432
+ "sonarjs/elseif-without-else": "off",
433
+ "sonarjs/encryption-secure-mode": "error",
434
+ "sonarjs/expression-complexity": "error",
435
+ // Requires a headerFormat option; errors on every file without one.
436
+ "sonarjs/file-header": "off",
437
+ // Fires on any file whose name differs from an exported class, which is
438
+ // noise for config and module files that export objects, not classes.
439
+ "sonarjs/file-name-differ-from-class": "off",
440
+ "sonarjs/file-permissions": "error",
441
+ "sonarjs/file-uploads": "error",
442
+ "sonarjs/fixme-tag": "error",
443
+ "sonarjs/for-in": "error",
444
+ "sonarjs/for-loop-increment-sign": "error",
445
+ "sonarjs/function-inside-loop": "error",
446
+ "sonarjs/function-name": "error",
447
+ "sonarjs/future-reserved-words": "error",
448
+ "sonarjs/generator-without-yield": "error",
449
+ "sonarjs/hardcoded-secret-signatures": "error",
450
+ "sonarjs/hashing": "error",
451
+ "sonarjs/inconsistent-function-call": "error",
452
+ "sonarjs/insecure-cookie": "error",
453
+ "sonarjs/insecure-jwt-token": "error",
454
+ "sonarjs/inverted-assertion-arguments": "error",
455
+ "sonarjs/label-position": "error",
456
+ "sonarjs/link-with-target-blank": "error",
457
+ // The preset disables max-lines everywhere.
458
+ "sonarjs/max-lines": "off",
459
+ // The preset disables max-lines-per-function everywhere.
460
+ "sonarjs/max-lines-per-function": "off",
461
+ "sonarjs/max-switch-cases": "error",
462
+ "sonarjs/max-union-size": "error",
463
+ "sonarjs/misplaced-loop-counter": "error",
464
+ // Duplicate of max-depth, which is off.
465
+ "sonarjs/nested-control-flow": "off",
466
+ "sonarjs/no-all-duplicated-branches": "error",
467
+ "sonarjs/no-angular-bypass-sanitization": "error",
468
+ "sonarjs/no-built-in-override": "error",
469
+ "sonarjs/no-case-label-in-switch": "error",
470
+ "sonarjs/no-clear-text-protocols": "error",
471
+ "sonarjs/no-code-after-done": "error",
472
+ "sonarjs/no-collapsible-if": "error",
473
+ "sonarjs/no-commented-code": "error",
474
+ "sonarjs/no-dead-store": "error",
475
+ "sonarjs/no-delete-var": "error",
476
+ "sonarjs/no-duplicate-in-composite": "error",
477
+ "sonarjs/no-duplicate-string": "error",
478
+ "sonarjs/no-duplicated-branches": "error",
479
+ "sonarjs/no-element-overwrite": "error",
480
+ "sonarjs/no-empty-collection": "error",
481
+ "sonarjs/no-empty-test-file": "error",
482
+ "sonarjs/no-equals-in-for-termination": "error",
483
+ "sonarjs/no-exclusive-tests": "error",
484
+ "sonarjs/no-extra-arguments": "error",
485
+ "sonarjs/no-fallthrough": "error",
486
+ "sonarjs/no-function-declaration-in-block": "error",
487
+ "sonarjs/no-global-this": "error",
488
+ "sonarjs/no-globals-shadowing": "error",
489
+ "sonarjs/no-gratuitous-expressions": "error",
490
+ "sonarjs/no-hardcoded-ip": "error",
491
+ "sonarjs/no-hardcoded-passwords": "error",
492
+ "sonarjs/no-hardcoded-secrets": "error",
493
+ "sonarjs/no-hook-setter-in-body": "error",
494
+ "sonarjs/no-identical-conditions": "error",
495
+ "sonarjs/no-identical-expressions": "error",
496
+ "sonarjs/no-identical-functions": "error",
497
+ "sonarjs/no-ignored-exceptions": "error",
498
+ // The JS plugin bridge has no dependency-manifest resolution, so this
499
+ // flags builtin (bun:test) and workspace imports as missing dependencies.
500
+ "sonarjs/no-implicit-dependencies": "off",
501
+ "sonarjs/no-implicit-global": "error",
502
+ "sonarjs/no-incomplete-assertions": "error",
503
+ "sonarjs/no-internal-api-use": "error",
504
+ "sonarjs/no-invariant-returns": "error",
505
+ "sonarjs/no-inverted-boolean-check": "error",
506
+ "sonarjs/no-labels": "error",
507
+ "sonarjs/no-literal-call": "error",
508
+ "sonarjs/no-mime-sniff": "error",
509
+ "sonarjs/no-nested-assignment": "error",
510
+ "sonarjs/no-nested-conditional": "error",
511
+ "sonarjs/no-nested-functions": "error",
512
+ "sonarjs/no-nested-incdec": "error",
513
+ "sonarjs/no-nested-switch": "error",
514
+ "sonarjs/no-nested-template-literals": "error",
515
+ "sonarjs/no-os-command-from-path": "error",
516
+ "sonarjs/no-parameter-reassignment": "error",
517
+ "sonarjs/no-primitive-wrappers": "error",
518
+ "sonarjs/no-redundant-assignments": "error",
519
+ "sonarjs/no-redundant-boolean": "error",
520
+ "sonarjs/no-redundant-jump": "error",
521
+ // The jsPlugins bridge provides no globals, so every identifier is flagged.
522
+ "sonarjs/no-reference-error": "off",
523
+ "sonarjs/no-referrer-policy": "error",
524
+ "sonarjs/no-same-argument-assert": "error",
525
+ "sonarjs/no-same-line-conditional": "error",
526
+ "sonarjs/no-session-cookies-on-static-assets": "error",
527
+ "sonarjs/no-skipped-tests": "error",
528
+ "sonarjs/no-sonar-comments": "error",
529
+ "sonarjs/no-table-as-layout": "error",
530
+ "sonarjs/no-undefined-assignment": "error",
531
+ "sonarjs/no-unenclosed-multiline-block": "error",
532
+ "sonarjs/no-uniq-key": "error",
533
+ "sonarjs/no-unthrown-error": "error",
534
+ "sonarjs/no-unused-collection": "error",
535
+ "sonarjs/no-unused-function-argument": "error",
536
+ "sonarjs/no-unused-vars": "error",
537
+ "sonarjs/no-use-of-empty-return-value": "error",
538
+ "sonarjs/no-useless-catch": "error",
539
+ "sonarjs/no-useless-increment": "error",
540
+ "sonarjs/no-useless-react-setstate": "error",
541
+ "sonarjs/no-variable-usage-before-declaration": "error",
542
+ "sonarjs/no-weak-cipher": "error",
543
+ "sonarjs/no-weak-keys": "error",
544
+ "sonarjs/no-wildcard-import": "error",
545
+ "sonarjs/non-existent-operator": "error",
546
+ "sonarjs/object-alt-content": "error",
547
+ "sonarjs/prefer-default-last": "error",
548
+ "sonarjs/prefer-object-literal": "error",
549
+ "sonarjs/prefer-promise-shorthand": "error",
550
+ "sonarjs/prefer-single-boolean-return": "error",
551
+ "sonarjs/prefer-type-guard": "error",
552
+ "sonarjs/prefer-while": "error",
553
+ "sonarjs/production-debug": "error",
554
+ "sonarjs/pseudo-random": "error",
555
+ "sonarjs/public-static-readonly": "error",
556
+ "sonarjs/publicly-writable-directories": "error",
557
+ "sonarjs/redundant-type-aliases": "error",
558
+ "sonarjs/review-blockchain-mnemonic": "error",
559
+ "sonarjs/session-regeneration": "error",
560
+ // Conflicts with sort-keys.
561
+ "sonarjs/shorthand-property-grouping": "off",
562
+ "sonarjs/stable-tests": "error",
563
+ "sonarjs/stateful-regex": "error",
564
+ "sonarjs/strict-transport-security": "error",
565
+ "sonarjs/table-header": "error",
566
+ "sonarjs/table-header-reference": "error",
567
+ "sonarjs/test-check-exception": "error",
568
+ "sonarjs/todo-tag": "error",
569
+ "sonarjs/too-many-break-or-continue-in-loop": "error",
570
+ "sonarjs/unverified-certificate": "error",
571
+ "sonarjs/unverified-hostname": "error",
572
+ "sonarjs/updated-const-var": "error",
573
+ "sonarjs/updated-loop-counter": "error",
574
+ "sonarjs/use-type-alias": "error",
575
+ "sonarjs/variable-name": "error",
576
+ "sonarjs/weak-ssl": "error",
577
+ "sonarjs/x-powered-by": "error",
578
+ "sonarjs/xml-parser-xxe": "error",
579
+
337
580
  // ── typescript ─────────────────────────────────────────────────────
338
581
  "typescript/adjacent-overload-signatures": "error",
339
582
  "typescript/array-type": "error",
@@ -459,11 +702,13 @@ export default defineConfig({
459
702
  "unicorn/explicit-length-check": "off",
460
703
  "unicorn/filename-case": "error",
461
704
  "unicorn/import-style": "error",
705
+ "unicorn/max-nested-calls": "off",
462
706
  "unicorn/new-for-builtins": "error",
463
707
  "unicorn/no-abusive-eslint-disable": "error",
464
708
  "unicorn/no-accessor-recursion": "error",
465
709
  "unicorn/no-anonymous-default-export": "error",
466
710
  "unicorn/no-array-callback-reference": "off",
711
+ "unicorn/no-array-fill-with-reference-type": "error",
467
712
  "unicorn/no-array-for-each": "error",
468
713
  "unicorn/no-array-method-this-argument": "error",
469
714
  "unicorn/no-array-reduce": "error",
@@ -533,6 +778,7 @@ export default defineConfig({
533
778
  "unicorn/prefer-dom-node-remove": "error",
534
779
  "unicorn/prefer-dom-node-text-content": "error",
535
780
  "unicorn/prefer-event-target": "error",
781
+ "unicorn/prefer-export-from": "error",
536
782
  "unicorn/prefer-global-this": "off",
537
783
  "unicorn/prefer-import-meta-properties": "error",
538
784
  "unicorn/prefer-includes": "error",
@@ -546,6 +792,7 @@ export default defineConfig({
546
792
  "unicorn/prefer-native-coercion-functions": "error",
547
793
  "unicorn/prefer-negative-index": "error",
548
794
  "unicorn/prefer-node-protocol": "error",
795
+ "unicorn/prefer-number-coercion": "error",
549
796
  "unicorn/prefer-number-properties": "error",
550
797
  "unicorn/prefer-object-from-entries": "error",
551
798
  "unicorn/prefer-optional-catch-binding": "error",
@@ -556,6 +803,7 @@ export default defineConfig({
556
803
  "unicorn/prefer-response-static-json": "error",
557
804
  "unicorn/prefer-set-has": "error",
558
805
  "unicorn/prefer-set-size": "error",
806
+ "unicorn/prefer-single-call": "error",
559
807
  "unicorn/prefer-spread": "error",
560
808
  "unicorn/prefer-string-raw": "off",
561
809
  "unicorn/prefer-string-replace-all": "error",
@@ -1,6 +1,12 @@
1
1
  import { defineConfig } from "oxlint";
2
2
 
3
+ // Every non-nursery nextjs rule oxlint implements is listed explicitly
4
+ // (mirroring the core config's philosophy), with decisions matching the
5
+ // ESLint next preset.
3
6
  export default defineConfig({
7
+ jsPlugins: [
8
+ { name: "react-doctor", specifier: "oxlint-plugin-react-doctor" },
9
+ ],
4
10
  overrides: [
5
11
  {
6
12
  files: ["**/next-env.d.ts"],
@@ -10,5 +16,51 @@ export default defineConfig({
10
16
  },
11
17
  ],
12
18
  plugins: ["nextjs"],
13
- rules: {},
19
+ rules: {
20
+ "nextjs/google-font-display": "error",
21
+ "nextjs/google-font-preconnect": "error",
22
+ "nextjs/inline-script-id": "error",
23
+ "nextjs/next-script-for-ga": "error",
24
+ "nextjs/no-assign-module-variable": "error",
25
+ "nextjs/no-async-client-component": "error",
26
+ "nextjs/no-before-interactive-script-outside-document": "error",
27
+ "nextjs/no-css-tags": "error",
28
+ "nextjs/no-document-import-in-page": "error",
29
+ "nextjs/no-duplicate-head": "error",
30
+ "nextjs/no-head-element": "error",
31
+ "nextjs/no-head-import-in-document": "error",
32
+ "nextjs/no-html-link-for-pages": "error",
33
+ "nextjs/no-img-element": "error",
34
+ "nextjs/no-page-custom-font": "error",
35
+ "nextjs/no-script-component-in-head": "error",
36
+ "nextjs/no-styled-jsx-in-document": "error",
37
+ "nextjs/no-sync-scripts": "error",
38
+ "nextjs/no-title-in-document-head": "error",
39
+ "nextjs/no-typos": "error",
40
+ "nextjs/no-unwanted-polyfillio": "error",
41
+
42
+ "react-doctor/nextjs-async-client-component": "error",
43
+ "react-doctor/nextjs-error-boundary-missing-use-client": "error",
44
+ "react-doctor/nextjs-global-error-missing-html-body": "error",
45
+ "react-doctor/nextjs-image-missing-sizes": "error",
46
+ "react-doctor/nextjs-inline-script-missing-id": "error",
47
+ "react-doctor/nextjs-missing-metadata": "error",
48
+ "react-doctor/nextjs-no-a-element": "error",
49
+ "react-doctor/nextjs-no-client-fetch-for-server-data": "error",
50
+ "react-doctor/nextjs-no-client-side-redirect": "error",
51
+ "react-doctor/nextjs-no-css-link": "error",
52
+ "react-doctor/nextjs-no-default-export-in-route-handler": "error",
53
+ "react-doctor/nextjs-no-edge-og-runtime": "error",
54
+ "react-doctor/nextjs-no-font-link": "error",
55
+ "react-doctor/nextjs-no-google-analytics-script": "error",
56
+ "react-doctor/nextjs-no-head-import": "error",
57
+ "react-doctor/nextjs-no-img-element": "error",
58
+ "react-doctor/nextjs-no-native-script": "error",
59
+ "react-doctor/nextjs-no-polyfill-script": "error",
60
+ "react-doctor/nextjs-no-redirect-in-try-catch": "error",
61
+ "react-doctor/nextjs-no-script-in-head": "error",
62
+ "react-doctor/nextjs-no-side-effect-in-get-handler": "error",
63
+ "react-doctor/nextjs-no-use-search-params-without-suspense": "error",
64
+ "react-doctor/nextjs-no-vercel-og-import": "error",
65
+ },
14
66
  });