@luxass/eslint-config 4.3.7 → 4.4.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/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,148 @@ 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: isUsingNext ? [
1867
+ "config",
1868
+ "generateStaticParams",
1869
+ "metadata",
1870
+ "generateMetadata",
1871
+ "viewport",
1872
+ "generateViewport"
1873
+ ] : isUsingRemix ? [
1874
+ "meta",
1875
+ "links",
1876
+ "headers",
1877
+ "loader",
1878
+ "action"
1879
+ ] : void 0
1880
+ }
1881
+ ],
1882
+ // recommended rules from @eslint-react
1883
+ "react/ensure-forward-ref-using-ref": "warn",
1884
+ "react/no-access-state-in-setstate": "error",
1885
+ "react/no-array-index-key": "warn",
1886
+ "react/no-children-count": "warn",
1887
+ "react/no-children-for-each": "warn",
1888
+ "react/no-children-map": "warn",
1889
+ "react/no-children-only": "warn",
1890
+ "react/no-children-prop": "warn",
1891
+ "react/no-children-to-array": "warn",
1892
+ "react/no-clone-element": "warn",
1893
+ "react/no-comment-textnodes": "warn",
1894
+ "react/no-component-will-mount": "error",
1895
+ "react/no-component-will-receive-props": "error",
1896
+ "react/no-component-will-update": "error",
1897
+ "react/no-create-ref": "error",
1898
+ "react/no-direct-mutation-state": "error",
1899
+ "react/no-duplicate-key": "error",
1900
+ "react/no-implicit-key": "error",
1901
+ "react/no-missing-key": "error",
1902
+ "react/no-nested-components": "warn",
1903
+ "react/no-redundant-should-component-update": "error",
1904
+ "react/no-set-state-in-component-did-mount": "warn",
1905
+ "react/no-set-state-in-component-did-update": "warn",
1906
+ "react/no-set-state-in-component-will-update": "warn",
1907
+ "react/no-string-refs": "error",
1908
+ "react/no-unsafe-component-will-mount": "warn",
1909
+ "react/no-unsafe-component-will-receive-props": "warn",
1910
+ "react/no-unsafe-component-will-update": "warn",
1911
+ "react/no-unstable-context-value": "error",
1912
+ "react/no-unstable-default-props": "error",
1913
+ "react/no-unused-class-component-members": "warn",
1914
+ "react/no-unused-state": "warn",
1915
+ "react/no-useless-fragment": "warn",
1916
+ "react/prefer-destructuring-assignment": "warn",
1917
+ "react/prefer-shorthand-boolean": "warn",
1918
+ "react/prefer-shorthand-fragment": "warn",
1919
+ ...isTypeAware ? {
1920
+ "react/no-leaked-conditional-rendering": "warn"
1949
1921
  } : {},
1950
1922
  // overrides
1951
1923
  ...overrides
1952
- },
1953
- settings: {
1954
- react: {
1955
- version: "detect"
1956
- }
1957
1924
  }
1958
1925
  }
1959
1926
  ];
@@ -2211,7 +2178,7 @@ async function formatters(options = {}, stylistic2 = {}) {
2211
2178
  if (options.html) {
2212
2179
  configs.push({
2213
2180
  name: "luxass/formatter/html",
2214
- files: ["**/*.html"],
2181
+ files: [GLOB_HTML],
2215
2182
  languageOptions: {
2216
2183
  parser: parserPlain
2217
2184
  },
@@ -2361,10 +2328,14 @@ async function solid(options = {}) {
2361
2328
  await ensure([
2362
2329
  "eslint-plugin-solid"
2363
2330
  ]);
2331
+ const tsconfigPath = options?.tsconfigPath ? toArray(options.tsconfigPath) : void 0;
2332
+ const isTypeAware = !!tsconfigPath;
2364
2333
  const [
2365
- pluginSolid
2334
+ pluginSolid,
2335
+ parserTs
2366
2336
  ] = await Promise.all([
2367
- interop(import("eslint-plugin-solid"))
2337
+ interop(import("eslint-plugin-solid")),
2338
+ interop(import("@typescript-eslint/parser"))
2368
2339
  ]);
2369
2340
  return [
2370
2341
  {
@@ -2377,42 +2348,41 @@ async function solid(options = {}) {
2377
2348
  name: "luxass/solid/rules",
2378
2349
  files,
2379
2350
  languageOptions: {
2351
+ parser: parserTs,
2380
2352
  parserOptions: {
2381
2353
  ecmaFeatures: {
2382
2354
  jsx: true
2383
- }
2355
+ },
2356
+ ...isTypeAware ? { project: tsconfigPath } : {}
2384
2357
  },
2385
2358
  sourceType: "module"
2386
2359
  },
2387
2360
  rules: {
2388
- // solid recommended rules
2389
2361
  // reactivity
2390
2362
  "solid/components-return-once": "warn",
2391
- "solid/event-handlers": "warn",
2363
+ "solid/event-handlers": ["error", {
2364
+ // if true, don't warn on ambiguously named event handlers like `onclick` or `onchange`
2365
+ ignoreCase: false,
2366
+ // if true, warn when spreading event handlers onto JSX. Enable for Solid < v1.6.
2367
+ warnOnSpread: false
2368
+ }],
2392
2369
  // these rules are mostly style suggestions
2393
- "solid/imports": "warn",
2370
+ "solid/imports": "error",
2394
2371
  // identifier usage is important
2395
2372
  "solid/jsx-no-duplicate-props": "error",
2396
2373
  "solid/jsx-no-script-url": "error",
2397
2374
  "solid/jsx-no-undef": "error",
2398
2375
  "solid/jsx-uses-vars": "error",
2399
- "solid/no-array-handlers": "off",
2400
2376
  "solid/no-destructure": "error",
2401
2377
  // 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",
2378
+ "solid/no-innerhtml": ["error", { allowStatic: true }],
2379
+ "solid/no-react-deps": "error",
2380
+ "solid/no-react-specific-props": "error",
2407
2381
  "solid/no-unknown-namespaces": "error",
2408
- // deprecated
2409
- "solid/prefer-classlist": "off",
2410
2382
  "solid/prefer-for": "error",
2411
- // handled by Solid compiler, opt-in style suggestion
2412
- "solid/prefer-show": "off",
2413
2383
  "solid/reactivity": "warn",
2414
- "solid/self-closing-comp": "warn",
2415
- "solid/style-prop": "warn",
2384
+ "solid/self-closing-comp": "error",
2385
+ "solid/style-prop": ["error", { styleProps: ["style", "css"] }],
2416
2386
  ...typescript2 ? {
2417
2387
  "solid/jsx-no-undef": ["error", { typescriptEnabled: true }],
2418
2388
  // namespaces taken care of by TS
@@ -2449,7 +2419,12 @@ var defaultPluginRenaming = {
2449
2419
  "import-x": "import",
2450
2420
  "n": "node",
2451
2421
  "vitest": "test",
2452
- "yml": "yaml"
2422
+ "yml": "yaml",
2423
+ "@eslint-react": "react",
2424
+ "@eslint-react/dom": "react-dom",
2425
+ "@eslint-react/hooks-extra": "react-hooks-extra",
2426
+ "@eslint-react/naming-convention": "react-naming-convention",
2427
+ "@next/next": "nextjs"
2453
2428
  };
2454
2429
  function luxass(options = {}, ...userConfigs) {
2455
2430
  const {
@@ -2461,6 +2436,7 @@ function luxass(options = {}, ...userConfigs) {
2461
2436
  nextjs: enableNextJS = false,
2462
2437
  react: enableReact = false,
2463
2438
  tailwindcss: enableTailwindCSS = false,
2439
+ svelte: enableSvelte = false,
2464
2440
  solid: enableSolid = false,
2465
2441
  typescript: enableTypeScript = isPackageExists4("typescript"),
2466
2442
  unocss: enableUnoCSS = false,
@@ -2522,8 +2498,7 @@ function luxass(options = {}, ...userConfigs) {
2522
2498
  configs.push(react({
2523
2499
  ...resolveSubOptions(options, "react"),
2524
2500
  overrides: getOverrides(options, "react"),
2525
- typescript: !!enableTypeScript,
2526
- refresh: !enableNextJS
2501
+ tsconfigPath: getOverrides(options, "typescript").tsconfigPath
2527
2502
  }));
2528
2503
  }
2529
2504
  if (enableNextJS) {
@@ -2543,6 +2518,16 @@ function luxass(options = {}, ...userConfigs) {
2543
2518
  })
2544
2519
  );
2545
2520
  }
2521
+ if (enableSvelte) {
2522
+ configs.push(
2523
+ svelte({
2524
+ ...resolveSubOptions(options, "svelte"),
2525
+ overrides: getOverrides(options, "svelte"),
2526
+ stylistic: stylisticOptions,
2527
+ typescript: !!enableTypeScript
2528
+ })
2529
+ );
2530
+ }
2546
2531
  if (enableVue) {
2547
2532
  configs.push(
2548
2533
  vue({
@@ -2619,15 +2604,15 @@ function luxass(options = {}, ...userConfigs) {
2619
2604
  if (Object.keys(fusedConfig).length) {
2620
2605
  configs.push([fusedConfig]);
2621
2606
  }
2622
- let pipeline = new FlatConfigComposer();
2623
- pipeline = pipeline.append(
2607
+ let composer = new FlatConfigComposer();
2608
+ composer = composer.append(
2624
2609
  ...configs,
2625
2610
  ...userConfigs
2626
2611
  );
2627
2612
  if (autoRenamePlugins) {
2628
- pipeline = pipeline.renamePlugins(defaultPluginRenaming);
2613
+ composer = composer.renamePlugins(defaultPluginRenaming);
2629
2614
  }
2630
- return pipeline;
2615
+ return composer;
2631
2616
  }
2632
2617
 
2633
2618
  // src/index.ts
@@ -2654,6 +2639,7 @@ export {
2654
2639
  GLOB_SRC,
2655
2640
  GLOB_SRC_EXT,
2656
2641
  GLOB_STYLE,
2642
+ GLOB_SVELTE,
2657
2643
  GLOB_TESTS,
2658
2644
  GLOB_TOML,
2659
2645
  GLOB_TS,
@@ -2673,6 +2659,7 @@ export {
2673
2659
  javascript,
2674
2660
  jsdoc,
2675
2661
  jsonc,
2662
+ luxass,
2676
2663
  markdown,
2677
2664
  nextjs,
2678
2665
  node,
@@ -2684,6 +2671,7 @@ export {
2684
2671
  sortPackageJson,
2685
2672
  sortTsconfig,
2686
2673
  stylistic,
2674
+ svelte,
2687
2675
  tailwindcss,
2688
2676
  test,
2689
2677
  toArray,