From 740b742aaec9ec3f77c7a01160f2c3a87bbcd99a Mon Sep 17 00:00:00 2001 From: Jose Luis Leon Date: Sat, 13 Jul 2024 18:42:27 -0500 Subject: [PATCH] chore(lint): Upgrade ESLint to v9 (#149) --- .eslintignore | 12 - .eslintrc.json | 261 ---- eslint.config.mjs | 304 +++++ example/{babel.config.js => babel.config.cjs} | 0 example/{metro.config.js => metro.config.cjs} | 0 ...tro.config.web.js => metro.config.web.cjs} | 0 ...tive.config.js => react-native.config.cjs} | 0 example/src/App.tsx | 29 +- example/src/DocsTooltip.tsx | 11 +- package.json | 25 +- package/src/lib/SpotlightTour.context.ts | 2 +- package/src/lib/SpotlightTour.provider.tsx | 4 +- .../attach-step/AttachStep.component.tsx | 2 +- .../tour-overlay/TourOverlay.component.tsx | 4 +- package/test/helpers/helper.ts | 16 +- package/test/hooks.ts | 1 - .../lib/AttachStep.component.test.tsx | 2 +- .../TourOverlay.component.test.tsx | 8 +- package/test/setup.ts | 1 - yarn.lock | 1130 ++++++++++------- 20 files changed, 1064 insertions(+), 748 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json create mode 100644 eslint.config.mjs rename example/{babel.config.js => babel.config.cjs} (100%) rename example/{metro.config.js => metro.config.cjs} (100%) rename example/{metro.config.web.js => metro.config.web.cjs} (100%) rename example/{react-native.config.js => react-native.config.cjs} (100%) diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 82c5e90..0000000 --- a/.eslintignore +++ /dev/null @@ -1,12 +0,0 @@ -# Core -.yarn/ -build/ -dist/ -node_modules/ - -# Example -example/.bundle/ -example/android/ -example/ios/ -example/vendor/ -example/public/ diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 2802bd7..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,261 +0,0 @@ -{ - "root": true, - "env": { - "browser": true, - "es6": true, - "node": true - }, - "settings": { - "import/resolver": { - "typescript": { - "alwaysTryTypes": true, - "project": [ - "./tsconfig.json", - "./package/tsconfig.json", - "./example/tsconfig.json" - ] - } - }, - "react": { - "version": "detect" - } - }, - "parserOptions": { - "ecmaVersion": "latest", - "project": [ - "./tsconfig.json", - "./package/tsconfig.json", - "./example/tsconfig.json" - ], - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint", - "better-styled-components", - "eslint-plugin-import", - "eslint-plugin-jsdoc", - "eslint-plugin-react", - "etc", - "react-hooks", - "sonarjs" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "plugin:etc/recommended", - "plugin:import/typescript", - "plugin:react/recommended", - "plugin:sonarjs/recommended" - ], - "overrides": [{ - "files": "*.ts?(x)", - "parser": "@typescript-eslint/parser" - }, { - "files": "*.test.ts?(x)", - "rules": { - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/restrict-template-expressions": "off", - "etc/throw-error": "off" - } - }, { - "files": "*.typetest.ts?(x)", - "rules": { - "@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": false }], - "etc/throw-error": "off" - } - }, { - "files": "*.js?(x)", - "rules": { - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-unsafe-argument": "off", - "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unsafe-call": "off", - "@typescript-eslint/no-unsafe-return": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/restrict-plus-operands": "off", - "@typescript-eslint/restrict-template-expressions": "off" - } - }], - "rules": { - "@typescript-eslint/ban-types": "error", - "@typescript-eslint/comma-dangle": ["error", "always-multiline"], - "@typescript-eslint/consistent-type-assertions": "error", - "@typescript-eslint/dot-notation": "error", - "@typescript-eslint/explicit-function-return-type": ["error", { "allowExpressions": true }], - "@typescript-eslint/explicit-member-accessibility": "error", - "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/member-ordering": ["error", { - "classes": [ - "static-field", - "field", - "constructor", - "static-method", - "abstract-method", - "protected-method", - "public-method", - "private-method" - ], - "interfaces": { "order": "alphabetically" }, - "typeLiterals": { "order": "alphabetically" } - }], - "@typescript-eslint/member-delimiter-style": ["error", { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": true - } - }], - "@typescript-eslint/no-empty-function": "error", - "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": ["error", { "ignoreRestArgs": true }], - "@typescript-eslint/no-floating-promises": "off", - "@typescript-eslint/no-inferrable-types": ["error", { - "ignoreParameters": true, - "ignoreProperties": true - }], - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/no-non-null-assertion": "error", - "@typescript-eslint/no-redundant-type-constituents": "error", - "@typescript-eslint/no-shadow": ["error", { "hoist": "all" }], - "@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }], - "@typescript-eslint/no-unused-vars": ["error", { - "destructuredArrayIgnorePattern": "^_", - "ignoreRestSiblings": true - }], - "@typescript-eslint/no-use-before-define": ["error", { - "functions": false, - "classes": false - }], - "@typescript-eslint/no-var-requires": "error", - "@typescript-eslint/parameter-properties": "error", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/quotes": ["error", "double", { - "avoidEscape": true, - "allowTemplateLiterals": false - }], - "@typescript-eslint/restrict-template-expressions": ["error", { - "allowNumber": true, - "allowBoolean": true, - "allowNullish": true - }], - "@typescript-eslint/semi": "error", - "@typescript-eslint/space-infix-ops": "error", - "@typescript-eslint/triple-slash-reference": "error", - "@typescript-eslint/type-annotation-spacing": "error", - "@typescript-eslint/unbound-method": ["error", { "ignoreStatic": true }], - "@typescript-eslint/unified-signatures": "error", - "array-bracket-spacing": "error", - "arrow-parens": ["error", "as-needed"], - "arrow-spacing": "error", - "brace-style": "error", - "better-styled-components/sort-declarations-alphabetically": "error", - "camelcase": "error", - "comma-spacing": "error", - "computed-property-spacing": "error", - "constructor-super": "error", - "curly": "error", - "etc/no-commented-out-code": "error", - "etc/throw-error": "error", - "eol-last": "error", - "eqeqeq": "error", - "func-style": ["error", "declaration", { "allowArrowFunctions": true }], - "import/newline-after-import": "error", - "import/no-absolute-path": "error", - "import/no-cycle": ["error", { - "allowUnsafeDynamicCyclicDependency": true, - "ignoreExternal": true - }], - "import/no-duplicates": "error", - "import/no-import-module-exports": "error", - "import/no-namespace": "error", - "import/no-relative-packages": "error", - "import/no-unresolved": "error", - "import/no-useless-path-segments": "error", - "import/order": ["error", { - "alphabetize": { - "caseInsensitive": false, - "order": "asc" - }, - "newlines-between": "always", - "groups": ["external", "parent", "sibling"] - }], - "jsdoc/check-alignment": "error", - "jsdoc/check-indentation": ["error", { "excludeTags": ["example", "param", "returns"] }], - "jsdoc/tag-lines": ["error", "any", { "startLines": 1 }], - "jsx-quotes": "error", - "keyword-spacing": "error", - "linebreak-style": "error", - "max-classes-per-file": ["error", 1], - "max-len": ["error", { - "code": 120, - "comments": 80, - "ignoreRegExpLiterals": true, - "ignorePattern": "^import (\\{ )?\\w+( \\})? from \".+\";$", - "ignoreUrls": true, - "tabWidth": 2 - }], - "new-parens": "error", - "no-caller": "error", - "no-cond-assign": "error", - "no-console": "error", - "no-duplicate-imports": "error", - "no-empty-function": "error", - "no-eval": "error", - "no-extra-boolean-cast": ["error", { "enforceForLogicalOperands": true }], - "no-invalid-this": "error", - "no-labels": "error", - "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 0 }], - "no-multi-spaces": "error", - "no-new-wrappers": "error", - "no-param-reassign": "error", - "no-tabs": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-underscore-dangle": "error", - "no-use-before-define": "off", - "no-useless-computed-key": ["error", { "enforceForClassMembers": true }], - "no-var": "error", - "object-curly-spacing": ["error", "always"], - "object-shorthand": "error", - "one-var": ["error", "never"], - "prefer-const": "error", - "quote-props": ["error", "as-needed"], - "radix": "error", - "rest-spread-spacing": "error", - "react/display-name": "off", - "react/hook-use-state": "error", - "react/jsx-boolean-value": ["error", "always"], - "react/jsx-closing-bracket-location": "error", - "react/jsx-curly-spacing": ["error", { "when": "never" }], - "react/jsx-equals-spacing": ["error", "never"], - "react/jsx-max-props-per-line": ["error", { - "maximum": 1, - "when": "multiline" - }], - "react/jsx-no-bind": "error", - "react/jsx-no-literals": "error", - "react/jsx-tag-spacing": "error", - "react/prop-types": "off", - "react/self-closing-comp": "error", - "react-hooks/rules-of-hooks": "error", - "semi-spacing": "error", - "sonarjs/cognitive-complexity": "off", - "sonarjs/no-duplicate-string": "off", - "sonarjs/no-inverted-boolean-check": "error", - "sort-keys": "error", - "space-before-blocks": "error", - "space-in-parens": "error", - "spaced-comment": "error", - "switch-colon-spacing": "error" - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..f3137c3 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,304 @@ +// @ts-check +import path from "path"; +import { fileURLToPath } from "url"; + +import { fixupPluginRules } from "@eslint/compat"; +import { FlatCompat } from "@eslint/eslintrc"; +import eslintJs from "@eslint/js"; +import stylistic from "@stylistic/eslint-plugin"; +import etc from "eslint-plugin-etc"; +import jsdoc from "eslint-plugin-jsdoc"; +import reactRecommended from "eslint-plugin-react/configs/recommended.js"; +import sonarjs from "eslint-plugin-sonarjs"; +import globals from "globals"; +import eslintTs from "typescript-eslint"; + +const project = "./tsconfig.json"; +const filename = fileURLToPath(import.meta.url); +const dirname = path.dirname(filename); +const compat = new FlatCompat({ + baseDirectory: dirname, + recommendedConfig: eslintJs.configs.recommended, +}); + +/** + * @param {string} name the pugin name + * @param {string} alias the plugin alias + * @returns {import("eslint").ESLint.Plugin} + */ +function legacyPlugin(name, alias = name) { + const plugin = compat.plugins(name)[0]?.plugins?.[alias]; + + if (!plugin) { + throw new Error(`Unable to resolve plugin ${name} and/or alias ${alias}`); + } + + return fixupPluginRules(plugin); +} + +export default eslintTs.config( + eslintJs.configs.recommended, + ...eslintTs.configs.recommendedTypeChecked, + ...compat.extends("plugin:import/typescript"), + reactRecommended, + sonarjs.configs.recommended, + stylistic.configs.customize({ + braceStyle: "1tbs", + flat: true, + quotes: "double", + semi: true, + }), + { + ignores: [ + ".yarn/**", + "**/.bundle/**", + "**/android/**", + "**/build/**", + "**/dist/**", + "**/ios/**", + "**/node_modules/**", + "**/public/**", + "**/vendor/**", + ], + }, + { + languageOptions: { + globals: { ...globals.browser, ...globals.node }, + parserOptions: { + ecmaFeatures: { jsx: true }, + ecmaVersion: 2024, + jsxPragma: null, + project, + tsconfigRootDir: import.meta.dirname, + }, + sourceType: "module", + }, + linterOptions: { + reportUnusedDisableDirectives: "error", + }, + plugins: { + "better-styled-components": legacyPlugin("better-styled-components"), + deprecation: legacyPlugin("eslint-plugin-deprecation", "deprecation"), + etc: fixupPluginRules(etc), + "extra-rules": legacyPlugin("eslint-plugin-extra-rules", "extra-rules"), + import: legacyPlugin("eslint-plugin-import", "import"), + jsdoc, + }, + settings: { + "import/resolver": { + typescript: { + alwaysTryTypes: true, + project, + }, + }, + react: { + version: "detect", + }, + }, + }, + { + rules: { + "@stylistic/arrow-parens": ["error", "as-needed"], + "@stylistic/indent": "off", + "@stylistic/indent-binary-ops": "off", + "@stylistic/jsx-curly-brace-presence": ["error", { children: "always" }], + "@stylistic/jsx-curly-newline": "off", + "@stylistic/jsx-pascal-case": ["error", { allowNamespace: true }], + "@stylistic/jsx-props-no-multi-spaces": "error", + "@stylistic/jsx-self-closing-comp": "error", + "@stylistic/jsx-wrap-multilines": ["error", { prop: "ignore" }], + "@stylistic/linebreak-style": "error", + "@stylistic/max-len": ["error", { + code: 120, + comments: 80, + ignorePattern: "^import (\\{ )?\\w+( \\})? from \".+\";$", + ignoreRegExpLiterals: true, + ignoreUrls: true, + tabWidth: 2, + }], + "@stylistic/member-delimiter-style": ["error", { singleline: { requireLast: true } }], + "@stylistic/no-extra-semi": "error", + "@stylistic/no-mixed-spaces-and-tabs": "error", + "@stylistic/no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }], + "@stylistic/object-curly-spacing": ["error", "always"], + "@stylistic/padded-blocks": ["error", "never", { allowSingleLineBlocks: false }], + "@stylistic/quote-props": ["error", "as-needed"], + "@stylistic/quotes": ["error", "double", { + allowTemplateLiterals: false, + avoidEscape: true, + }], + "@stylistic/space-before-function-paren": ["error", { anonymous: "never", named: "never" }], + "@stylistic/switch-colon-spacing": "error", + "@typescript-eslint/ban-types": "error", + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/consistent-type-exports": "off", + "@typescript-eslint/consistent-type-imports": ["off", { fixStyle: "inline-type-imports" }], + "@typescript-eslint/dot-notation": "error", + "@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }], + "@typescript-eslint/explicit-member-accessibility": "error", + "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/member-ordering": ["error", { + classes: [ + "static-field", + "field", + "constructor", + "static-method", + "abstract-method", + "protected-method", + "public-method", + "private-method", + ], + interfaces: { order: "alphabetically" }, + typeLiterals: { order: "alphabetically" }, + }], + "@typescript-eslint/no-empty-function": "error", + "@typescript-eslint/no-empty-interface": "error", + "@typescript-eslint/no-explicit-any": ["error", { ignoreRestArgs: true }], + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-inferrable-types": ["error", { + ignoreParameters: true, + ignoreProperties: true, + }], + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-non-null-assertion": "error", + "@typescript-eslint/no-redundant-type-constituents": "error", + "@typescript-eslint/no-shadow": ["error", { hoist: "all" }], + "@typescript-eslint/no-unused-expressions": ["error", { allowTernary: true }], + "@typescript-eslint/no-unused-vars": ["error", { + destructuredArrayIgnorePattern: "^_", + ignoreRestSiblings: true, + }], + "@typescript-eslint/no-use-before-define": ["error", { + classes: false, + functions: false, + }], + "@typescript-eslint/no-var-requires": "error", + "@typescript-eslint/only-throw-error": "error", + "@typescript-eslint/parameter-properties": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/restrict-template-expressions": ["error", { + allowBoolean: true, + allowNullish: true, + allowNumber: true, + }], + "@typescript-eslint/triple-slash-reference": "error", + "@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }], + "@typescript-eslint/unified-signatures": "error", + "better-styled-components/sort-declarations-alphabetically": "error", + camelcase: "error", + "constructor-super": "error", + curly: "error", + "deprecation/deprecation": "error", + eqeqeq: "error", + "etc/no-assign-mutated-array": "error", + "etc/no-internal": "error", + "extra-rules/no-commented-out-code": "error", + "func-style": ["error", "declaration", { allowArrowFunctions: true }], + "import/newline-after-import": "error", + "import/no-absolute-path": "error", + "import/no-cycle": ["error", { + allowUnsafeDynamicCyclicDependency: true, + ignoreExternal: true, + maxDepth: 1, + }], + "import/no-duplicates": ["error", { "prefer-inline": true }], + "import/no-import-module-exports": "error", + "import/no-namespace": "error", + "import/no-relative-packages": "error", + "import/no-unresolved": "error", + "import/no-useless-path-segments": "error", + "import/order": ["error", { + alphabetize: { + caseInsensitive: false, + order: "asc", + orderImportKind: "asc", + }, + groups: [ + "builtin", + ["external", "internal"], + "parent", + "sibling", + "index", + "type", + ], + "newlines-between": "always", + }], + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": ["error", { excludeTags: ["example", "param", "returns"] }], + "jsdoc/tag-lines": ["error", "any", { startLines: 1 }], + "max-classes-per-file": ["error", 1], + "no-caller": "error", + "no-cond-assign": "error", + "no-console": "error", + "no-duplicate-imports": "error", + "no-empty-function": "error", + "no-eval": "error", + "no-extra-boolean-cast": ["error", { enforceForLogicalOperands: true }], + "no-inner-declarations": ["error", "both"], + "no-invalid-this": "error", + "no-labels": "error", + "no-new-wrappers": "error", + "no-param-reassign": "error", + "no-throw-literal": "off", + "no-underscore-dangle": "error", + "no-use-before-define": "off", + "no-useless-computed-key": ["error", { enforceForClassMembers: true }], + "no-var": "error", + "object-shorthand": "error", + "one-var": ["error", "never"], + "prefer-const": "error", + radix: "error", + "react/display-name": "off", + "react/hook-use-state": "error", + "react/jsx-boolean-value": ["error", "always"], + "react/jsx-no-bind": "error", + "react/jsx-no-literals": "error", + "react/prop-types": "off", + "sonarjs/cognitive-complexity": "off", + "sonarjs/no-duplicate-string": "off", + "sonarjs/no-inverted-boolean-check": "error", + "sort-imports": ["error", { ignoreDeclarationSort: true }], + "sort-keys": "error", + }, + }, + { + files: ["**/*.?(c|m)js"], + languageOptions: { + parserOptions: { + programs: null, + project: false, + }, + }, + rules: { + ...eslintTs.configs.disableTypeChecked.rules, + "@typescript-eslint/explicit-function-return-type": "off", + "deprecation/deprecation": "off", + "etc/no-assign-mutated-array": "off", + "etc/no-internal": "off", + }, + }, + { + files: ["**/*.cjs"], + rules: { + "@typescript-eslint/no-var-requires": "off", + }, + }, + { + files: ["**/*.test.ts?(x)"], + rules: { + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "etc/throw-error": "off", + }, + }, + { + files: ["**/*.typetest.ts?(x)"], + rules: { + "@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": false }], + }, + }, +); diff --git a/example/babel.config.js b/example/babel.config.cjs similarity index 100% rename from example/babel.config.js rename to example/babel.config.cjs diff --git a/example/metro.config.js b/example/metro.config.cjs similarity index 100% rename from example/metro.config.js rename to example/metro.config.cjs diff --git a/example/metro.config.web.js b/example/metro.config.web.cjs similarity index 100% rename from example/metro.config.web.js rename to example/metro.config.web.cjs diff --git a/example/react-native.config.js b/example/react-native.config.cjs similarity index 100% rename from example/react-native.config.js rename to example/react-native.config.cjs diff --git a/example/src/App.tsx b/example/src/App.tsx index c9eeb31..e8a435f 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -4,9 +4,9 @@ import { Alert, Animated, Button, Dimensions, SafeAreaView, Text } from "react-n import { AttachStep, SpotlightTourProvider, + StopParams, TourBox, TourStep, - StopParams, } from "react-native-spotlight-tour"; import { @@ -37,8 +37,11 @@ export function App(): ReactElement { {"Tour: Intro section\n"} - {"This is the first step of tour example.\n"} - {"If you want to go to the next step, please press "}{"Next.\n"} + {dedent` + This is the first step of tour example. + If you want to go to the next step, please press \ + `} + {"Next.\n"}