@luxass/eslint-config 4.3.7 → 4.4.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.
package/dist/index.js CHANGED
@@ -99,6 +99,7 @@ var GLOB_JSON5 = "**/*.json5";
99
99
  var GLOB_JSONC = "**/*.jsonc";
100
100
  var GLOB_MARKDOWN = "**/*.md";
101
101
  var GLOB_MARKDOWN_IN_MARKDOWN = "**/*.md/*.md";
102
+ var GLOB_SVELTE = "**/*.svelte";
102
103
  var GLOB_VUE = "**/*.vue";
103
104
  var GLOB_YAML = "**/*.y?(a)ml";
104
105
  var GLOB_TOML = "**/*.toml";
@@ -423,6 +424,172 @@ function sortTsconfig() {
423
424
  ];
424
425
  }
425
426
 
427
+ // src/utils.ts
428
+ import process from "node:process";
429
+ import { isPackageExists } from "local-pkg";
430
+ var parserPlain = {
431
+ meta: {
432
+ name: "parser-plain"
433
+ },
434
+ parseForESLint: (code) => ({
435
+ ast: {
436
+ body: [],
437
+ comments: [],
438
+ loc: { end: code.length, start: 0 },
439
+ range: [0, code.length],
440
+ tokens: [],
441
+ type: "Program"
442
+ },
443
+ scopeManager: null,
444
+ services: { isPlain: true },
445
+ visitorKeys: {
446
+ Program: []
447
+ }
448
+ })
449
+ };
450
+ async function combine(...configs) {
451
+ const resolved = await Promise.all(configs);
452
+ return resolved.flat();
453
+ }
454
+ function renameRules(rules, from, to) {
455
+ return Object.fromEntries(
456
+ Object.entries(rules).map(([key, value]) => {
457
+ if (key.startsWith(from)) {
458
+ return [to + key.slice(from.length), value];
459
+ }
460
+ return [key, value];
461
+ })
462
+ );
463
+ }
464
+ function toArray(value) {
465
+ return Array.isArray(value) ? value : [value];
466
+ }
467
+ async function interop(m) {
468
+ const resolved = await m;
469
+ return resolved.default || resolved;
470
+ }
471
+ async function ensure(packages) {
472
+ if (process.env.CI || process.stdout.isTTY === false) {
473
+ return;
474
+ }
475
+ ;
476
+ const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
477
+ if (nonExistingPackages.length === 0) {
478
+ return;
479
+ }
480
+ const p = await import("@clack/prompts");
481
+ const result = await p.confirm({
482
+ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`
483
+ });
484
+ if (result) {
485
+ await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
486
+ }
487
+ }
488
+ function resolveSubOptions(options, key) {
489
+ return typeof options[key] === "boolean" ? {} : options[key] || {};
490
+ }
491
+ function getOverrides(options, key) {
492
+ const sub = resolveSubOptions(options, key);
493
+ return {
494
+ ..."overrides" in sub ? sub.overrides : {}
495
+ };
496
+ }
497
+
498
+ // src/configs/svelte.ts
499
+ async function svelte(options = {}) {
500
+ const {
501
+ files = [GLOB_SVELTE],
502
+ overrides = {},
503
+ stylistic: stylistic2 = true
504
+ } = options;
505
+ const {
506
+ indent = 2,
507
+ quotes = "single"
508
+ } = typeof stylistic2 === "boolean" ? {} : stylistic2;
509
+ await ensure([
510
+ "eslint-plugin-svelte"
511
+ ]);
512
+ const [
513
+ pluginSvelte,
514
+ parserSvelte
515
+ ] = await Promise.all([
516
+ interop(import("eslint-plugin-svelte")),
517
+ interop(import("svelte-eslint-parser"))
518
+ ]);
519
+ return [
520
+ {
521
+ name: "antfu/svelte/setup",
522
+ plugins: {
523
+ svelte: pluginSvelte
524
+ }
525
+ },
526
+ {
527
+ files,
528
+ languageOptions: {
529
+ parser: parserSvelte,
530
+ parserOptions: {
531
+ extraFileExtensions: [".svelte"],
532
+ parser: options.typescript ? await interop(import("@typescript-eslint/parser")) : null
533
+ }
534
+ },
535
+ name: "antfu/svelte/rules",
536
+ processor: pluginSvelte.processors[".svelte"],
537
+ rules: {
538
+ "import/no-mutable-exports": "off",
539
+ "no-undef": "off",
540
+ // incompatible with most recent (attribute-form) generic types RFC
541
+ "no-unused-vars": ["error", {
542
+ args: "none",
543
+ caughtErrors: "none",
544
+ ignoreRestSiblings: true,
545
+ vars: "all",
546
+ varsIgnorePattern: "^(\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)"
547
+ }],
548
+ "svelte/comment-directive": "error",
549
+ "svelte/no-at-debug-tags": "warn",
550
+ "svelte/no-at-html-tags": "error",
551
+ "svelte/no-dupe-else-if-blocks": "error",
552
+ "svelte/no-dupe-style-properties": "error",
553
+ "svelte/no-dupe-use-directives": "error",
554
+ "svelte/no-dynamic-slot-name": "error",
555
+ "svelte/no-export-load-in-svelte-module-in-kit-pages": "error",
556
+ "svelte/no-inner-declarations": "error",
557
+ "svelte/no-not-function-handler": "error",
558
+ "svelte/no-object-in-text-mustaches": "error",
559
+ "svelte/no-reactive-functions": "error",
560
+ "svelte/no-reactive-literals": "error",
561
+ "svelte/no-shorthand-style-property-overrides": "error",
562
+ "svelte/no-unknown-style-directive-property": "error",
563
+ "svelte/no-unused-svelte-ignore": "error",
564
+ "svelte/no-useless-mustaches": "error",
565
+ "svelte/require-store-callbacks-use-set-param": "error",
566
+ "svelte/system": "error",
567
+ "svelte/valid-compile": "error",
568
+ "svelte/valid-each-key": "error",
569
+ "unused-imports/no-unused-vars": [
570
+ "error",
571
+ { args: "after-used", argsIgnorePattern: "^_", vars: "all", varsIgnorePattern: "^(_|\\$\\$Props$|\\$\\$Events$|\\$\\$Slots$)" }
572
+ ],
573
+ ...stylistic2 ? {
574
+ "style/indent": "off",
575
+ // superseded by svelte/indent
576
+ "style/no-trailing-spaces": "off",
577
+ // superseded by svelte/no-trailing-spaces
578
+ "svelte/derived-has-same-inputs-outputs": "error",
579
+ "svelte/html-closing-bracket-spacing": "error",
580
+ "svelte/html-quotes": ["error", { prefer: quotes }],
581
+ "svelte/indent": ["error", { alignAttributesVertically: true, indent }],
582
+ "svelte/mustache-spacing": "error",
583
+ "svelte/no-spaces-around-equal-signs-in-attribute": "error",
584
+ "svelte/no-trailing-spaces": "error",
585
+ "svelte/spaced-html-comment": "error"
586
+ } : {},
587
+ ...overrides
588
+ }
589
+ }
590
+ ];
591
+ }
592
+
426
593
  // src/configs/imports.ts
427
594
  import pluginImport from "eslint-plugin-import-x";
428
595
  import pluginAntfu from "eslint-plugin-antfu";
@@ -722,77 +889,6 @@ async function javascript(options = {}) {
722
889
  ];
723
890
  }
724
891
 
725
- // src/utils.ts
726
- import process from "node:process";
727
- import { isPackageExists } from "local-pkg";
728
- var parserPlain = {
729
- meta: {
730
- name: "parser-plain"
731
- },
732
- parseForESLint: (code) => ({
733
- ast: {
734
- body: [],
735
- comments: [],
736
- loc: { end: code.length, start: 0 },
737
- range: [0, code.length],
738
- tokens: [],
739
- type: "Program"
740
- },
741
- scopeManager: null,
742
- services: { isPlain: true },
743
- visitorKeys: {
744
- Program: []
745
- }
746
- })
747
- };
748
- async function combine(...configs) {
749
- const resolved = await Promise.all(configs);
750
- return resolved.flat();
751
- }
752
- function renameRules(rules, from, to) {
753
- return Object.fromEntries(
754
- Object.entries(rules).map(([key, value]) => {
755
- if (key.startsWith(from)) {
756
- return [to + key.slice(from.length), value];
757
- }
758
- return [key, value];
759
- })
760
- );
761
- }
762
- function toArray(value) {
763
- return Array.isArray(value) ? value : [value];
764
- }
765
- async function interop(m) {
766
- const resolved = await m;
767
- return resolved.default || resolved;
768
- }
769
- async function ensure(packages) {
770
- if (process.env.CI || process.stdout.isTTY === false) {
771
- return;
772
- }
773
- ;
774
- const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
775
- if (nonExistingPackages.length === 0) {
776
- return;
777
- }
778
- const p = await import("@clack/prompts");
779
- const result = await p.confirm({
780
- message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`
781
- });
782
- if (result) {
783
- await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
784
- }
785
- }
786
- function resolveSubOptions(options, key) {
787
- return typeof options[key] === "boolean" ? {} : options[key] || {};
788
- }
789
- function getOverrides(options, key) {
790
- const sub = resolveSubOptions(options, key);
791
- return {
792
- ..."overrides" in sub ? sub.overrides : {}
793
- };
794
- }
795
-
796
892
  // src/configs/jsdoc.ts
797
893
  async function jsdoc(options = {}) {
798
894
  const {
@@ -929,7 +1025,7 @@ async function markdown(options = {}) {
929
1025
  }
930
1026
  },
931
1027
  {
932
- name: "luxass/markdown:processor",
1028
+ name: "luxass/markdown/processor",
933
1029
  files,
934
1030
  ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
935
1031
  // `eslint-plugin-markdown` only creates virtual files for code blocks,
@@ -1518,6 +1614,7 @@ async function yaml(options = {}) {
1518
1614
  }
1519
1615
 
1520
1616
  // src/configs/test.ts
1617
+ var _pluginTest;
1521
1618
  async function test(options = {}) {
1522
1619
  const {
1523
1620
  editor = false,
@@ -1529,16 +1626,12 @@ async function test(options = {}) {
1529
1626
  ] = await Promise.all([
1530
1627
  interop(import("eslint-plugin-vitest"))
1531
1628
  ]);
1629
+ _pluginTest = _pluginTest || pluginVitest;
1532
1630
  return [
1533
1631
  {
1534
1632
  name: "luxass/test/setup",
1535
1633
  plugins: {
1536
- test: {
1537
- ...pluginVitest,
1538
- rules: {
1539
- ...pluginVitest.rules
1540
- }
1541
- }
1634
+ test: _pluginTest
1542
1635
  }
1543
1636
  },
1544
1637
  {
@@ -1614,35 +1707,42 @@ async function nextjs(options = {}) {
1614
1707
  {
1615
1708
  name: "luxass/nextjs/setup",
1616
1709
  plugins: {
1617
- "@next/next": pluginNextjs
1710
+ nextjs: pluginNextjs
1618
1711
  }
1619
1712
  },
1620
1713
  {
1621
1714
  name: "luxass/nextjs/rules",
1622
1715
  files,
1623
1716
  rules: {
1624
- ...pluginNextjs.configs.recommended.rules,
1625
- ...pluginNextjs.configs["core-web-vitals"].rules,
1626
- "@next/next/google-font-display": ["error"],
1627
- "@next/next/google-font-preconnect": ["error"],
1628
- "@next/next/inline-script-id": ["error"],
1629
- "@next/next/next-script-for-ga": ["warn"],
1630
- "@next/next/no-assign-module-variable": ["error"],
1631
- "@next/next/no-css-tags": ["warn"],
1632
- "@next/next/no-document-import-in-page": ["error"],
1633
- "@next/next/no-duplicate-head": ["error"],
1634
- "@next/next/no-head-element": ["warn"],
1635
- "@next/next/no-head-import-in-document": ["error"],
1636
- "@next/next/no-html-link-for-pages": ["off"],
1637
- "@next/next/no-img-element": ["warn"],
1638
- "@next/next/no-page-custom-font": ["warn"],
1639
- "@next/next/no-script-component-in-head": ["error"],
1640
- "@next/next/no-styled-jsx-in-document": ["warn"],
1641
- "@next/next/no-sync-scripts": ["warn"],
1642
- "@next/next/no-title-in-document-head": ["warn"],
1643
- "@next/next/no-typos": ["warn"],
1644
- "@next/next/no-unwanted-polyfillio": ["warn"],
1645
- // "jsx-a11y/anchor-is-valid": ["off"],
1717
+ ...renameRules(
1718
+ pluginNextjs.configs.recommended.rules,
1719
+ "@next/next/",
1720
+ "nextjs/"
1721
+ ),
1722
+ ...renameRules(
1723
+ pluginNextjs.configs["core-web-vitals"].rules,
1724
+ "@next/next/",
1725
+ "nextjs/"
1726
+ ),
1727
+ "nextjs/google-font-display": ["error"],
1728
+ "nextjs/google-font-preconnect": ["error"],
1729
+ "nextjs/inline-script-id": ["error"],
1730
+ "nextjs/next-script-for-ga": ["warn"],
1731
+ "nextjs/no-assign-module-variable": ["error"],
1732
+ "nextjs/no-css-tags": ["warn"],
1733
+ "nextjs/no-document-import-in-page": ["error"],
1734
+ "nextjs/no-duplicate-head": ["error"],
1735
+ "nextjs/no-head-element": ["warn"],
1736
+ "nextjs/no-head-import-in-document": ["error"],
1737
+ "nextjs/no-html-link-for-pages": ["off"],
1738
+ "nextjs/no-img-element": ["warn"],
1739
+ "nextjs/no-page-custom-font": ["warn"],
1740
+ "nextjs/no-script-component-in-head": ["error"],
1741
+ "nextjs/no-styled-jsx-in-document": ["warn"],
1742
+ "nextjs/no-sync-scripts": ["warn"],
1743
+ "nextjs/no-title-in-document-head": ["warn"],
1744
+ "nextjs/no-typos": ["warn"],
1745
+ "nextjs/no-unwanted-polyfillio": ["warn"],
1646
1746
  // This rule creates errors with webpack parsing on edge runtime
1647
1747
  "unicorn/prefer-node-protocol": ["off"],
1648
1748
  ...overrides
@@ -1668,7 +1768,7 @@ async function nextjs(options = {}) {
1668
1768
  name: "luxass/nextjs/og-override",
1669
1769
  files: GLOB_NEXTJS_OG,
1670
1770
  rules: {
1671
- "@next/next/no-img-element": "off",
1771
+ "nextjs/no-img-element": "off",
1672
1772
  "react/no-unknown-property": ["error", {
1673
1773
  ignore: ["tw"]
1674
1774
  }]
@@ -1679,281 +1779,151 @@ async function nextjs(options = {}) {
1679
1779
 
1680
1780
  // src/configs/react.ts
1681
1781
  import { isPackageExists as isPackageExists2 } from "local-pkg";
1782
+ var ReactRefreshAllowConstantExportPackages = [
1783
+ "vite"
1784
+ ];
1785
+ var RemixPackages = [
1786
+ "@remix-run/node",
1787
+ "@remix-run/react",
1788
+ "@remix-run/serve",
1789
+ "@remix-run/dev"
1790
+ ];
1682
1791
  async function react(options = {}) {
1683
1792
  const {
1684
- a11y = false,
1685
- files = [GLOB_JSX, GLOB_TSX],
1686
- overrides = {},
1687
- refresh = true,
1688
- typescript: typescript2 = true
1793
+ files = [GLOB_TS, GLOB_TSX],
1794
+ overrides = {}
1689
1795
  } = options;
1690
1796
  await ensure([
1691
- "eslint-plugin-react",
1797
+ "@eslint-react/eslint-plugin",
1692
1798
  "eslint-plugin-react-hooks",
1693
- ...refresh ? ["eslint-plugin-react-refresh"] : [],
1694
- ...a11y ? ["eslint-plugin-jsx-a11y"] : []
1799
+ "eslint-plugin-react-refresh"
1695
1800
  ]);
1801
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
1802
+ const isTypeAware = !!tsconfigPath;
1696
1803
  const [
1697
1804
  pluginReact,
1698
1805
  pluginReactHooks,
1699
1806
  pluginReactRefresh,
1700
- pluginA11y
1807
+ parserTs
1701
1808
  ] = await Promise.all([
1702
- interop(import("eslint-plugin-react")),
1809
+ interop(import("@eslint-react/eslint-plugin")),
1703
1810
  interop(import("eslint-plugin-react-hooks")),
1704
- ...refresh ? [interop(import("eslint-plugin-react-refresh"))] : [],
1705
- ...a11y ? [interop(import("eslint-plugin-jsx-a11y"))] : []
1811
+ interop(import("eslint-plugin-react-refresh")),
1812
+ interop(import("@typescript-eslint/parser"))
1706
1813
  ]);
1707
- const isAllowConstantExport = isPackageExists2("vite");
1814
+ const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
1815
+ (i) => isPackageExists2(i)
1816
+ );
1817
+ const isUsingRemix = RemixPackages.some((i) => isPackageExists2(i));
1818
+ const isUsingNext = isPackageExists2("next");
1819
+ const plugins = pluginReact.configs.all.plugins;
1708
1820
  return [
1709
1821
  {
1710
1822
  name: "luxass/react/setup",
1711
1823
  plugins: {
1712
- "react": pluginReact,
1824
+ "react": plugins["@eslint-react"],
1825
+ "react-dom": plugins["@eslint-react/dom"],
1713
1826
  "react-hooks": pluginReactHooks,
1714
- ...refresh ? { "react-refresh": pluginReactRefresh } : {},
1715
- ...a11y ? { "jsx-a11y": pluginA11y } : {}
1827
+ "react-hooks-extra": plugins["@eslint-react/hooks-extra"],
1828
+ "react-naming-convention": plugins["@eslint-react/naming-convention"],
1829
+ "react-refresh": pluginReactRefresh
1716
1830
  }
1717
1831
  },
1718
1832
  {
1719
1833
  name: "luxass/react/rules",
1720
1834
  files,
1721
1835
  languageOptions: {
1836
+ parser: parserTs,
1722
1837
  parserOptions: {
1723
1838
  ecmaFeatures: {
1724
1839
  jsx: true
1725
- }
1726
- }
1840
+ },
1841
+ ...isTypeAware ? { project: tsconfigPath } : {}
1842
+ },
1843
+ sourceType: "module"
1727
1844
  },
1728
1845
  rules: {
1729
- ...a11y ? {
1730
- // recommended rules for jsx-a11y
1731
- "jsx-a11y/alt-text": "error",
1732
- "jsx-a11y/anchor-ambiguous-text": "off",
1733
- "jsx-a11y/anchor-has-content": "error",
1734
- "jsx-a11y/anchor-is-valid": "error",
1735
- "jsx-a11y/aria-activedescendant-has-tabindex": "error",
1736
- "jsx-a11y/aria-props": "error",
1737
- "jsx-a11y/aria-proptypes": "error",
1738
- "jsx-a11y/aria-role": "error",
1739
- "jsx-a11y/aria-unsupported-elements": "error",
1740
- "jsx-a11y/autocomplete-valid": "error",
1741
- "jsx-a11y/click-events-have-key-events": "error",
1742
- "jsx-a11y/control-has-associated-label": [
1743
- "off",
1744
- {
1745
- ignoreElements: [
1746
- "audio",
1747
- "canvas",
1748
- "embed",
1749
- "input",
1750
- "textarea",
1751
- "tr",
1752
- "video"
1753
- ],
1754
- ignoreRoles: [
1755
- "grid",
1756
- "listbox",
1757
- "menu",
1758
- "menubar",
1759
- "radiogroup",
1760
- "row",
1761
- "tablist",
1762
- "toolbar",
1763
- "tree",
1764
- "treegrid"
1765
- ],
1766
- includeRoles: [
1767
- "alert",
1768
- "dialog"
1769
- ]
1770
- }
1771
- ],
1772
- "jsx-a11y/heading-has-content": "error",
1773
- "jsx-a11y/html-has-lang": "error",
1774
- "jsx-a11y/iframe-has-title": "error",
1775
- "jsx-a11y/img-redundant-alt": "error",
1776
- "jsx-a11y/interactive-supports-focus": [
1777
- "error",
1778
- {
1779
- tabbable: [
1780
- "button",
1781
- "checkbox",
1782
- "link",
1783
- "searchbox",
1784
- "spinbutton",
1785
- "switch",
1786
- "textbox"
1787
- ]
1788
- }
1789
- ],
1790
- "jsx-a11y/label-has-associated-control": "error",
1791
- "jsx-a11y/label-has-for": "off",
1792
- "jsx-a11y/media-has-caption": "error",
1793
- "jsx-a11y/mouse-events-have-key-events": "error",
1794
- "jsx-a11y/no-access-key": "error",
1795
- "jsx-a11y/no-autofocus": "error",
1796
- "jsx-a11y/no-distracting-elements": "error",
1797
- "jsx-a11y/no-interactive-element-to-noninteractive-role": [
1798
- "error",
1799
- {
1800
- canvas: [
1801
- "img"
1802
- ],
1803
- tr: [
1804
- "none",
1805
- "presentation"
1806
- ]
1807
- }
1808
- ],
1809
- "jsx-a11y/no-noninteractive-element-interactions": [
1810
- "error",
1811
- {
1812
- alert: [
1813
- "onKeyUp",
1814
- "onKeyDown",
1815
- "onKeyPress"
1816
- ],
1817
- body: [
1818
- "onError",
1819
- "onLoad"
1820
- ],
1821
- dialog: [
1822
- "onKeyUp",
1823
- "onKeyDown",
1824
- "onKeyPress"
1825
- ],
1826
- handlers: [
1827
- "onClick",
1828
- "onError",
1829
- "onLoad",
1830
- "onMouseDown",
1831
- "onMouseUp",
1832
- "onKeyPress",
1833
- "onKeyDown",
1834
- "onKeyUp"
1835
- ],
1836
- iframe: [
1837
- "onError",
1838
- "onLoad"
1839
- ],
1840
- img: [
1841
- "onError",
1842
- "onLoad"
1843
- ]
1844
- }
1845
- ],
1846
- "jsx-a11y/no-noninteractive-element-to-interactive-role": [
1847
- "error",
1848
- {
1849
- fieldset: [
1850
- "radiogroup",
1851
- "presentation"
1852
- ],
1853
- li: [
1854
- "menuitem",
1855
- "option",
1856
- "row",
1857
- "tab",
1858
- "treeitem"
1859
- ],
1860
- ol: [
1861
- "listbox",
1862
- "menu",
1863
- "menubar",
1864
- "radiogroup",
1865
- "tablist",
1866
- "tree",
1867
- "treegrid"
1868
- ],
1869
- table: [
1870
- "grid"
1871
- ],
1872
- td: [
1873
- "gridcell"
1874
- ],
1875
- ul: [
1876
- "listbox",
1877
- "menu",
1878
- "menubar",
1879
- "radiogroup",
1880
- "tablist",
1881
- "tree",
1882
- "treegrid"
1883
- ]
1884
- }
1885
- ],
1886
- "jsx-a11y/no-noninteractive-tabindex": [
1887
- "error",
1888
- {
1889
- allowExpressionValues: true,
1890
- roles: [
1891
- "tabpanel"
1892
- ],
1893
- tags: []
1894
- }
1895
- ],
1896
- "jsx-a11y/no-redundant-roles": "error",
1897
- "jsx-a11y/no-static-element-interactions": [
1898
- "error",
1899
- {
1900
- allowExpressionValues: true,
1901
- handlers: [
1902
- "onClick",
1903
- "onMouseDown",
1904
- "onMouseUp",
1905
- "onKeyPress",
1906
- "onKeyDown",
1907
- "onKeyUp"
1908
- ]
1909
- }
1910
- ],
1911
- "jsx-a11y/role-has-required-aria-props": "error",
1912
- "jsx-a11y/role-supports-aria-props": "error",
1913
- "jsx-a11y/scope": "error",
1914
- "jsx-a11y/tabindex-no-positive": "error"
1915
- } : {},
1916
- // recommended rules react
1917
- "react/display-name": "error",
1918
- "react/jsx-key": "error",
1919
- "react/jsx-no-comment-textnodes": "error",
1920
- "react/jsx-no-duplicate-props": "error",
1921
- "react/jsx-no-target-blank": "error",
1922
- "react/jsx-no-undef": "error",
1923
- "react/jsx-uses-react": "error",
1924
- "react/jsx-uses-vars": "error",
1925
- "react/no-children-prop": "error",
1926
- "react/no-danger-with-children": "error",
1927
- "react/no-deprecated": "error",
1928
- "react/no-direct-mutation-state": "error",
1929
- "react/no-find-dom-node": "error",
1930
- "react/no-is-mounted": "error",
1931
- "react/no-render-return-value": "error",
1932
- "react/no-string-refs": "error",
1933
- "react/no-unescaped-entities": "error",
1934
- "react/no-unknown-property": "error",
1935
- "react/no-unsafe": "off",
1936
- "react/prop-types": "error",
1937
- "react/react-in-jsx-scope": "off",
1938
- "react/require-render-return": "error",
1846
+ // recommended rules from @eslint-react/dom
1847
+ "react-dom/no-children-in-void-dom-elements": "warn",
1848
+ "react-dom/no-dangerously-set-innerhtml": "warn",
1849
+ "react-dom/no-dangerously-set-innerhtml-with-children": "error",
1850
+ "react-dom/no-find-dom-node": "error",
1851
+ "react-dom/no-missing-button-type": "warn",
1852
+ "react-dom/no-missing-iframe-sandbox": "warn",
1853
+ "react-dom/no-namespace": "error",
1854
+ "react-dom/no-render-return-value": "error",
1855
+ "react-dom/no-script-url": "warn",
1856
+ "react-dom/no-unsafe-iframe-sandbox": "warn",
1857
+ "react-dom/no-unsafe-target-blank": "warn",
1939
1858
  // recommended rules react-hooks
1940
1859
  "react-hooks/exhaustive-deps": "warn",
1941
1860
  "react-hooks/rules-of-hooks": "error",
1942
1861
  // react refresh
1943
- ...refresh ? {
1944
- "react-refresh/only-export-components": ["warn", { allowConstantExport: isAllowConstantExport }]
1945
- } : {},
1946
- ...typescript2 ? {
1947
- "react/jsx-no-undef": "off",
1948
- "react/prop-type": "off"
1862
+ "react-refresh/only-export-components": [
1863
+ "warn",
1864
+ {
1865
+ allowConstantExport: isAllowConstantExport,
1866
+ allowExportNames: [
1867
+ ...isUsingNext ? [
1868
+ "config",
1869
+ "generateStaticParams",
1870
+ "metadata",
1871
+ "generateMetadata",
1872
+ "viewport",
1873
+ "generateViewport"
1874
+ ] : [],
1875
+ ...isUsingRemix ? [
1876
+ "meta",
1877
+ "links",
1878
+ "headers",
1879
+ "loader",
1880
+ "action"
1881
+ ] : []
1882
+ ]
1883
+ }
1884
+ ],
1885
+ // recommended rules from @eslint-react
1886
+ "react/ensure-forward-ref-using-ref": "warn",
1887
+ "react/no-access-state-in-setstate": "error",
1888
+ "react/no-array-index-key": "warn",
1889
+ "react/no-children-count": "warn",
1890
+ "react/no-children-for-each": "warn",
1891
+ "react/no-children-map": "warn",
1892
+ "react/no-children-only": "warn",
1893
+ "react/no-children-prop": "warn",
1894
+ "react/no-children-to-array": "warn",
1895
+ "react/no-clone-element": "warn",
1896
+ "react/no-comment-textnodes": "warn",
1897
+ "react/no-component-will-mount": "error",
1898
+ "react/no-component-will-receive-props": "error",
1899
+ "react/no-component-will-update": "error",
1900
+ "react/no-create-ref": "error",
1901
+ "react/no-direct-mutation-state": "error",
1902
+ "react/no-duplicate-key": "error",
1903
+ "react/no-implicit-key": "error",
1904
+ "react/no-missing-key": "error",
1905
+ "react/no-nested-components": "warn",
1906
+ "react/no-redundant-should-component-update": "error",
1907
+ "react/no-set-state-in-component-did-mount": "warn",
1908
+ "react/no-set-state-in-component-did-update": "warn",
1909
+ "react/no-set-state-in-component-will-update": "warn",
1910
+ "react/no-string-refs": "error",
1911
+ "react/no-unsafe-component-will-mount": "warn",
1912
+ "react/no-unsafe-component-will-receive-props": "warn",
1913
+ "react/no-unsafe-component-will-update": "warn",
1914
+ "react/no-unstable-context-value": "error",
1915
+ "react/no-unstable-default-props": "error",
1916
+ "react/no-unused-class-component-members": "warn",
1917
+ "react/no-unused-state": "warn",
1918
+ "react/no-useless-fragment": "warn",
1919
+ "react/prefer-destructuring-assignment": "warn",
1920
+ "react/prefer-shorthand-boolean": "warn",
1921
+ "react/prefer-shorthand-fragment": "warn",
1922
+ ...isTypeAware ? {
1923
+ "react/no-leaked-conditional-rendering": "warn"
1949
1924
  } : {},
1950
1925
  // overrides
1951
1926
  ...overrides
1952
- },
1953
- settings: {
1954
- react: {
1955
- version: "detect"
1956
- }
1957
1927
  }
1958
1928
  }
1959
1929
  ];
@@ -2211,7 +2181,7 @@ async function formatters(options = {}, stylistic2 = {}) {
2211
2181
  if (options.html) {
2212
2182
  configs.push({
2213
2183
  name: "luxass/formatter/html",
2214
- files: ["**/*.html"],
2184
+ files: [GLOB_HTML],
2215
2185
  languageOptions: {
2216
2186
  parser: parserPlain
2217
2187
  },
@@ -2361,10 +2331,14 @@ async function solid(options = {}) {
2361
2331
  await ensure([
2362
2332
  "eslint-plugin-solid"
2363
2333
  ]);
2334
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
2335
+ const isTypeAware = !!tsconfigPath;
2364
2336
  const [
2365
- pluginSolid
2337
+ pluginSolid,
2338
+ parserTs
2366
2339
  ] = await Promise.all([
2367
- interop(import("eslint-plugin-solid"))
2340
+ interop(import("eslint-plugin-solid")),
2341
+ interop(import("@typescript-eslint/parser"))
2368
2342
  ]);
2369
2343
  return [
2370
2344
  {
@@ -2377,42 +2351,41 @@ async function solid(options = {}) {
2377
2351
  name: "luxass/solid/rules",
2378
2352
  files,
2379
2353
  languageOptions: {
2354
+ parser: parserTs,
2380
2355
  parserOptions: {
2381
2356
  ecmaFeatures: {
2382
2357
  jsx: true
2383
- }
2358
+ },
2359
+ ...isTypeAware ? { project: tsconfigPath } : {}
2384
2360
  },
2385
2361
  sourceType: "module"
2386
2362
  },
2387
2363
  rules: {
2388
- // solid recommended rules
2389
2364
  // reactivity
2390
2365
  "solid/components-return-once": "warn",
2391
- "solid/event-handlers": "warn",
2366
+ "solid/event-handlers": ["error", {
2367
+ // if true, don't warn on ambiguously named event handlers like `onclick` or `onchange`
2368
+ ignoreCase: false,
2369
+ // if true, warn when spreading event handlers onto JSX. Enable for Solid < v1.6.
2370
+ warnOnSpread: false
2371
+ }],
2392
2372
  // these rules are mostly style suggestions
2393
- "solid/imports": "warn",
2373
+ "solid/imports": "error",
2394
2374
  // identifier usage is important
2395
2375
  "solid/jsx-no-duplicate-props": "error",
2396
2376
  "solid/jsx-no-script-url": "error",
2397
2377
  "solid/jsx-no-undef": "error",
2398
2378
  "solid/jsx-uses-vars": "error",
2399
- "solid/no-array-handlers": "off",
2400
2379
  "solid/no-destructure": "error",
2401
2380
  // security problems
2402
- "solid/no-innerhtml": "error",
2403
- // only necessary for resource-constrained environments
2404
- "solid/no-proxy-apis": "off",
2405
- "solid/no-react-deps": "warn",
2406
- "solid/no-react-specific-props": "warn",
2381
+ "solid/no-innerhtml": ["error", { allowStatic: true }],
2382
+ "solid/no-react-deps": "error",
2383
+ "solid/no-react-specific-props": "error",
2407
2384
  "solid/no-unknown-namespaces": "error",
2408
- // deprecated
2409
- "solid/prefer-classlist": "off",
2410
2385
  "solid/prefer-for": "error",
2411
- // handled by Solid compiler, opt-in style suggestion
2412
- "solid/prefer-show": "off",
2413
2386
  "solid/reactivity": "warn",
2414
- "solid/self-closing-comp": "warn",
2415
- "solid/style-prop": "warn",
2387
+ "solid/self-closing-comp": "error",
2388
+ "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
2416
2389
  ...typescript2 ? {
2417
2390
  "solid/jsx-no-undef": ["error", { typescriptEnabled: true }],
2418
2391
  // namespaces taken care of by TS
@@ -2449,7 +2422,12 @@ var defaultPluginRenaming = {
2449
2422
  "import-x": "import",
2450
2423
  "n": "node",
2451
2424
  "vitest": "test",
2452
- "yml": "yaml"
2425
+ "yml": "yaml",
2426
+ "@eslint-react": "react",
2427
+ "@eslint-react/dom": "react-dom",
2428
+ "@eslint-react/hooks-extra": "react-hooks-extra",
2429
+ "@eslint-react/naming-convention": "react-naming-convention",
2430
+ "@next/next": "nextjs"
2453
2431
  };
2454
2432
  function luxass(options = {}, ...userConfigs) {
2455
2433
  const {
@@ -2461,6 +2439,7 @@ function luxass(options = {}, ...userConfigs) {
2461
2439
  nextjs: enableNextJS = false,
2462
2440
  react: enableReact = false,
2463
2441
  tailwindcss: enableTailwindCSS = false,
2442
+ svelte: enableSvelte = false,
2464
2443
  solid: enableSolid = false,
2465
2444
  typescript: enableTypeScript = isPackageExists4("typescript"),
2466
2445
  unocss: enableUnoCSS = false,
@@ -2522,8 +2501,7 @@ function luxass(options = {}, ...userConfigs) {
2522
2501
  configs.push(react({
2523
2502
  ...resolveSubOptions(options, "react"),
2524
2503
  overrides: getOverrides(options, "react"),
2525
- typescript: !!enableTypeScript,
2526
- refresh: !enableNextJS
2504
+ tsconfigPath: getOverrides(options, "typescript").tsconfigPath
2527
2505
  }));
2528
2506
  }
2529
2507
  if (enableNextJS) {
@@ -2543,6 +2521,16 @@ function luxass(options = {}, ...userConfigs) {
2543
2521
  })
2544
2522
  );
2545
2523
  }
2524
+ if (enableSvelte) {
2525
+ configs.push(
2526
+ svelte({
2527
+ ...resolveSubOptions(options, "svelte"),
2528
+ overrides: getOverrides(options, "svelte"),
2529
+ stylistic: stylisticOptions,
2530
+ typescript: !!enableTypeScript
2531
+ })
2532
+ );
2533
+ }
2546
2534
  if (enableVue) {
2547
2535
  configs.push(
2548
2536
  vue({
@@ -2619,15 +2607,15 @@ function luxass(options = {}, ...userConfigs) {
2619
2607
  if (Object.keys(fusedConfig).length) {
2620
2608
  configs.push([fusedConfig]);
2621
2609
  }
2622
- let pipeline = new FlatConfigComposer();
2623
- pipeline = pipeline.append(
2610
+ let composer = new FlatConfigComposer();
2611
+ composer = composer.append(
2624
2612
  ...configs,
2625
2613
  ...userConfigs
2626
2614
  );
2627
2615
  if (autoRenamePlugins) {
2628
- pipeline = pipeline.renamePlugins(defaultPluginRenaming);
2616
+ composer = composer.renamePlugins(defaultPluginRenaming);
2629
2617
  }
2630
- return pipeline;
2618
+ return composer;
2631
2619
  }
2632
2620
 
2633
2621
  // src/index.ts
@@ -2654,6 +2642,7 @@ export {
2654
2642
  GLOB_SRC,
2655
2643
  GLOB_SRC_EXT,
2656
2644
  GLOB_STYLE,
2645
+ GLOB_SVELTE,
2657
2646
  GLOB_TESTS,
2658
2647
  GLOB_TOML,
2659
2648
  GLOB_TS,
@@ -2673,6 +2662,7 @@ export {
2673
2662
  javascript,
2674
2663
  jsdoc,
2675
2664
  jsonc,
2665
+ luxass,
2676
2666
  markdown,
2677
2667
  nextjs,
2678
2668
  node,
@@ -2684,6 +2674,7 @@ export {
2684
2674
  sortPackageJson,
2685
2675
  sortTsconfig,
2686
2676
  stylistic,
2677
+ svelte,
2687
2678
  tailwindcss,
2688
2679
  test,
2689
2680
  toArray,